Merge pull request #184 from Flipper-Zero/aku_nfc_clean

NFC: application + rfal + driver.
This commit is contained in:
coreglitch 2020-10-21 18:26:49 +06:00 committed by GitHub
commit e5f9159f66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
75 changed files with 42830 additions and 35 deletions

View file

@ -27,6 +27,7 @@ void gui_task(void* p);
void backlight_control(void* p);
void app_loader(void* p);
void cc1101_workaround(void* p);
void nfc_task(void* p);
const FlipperStartupApp FLIPPER_STARTUP[] = {
#ifdef APP_DISPLAY
@ -51,6 +52,10 @@ const FlipperStartupApp FLIPPER_STARTUP[] = {
{.app = cc1101_workaround, .name = "cc1101 workaround", .libs = {1, FURI_LIB{"gui_task"}}},
#endif
#ifdef APP_NFC
{.app = nfc_task, .name = "nfc_task", .libs = {1, FURI_LIB{"menu_task"}}},
#endif
// {.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .libs = ""},
#ifdef APP_TEST

View file

@ -9,12 +9,20 @@ CFLAGS += -I$(APP_DIR)
APP_RELEASE ?= 0
ifeq ($(APP_RELEASE), 1)
APP_MENU = 1
APP_NFC = 1
BUILD_EXAMPLE_BLINK = 1
BUILD_EXAMPLE_UART_WRITE = 1
BUILD_EXAMPLE_INPUT_DUMP = 1
BUILD_CC1101 = 1
endif
APP_NFC ?= 0
ifeq ($(APP_NFC), 1)
APP_MENU = 1
CFLAGS += -DAPP_NFC
C_SOURCES += $(wildcard $(APP_DIR)/nfc/*.c)
endif
APP_MENU ?= 0
ifeq ($(APP_MENU), 1)
CFLAGS += -DAPP_MENU

View file

@ -23,11 +23,34 @@ CC1101::CC1101(GpioPin ss_pin) {
//******************************************************************************
//SpiInit
/******************************************************************************/
extern SPI_HandleTypeDef hspi3;
void CC1101::SpiInit(void) {
//initialize spi pins
//Enable spi master, MSB, SPI mode 0, FOSC/4
SpiMode(0);
if(HAL_SPI_DeInit(&hspi3) != HAL_OK) {
Error_Handler();
}
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if(HAL_SPI_Init(&hspi3) != HAL_OK) {
Error_Handler();
}
}
void CC1101::SpiEnd(void) {
@ -68,8 +91,6 @@ void CC1101::SpiMode(byte config) {
*INPUT :value: data to send
*OUTPUT :data to receive
****************************************************************/
extern SPI_HandleTypeDef hspi3;
byte CC1101::SpiTransfer(byte value) {
uint8_t buf[1] = {value};
uint8_t rxbuf[1] = {0};

View file

@ -3,6 +3,10 @@
#include <stdio.h>
#include <flipper.h>
#ifdef APP_NFC
void st25r3916Isr(void);
#endif
static volatile bool initialized = false;
static SemaphoreHandle_t event;
static InputState input_state = {
@ -100,6 +104,13 @@ void input_task(void* p) {
}
void HAL_GPIO_EXTI_Callback(uint16_t pin) {
#ifdef APP_NFC
if(pin == RFID_PULL_Pin) {
st25r3916Isr();
return;
}
#endif
if(!initialized) return;
BaseType_t task_woken = pdFALSE;

View file

@ -56,9 +56,6 @@ void menu_build_main(Menu* menu) {
menu->root = menu_item_alloc_menu(NULL, NULL);
menu->settings = menu_item_alloc_menu("Setting", NULL);
menu_item_subitem_add(menu->settings, menu_item_alloc_function("one", NULL, NULL, NULL));
menu_item_subitem_add(menu->settings, menu_item_alloc_function("two", NULL, NULL, NULL));
menu_item_subitem_add(menu->settings, menu_item_alloc_function("three", NULL, NULL, NULL));
menu_item_add(menu, menu->settings);
}
@ -88,11 +85,16 @@ void menu_widget_callback(CanvasApi* canvas, void* context) {
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontSecondary);
for(size_t i = 0; i < 5; i++) {
size_t shift_position = i + menu->position + MenuItemArray_size(*items) - 2;
shift_position = shift_position % (MenuItemArray_size(*items));
MenuItem* item = *MenuItemArray_get(*items, shift_position);
canvas->draw_str(canvas, 2, 12 * (i + 1), menu_item_get_label(item));
if(MenuItemArray_size(*items)) {
for(size_t i = 0; i < 5; i++) {
size_t shift_position = i + menu->position + MenuItemArray_size(*items) - 2;
shift_position = shift_position % (MenuItemArray_size(*items));
MenuItem* item = *MenuItemArray_get(*items, shift_position);
canvas->draw_str(canvas, 2, 12 * (i + 1), menu_item_get_label(item));
}
} else {
canvas->draw_str(canvas, 2, 32, "Empty");
}
}

View file

@ -0,0 +1,56 @@
#include "dispatcher.h"
#include <flipper.h>
struct Dispatcher {
void* message;
size_t message_size;
osMessageQueueId_t mqueue;
osMutexId_t lock_mutex;
};
Dispatcher* dispatcher_alloc(size_t queue_size, size_t message_size) {
Dispatcher* dispatcher = furi_alloc(sizeof(Dispatcher));
dispatcher->message = furi_alloc(message_size);
dispatcher->message_size = message_size;
dispatcher->mqueue = osMessageQueueNew(queue_size, message_size, NULL);
assert(dispatcher->mqueue);
dispatcher->lock_mutex = osMutexNew(NULL);
assert(dispatcher->lock_mutex);
dispatcher_lock(dispatcher);
return dispatcher;
}
void dispatcher_free(Dispatcher* dispatcher) {
assert(dispatcher);
free(dispatcher);
}
void dispatcher_send(Dispatcher* dispatcher, Message* message) {
assert(dispatcher);
assert(message);
assert(osMessageQueuePut(dispatcher->mqueue, message, 0, osWaitForever) == osOK);
}
// TODO: bad side-effect
void dispatcher_recieve(Dispatcher* dispatcher, Message* message) {
assert(dispatcher);
assert(message);
dispatcher_unlock(dispatcher);
assert(osMessageQueueGet(dispatcher->mqueue, message, NULL, osWaitForever) == osOK);
dispatcher_lock(dispatcher);
}
void dispatcher_lock(Dispatcher* dispatcher) {
assert(dispatcher);
assert(osMutexAcquire(dispatcher->lock_mutex, osWaitForever) == osOK);
}
void dispatcher_unlock(Dispatcher* dispatcher) {
assert(dispatcher);
assert(osMutexRelease(dispatcher->lock_mutex) == osOK);
}

View file

@ -0,0 +1,28 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
enum MessageTypeBase {
MessageTypeExit = 0x00,
MessageTypeMemoryLow = 0x01,
MessageTypeBatteryLow = 0x02,
};
typedef struct {
enum MessageTypeBase type;
} Message;
typedef struct Dispatcher Dispatcher;
Dispatcher* dispatcher_alloc(size_t queue_size, size_t message_size);
void dispatcher_free(Dispatcher* dispatcher);
void dispatcher_send(Dispatcher* dispatcher, Message* message);
void dispatcher_recieve(Dispatcher* dispatcher, Message* message);
void dispatcher_lock(Dispatcher* dispatcher);
void dispatcher_unlock(Dispatcher* dispatcher);

289
applications/nfc/nfc.c Normal file
View file

@ -0,0 +1,289 @@
#include "nfc.h"
#include <assert.h>
#include <flipper_v2.h>
#include <gui/gui.h>
#include <gui/widget.h>
#include <gui/canvas.h>
#include <menu/menu.h>
#include <menu/menu_item.h>
#include <rfal_analogConfig.h>
#include <rfal_rf.h>
#include <rfal_nfc.h>
#include <rfal_nfca.h>
#include "dispatcher.h"
typedef enum {
MessageTypeBase,
} NfcMessageType;
typedef struct {
Message base;
void* data;
} NfcMessage;
struct Nfc {
Dispatcher* dispatcher;
Widget* widget;
MenuItem* menu;
FuriRecordSubscriber* gui_record;
FuriRecordSubscriber* menu_record;
rfalNfcDiscoverParam* disParams;
osThreadAttr_t worker_attr;
osThreadId_t worker;
uint8_t screen;
uint8_t ret;
uint8_t devCnt;
uint8_t ticker;
char* current;
};
#define EXAMPLE_NFCA_DEVICES 5
void nfc_worker_task(void* context) {
Nfc* nfc = context;
ReturnCode err;
rfalNfcaSensRes sensRes;
rfalNfcaSelRes selRes;
rfalNfcaListenDevice nfcaDevList[EXAMPLE_NFCA_DEVICES];
uint8_t devCnt;
uint8_t devIt;
rfalLowPowerModeStop();
nfc->ticker = 0;
while(widget_is_enabled(nfc->widget)) {
rfalFieldOff();
platformDelay(1000);
nfc->ticker += 1;
nfc->current = "Not detected";
nfc->devCnt = 0;
rfalNfcaPollerInitialize();
rfalFieldOnAndStartGT();
nfc->ret = err = rfalNfcaPollerTechnologyDetection(RFAL_COMPLIANCE_MODE_NFC, &sensRes);
if(err == ERR_NONE) {
err = rfalNfcaPollerFullCollisionResolution(
RFAL_COMPLIANCE_MODE_NFC, EXAMPLE_NFCA_DEVICES, nfcaDevList, &devCnt);
nfc->devCnt = devCnt;
if((err == ERR_NONE) && (devCnt > 0)) {
platformLog("NFC-A device(s) found %d\r\n", devCnt);
devIt = 0;
if(nfcaDevList[devIt].isSleep) {
err = rfalNfcaPollerCheckPresence(
RFAL_14443A_SHORTFRAME_CMD_WUPA, &sensRes); /* Wake up all cards */
if(err != ERR_NONE) {
continue;
}
err = rfalNfcaPollerSelect(
nfcaDevList[devIt].nfcId1,
nfcaDevList[devIt].nfcId1Len,
&selRes); /* Select specific device */
if(err != ERR_NONE) {
continue;
}
}
switch(nfcaDevList[devIt].type) {
case RFAL_NFCA_T1T:
/* No further activation needed for a T1T (RID already performed)*/
platformLog(
"NFC-A T1T device found \r\n"); /* NFC-A T1T device found, NFCID/UID is contained in: t1tRidRes.uid */
nfc->current = "NFC-A T1T";
/* Following communications shall be performed using:
* - Non blocking: rfalStartTransceive() + rfalGetTransceiveState()
* - Blocking: rfalTransceiveBlockingTx() + rfalTransceiveBlockingRx() or rfalTransceiveBlockingTxRx() */
break;
case RFAL_NFCA_T2T:
/* No specific activation needed for a T2T */
platformLog(
"NFC-A T2T device found \r\n"); /* NFC-A T2T device found, NFCID/UID is contained in: nfcaDev.nfcid */
nfc->current = "NFC-A T2T";
/* Following communications shall be performed using:
* - Non blocking: rfalStartTransceive() + rfalGetTransceiveState()
* - Blocking: rfalTransceiveBlockingTx() + rfalTransceiveBlockingRx() or rfalTransceiveBlockingTxRx() */
break;
case RFAL_NFCA_T4T:
platformLog(
"NFC-A T4T (ISO-DEP) device found \r\n"); /* NFC-A T4T device found, NFCID/UID is contained in: nfcaDev.nfcid */
nfc->current = "NFC-A T4T";
/* Activation should continue using rfalIsoDepPollAHandleActivation(), see exampleRfalPoller.c */
break;
case RFAL_NFCA_T4T_NFCDEP: /* Device supports T4T and NFC-DEP */
case RFAL_NFCA_NFCDEP: /* Device supports NFC-DEP */
platformLog(
"NFC-A P2P (NFC-DEP) device found \r\n"); /* NFC-A P2P device found, NFCID/UID is contained in: nfcaDev.nfcid */
nfc->current = "NFC-A P2P";
/* Activation should continue using rfalNfcDepInitiatorHandleActivation(), see exampleRfalPoller.c */
break;
}
rfalNfcaPollerSleep(); /* Put device to sleep / HLTA (useless as the field will be turned off anyhow) */
}
}
widget_update(nfc->widget);
}
rfalFieldOff();
rfalLowPowerModeStart();
nfc->ret = ERR_NONE;
nfc->worker = NULL;
osThreadExit();
}
void nfc_draw_callback(CanvasApi* canvas, void* context) {
assert(context);
Nfc* nfc = context;
dispatcher_lock(nfc->dispatcher);
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
if(nfc->screen == 0) {
char status[128 / 8];
if(nfc->ret == ERR_WRONG_STATE)
canvas->draw_str(canvas, 2, 16, "NFC Wrong State");
else if(nfc->ret == ERR_PARAM)
canvas->draw_str(canvas, 2, 16, "NFC Wrong Param");
else if(nfc->ret == ERR_IO)
canvas->draw_str(canvas, 2, 16, "NFC IO Error");
else if(nfc->ret == ERR_NONE)
canvas->draw_str(canvas, 2, 16, "NFC Device Found");
else if(nfc->ret == ERR_TIMEOUT)
canvas->draw_str(canvas, 2, 16, "NFC Timeout");
else
canvas->draw_str(canvas, 2, 16, "NFC error");
snprintf(status, sizeof(status), "Tck:%d Cnt:%d", nfc->ticker, nfc->devCnt);
canvas->draw_str(canvas, 2, 32, status);
canvas->draw_str(canvas, 2, 46, nfc->current);
} else {
canvas->draw_str(canvas, 2, 16, "Not implemented");
}
dispatcher_unlock(nfc->dispatcher);
}
void nfc_input_callback(InputEvent* event, void* context) {
assert(context);
Nfc* nfc = context;
if(!event->state) return;
widget_enabled_set(nfc->widget, false);
}
void nfc_test_callback(void* context) {
assert(context);
Nfc* nfc = context;
dispatcher_lock(nfc->dispatcher);
nfc->screen = 0;
widget_enabled_set(nfc->widget, true);
if(nfc->ret == ERR_NONE && !nfc->worker) {
// TODO change to fuirac_start
nfc->worker = osThreadNew(nfc_worker_task, nfc, &nfc->worker_attr);
}
dispatcher_unlock(nfc->dispatcher);
}
void nfc_read_callback(void* context) {
assert(context);
Nfc* nfc = context;
nfc->screen = 1;
widget_enabled_set(nfc->widget, true);
}
void nfc_write_callback(void* context) {
assert(context);
Nfc* nfc = context;
nfc->screen = 1;
widget_enabled_set(nfc->widget, true);
}
void nfc_bridge_callback(void* context) {
assert(context);
Nfc* nfc = context;
nfc->screen = 1;
widget_enabled_set(nfc->widget, true);
}
Nfc* nfc_alloc() {
Nfc* nfc = furi_alloc(sizeof(Nfc));
assert(nfc);
nfc->dispatcher = dispatcher_alloc(32, sizeof(NfcMessage));
nfc->widget = widget_alloc();
widget_draw_callback_set(nfc->widget, nfc_draw_callback, nfc);
widget_input_callback_set(nfc->widget, nfc_input_callback, nfc);
nfc->menu = menu_item_alloc_menu("NFC", NULL);
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Test", NULL, nfc_test_callback, nfc));
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Read", NULL, nfc_read_callback, nfc));
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Write", NULL, nfc_write_callback, nfc));
menu_item_subitem_add(
nfc->menu, menu_item_alloc_function("Brdige", NULL, nfc_bridge_callback, nfc));
nfc->gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL);
assert(nfc->gui_record);
nfc->menu_record = furi_open_deprecated("menu", false, false, NULL, NULL, NULL);
assert(nfc->menu_record);
nfc->worker_attr.name = "nfc_worker";
// nfc->worker_attr.attr_bits = osThreadJoinable;
nfc->worker_attr.stack_size = 4096;
return nfc;
}
void nfc_task(void* p) {
Nfc* nfc = nfc_alloc();
GuiApi* gui = furi_take(nfc->gui_record);
assert(gui);
widget_enabled_set(nfc->widget, false);
gui->add_widget(gui, nfc->widget, WidgetLayerFullscreen);
furi_commit(nfc->gui_record);
ValueMutex* menu_mutex = furi_open("menu");
assert(menu_mutex);
Menu* menu = acquire_mutex_block(menu_mutex);
menu_item_add(menu, nfc->menu);
release_mutex(menu_mutex, menu);
if(!furi_create("nfc", nfc)) {
printf("[nfc_task] cannot create nfc record\n");
furiac_exit(NULL);
}
furiac_ready();
nfc->ret = rfalNfcInitialize();
rfalLowPowerModeStart();
NfcMessage message;
while(1) {
dispatcher_recieve(nfc->dispatcher, (Message*)&message);
if(message.base.type == MessageTypeExit) {
break;
}
}
}

3
applications/nfc/nfc.h Normal file
View file

@ -0,0 +1,3 @@
#pragma once
typedef struct Nfc Nfc;

View file

@ -3,8 +3,8 @@ PROJECT = firmware
include $(PROJECT_ROOT)/make/base.mk
include $(PROJECT_ROOT)/core/core.mk
include $(PROJECT_ROOT)/lib/lib.mk
include $(PROJECT_ROOT)/applications/applications.mk
include $(PROJECT_ROOT)/lib/lib.mk
TARGET ?= f2
TARGET_DIR = targets/$(TARGET)

View file

@ -94,6 +94,7 @@ void Error_Handler(void);
#define LED_GREEN_GPIO_Port GPIOB
#define RFID_PULL_Pin GPIO_PIN_15
#define RFID_PULL_GPIO_Port GPIOB
#define RFID_PULL_EXTI_IRQn EXTI15_10_IRQn
#define VIBRO_Pin GPIO_PIN_6
#define VIBRO_GPIO_Port GPIOC
#define iButton_Pin GPIO_PIN_7

View file

@ -50,10 +50,10 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, DISPLAY_DI_Pin|CC1101_CS_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(DISPLAY_DI_GPIO_Port, DISPLAY_DI_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, NFC_CS_Pin|VIBRO_Pin|DISPLAY_CS_Pin|SD_CS_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC, NFC_CS_Pin|SD_CS_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, LED_BLUE_Pin|LED_GREEN_Pin, GPIO_PIN_SET);
@ -62,7 +62,10 @@ void MX_GPIO_Init(void)
HAL_GPIO_WritePin(GPIOB, DISPLAY_RST_Pin|IR_TX_Pin|DISPLAY_BACKLIGHT_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, VIBRO_Pin|DISPLAY_CS_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, LED_RED_Pin|CC1101_CS_Pin, GPIO_PIN_SET);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = BUTTON_BACK_Pin;
@ -134,6 +137,12 @@ void MX_GPIO_Init(void)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = RFID_PULL_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(RFID_PULL_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = LED_RED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;

View file

@ -60,7 +60,7 @@ void MX_SPI3_Init(void)
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
@ -68,7 +68,7 @@ void MX_SPI3_Init(void)
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
@ -120,7 +120,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

View file

@ -256,6 +256,7 @@ void EXTI15_10_IRQHandler(void)
/* USER CODE END EXTI15_10_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
/* USER CODE BEGIN EXTI15_10_IRQn 1 */
/* USER CODE END EXTI15_10_IRQn 1 */

View file

@ -140,10 +140,6 @@ void MX_TIM15_Init(void)
{
Error_Handler();
}
if (HAL_TIM_OC_ConfigChannel(&htim15, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
@ -255,14 +251,13 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM15 GPIO Configuration
PB13 ------> TIM15_CH1N
PB15 ------> TIM15_CH2
*/
GPIO_InitStruct.Pin = RFID_OUT_Pin|RFID_PULL_Pin;
GPIO_InitStruct.Pin = RFID_OUT_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_TIM15;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_Init(RFID_OUT_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN TIM15_MspPostInit 1 */

View file

@ -1,10 +1,11 @@
#MicroXplorer Configuration settings - do not modify
PB13.GPIOParameters=GPIO_Label
PC7.GPIOParameters=GPIO_ModeDefaultPP,GPIO_Speed,GPIO_PuPd,GPIO_Label
PA15\ (JTDI).GPIOParameters=GPIO_Label
PA15\ (JTDI).GPIOParameters=PinState,GPIO_Label
RCC.USART1Freq_Value=64000000
TIM8.ICPolarity_CH2=TIM_INPUTCHANNELPOLARITY_BOTHEDGE
SPI3.Direction=SPI_DIRECTION_2LINES
PC10.GPIO_PuPd=GPIO_PULLDOWN
SPI3.VirtualType=VM_MASTER
SPI1.VirtualType=VM_MASTER
VP_ADC1_TempSens_Input.Mode=IN-TempSens
@ -103,12 +104,13 @@ RCC.LPUART1Freq_Value=64000000
USB_OTG_FS.IPParameters=VirtualMode
PB13.Mode=Output Compare1 CH1N
PB10.GPIOParameters=GPIO_Label
PC12.GPIO_PuPd=GPIO_PULLDOWN
PA13\ (JTMS-SWDIO).Signal=SYS_JTMS-SWDIO
PA13\ (JTMS-SWDIO).GPIOParameters=GPIO_Label
PH0-OSC_IN\ (PH0).Mode=HSE-External-Oscillator
PA8.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
ProjectManager.CustomerFirmwarePackage=../../../lib/STM32CubeL4
PC4.GPIOParameters=GPIO_Label
PC4.GPIOParameters=PinState,GPIO_Label
PC2.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
NVIC.EXTI4_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true
RCC.PLLQoutputFreq_Value=64000000
@ -117,6 +119,7 @@ FREERTOS.Tasks01=defaultTask,24,1024,StartDefaultTask,Default,NULL,Dynamic,NULL,
ADC1.Rank-0\#ChannelRegularConversion=1
TIM5.IPParameters=Prescaler,Period,Channel-PWM Generation4 CH4,Pulse-PWM Generation4 CH4
Mcu.PinsNb=58
PC4.PinState=GPIO_PIN_SET
PC11.Locked=true
VP_SYS_VS_tim17.Mode=TIM17
ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,master,NbrOfConversion
@ -129,10 +132,12 @@ PB8.GPIO_PuPd=GPIO_PULLDOWN
PC6.Signal=GPIO_Output
PC2.Signal=GPXTI2
PB11.GPIO_Label=IR_TX
PC9.PinState=GPIO_PIN_SET
SH.GPXTI0.ConfNb=1
SPI1.CLKPhase=SPI_PHASE_1EDGE
PC0.Signal=GPIO_Analog
PB14.Locked=true
PC11.GPIOParameters=GPIO_PuPd
SH.S_TIM8_CH2.0=TIM8_CH2,Input_Capture2_from_TI2
PC3.GPIOParameters=GPIO_Label
PB8.GPIO_Label=BUTTON_RIGHT
@ -160,7 +165,6 @@ Mcu.Pin49=PB8
RCC.PLLSAI1PoutputFreq_Value=13714285.714285715
Mcu.Pin46=PB5
Mcu.Pin47=PB6
TIM15.Channel-Output\ Compare2\ CH2=TIM_CHANNEL_2
PB10.Signal=GPIO_Output
PB14.Signal=GPIO_Output
RCC.PLLSAI2RoutputFreq_Value=32000000
@ -173,7 +177,6 @@ Mcu.Pin45=PB4 (NJTRST)
Mcu.Pin42=PC12
Mcu.Pin43=PD2
ProjectManager.LastFirmware=true
SH.S_TIM15_CH2.ConfNb=1
Mcu.Pin37=PA13 (JTMS-SWDIO)
Mcu.Pin38=PA14 (JTCK-SWCLK)
PB15.GPIO_Label=RFID_PULL
@ -195,9 +198,10 @@ SH.ADCx_IN4.0=ADC1_IN4,IN4-Single-Ended
Mcu.Pin32=PA8
PA9.Locked=true
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PC10.GPIOParameters=GPIO_PuPd
SH.S_TIM5_CH4.ConfNb=1
ProjectManager.FreePins=false
PC9.GPIOParameters=GPIO_Label
PC9.GPIOParameters=PinState,GPIO_Label
RCC.LPTIM2Freq_Value=64000000
Mcu.Pin26=PB14
Mcu.Pin27=PB15
@ -231,6 +235,7 @@ Mcu.Pin16=PA7
Mcu.Pin13=PA4
Mcu.Pin14=PA5
Mcu.Pin19=PB0
SH.GPXTI15.ConfNb=1
ProjectManager.ComputerToolchain=false
Mcu.Pin17=PC4
Mcu.Pin18=PC5
@ -241,6 +246,7 @@ Mcu.Pin12=PA3
Mcu.Pin10=PA1
PC3.GPIO_Label=BATT_V
RCC.PWRFreq_Value=64000000
PA15\ (JTDI).PinState=GPIO_PIN_SET
SH.ADCx_IN5.ConfNb=1
PB4\ (NJTRST).GPIO_Label=BUTTON_LEFT
PB1.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
@ -278,18 +284,18 @@ PC13.GPIO_Label=BUTTON_BACK
PC1.Locked=true
PB13.GPIO_Label=RFID_OUT
PB11.Signal=GPIO_Output
PB15.Signal=S_TIM15_CH2
PB15.Signal=GPXTI15
ProjectManager.StackSize=0x400
PB3\ (JTDO-TRACESWO).Signal=SPI1_SCK
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
SH.GPXTI2.0=GPIO_EXTI2
SH.S_TIM15_CH2.0=TIM15_CH2,Output Compare2 CH2
RCC.I2C3Freq_Value=64000000
Mcu.IP4=RCC
RCC.FCLKCortexFreq_Value=64000000
Mcu.IP5=SPI1
Mcu.IP2=FREERTOS
Mcu.IP3=NVIC
PC11.GPIO_PuPd=GPIO_PULLDOWN
Mcu.IP0=ADC1
Mcu.IP1=COMP1
PA12.Locked=true
@ -352,6 +358,7 @@ PB7.GPIO_Label=CC1101_G0
PB4\ (NJTRST).Locked=true
PA6.Signal=GPIO_Analog
PA7.Locked=true
PB15.GPIO_PuPd=GPIO_PULLDOWN
NVIC.OTG_FS_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true
ProjectManager.ToolChainLocation=
PA2.GPIO_Label=DISPLAY_DI
@ -362,7 +369,7 @@ VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS
PC14-OSC32_IN\ (PC14).Locked=true
TIM8.Prescaler=64-1
PC4.Locked=true
SPI3.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler,CLKPolarity
SPI3.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler,CLKPolarity,CLKPhase
PC5.Signal=COMP1_INP
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16
PA1.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
@ -401,6 +408,7 @@ RCC.FamilyName=M
PH1-OSC_OUT\ (PH1).Signal=RCC_OSC_OUT
PB9.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
PC8.GPIO_Label=DISPLAY_CS
PC12.GPIOParameters=GPIO_PuPd
USART1.VirtualMode-Asynchronous=VM_ASYNC
FREERTOS.configUSE_IDLE_HOOK=1
PA9.Mode=Asynchronous
@ -417,12 +425,14 @@ PC2.Locked=true
ProjectManager.RegisterCallBack=
PC15-OSC32_OUT\ (PC15).Locked=true
RCC.USBFreq_Value=48000000
TIM15.IPParameters=Channel-Output Compare1 CH1N,Channel-Output Compare2 CH2
TIM15.IPParameters=Channel-Output Compare1 CH1N
PB14.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
PA1.Signal=GPXTI1
PB1.Locked=true
PB15.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING
PH1-OSC_OUT\ (PH1).Locked=true
board=NUCLEO-L476RG
SPI3.CLKPhase=SPI_PHASE_2EDGE
PC7.GPIO_Speed=GPIO_SPEED_FREQ_MEDIUM
RCC.VCOOutputFreq_Value=128000000
NVIC.SavedSystickIrqHandlerGenerated=true
@ -439,7 +449,7 @@ VP_ADC1_Vref_Input.Signal=ADC1_Vref_Input
SH.S_TIM5_CH4.0=TIM5_CH4,PWM Generation4 CH4
PC2.GPIO_PuPd=GPIO_PULLUP
RCC.UART5Freq_Value=64000000
PB15.GPIOParameters=GPIO_Label
PB15.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI
ADC1.NbrOfConversion=1
PA15\ (JTDI).GPIO_Label=CC1101_CS
RCC.IPParameters=ADCCLockSelection,ADCFreq_Value,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,DFSDMFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSI_VALUE,MCO1PinFreq_Value,MSI_VALUE,PLLM,PLLN,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1N,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSAI2PoutputFreq_Value,PLLSAI2RoutputFreq_Value,PLLSourceVirtual,PREFETCH_ENABLE,PWRFreq_Value,RNGFreq_Value,SAI1Freq_Value,SAI2Freq_Value,SDMMCFreq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value,VCOSAI2OutputFreq_Value
@ -471,6 +481,7 @@ SH.GPXTI4.ConfNb=1
PC6.GPIOParameters=GPIO_Label
RCC.HSI_VALUE=16000000
ADC1.NbrOfConversionFlag=1
SH.GPXTI15.0=GPIO_EXTI15
RCC.PLLM=2
RCC.PLLN=16
TIM8.Channel-Input_Capture2_from_TI2=TIM_CHANNEL_2

View file

@ -0,0 +1,354 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="File-List" href="Library_files/filelist.xml">
<link rel="Edit-Time-Data" href="Library_files/editdata.mso">
<!--[if !mso]> <style> v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]-->
<title>Release Notes for RFAL Library</title>
<!--[if gte mso 9]><xml> <o:DocumentProperties> <o:Author>STMicroelectronics</o:Author> <o:LastAuthor>STMicroelectronics</o:LastAuthor> <o:Revision>37</o:Revision> <o:TotalTime>136</o:TotalTime> <o:Created>2009-02-27T19:26:00Z</o:Created> <o:LastSaved>2009-03-01T17:56:00Z</o:LastSaved> <o:Pages>1</o:Pages> <o:Words>522</o:Words> <o:Characters>2977</o:Characters> <o:Company>STMicroelectronics</o:Company> <o:Lines>24</o:Lines> <o:Paragraphs>6</o:Paragraphs> <o:CharactersWithSpaces>3493</o:CharactersWithSpaces> <o:Version>11.6568</o:Version> </o:DocumentProperties> </xml><![endif]--><!--[if gte mso 9]><xml> <w:WordDocument> <w:Zoom>110</w:Zoom> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]-->
<style>
<!--
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0in;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";}
h2
{mso-style-next:Normal;
margin-top:12.0pt;
margin-right:0in;
margin-bottom:3.0pt;
margin-left:0in;
mso-pagination:widow-orphan;
page-break-after:avoid;
mso-outline-level:2;
font-size:14.0pt;
font-family:Arial;
font-weight:bold;
font-style:italic;}
a:link, span.MsoHyperlink
{color:blue;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{color:blue;
text-decoration:underline;
text-underline:single;}
p
{mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";}
@page Section1
{size:8.5in 11.0in;
margin:1.0in 1.25in 1.0in 1.25in;
mso-header-margin:.5in;
mso-footer-margin:.5in;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
</style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]--><!--[if gte mso 9]><xml> <o:shapedefaults v:ext="edit" spidmax="5122"/> </xml><![endif]--><!--[if gte mso 9]><xml> <o:shapelayout v:ext="edit"> <o:idmap v:ext="edit" data="1"/> </o:shapelayout></xml><![endif]-->
<meta content="MCD Application Team" name="author">
</head><body link="blue" vlink="blue">
<div class="Section1">
<p class="MsoNormal"><span style="font-family: Arial;"><o:p><br>
</o:p></span></p>
<div align="center">
<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" cellspacing="0" width="900">
<tbody>
<tr>
<td style="padding: 0cm;" valign="top">
<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" cellspacing="0" width="900">
<tbody>
<tr>
<td style="vertical-align: top;"> <br>
</td>
</tr>
<tr style="">
<td style="padding: 1.5pt;">
<h1 style="margin-bottom: 18pt; text-align: center;" align="center"><span style="font-size: 20pt; font-family: Verdana; color: rgb(51, 102, 255);">Release
Notes for RFAL software Library</span><span style="font-size: 20pt; font-family: Verdana;"><o:p></o:p></span></h1>
<p class="MsoNormal" style="text-align: center;" align="center"><span style="font-size: 10pt; font-family: Arial; color: black;">Copyright
2019 STMicroelectronics</span><span style="color: black;"><u1:p></u1:p><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: center;" align="center"><span style="font-size: 10pt; font-family: Arial; color: black;"><img style="border: 0px solid ; width: 104px; height: 77px;" alt="" id="_x0000_i1025" src="_htmresc/st_logo.png"></span><span style="font-size: 10pt;"><o:p></o:p></span></p>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal"><span style="font-family: Arial; display: none;"><o:p>&nbsp;</o:p></span></p>
<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" width="900">
<tbody>
<tr>
<td class="MsoNormal" style="padding: 0cm;" valign="top"><br>
<div style="margin-left: 40px;"><span style="font-size: 10pt; font-family: Verdana;">The <span style="font-weight: bold; font-style: italic;">RFAL Library</span>
(RF Abstraction Layer) provides several functionalities required to perform RF/NFC communications.</span><span style="font-size: 10pt; font-family: Verdana;">
The RFAL encapsulates the different RF ICs (ST25R3911, ST25R3916, ST25R95 and future ST25R devices) into a common and easy to use interface.</span><br>
<span style="font-size: 10pt; font-family: Verdana;"> </span><br>
<span style="font-size: 10pt; font-family: Verdana;"> </span><span style="font-size: 10pt; font-family: Verdana;">The technologies currently supported by RFAL are:
<ul>
<li> NFC-A \ ISO14443A (T1T, T2T, T4TA) </li>
<li> NFC-B \ ISO14443B (T4TB) </li>
<li> NFC-F \ FeliCa (T3T) </li>
<li> NFC-V \ ISO15693 (T5T) </li>
<li> P2P \ ISO18092 (NFCIP1, Passive-Active P2P) </li>
<li> ST25TB (ISO14443-2 Type B with Proprietary Protocol) </li>
<li> PicoPass \ iClass </li>
<li> B' \ Calypso </li>
<li> CTS \ CTM </li>
</ul>
</span><br>
<span style="font-size: 10pt; font-family: Verdana;"> </span><span style="font-size: 10pt; font-family: Verdana;">The protocols provided by RFAL are:
<ul>
<li> ISO-DEP (ISO14443-4) </li>
<li> NFC-DEP (ISO18092) </li>
</ul>
<br>
</span></div>
<ol style="margin-top: 0cm;" start="1" type="1">
</ol>
<span style="font-family: &quot;Times New Roman&quot;;"> </span>
<h2 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><a name="History"></a><span style="font-size: 12pt; color: white;">Update History</span></h2>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V2.2.0 / 22-May-2020</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;"></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Better alignment to NFC Forum latest requirements (CR12) <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended NFC-V module with non-addressed mode support and improved aticollision <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Feature Switches changed to be not mandatory. Modules disabled by default <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Aligned APIs on platform.h <i>(breaks compatibility with previous versions, see example in rfal.chm)</i> <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added API for release/deletion of timers <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">ST25R3916 default analog table modified to X-NUCLEO-NFC06A1 board <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Improved AP2P operation <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed issues introduced on previous release linked to SFGT and anticollision retries <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Introduced Low-Power mode <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several driver improvements <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V2.1.2 / 27-Jan-2020</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;"></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended ISO-DEP and NFC-A module to support non-blocking activation interfaces <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended NFC/HL module to make use of the new APIs further splitting the execution of the worker during the different activities<span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Modified NFC-A anticollision to strictly comply to NFC Forum DP. A separate proprietary method is now available. <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">NFC-V changed to use OOK (100% AM) by default <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed FWT used by NFC-V Sleep <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed NFC-F FDT Poll value <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed incorrect register access on ST25R3911B RFO Get/Set method <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">SPI driver modified to clear Rx buffer prior to operation <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added further code size optimizations based on enabled features <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Updated ST25R3916 driver to DS Rev2 <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Updated SW Tag Detection as describded in AN Rev3 <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several driver improvements <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V2.1.0 / 30-Sep-2019</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;"></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended RFAL NFC Higher Layer for increased functionality and configurations <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several improvements on the ISO-DEP protocol layer <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Protocol buffer sizes made fully configurable for increased memory management <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Introduced option for Collision Avoidance with Automatic Gain Control <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several driver improvements <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">ST25R3916 overheat protection disabled <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">RF Transceive modified for transmission errors to precede other errors <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Analog Configs extended to support different DPO power levels <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V2.0.10 / 25-Jun-2019</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;"></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Various improvements on RFAL NFC Higher layer <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added alternative NFC-V anticollision method (non NFC Forum compliant) <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several minor improvements and fixes <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V2.0.6 / 10-Apr-2019</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;"></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several NFC-V interoperability improvements <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended support for specific features of ST's ISO15693 Tags. New ST25Dx module added<span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Interrupt handling changed and further protection added <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">RFAL feature switches have been modified and features are now disabled if omitted <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">ST25R3916 AAT (Automatic Antenna Tunning) module added <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">RFAL NFC Higher layer added <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several driver improvements <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V2.0.4 / 06-Fev-2019</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with ST25R3916 DISCO v1.0.0 / EMVCo v1.2.0<o:p></o:p></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Minor improvements on NFC-F module <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several improvements on NFC-V module including support for ST proprietary features<span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed issue with Delta RWT calculation <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed incorrect usage of NFCB dTbPoll / DdFWT <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added compile switch for Listen Mode <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Low power Listen Mode support added <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Listen Mode aligned to NFC Forum Digital 2.1 <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added handling for EMVCo 3.0 static FDTListen <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Introduced SW Tag Detection <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V2.0.2 / 31-Oct-2018</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with ST25R3916 DISCO v0.9.4 (binary only)<o:p></o:p></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">New T4T module added <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added support for T3T Check and Update commands <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Improved NFC-V module and added Write Multiple Blocks support <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">New rfalWorker protection added for improved control in multi-thread environments <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added support for user defined Analog Config tables <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several driver improvements and protections added <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V2.0.0 / 28-Aug-2018</span></h3>
<!-- <p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with STM8-NFC05A1 <o:p></o:p></span></u></b></p> -->
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">MISRA C 2012 compliant <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">ST25R3916 support added <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">ST25R95 support added <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fix unwanted Field Detector disable when entering Wake-up mode <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended Analog Config to have specific events <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed NFC-DEP potential issue if DID used <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended NFC-V commands <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">T2T module added <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Improved initial Listen mode handling <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended Wake-Up mode to support Capacitive measurement <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V1.3.6 / 08-May-2018</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with ST25R3911B DISCO v1.2.0<o:p></o:p></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added ISO15693 x4 and x8 mode support <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added S(PARAMETERS) support <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Interface changes for measurement, Wake-Up and DPO methods <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added further feature switches to enable/disable individual modules <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Changed communication protection <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Improved NFC-A anti-collision <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several driver improvements <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V1.3.4 / 07-May-2018</span></h3>
<!--<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with <o:p></o:p></span></u></b></p>-->
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed NFC-V Read operation in addressed mode <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V1.3.2 / 31-January-2018</span></h3>
<!--<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with <o:p></o:p></span></u></b></p>-->
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Modified Wake-Up mode interface <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed SFGI calculation in ISO-DEP <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V1.3.0 / 22-January-2018</span></h3>
<!--<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with <o:p></o:p></span></u></b></p>-->
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Introduced a new IRQ status handling to read the registers only once <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several changes for supporting Linux platform <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">SPI Select/Deselect moved to platform.h <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Aditional protection of the IRQ status reading, new macros available: platformProtectST25R391xIrqStatus / platformUnprotectST25R391xIrqStatus<span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Renamed the IRQ Enable/Disable macros to platformProtectST25R391xComm / platformUnprotectST25R391xComm <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Renamed SPI pins from chip specific to ST25R391X <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Introduced a new option ST25R391X_COM_SINGLETXRX which executes SPI in one single exchange (additional buffer required) <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Updated and added errata handlings to latest ST25R3911 Errata version <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed inconsitency on Analog settings for NFC-V <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed issue on NFC-V 1of256 decoding <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Changed the default NFC-A FDT Listen to be more strict <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added Wake-Up mode support <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added RFAL version definition <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V1.2.0 / 17-August-2017</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with ST25R3911B Disco v1.1.16<o:p></o:p></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Aligned Technology modules to NFC Activity v1.1 and EMVCo v2.6 <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended NFC-B Collision Resolution allowing user define Slots <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added feature switches to enable/disable individual modules <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">ISO-DEP Interface changes allowing more user configurations and further EMVCo alignment <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Changed ST25TB detection to always perform Anti Collision loop regardeless of the result of the Poll<span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Fixed FIFO WL handling <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Modified FDT Poll handling <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">changed rfalCalibrate() to not overwrite dynamic configs <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added adjustment for TR1PUTMIN <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<span style="font-size: 10pt; font-family: Verdana;"></span>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V1.1.0 / 30-June-2017</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with ST25R3911B Disco v1.1.12<o:p></o:p></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">EMD supression enabled for ST25R3911B<span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<span style="font-size: 10pt; font-family: Verdana;"></span>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.0 / 16-May-2017</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with X-NUCLEO-NFC05A1 v1.0.0<o:p></o:p></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<ul style="margin-top: 0cm;" type="square">
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Added support for B', CTS and PicoPass/iClass mode <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Several impromvements for NFC-V mode <span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Improved error detection during NFC-B collision resolution<span style="font-weight: bold; font-style: italic;"></span></span></li>
<li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">Extended T1T module <span style="font-weight: bold; font-style: italic;"></span></span></li>
</ul>
<span style="font-size: 10pt; font-family: Verdana;"></span>
<br>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V0.9.0 / 02-March-2017</span></h3>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Provided with ST25R3911B Discovery Kit on Embedded World Conference (binary only)<o:p></o:p></span></u></b></p>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main Changes<o:p></o:p></span></u></b></p>
<span style="font-size: 10pt; font-family: Verdana;"></span>
<br>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal"><span style="font-size: 10pt;"><o:p></o:p></span></p>
</td>
</tr>
</tbody>
</table>
</div>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
</div>
</body></html>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b8781c6ed094b417a14afe877226d84c0f68d032432e4488ed0d819355a932cd
size 18616

BIN
lib/ST25RFAL002/doc/rfal.chm Executable file

Binary file not shown.

View file

@ -0,0 +1,357 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_AnalogConfig.h
*
* \author bkam
*
* \brief RF Chip Analog Configuration Settings
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-HAL
* \brief RFAL Hardware Abstraction Layer
* @{
*
* \addtogroup AnalogConfig
* \brief RFAL Analog Config Module
* @{
*
*/
#ifndef RFAL_ANALOG_CONFIG_H
#define RFAL_ANALOG_CONFIG_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
#define RFAL_ANALOG_CONFIG_LUT_SIZE (87U) /*!< Maximum number of Configuration IDs in the Loop Up Table */
#define RFAL_ANALOG_CONFIG_LUT_NOT_FOUND (0xFFU) /*!< Index value indicating no Configuration IDs found */
#define RFAL_ANALOG_CONFIG_TBL_SIZE (1024U) /*!< Maximum number of Register-Mask-Value in the Setting List */
#define RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK (0x8000U) /*!< Mask bit of Poll Mode in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_MASK (0x7F00U) /*!< Mask bits for Technology in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_MASK (0x00F0U) /*!< Mask bits for Bit rate in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_DIRECTION_MASK (0x000FU) /*!< Mask bits for Direction in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_CHIP_SPECIFIC_MASK (0x00FFU) /*!< Mask bits for Chip Specific Technology */
#define RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_SHIFT (15U) /*!< Shift value of Poll Mode in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_SHIFT (8U) /*!< Shift value for Technology in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_SHIFT (4U) /*!< Shift value for Technology in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_DIRECTION_SHIFT (0U) /*!< Shift value for Direction in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_POLL (0x0000U) /*!< Poll Mode bit setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_LISTEN (0x8000U) /*!< Listen Mode bit setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_CHIP (0x0000U) /*!< Chip-Specific bit setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_NFCA (0x0100U) /*!< NFC-A Technology bits setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_NFCB (0x0200U) /*!< NFC-B Technology bits setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_NFCF (0x0400U) /*!< NFC-F Technology bits setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_AP2P (0x0800U) /*!< AP2P Technology bits setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_NFCV (0x1000U) /*!< NFC-V Technology bits setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_TECH_RFU (0x2000U) /*!< RFU for Technology bits */
#define RFAL_ANALOG_CONFIG_BITRATE_COMMON (0x0000U) /*!< Common settings for all bit rates in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_106 (0x0010U) /*!< 106kbits/s settings in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_212 (0x0020U) /*!< 212kbits/s settings in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_424 (0x0030U) /*!< 424kbits/s settings in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_848 (0x0040U) /*!< 848kbits/s settings in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_1695 (0x0050U) /*!< 1695kbits/s settings in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_3390 (0x0060U) /*!< 3390kbits/s settings in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_6780 (0x0070U) /*!< 6780kbits/s settings in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_1OF4 (0x00C0U) /*!< 1 out of 4 for NFC-V setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_BITRATE_1OF256 (0x00D0U) /*!< 1 out of 256 for NFC-V setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_NO_DIRECTION (0x0000U) /*!< No direction setting in Analog Conf ID (Chip Specific only) */
#define RFAL_ANALOG_CONFIG_TX (0x0001U) /*!< Transmission bit setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_RX (0x0002U) /*!< Reception bit setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_ANTICOL (0x0003U) /*!< Anticollision setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_DPO (0x0004U) /*!< DPO setting in Analog Configuration ID */
#define RFAL_ANALOG_CONFIG_CHIP_INIT (0x0000U) /*!< Chip-Specific event: Startup;Reset;Initialize */
#define RFAL_ANALOG_CONFIG_CHIP_DEINIT (0x0001U) /*!< Chip-Specific event: Deinitialize */
#define RFAL_ANALOG_CONFIG_CHIP_FIELD_ON (0x0002U) /*!< Chip-Specific event: Field On */
#define RFAL_ANALOG_CONFIG_CHIP_FIELD_OFF (0x0003U) /*!< Chip-Specific event: Field Off */
#define RFAL_ANALOG_CONFIG_CHIP_WAKEUP_ON (0x0004U) /*!< Chip-Specific event: Wake-up On */
#define RFAL_ANALOG_CONFIG_CHIP_WAKEUP_OFF (0x0005U) /*!< Chip-Specific event: Wake-up Off */
#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_ON (0x0006U) /*!< Chip-Specific event: Listen On */
#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_OFF (0x0007U) /*!< Chip-Specific event: Listen Off */
#define RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON (0x0008U) /*!< Chip-Specific event: Poll common */
#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_COMMON (0x0009U) /*!< Chip-Specific event: Listen common */
#define RFAL_ANALOG_CONFIG_CHIP_LOWPOWER_ON (0x000AU) /*!< Chip-Specific event: Low Power On */
#define RFAL_ANALOG_CONFIG_CHIP_LOWPOWER_OFF (0x000BU) /*!< Chip-Specific event: Low Power Off */
#define RFAL_ANALOG_CONFIG_UPDATE_LAST (0x00U) /*!< Value indicating Last configuration set during update */
#define RFAL_ANALOG_CONFIG_UPDATE_MORE (0x01U) /*!< Value indicating More configuration set coming during update */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define RFAL_ANALOG_CONFIG_ID_GET_POLL_LISTEN(id) (RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK & (id)) /*!< Check if id indicates Listen mode */
#define RFAL_ANALOG_CONFIG_ID_GET_TECH(id) (RFAL_ANALOG_CONFIG_TECH_MASK & (id)) /*!< Get the technology of Configuration ID */
#define RFAL_ANALOG_CONFIG_ID_IS_CHIP(id) (RFAL_ANALOG_CONFIG_TECH_MASK & (id)) /*!< Check if ID indicates Chip-specific */
#define RFAL_ANALOG_CONFIG_ID_IS_NFCA(id) (RFAL_ANALOG_CONFIG_TECH_NFCA & (id)) /*!< Check if ID indicates NFC-A */
#define RFAL_ANALOG_CONFIG_ID_IS_NFCB(id) (RFAL_ANALOG_CONFIG_TECH_NFCB & (id)) /*!< Check if ID indicates NFC-B */
#define RFAL_ANALOG_CONFIG_ID_IS_NFCF(id) (RFAL_ANALOG_CONFIG_TECH_NFCF & (id)) /*!< Check if ID indicates NFC-F */
#define RFAL_ANALOG_CONFIG_ID_IS_AP2P(id) (RFAL_ANALOG_CONFIG_TECH_AP2P & (id)) /*!< Check if ID indicates AP2P */
#define RFAL_ANALOG_CONFIG_ID_IS_NFCV(id) (RFAL_ANALOG_CONFIG_TECH_NFCV & (id)) /*!< Check if ID indicates NFC-V */
#define RFAL_ANALOG_CONFIG_ID_GET_BITRATE(id) (RFAL_ANALOG_CONFIG_BITRATE_MASK & (id)) /*!< Get Bitrate of Configuration ID */
#define RFAL_ANALOG_CONFIG_ID_IS_COMMON(id) (RFAL_ANALOG_CONFIG_BITRATE_MASK & (id)) /*!< Check if ID indicates common bitrate */
#define RFAL_ANALOG_CONFIG_ID_IS_106(id) (RFAL_ANALOG_CONFIG_BITRATE_106 & (id)) /*!< Check if ID indicates 106kbits/s */
#define RFAL_ANALOG_CONFIG_ID_IS_212(id) (RFAL_ANALOG_CONFIG_BITRATE_212 & (id)) /*!< Check if ID indicates 212kbits/s */
#define RFAL_ANALOG_CONFIG_ID_IS_424(id) (RFAL_ANALOG_CONFIG_BITRATE_424 & (id)) /*!< Check if ID indicates 424kbits/s */
#define RFAL_ANALOG_CONFIG_ID_IS_848(id) (RFAL_ANALOG_CONFIG_BITRATE_848 & (id)) /*!< Check if ID indicates 848kbits/s */
#define RFAL_ANALOG_CONFIG_ID_IS_1695(id) (RFAL_ANALOG_CONFIG_BITRATE_1695 & (id)) /*!< Check if ID indicates 1695kbits/s */
#define RFAL_ANALOG_CONFIG_ID_IS_3390(id) (RFAL_ANALOG_CONFIG_BITRATE_3390 & (id)) /*!< Check if ID indicates 3390kbits/s */
#define RFAL_ANALOG_CONFIG_ID_IS_6780(id) (RFAL_ANALOG_CONFIG_BITRATE_6780 & (id)) /*!< Check if ID indicates 6780kbits/s */
#define RFAL_ANALOG_CONFIG_ID_IS_1OF4(id) (RFAL_ANALOG_CONFIG_BITRATE_1OF4 & (id)) /*!< Check if ID indicates 1 out of 4 bitrate */
#define RFAL_ANALOG_CONFIG_ID_IS_1OF256(id) (RFAL_ANALOG_CONFIG_BITRATE_1OF256 & (id)) /*!< Check if ID indicates 1 out of 256 bitrate */
#define RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(id) (RFAL_ANALOG_CONFIG_DIRECTION_MASK & (id)) /*!< Get Direction of Configuration ID */
#define RFAL_ANALOG_CONFIG_ID_IS_TX(id) (RFAL_ANALOG_CONFIG_TX & (id)) /*!< Check if id indicates TX */
#define RFAL_ANALOG_CONFIG_ID_IS_RX(id) (RFAL_ANALOG_CONFIG_RX & (id)) /*!< Check if id indicates RX */
#define RFAL_ANALOG_CONFIG_CONFIG_NUM(x) (sizeof(x)/sizeof((x)[0])) /*!< Get Analog Config number */
/*! Set Analog Config ID value by: Mode, Technology, Bitrate and Direction */
#define RFAL_ANALOG_CONFIG_ID_SET(mode, tech, br, direction) \
( RFAL_ANALOG_CONFIG_ID_GET_POLL_LISTEN(mode) \
| RFAL_ANALOG_CONFIG_ID_GET_TECH(tech) \
| RFAL_ANALOG_CONFIG_ID_GET_BITRATE(br) \
| RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(direction) \
)
/*
******************************************************************************
* GLOBAL DATA TYPES
******************************************************************************
*/
typedef uint8_t rfalAnalogConfigMode; /*!< Polling or Listening Mode of Configuration */
typedef uint8_t rfalAnalogConfigTech; /*!< Technology of Configuration */
typedef uint8_t rfalAnalogConfigBitrate; /*!< Bitrate of Configuration */
typedef uint8_t rfalAnalogConfigDirection; /*!< Transmit/Receive direction of Configuration */
typedef uint8_t rfalAnalogConfigRegAddr[2]; /*!< Register Address to ST Chip */
typedef uint8_t rfalAnalogConfigRegMask; /*!< Register Mask Value */
typedef uint8_t rfalAnalogConfigRegVal; /*!< Register Value */
typedef uint16_t rfalAnalogConfigId; /*!< Analog Configuration ID */
typedef uint16_t rfalAnalogConfigOffset; /*!< Analog Configuration offset address in the table */
typedef uint8_t rfalAnalogConfigNum; /*!< Number of Analog settings for the respective Configuration ID */
/*! Struct that contain the Register-Mask-Value set. Make sure that the whole structure size is even and unaligned! */
typedef struct {
rfalAnalogConfigRegAddr addr; /*!< Register Address */
rfalAnalogConfigRegMask mask; /*!< Register Mask Value */
rfalAnalogConfigRegVal val; /*!< Register Value */
} rfalAnalogConfigRegAddrMaskVal;
/*! Struct that represents the Analog Configs */
typedef struct {
uint8_t id[sizeof(rfalAnalogConfigId)]; /*!< Configuration ID */
rfalAnalogConfigNum num; /*!< Number of Config Sets to follow */
rfalAnalogConfigRegAddrMaskVal regSet[]; /*!< Register-Mask-Value sets */ /* PRQA S 1060 # MISRA 18.7 - Flexible Array Members are the only meaningful way of denoting a variable length input buffer which follows a fixed header structure. */
} rfalAnalogConfig;
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize the Analog Configuration
*
* Reset the Analog Configuration LUT pointer to reference to default settings.
*
*****************************************************************************
*/
void rfalAnalogConfigInitialize( void );
/*!
*****************************************************************************
* \brief Indicate if the current Analog Configuration Table is complete and ready to be used.
*
* \return true if current Analog Configuration Table is complete and ready to be used.
* \return false if current Analog Configuration Table is incomplete
*
*****************************************************************************
*/
bool rfalAnalogConfigIsReady( void );
/*!
*****************************************************************************
* \brief Write the whole Analog Configuration table in raw format
*
* Writes the Analog Configuration and Look Up Table with the given raw table
*
* NOTE: Function does not check the validity of the given Table contents
*
* \param[in] configTbl: location of config Table to be loaded
* \param[in] configTblSize: size of the config Table to be loaded
*
* \return ERR_NONE : if setting is updated
* \return ERR_PARAM : if configTbl is invalid
* \return ERR_NOMEM : if the given Table is bigger exceeds the max size
* \return ERR_REQUEST : if the update Configuration Id is disabled
*
*****************************************************************************
*/
ReturnCode rfalAnalogConfigListWriteRaw( const uint8_t *configTbl, uint16_t configTblSize );
/*!
*****************************************************************************
* \brief Write the Analog Configuration table with new analog settings.
*
* Writes the Analog Configuration and Look Up Table with the new list of register-mask-value
* and Configuration ID respectively.
*
* NOTE: Function does not check for the validity of the Register Address.
*
* \param[in] more: 0x00 indicates it is last Configuration ID settings;
* 0x01 indicates more Configuration ID setting(s) are coming.
* \param[in] *config: reference to the configuration list of current Configuraiton ID.
*
* \return ERR_PARAM : if Configuration ID or parameter is invalid
* \return ERR_NOMEM : if LUT is full
* \return ERR_REQUEST : if the update Configuration Id is disabled
* \return ERR_NONE : if setting is updated
*
*****************************************************************************
*/
ReturnCode rfalAnalogConfigListWrite( uint8_t more, const rfalAnalogConfig *config );
/*!
*****************************************************************************
* \brief Read the whole Analog Configuration table in raw format
*
* Reads the whole Analog Configuration Table in raw format
*
* \param[out] tblBuf: location to the buffer to place the Config Table
* \param[in] tblBufLen: length of the buffer to place the Config Table
* \param[out] configTblSize: Config Table size
*
* \return ERR_PARAM : if configTbl or configTblSize is invalid
* \return ERR_NOMEM : if configTblSize is not enough for the whole table
* \return ERR_NONE : if read is successful
*
*****************************************************************************
*/
ReturnCode rfalAnalogConfigListReadRaw( uint8_t *tblBuf, uint16_t tblBufLen, uint16_t *configTblSize );
/*!
*****************************************************************************
* \brief Read the Analog Configuration table.
*
* Read the Analog Configuration Table
*
* \param[in] configOffset: offset to the next Configuration ID in the List Table to be read.
* \param[out] more: 0x00 indicates it is last Configuration ID settings;
* 0x01 indicates more Configuration ID setting(s) are coming.
* \param[out] config: configuration id, number of configuration sets and register-mask-value sets
* \param[in] numConfig: the remaining configuration settings space available;
*
* \return ERR_NOMEM : if number of Configuration for respective Configuration ID is greater the the remaining configuration setting space available
* \return ERR_NONE : if read is successful
*
*****************************************************************************
*/
ReturnCode rfalAnalogConfigListRead( rfalAnalogConfigOffset *configOffset, uint8_t *more, rfalAnalogConfig *config, rfalAnalogConfigNum numConfig );
/*!
*****************************************************************************
* \brief Set the Analog settings of indicated Configuration ID.
*
* Update the chip with indicated analog settings of indicated Configuration ID.
*
* \param[in] configId: configuration ID
*
* \return ERR_PARAM if Configuration ID is invalid
* \return ERR_INTERNAL if error updating setting to chip
* \return ERR_NONE if new settings is applied to chip
*
*****************************************************************************
*/
ReturnCode rfalSetAnalogConfig( rfalAnalogConfigId configId );
/*!
*****************************************************************************
* \brief Generates Analog Config mode ID
*
* Converts RFAL mode and bitrate into Analog Config Mode ID.
*
* Update the chip with indicated analog settings of indicated Configuration ID.
*
* \param[in] md: RFAL mode format
* \param[in] br: RFAL bit rate format
* \param[in] dir: Analog Config communication direction
*
* \return Analog Config Mode ID
*
*****************************************************************************
*/
uint16_t rfalAnalogConfigGenModeID( rfalMode md, rfalBitRate br, uint16_t dir );
#endif /* RFAL_ANALOG_CONFIG_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,296 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_chip.h
*
* \author Gustavo Patricio
*
* \brief RF Chip specific Layer
*
* \warning This layer, which provides direct access to RF chip, should
* only be used for debug purposes and/or advanced features
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-HAL
* \brief RFAL Hardware Abstraction Layer
* @{
*
* \addtogroup Chip
* \brief RFAL RF Chip Module
* @{
*
*/
#ifndef RFAL_CHIP_H
#define RFAL_CHIP_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
/*****************************************************************************
* RF Chip *
*****************************************************************************/
/*!
*****************************************************************************
* \brief Writes a register on the RF Chip
*
* Checks if the given register is valid and if so, writes the value(s)
* on the RF Chip register
*
* \param[in] reg: register address to be written, or the first if len > 1
* \param[in] values: pointer with content to be written on the register(s)
* \param[in] len: number of consecutive registers to be written
*
*
* \return ERR_PARAM : Invalid register or bad request
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : Write done with no error
*****************************************************************************
*/
ReturnCode rfalChipWriteReg( uint16_t reg, const uint8_t* values, uint8_t len );
/*!
*****************************************************************************
* \brief Reads a register on the RF Chip
*
* Checks if the given register is valid and if so, reads the value(s)
* of the RF Chip register(s)
*
* \param[in] reg: register address to be read, or the first if len > 1
* \param[out] values: pointer where the register(s) read content will be placed
* \param[in] len: number of consecutive registers to be read
*
* \return ERR_PARAM : Invalid register or bad request
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : Read done with no error
*****************************************************************************
*/
ReturnCode rfalChipReadReg( uint16_t reg, uint8_t* values, uint8_t len );
/*!
*****************************************************************************
* \brief Change a register on the RF Chip
*
* Change the value of the register bits on the RF Chip Test set in the valueMask.
*
* \param[in] reg: register address to be modified
* \param[in] valueMask: mask value of the register bits to be changed
* \param[in] value: register value to be set
*
* \return ERR_PARAM : Invalid register or bad request
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_OK : Change done with no error
*****************************************************************************
*/
ReturnCode rfalChipChangeRegBits( uint16_t reg, uint8_t valueMask, uint8_t value );
/*!
*****************************************************************************
* \brief Writes a Test register on the RF Chip
*
* Writes the value on the RF Chip Test register
*
* \param[in] reg: register address to be written
* \param[in] value: value to be written on the register
*
*
* \return ERR_PARAM : Invalid register or bad request
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : Write done with no error
*****************************************************************************
*/
ReturnCode rfalChipWriteTestReg( uint16_t reg, uint8_t value );
/*!
*****************************************************************************
* \brief Reads a Test register on the RF Chip
*
* Reads the value of the RF Chip Test register
*
* \param[in] reg: register address to be read
* \param[out] value: pointer where the register content will be placed
*
* \return ERR_PARAM :Invalid register or bad request
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : Read done with no error
*****************************************************************************
*/
ReturnCode rfalChipReadTestReg( uint16_t reg, uint8_t* value );
/*!
*****************************************************************************
* \brief Change a Test register on the RF Chip
*
* Change the value of the register bits on the RF Chip Test set in the valueMask.
*
* \param[in] reg: test register address to be modified
* \param[in] valueMask: mask value of the register bits to be changed
* \param[in] value: register value to be set
*
* \return ERR_PARAM : Invalid register or bad request
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_OK : Change done with no error
*****************************************************************************
*/
ReturnCode rfalChipChangeTestRegBits( uint16_t reg, uint8_t valueMask, uint8_t value );
/*!
*****************************************************************************
* \brief Execute command on the RF Chip
*
* Checks if the given command is valid and if so, executes it on
* the RF Chip
*
* \param[in] cmd: direct command to be executed
*
* \return ERR_PARAM : Invalid command or bad request
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : Direct command executed with no error
*****************************************************************************
*/
ReturnCode rfalChipExecCmd( uint16_t cmd );
/*!
*****************************************************************************
* \brief Set RFO
*
* Sets the RFO value to be used when the field is on (unmodulated/active)
*
* \param[in] rfo : the RFO value to be used
*
* \return ERR_IO : Internal error
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalChipSetRFO( uint8_t rfo );
/*!
*****************************************************************************
* \brief Get RFO
*
* Gets the RFO value used used when the field is on (unmodulated/active)
*
* \param[out] result : the current RFO value
*
* \return ERR_IO : Internal error
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalChipGetRFO( uint8_t* result );
/*!
*****************************************************************************
* \brief Measure Amplitude
*
* Measures the RF Amplitude
*
* \param[out] result : result of RF measurement
*
* \return ERR_IO : Internal error
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalChipMeasureAmplitude( uint8_t* result );
/*!
*****************************************************************************
* \brief Measure Phase
*
* Measures the Phase
*
* \param[out] result : result of Phase measurement
*
* \return ERR_IO : Internal error
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalChipMeasurePhase( uint8_t* result );
/*!
*****************************************************************************
* \brief Measure Capacitance
*
* Measures the Capacitance
*
* \param[out] result : result of Capacitance measurement
*
* \return ERR_IO : Internal error
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalChipMeasureCapacitance( uint8_t* result );
/*!
*****************************************************************************
* \brief Measure Power Supply
*
* Measures the Power Supply
*
* \param[in] param : measurement parameter (chip specific)
* \param[out] result : result of the measurement
*
* \return ERR_IO : Internal error
* \return ERR_NOTSUPP : Feature not supported
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalChipMeasurePowerSupply( uint8_t param, uint8_t* result );
#endif /* RFAL_CHIP_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,75 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_crc.h
*
* \author Ulrich Herrmann
*
* \brief CRC calculation module
*
*/
/*!
*
*/
#ifndef RFAL_CRC_H_
#define RFAL_CRC_H_
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Calculate CRC according to CCITT standard.
*
* This function takes \a length bytes from \a buf and calculates the CRC
* for this data. The result is returned.
* \note This implementation calculates the CRC with LSB first, i.e. all
* bytes are "read" from right to left.
*
* \param[in] preloadValue : Initial value of CRC calculation.
* \param[in] buf : buffer to calculate the CRC for.
* \param[in] length : size of the buffer.
*
* \return 16 bit long crc value.
*
*****************************************************************************
*/
extern uint16_t rfalCrcCalculateCcitt(uint16_t preloadValue, const uint8_t* buf, uint16_t length);
#endif /* RFAL_CRC_H_ */

View file

@ -0,0 +1,209 @@
/******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* $Revision: $
* LANGUAGE: ISO C99
*/
/*! \file rfal_dpo.h
*
* \author Martin Zechleitner
*
* \brief Dynamic Power adjustment
*
* This module provides an interface to perform the power adjustment dynamically
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-HAL
* \brief RFAL Hardware Abstraction Layer
* @{
*
* \addtogroup DPO
* \brief RFAL Dynamic Power Module
* @{
*
*/
#ifndef RFAL_DPO_H
#define RFAL_DPO_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_DPO_TABLE_SIZE_MAX 15U /*!< Max DPO table size */
#define RFAL_DPO_TABLE_PARAMETER 3U /*!< DPO table Parameter length */
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! DPO table entry struct */
typedef struct {
uint8_t rfoRes; /*!< Setting for the resistance level of the RFO */
uint8_t inc; /*!< Threshold for incrementing the output power */
uint8_t dec; /*!< Threshold for decrementing the output power */
}rfalDpoEntry;
/*! Function pointer to methode doing the reference measurement */
typedef ReturnCode (*rfalDpoMeasureFunc)(uint8_t*);
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize dynamic power table
*
* This function sets the internal dynamic power table to the default
* values stored in rfal_DpoTbl.h
*
*****************************************************************************
*/
void rfalDpoInitialize( void );
/*!
*****************************************************************************
* \brief Set the measurement methode
*
* This function sets the measurement method used for reference measurement.
* Based on the measurement the power will then be adjusted
*
* \param[in] dpoMeasureFunc: callback of measurement function
*
*****************************************************************************
*/
void rfalDpoSetMeasureCallback( rfalDpoMeasureFunc dpoMeasureFunc );
/*!
*****************************************************************************
* \brief Write dynamic power table
*
* Load the dynamic power table
*
* \param[in] powerTbl: location of power Table to be loaded
* \param[in] powerTblEntries: number of entries of the power Table to be loaded
*
* \return ERR_NONE : No error
* \return ERR_PARAM : if configTbl is invalid
* \return ERR_NOMEM : if the given Table is bigger exceeds the max size
*****************************************************************************
*/
ReturnCode rfalDpoTableWrite( rfalDpoEntry* powerTbl, uint8_t powerTblEntries );
/*!
*****************************************************************************
* \brief Dynamic power table Read
*
* Read the dynamic power table
*
* \param[out] tblBuf: location to the rfalDpoEntry[] to place the Table
* \param[in] tblBufEntries: number of entries available in tblBuf to place the power Table
* \param[out] tableEntries: returned number of entries actually written into tblBuf
*
* \return ERR_NONE : No error
* \return ERR_PARAM : if configTbl is invalid or parameters are invalid
*****************************************************************************
*/
ReturnCode rfalDpoTableRead( rfalDpoEntry* tblBuf, uint8_t tblBufEntries, uint8_t* tableEntries );
/*!
*****************************************************************************
* \brief Dynamic power adjust
*
* It measures the current output and adjusts the power accordingly to
* the dynamic power table
*
* \return ERR_NONE : No error
* \return ERR_PARAM : if configTbl is invalid or parameters are invalid
* \return ERR_WRONG_STATE : if the current state is valid for DPO Adjustment
*****************************************************************************
*/
ReturnCode rfalDpoAdjust( void );
/*!
*****************************************************************************
* \brief Get Current Dynamic power table entry
*
* Return current used DPO power table entry settings
*
* \return ERR_NONE : Current DpoEntry. This includes d_res, inc and dec
*
*****************************************************************************
*/
rfalDpoEntry* rfalDpoGetCurrentTableEntry(void);
/*!
*****************************************************************************
* \brief Dynamic power set enabled state
*
* \param[in] enable: new active state
*
* Set state to enable or disable the Dynamic power adjustment
*
*****************************************************************************
*/
void rfalDpoSetEnabled( bool enable );
/*!
*****************************************************************************
* \brief Get the Dynamic power enabled state
*
* Get state of the Dynamic power adjustment
*
* \return true : enabled
* \return false : disabled
*****************************************************************************
*/
bool rfalDpoIsEnabled(void);
#endif /* RFAL_DPO_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,202 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_iso15693_2.h
*
* \author Ulrich Herrmann
*
* \brief Implementation of ISO-15693-2
*
*/
/*!
*
*/
#ifndef RFAL_ISO_15693_2_H
#define RFAL_ISO_15693_2_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
/*
******************************************************************************
* GLOBAL DATATYPES
******************************************************************************
*/
/*! Enum holding possible VCD codings */
typedef enum
{
ISO15693_VCD_CODING_1_4,
ISO15693_VCD_CODING_1_256
}iso15693VcdCoding_t;
/*! Enum holding possible VICC datarates */
/*! Configuration parameter used by #iso15693PhyConfigure */
typedef struct
{
iso15693VcdCoding_t coding; /*!< desired VCD coding */
uint32_t speedMode; /*!< 0: normal mode, 1: 2^1 = x2 Fast mode, 2 : 2^2 = x4 mode, 3 : 2^3 = x8 mode - all rx pulse numbers and times are divided by 1,2,4,8 */
}iso15693PhyConfig_t;
/*! Parameters how the stream mode should work */
struct iso15693StreamConfig {
uint8_t useBPSK; /*!< 0: subcarrier, 1:BPSK */
uint8_t din; /*!< the divider for the in subcarrier frequency: fc/2^din */
uint8_t dout; /*!< the divider for the in subcarrier frequency fc/2^dout */
uint8_t report_period_length; /*!< the length of the reporting period 2^report_period_length*/
};
/*
******************************************************************************
* GLOBAL CONSTANTS
******************************************************************************
*/
#define ISO15693_REQ_FLAG_TWO_SUBCARRIERS 0x01U /*!< Flag indication that communication uses two subcarriers */
#define ISO15693_REQ_FLAG_HIGH_DATARATE 0x02U /*!< Flag indication that communication uses high bitrate */
#define ISO15693_MASK_FDT_LISTEN (65) /*!< t1min = 308,2us = 4192/fc = 65.5 * 64/fc */
/*! t1max = 323,3us = 4384/fc = 68.5 * 64/fc
* 12 = 768/fc unmodulated time of single subcarrior SoF */
#define ISO15693_FWT (69 + 12)
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize the ISO15693 phy
*
* \param[in] config : ISO15693 phy related configuration (See #iso15693PhyConfig_t)
* \param[out] needed_stream_config : return a pointer to the stream config
* needed for this iso15693 config. To be used for configure RF chip.
*
* \return ERR_IO : Error during communication.
* \return ERR_NONE : No error.
*
*****************************************************************************
*/
extern ReturnCode iso15693PhyConfigure(const iso15693PhyConfig_t* config,
const struct iso15693StreamConfig ** needed_stream_config );
/*!
*****************************************************************************
* \brief Return current phy configuration
*
* This function returns current Phy configuration previously
* set by #iso15693PhyConfigure
*
* \param[out] config : ISO15693 phy configuration.
*
* \return ERR_NONE : No error.
*
*****************************************************************************
*/
extern ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t* config);
/*!
*****************************************************************************
* \brief Code an ISO15693 compatible frame
*
* This function takes \a length bytes from \a buffer, perform proper
* encoding and sends out the frame to the ST25R391x.
*
* \param[in] buffer : data to send, modified to adapt flags.
* \param[in] length : number of bytes to send.
* \param[in] sendCrc : If set to true, CRC is appended to the frame
* \param[in] sendFlags: If set to true, flag field is sent according to
* ISO15693.
* \param[in] picopassMode : If set to true, the coding will be according to Picopass
* \param[out] subbit_total_length : Return the complete bytes which need to
* be send for the current coding
* \param[in,out] offset : Set to 0 for first transfer, function will update it to
point to next byte to be coded
* \param[out] outbuf : buffer where the function will store the coded subbit stream
* \param[out] outBufSize : the size of the output buffer
* \param[out] actOutBufSize : the amount of data stored into the buffer at this call
*
* \return ERR_IO : Error during communication.
* \return ERR_AGAIN : Data was not coded all the way. Call function again with a new/emptied buffer
* \return ERR_NO_MEM : In case outBuf is not big enough. Needs to have at
least 5 bytes for 1of4 coding and 65 bytes for 1of256 coding
* \return ERR_NONE : No error.
*
*****************************************************************************
*/
extern ReturnCode iso15693VCDCode(uint8_t* buffer, uint16_t length, bool sendCrc, bool sendFlags, bool picopassMode,
uint16_t *subbit_total_length, uint16_t *offset,
uint8_t* outbuf, uint16_t outBufSize, uint16_t* actOutBufSize);
/*!
*****************************************************************************
* \brief Receive an ISO15693 compatible frame
*
* This function receives an ISO15693 frame from the ST25R391x, decodes the frame
* and writes the raw data to \a buffer.
* \note Buffer needs to be big enough to hold CRC also (+2 bytes)
*
* \param[in] inBuf : buffer with the hamming coded stream to be decoded
* \param[in] inBufLen : number of bytes to decode (=length of buffer).
* \param[out] outBuf : buffer where received data shall be written to.
* \param[in] outBufLen : Length of output buffer, should be approx twice the size of inBuf
* \param[out] outBufPos : The number of decoded bytes. Could be used in
* extended implementation to allow multiple calls
* \param[out] bitsBeforeCol : in case of ERR_COLLISION this value holds the
* number of bits in the current byte where the collision happened.
* \param[in] ignoreBits : number of bits in the beginning where collisions will be ignored
* \param[in] picopassMode : if set to true, the decoding will be according to Picopass
*
* \return ERR_COLLISION : collision occured, data uncorrect
* \return ERR_CRC : CRC error, data uncorrect
* \return ERR_TIMEOUT : timeout waiting for data.
* \return ERR_NONE : No error.
*
*****************************************************************************
*/
extern ReturnCode iso15693VICCDecode(const uint8_t *inBuf,
uint16_t inBufLen,
uint8_t* outBuf,
uint16_t outBufLen,
uint16_t* outBufPos,
uint16_t* bitsBeforeCol,
uint16_t ignoreBits,
bool picopassMode );
#endif /* RFAL_ISO_15693_2_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,415 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfc.h
*
* \brief RFAL NFC device
*
* This module provides the required features to behave as an NFC Poller
* or Listener device. It grants an easy to use interface for the following
* activities: Technology Detection, Collision Resolution, Activation,
* Data Exchange, and Deactivation
*
* This layer is influenced by (but not fully aligned with) the NFC Forum
* specifications, in particular: Activity 2.0 and NCI 2.0
*
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-HL
* \brief RFAL Higher Layer
* @{
*
* \addtogroup NFC
* \brief RFAL NFC Device
* @{
*
*/
#ifndef RFAL_NFC_H
#define RFAL_NFC_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
#include "rfal_nfca.h"
#include "rfal_nfcb.h"
#include "rfal_nfcf.h"
#include "rfal_nfcv.h"
#include "rfal_st25tb.h"
#include "rfal_nfcDep.h"
#include "rfal_isoDep.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFC_TECH_NONE 0x0000U /*!< No technology */
#define RFAL_NFC_POLL_TECH_A 0x0001U /*!< NFC-A technology Flag */
#define RFAL_NFC_POLL_TECH_B 0x0002U /*!< NFC-B technology Flag */
#define RFAL_NFC_POLL_TECH_F 0x0004U /*!< NFC-F technology Flag */
#define RFAL_NFC_POLL_TECH_V 0x0008U /*!< NFC-V technology Flag */
#define RFAL_NFC_POLL_TECH_AP2P 0x0010U /*!< AP2P technology Flag */
#define RFAL_NFC_POLL_TECH_ST25TB 0x0020U /*!< ST25TB technology Flag */
#define RFAL_NFC_LISTEN_TECH_A 0x1000U /*!< NFC-V technology Flag */
#define RFAL_NFC_LISTEN_TECH_B 0x2000U /*!< NFC-V technology Flag */
#define RFAL_NFC_LISTEN_TECH_F 0x4000U /*!< NFC-V technology Flag */
#define RFAL_NFC_LISTEN_TECH_AP2P 0x8000U /*!< NFC-V technology Flag */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*! Checks if a device is currently activated */
#define rfalNfcIsDevActivated( st ) ( ((st)>= RFAL_NFC_STATE_ACTIVATED) && ((st)<RFAL_NFC_STATE_DEACTIVATION) )
/*! Checks if a device is in discovery */
#define rfalNfcIsInDiscovery( st ) ( ((st)>= RFAL_NFC_STATE_START_DISCOVERY) && ((st)<RFAL_NFC_STATE_ACTIVATED) )
/*! Checks if remote device is in Poll mode */
#define rfalNfcIsRemDevPoller( tp ) ( ((tp)>= RFAL_NFC_POLL_TYPE_NFCA) && ((tp)<=RFAL_NFC_POLL_TYPE_AP2P ) )
/*! Checks if remote device is in Listen mode */
#define rfalNfcIsRemDevListener( tp ) ( ((int16_t)(tp)>= (int16_t)RFAL_NFC_LISTEN_TYPE_NFCA) && ((tp)<=RFAL_NFC_LISTEN_TYPE_AP2P) )
/*
******************************************************************************
* GLOBAL ENUMS
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! Main state */
typedef enum{
RFAL_NFC_STATE_NOTINIT = 0, /*!< Not Initialized state */
RFAL_NFC_STATE_IDLE = 1, /*!< Initialize state */
RFAL_NFC_STATE_START_DISCOVERY = 2, /*!< Start Discovery loop state */
RFAL_NFC_STATE_WAKEUP_MODE = 3, /*!< Wake-Up state */
RFAL_NFC_STATE_POLL_TECHDETECT = 10, /*!< Technology Detection state */
RFAL_NFC_STATE_POLL_COLAVOIDANCE = 11, /*!< Collision Avoidance state */
RFAL_NFC_STATE_POLL_SELECT = 12, /*!< Wait for Selection state */
RFAL_NFC_STATE_POLL_ACTIVATION = 13, /*!< Activation state */
RFAL_NFC_STATE_LISTEN_TECHDETECT = 20, /*!< Listen Tech Detect */
RFAL_NFC_STATE_LISTEN_COLAVOIDANCE = 21, /*!< Listen Collision Avoidance */
RFAL_NFC_STATE_LISTEN_ACTIVATION = 22, /*!< Listen Activation state */
RFAL_NFC_STATE_LISTEN_SLEEP = 23, /*!< Listen Sleep state */
RFAL_NFC_STATE_ACTIVATED = 30, /*!< Activated state */
RFAL_NFC_STATE_DATAEXCHANGE = 31, /*!< Data Exchange Start state */
RFAL_NFC_STATE_DATAEXCHANGE_DONE = 33, /*!< Data Exchange terminated */
RFAL_NFC_STATE_DEACTIVATION = 34 /*!< Deactivation state */
}rfalNfcState;
/*! Device type */
typedef enum{
RFAL_NFC_LISTEN_TYPE_NFCA = 0, /*!< NFC-A Listener device type */
RFAL_NFC_LISTEN_TYPE_NFCB = 1, /*!< NFC-B Listener device type */
RFAL_NFC_LISTEN_TYPE_NFCF = 2, /*!< NFC-F Listener device type */
RFAL_NFC_LISTEN_TYPE_NFCV = 3, /*!< NFC-V Listener device type */
RFAL_NFC_LISTEN_TYPE_ST25TB = 4, /*!< ST25TB Listener device type */
RFAL_NFC_LISTEN_TYPE_AP2P = 5, /*!< AP2P Listener device type */
RFAL_NFC_POLL_TYPE_NFCA = 10, /*!< NFC-A Poller device type */
RFAL_NFC_POLL_TYPE_NFCB = 11, /*!< NFC-B Poller device type */
RFAL_NFC_POLL_TYPE_NFCF = 12, /*!< NFC-F Poller device type */
RFAL_NFC_POLL_TYPE_NFCV = 13, /*!< NFC-V Poller device type */
RFAL_NFC_POLL_TYPE_AP2P = 15 /*!< AP2P Poller device type */
}rfalNfcDevType;
/*! Device interface */
typedef enum{
RFAL_NFC_INTERFACE_RF = 0, /*!< RF Frame interface */
RFAL_NFC_INTERFACE_ISODEP = 1, /*!< ISO-DEP interface */
RFAL_NFC_INTERFACE_NFCDEP = 2 /*!< NFC-DEP interface */
}rfalNfcRfInterface;
/*! Device struct containing all its details */
typedef struct{
rfalNfcDevType type; /*!< Device's type */
union{ /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one technology at a time */
rfalNfcaListenDevice nfca; /*!< NFC-A Listen Device instance */
rfalNfcbListenDevice nfcb; /*!< NFC-B Listen Device instance */
rfalNfcfListenDevice nfcf; /*!< NFC-F Listen Device instance */
rfalNfcvListenDevice nfcv; /*!< NFC-V Listen Device instance */
rfalSt25tbListenDevice st25tb; /*!< ST25TB Listen Device instance*/
}dev; /*!< Device's instance */
uint8_t *nfcid; /*!< Device's NFCID */
uint8_t nfcidLen; /*!< Device's NFCID length */
rfalNfcRfInterface rfInterface; /*!< Device's interface */
union{ /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one protocol at a time */
rfalIsoDepDevice isoDep; /*!< ISO-DEP instance */
rfalNfcDepDevice nfcDep; /*!< NFC-DEP instance */
}proto; /*!< Device's protocol */
}rfalNfcDevice;
/*! Discovery parameters */
typedef struct{
rfalComplianceMode compMode; /*!< Compliancy mode to be used */
uint16_t techs2Find; /*!< Technologies to search for */
uint16_t totalDuration; /*!< Duration of a whole Poll + Listen cycle */
uint8_t devLimit; /*!< Max number of devices */
rfalBitRate maxBR; /*!< Max Bit rate to be used for communications */
rfalBitRate nfcfBR; /*!< Bit rate to poll for NFC-F */
uint8_t nfcid3[RFAL_NFCDEP_NFCID3_LEN]; /*!< NFCID3 to be used on the ATR_REQ/ATR_RES */
uint8_t GB[RFAL_NFCDEP_GB_MAX_LEN]; /*!< General bytes to be used on the ATR-REQ */
uint8_t GBLen; /*!< Length of the General Bytes */
rfalBitRate ap2pBR; /*!< Bit rate to poll for AP2P */
rfalLmConfPA lmConfigPA; /*!< Configuration for Passive Listen mode NFC-A */
rfalLmConfPF lmConfigPF; /*!< Configuration for Passive Listen mode NFC-A */
void (*notifyCb)( rfalNfcState st ); /*!< Callback to Notify upper layer */
bool wakeupEnabled; /*!< Enable Wake-Up mode before polling */
bool wakeupConfigDefault; /*!< Wake-Up mode default configuration */
rfalWakeUpConfig wakeupConfig; /*!< Wake-Up mode configuration */
}rfalNfcDiscoverParam;
/*! Buffer union, only one interface is used at a time */
typedef union{ /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one interface at a time */
uint8_t rfBuf[RFAL_FEATURE_NFC_RF_BUF_LEN]; /*!< RF buffer */
rfalIsoDepApduBufFormat isoDepBuf; /*!< ISO-DEP buffer format (with header/prologue) */
rfalNfcDepPduBufFormat nfcDepBuf; /*!< NFC-DEP buffer format (with header/prologue) */
}rfalNfcBuffer;
/*******************************************************************************/
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief RFAL NFC Worker
*
* It runs the internal state machine and runs the RFAL RF worker.
*****************************************************************************
*/
void rfalNfcWorker( void );
/*!
*****************************************************************************
* \brief RFAL NFC Initialize
*
* It initializes this module and its dependencies
*
* \return ERR_WRONG_STATE : Incorrect state for this operation
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcInitialize( void );
/*!
*****************************************************************************
* \brief RFAL NFC Discovery
*
* It set the device in Discovery state.
* In discovery it will Poll and/or Listen for the technologies configured,
* and perform Wake-up mode if configured to do so.
*
* The device list passed on disParams must not be empty.
* The number of devices on the list is indicated by the devLimit and shall
* be at >= 1.
*
* \param[in] disParams : discovery configuration parameters
*
* \return ERR_WRONG_STATE : Incorrect state for this operation
* \return ERR_PARAM : Invalid parameters
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcDiscover( const rfalNfcDiscoverParam *disParams );
/*!
*****************************************************************************
* \brief RFAL NFC Get State
*
* It returns the current state
*
* \return rfalNfcState : the current state
*****************************************************************************
*/
rfalNfcState rfalNfcGetState( void );
/*!
*****************************************************************************
* \brief RFAL NFC Get Devices Found
*
* It returns the location of the device list and the number of
* devices found.
*
* \param[out] devList : device list location
* \param[out] devCnt : number of devices found
*
* \return ERR_WRONG_STATE : Incorrect state for this operation
* Discovery still ongoing
* \return ERR_PARAM : Invalid parameters
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcGetDevicesFound( rfalNfcDevice **devList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief RFAL NFC Get Active Device
*
* It returns the location of the device current Active device
*
* \param[out] dev : device info location
*
* \return ERR_WRONG_STATE : Incorrect state for this operation
* No device activated
* \return ERR_PARAM : Invalid parameters
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcGetActiveDevice( rfalNfcDevice **dev );
/*!
*****************************************************************************
* \brief RFAL NFC Select Device
*
* It selects the device to be activated.
* It shall be called when more than one device has been identified to
* indiacte which device shall be actived
*
* \param[in] devIdx : device index to be activated
*
* \return ERR_WRONG_STATE : Incorrect state for this operation
* Not in select state
* \return ERR_PARAM : Invalid parameters
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcSelect( uint8_t devIdx );
/*!
*****************************************************************************
* \brief RFAL NFC Start Data Exchange
*
* After a device has been activated, it starts a data exchange.
* It handles automatically which interface/protocol to be used and acts accordingly.
*
* In Listen mode the first frame/data shall be sent by the Reader/Initiator
* therefore this method must be called first with txDataLen set to zero
* to retrieve the rxData and rcvLen locations.
*
*
* \param[in] txData : data to be transmitted
* \param[in] txDataLen : size of the data to be transmitted
* \param[out] rxData : location of the received data after operation is completed
* \param[out] rvdLen : location of thelength of the received data
* \param[in] fwt : FWT to be used in case of RF interface.
* If ISO-DEP or NFC-DEP interface is used, this will be ignored
*
* \return ERR_WRONG_STATE : Incorrect state for this operation
* \return ERR_PARAM : Invalid parameters
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcDataExchangeStart( uint8_t *txData, uint16_t txDataLen, uint8_t **rxData, uint16_t **rvdLen, uint32_t fwt );
/*!
*****************************************************************************
* \brief RFAL NFC Get Data Exchange Status
*
* Gets current Data Exchange status
*
* \return ERR_NONE : Transceive done with no error
* \return ERR_BUSY : Transceive ongoing
* \return ERR_AGAIN : received one chaining block, copy received data
* and continue to call this method to retrieve the
* remaining blocks
* \return ERR_XXXX : Error occurred
* \return ERR_TIMEOUT : No response
* \return ERR_FRAMING : Framing error detected
* \return ERR_PAR : Parity error detected
* \return ERR_CRC : CRC error detected
* \return ERR_LINK_LOSS : Link Loss - External Field is Off
* \return ERR_RF_COLLISION : Collision detected
* \return ERR_IO : Internal error
*****************************************************************************
*/
ReturnCode rfalNfcDataExchangeGetStatus( void );
/*!
*****************************************************************************
* \brief RFAL NFC Deactivate
*
* It triggers the deactivation procedure to terminate communications with
* remote device. At the end the field will be turned off.
*
* \param[in] discovery : TRUE if after deactivation go back into discovery
* : FALSE if after deactivation remain in idle
*
* \return ERR_WRONG_STATE : Incorrect state for this operation
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcDeactivate( bool discovery );
#endif /* RFAL_NFC_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,788 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfcDep.h
*
* \author Gustavo Patricio
*
* \brief Implementation of NFC-DEP protocol
*
* NFC-DEP is also known as NFCIP - Near Field Communication
* Interface and Protocol
*
* This implementation was based on the following specs:
* - NFC Forum Digital 1.1
* - ECMA 340 3rd Edition 2013
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup NFC-DEP
* \brief RFAL NFC-DEP Module
* @{
*/
#ifndef RFAL_NFCDEP_H_
#define RFAL_NFCDEP_H_
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_NFC_DEP
#define RFAL_FEATURE_NFC_DEP false /*!< NFC-DEP module configuration missing. Disabled by default */
#endif
/* If module is disabled remove the need for the user to set lengths */
#if !RFAL_FEATURE_NFC_DEP
#undef RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN
#undef RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN
#define RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN 1U /*!< NFC-DEP Block/Payload length, set to "none" */
#define RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN 1U /*!< NFC-DEP PDU length, set to "none" */
#endif /* !RFAL_FEATURE_NFC_DEP */
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
#define RFAL_NFCDEP_FRAME_SIZE_MAX_LEN 254U /*!< Maximum Frame Size Digital 2.0 Table 90 */
#define RFAL_NFCDEP_DEPREQ_HEADER_LEN 5U /*!< DEP_REQ header length: CMD_TYPE + CMD_CMD + PBF + DID + NAD */
/*! Length NFCIP DEP REQ or RES header (incl LEN) */
#define RFAL_NFCDEP_DEP_HEADER ( RFAL_NFCDEP_LEN_LEN + RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN + RFAL_NFCDEP_DEP_PFB_LEN )
#define RFAL_NFCDEP_HEADER ( RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN ) /*!< NFCIP header length */
#define RFAL_NFCDEP_SB_LEN 1U /*!< SB length on NFCIP fram for NFC-A */
#define RFAL_NFCDEP_LEN_LEN 1U /*!< LEN length on NFCIP frame */
#define RFAL_NFCDEP_CMDTYPE_LEN 1U /*!< Length of the cmd type (REQ | RES) on NFCIP frame */
#define RFAL_NFCDEP_CMD_LEN 1U /*!< Length of the cmd on NFCIP frame */
#define RFAL_NFCDEP_DID_LEN 1U /*!< Length of did on NFCIP frame */
#define RFAL_NFCDEP_DEP_PFB_LEN 1U /*!< Length of the PFB field on NFCIP frame */
#define RFAL_NFCDEP_DSL_RLS_LEN_NO_DID (RFAL_NFCDEP_LEN_LEN + RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN) /*!< Length of DSL_REQ and RLS_REQ with no DID */
#define RFAL_NFCDEP_DSL_RLS_LEN_DID (RFAL_NFCDEP_DSL_RLS_LEN_NO_DID + RFAL_NFCDEP_DID_LEN) /*!< Length of DSL_REQ and RLS_REQ with DID */
#define RFAL_NFCDEP_FS_VAL_MIN 64U /*!< Minimum LR value */
#define RFAL_NFCDEP_LR_VAL_MASK 0x03U /*!< Bit mask for a LR value */
#define RFAL_NFCDEP_PP_LR_MASK 0x30U /*!< Bit mask for LR value in PP byte on a ATR REQ/RES */
#define RFAL_NFCDEP_PP_LR_SHIFT 4U /*!< Position of LR value in PP byte on a ATR REQ/RES */
#define RFAL_NFCDEP_DID_MAX 14U /*!< Max DID value Digital 14.6.2.3 */
#define RFAL_NFCDEP_DID_KEEP 0xFFU /*!< Keep DID value already configured */
#define RFAL_NFCDEP_DID_NO 0x00U /*!< No DID shall be used */
#define RFAL_NFCDEP_NAD_NO 0x00U /*!< No NAD shall be used */
#define RFAL_NFCDEP_OPER_RTOX_REQ_DIS 0x01U /*!< Operation config: RTOX REQ disable */
#define RFAL_NFCDEP_OPER_RTOX_REQ_EN 0x00U /*!< Operation config: RTOX REQ enable */
#define RFAL_NFCDEP_OPER_ATN_DIS 0x00U /*!< Operation config: ATN disable */
#define RFAL_NFCDEP_OPER_ATN_EN 0x02U /*!< Operation config: ATN enable */
#define RFAL_NFCDEP_OPER_EMPTY_DEP_DIS 0x04U /*!< Operation config: empty DEPs disable */
#define RFAL_NFCDEP_OPER_EMPTY_DEP_EN 0x00U /*!< Operation config: empty DEPs enable */
#define RFAL_NFCDEP_OPER_FULL_MI_DIS 0x00U /*!< Operation config: full chaining DEPs disable */
#define RFAL_NFCDEP_OPER_FULL_MI_EN 0x08U /*!< Operation config: full chaining DEPs enable */
#define RFAL_NFCDEP_BRS_MAINTAIN 0xC0U /*!< Value signalling that BR is to be maintained (no PSL) */
#define RFAL_NFCDEP_BRS_Dx_MASK 0x07U /*!< Value signalling that BR is to be maintained (no PSL) */
#define RFAL_NFCDEP_BRS_DSI_POS 3U /*!< Value signalling that BR is to be maintained (no PSL) */
#define RFAL_NFCDEP_WT_DELTA (16U - RFAL_NFCDEP_WT_DELTA_ADJUST) /*!< NFC-DEP dWRT (adjusted) Digital 2.0 B.10 */
#define RFAL_NFCDEP_WT_DELTA_ADJUST 4U /*!< dWRT value adjustment */
#define RFAL_NFCDEP_ATR_REQ_NFCID3_POS 2U /*!< NFCID3 offset in ATR_REQ frame */
#define RFAL_NFCDEP_NFCID3_LEN 10U /*!< NFCID3 Length */
#define RFAL_NFCDEP_LEN_MIN 3U /*!< Minimum length byte LEN value */
#define RFAL_NFCDEP_LEN_MAX 255U /*!< Maximum length byte LEN value */
#define RFAL_NFCDEP_ATRRES_HEADER_LEN 2U /*!< ATR RES Header Len: CmdType: 0xD5 + Cod: 0x01 */
#define RFAL_NFCDEP_ATRRES_MIN_LEN 17U /*!< Minimum length for an ATR RES */
#define RFAL_NFCDEP_ATRRES_MAX_LEN 64U /*!< Maximum length for an ATR RES Digital 1.0 14.6.1 */
#define RFAL_NFCDEP_ATRREQ_MIN_LEN 16U /*!< Minimum length for an ATR REQ */
#define RFAL_NFCDEP_ATRREQ_MAX_LEN RFAL_NFCDEP_ATRRES_MAX_LEN /*!< Maximum length for an ATR REQ Digital 1.0 14.6.1 */
#define RFAL_NFCDEP_GB_MAX_LEN (RFAL_NFCDEP_ATRREQ_MAX_LEN - RFAL_NFCDEP_ATRREQ_MIN_LEN) /*!< Maximum length the General Bytes on ATR Digital 1.1 16.6.3 */
#define RFAL_NFCDEP_WT_INI_DEFAULT RFAL_NFCDEP_WT_INI_MAX /*!< WT Initiator default value Digital 1.0 14.6.3.8 */
#define RFAL_NFCDEP_WT_INI_MIN 0U /*!< WT Initiator minimum value Digital 1.0 14.6.3.8 */
#define RFAL_NFCDEP_WT_INI_MAX 14U /*!< WT Initiator maximum value Digital 1.0 14.6.3.8 A.10 */
#define RFAL_NFCDEP_RWT_INI_MAX rfalNfcDepWT2RWT( RFAL_NFCDEP_WT_INI_MAX ) /*!< RWT Initiator maximum value */
#define RFAL_NFCDEP_WT_TRG_MAX_D10 8U /*!< WT target max Digital 1.0 14.6.3.8 A.10 */
#define RFAL_NFCDEP_WT_TRG_MAX_D11 14U /*!< WT target max Digital 1.1 16.6.3.9 A.9 */
#define RFAL_NFCDEP_WT_TRG_MAX_L13 10U /*!< WT target max [LLCP] 1.3 6.2.1 */
#define RFAL_NFCDEP_WT_TRG_MAX RFAL_NFCDEP_WT_TRG_MAX_D11 /*!< WT target max Digital x.x | LLCP x.x */
#define RFAL_NFCDEP_RWT_TRG_MAX rfalNfcDepWT2RWT( RFAL_NFCDEP_WT_TRG_MAX ) /*!< RWT Initiator maximum value */
/*! Maximum Frame Waiting Time = ((256 * 16/fc)*2^FWImax) = ((256*16/fc)*2^14) = (1048576 / 64)/fc = (100000h*64)/fc */
#define RFAL_NFCDEP_MAX_FWT ((uint32_t)1U<<20)
#define RFAL_NFCDEP_WT_MASK 0x0FU /*!< Bit mask for the Wait Time value */
#define RFAL_NFCDEP_BR_MASK_106 0x01U /*!< Enable mask bit rate 106 */
#define RFAL_NFCDEP_BR_MASK_212 0x02U /*!< Enable mask bit rate 242 */
#define RFAL_NFCDEP_BR_MASK_424 0x04U /*!< Enable mask bit rate 424 */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define rfalNfcDepWT2RWT( wt ) ( (uint32_t)1U << (((uint32_t)(wt) & RFAL_NFCDEP_WT_MASK) + 12U) ) /*!< Converts WT value to RWT (1/fc) */
/*! Returns the BRS value from the given bit rate */
#define rfalNfcDepDx2BRS( br ) ( (((uint8_t)(br) & RFAL_NFCDEP_BRS_Dx_MASK) << RFAL_NFCDEP_BRS_DSI_POS) | ((uint8_t)(br) & RFAL_NFCDEP_BRS_Dx_MASK) )
#define rfalNfcDepBRS2DRI( brs ) (uint8_t)( (uint8_t)(brs) & RFAL_NFCDEP_BRS_Dx_MASK ) /*!< Returns the DRI value from the given BRS byte */
#define rfalNfcDepBRS2DSI( brs ) (uint8_t)( ((uint8_t)(brs) >> RFAL_NFCDEP_BRS_DSI_POS) & RFAL_NFCDEP_BRS_Dx_MASK ) /*!< Returns the DSI value from the given BRS byte */
#define rfalNfcDepPP2LR( PPx ) ( ((uint8_t)(PPx) & RFAL_NFCDEP_PP_LR_MASK ) >> RFAL_NFCDEP_PP_LR_SHIFT) /*!< Returns the LR value from the given PPx byte */
#define rfalNfcDepLR2PP( LRx ) ( ((uint8_t)(LRx) << RFAL_NFCDEP_PP_LR_SHIFT) & RFAL_NFCDEP_PP_LR_MASK) /*!< Returns the PP byte with the given LRx value */
/*! Returns the Frame size value from the given LRx value */
#define rfalNfcDepLR2FS( LRx ) (uint16_t)(MIN( (RFAL_NFCDEP_FS_VAL_MIN * ((uint16_t)(LRx) + 1U) ), RFAL_NFCDEP_FRAME_SIZE_MAX_LEN ))
/*!
* Despite DIGITAL 1.0 14.6.2.1 stating that the last two bytes may filled with
* any value, some devices (Samsung Google Nexus) only accept when these are 0 */
#define rfalNfcDepSetNFCID( dst, src, len ) ST_MEMSET( (dst), 0x00, RFAL_NFCDEP_NFCID3_LEN ); \
if( (len) > 0U ) {ST_MEMCPY( (dst), (src), (len) );}
/*
******************************************************************************
* GLOBAL ENUMERATIONS
******************************************************************************
*/
/*! Enumeration of NFC-DEP bit rate in ATR Digital 1.0 Table 93 and 94 */
enum{
RFAL_NFCDEP_Bx_NO_HIGH_BR = 0x00, /*!< Peer supports no high bit rates */
RFAL_NFCDEP_Bx_08_848 = 0x01, /*!< Peer also supports 848 */
RFAL_NFCDEP_Bx_16_1695 = 0x02, /*!< Peer also supports 1695 */
RFAL_NFCDEP_Bx_32_3390 = 0x04, /*!< Peer also supports 3390 */
RFAL_NFCDEP_Bx_64_6780 = 0x08 /*!< Peer also supports 6780 */
};
/*! Enumeration of NFC-DEP bit rate Dividor in PSL Digital 1.0 Table 100 */
enum{
RFAL_NFCDEP_Dx_01_106 = RFAL_BR_106, /*!< Divisor D = 1 : bit rate = 106 */
RFAL_NFCDEP_Dx_02_212 = RFAL_BR_212, /*!< Divisor D = 2 : bit rate = 212 */
RFAL_NFCDEP_Dx_04_424 = RFAL_BR_424, /*!< Divisor D = 4 : bit rate = 424 */
RFAL_NFCDEP_Dx_08_848 = RFAL_BR_848, /*!< Divisor D = 8 : bit rate = 848 */
RFAL_NFCDEP_Dx_16_1695 = RFAL_BR_1695, /*!< Divisor D = 16 : bit rate = 1695 */
RFAL_NFCDEP_Dx_32_3390 = RFAL_BR_3390, /*!< Divisor D = 32 : bit rate = 3390 */
RFAL_NFCDEP_Dx_64_6780 = RFAL_BR_6780 /*!< Divisor D = 64 : bit rate = 6780 */
};
/*! Enumeration of NFC-DEP Length Reduction (LR) Digital 1.0 Table 91 */
enum{
RFAL_NFCDEP_LR_64 = 0x00, /*!< Maximum payload size is 64 bytes */
RFAL_NFCDEP_LR_128 = 0x01, /*!< Maximum payload size is 128 bytes */
RFAL_NFCDEP_LR_192 = 0x02, /*!< Maximum payload size is 192 bytes */
RFAL_NFCDEP_LR_254 = 0x03 /*!< Maximum payload size is 254 bytes */
};
/*
******************************************************************************
* GLOBAL DATA TYPES
******************************************************************************
*/
/*! NFC-DEP callback to check if upper layer has deactivation pending */
typedef bool (* rfalNfcDepDeactCallback)(void);
/*! Enumeration of the nfcip communication modes */
typedef enum{
RFAL_NFCDEP_COMM_PASSIVE, /*!< Passive communication mode */
RFAL_NFCDEP_COMM_ACTIVE /*!< Active communication mode */
} rfalNfcDepCommMode;
/*! Enumeration of the nfcip roles */
typedef enum{
RFAL_NFCDEP_ROLE_INITIATOR, /*!< Perform as Initiator */
RFAL_NFCDEP_ROLE_TARGET /*!< Perform as Target */
} rfalNfcDepRole;
/*! Struct that holds all NFCIP configs */
typedef struct{
rfalNfcDepRole role; /*!< Current NFCIP role */
rfalNfcDepCommMode commMode; /*!< Current NFCIP communication mode */
uint8_t oper; /*!< Operation config similar to NCI 1.0 Table 81 */
uint8_t did; /*!< Current Device ID (DID) */
uint8_t nad; /*!< Current Node Addressing (NAD) */
uint8_t bs; /*!< Bit rate in Sending Direction */
uint8_t br; /*!< Bit rate in Receiving Direction */
uint8_t nfcid[RFAL_NFCDEP_NFCID3_LEN]; /*!< Pointer to the NFCID to be used */
uint8_t nfcidLen; /*!< Length of the given NFCID in nfcid */
uint8_t gb[RFAL_NFCDEP_GB_MAX_LEN]; /*!< Pointer General Bytes (GB) to be used */
uint8_t gbLen; /*!< Length of the given GB in gb */
uint8_t lr; /*!< Length Reduction (LR) to be used */
uint8_t to; /*!< Timeout (TO) to be used */
uint32_t fwt; /*!< Frame Waiting Time (FWT) to be used */
uint32_t dFwt; /*!< Delta Frame Waiting Time (dFWT) to be used */
} rfalNfcDepConfigs;
/*! ATR_REQ command Digital 1.1 16.6.2 */
typedef struct {
uint8_t CMD1; /*!< Command format 0xD4 */
uint8_t CMD2; /*!< Command Value */
uint8_t NFCID3[RFAL_NFCDEP_NFCID3_LEN]; /*!< NFCID3 value */
uint8_t DID; /*!< DID */
uint8_t BSi; /*!< Sending Bitrate for Initiator */
uint8_t BRi; /*!< Receiving Bitrate for Initiator */
uint8_t PPi; /*!< Optional Parameters presence indicator */
uint8_t GBi[RFAL_NFCDEP_GB_MAX_LEN]; /*!< General Bytes */
} rfalNfcDepAtrReq;
/*! ATR_RES response Digital 1.1 16.6.3 */
typedef struct {
uint8_t CMD1; /*!< Response Byte 0xD5 */
uint8_t CMD2; /*!< Command Value */
uint8_t NFCID3[RFAL_NFCDEP_NFCID3_LEN]; /*!< NFCID3 value */
uint8_t DID; /*!< DID */
uint8_t BSt; /*!< Sending Bitrate for Initiator */
uint8_t BRt; /*!< Receiving Bitrate for Initiator */
uint8_t TO; /*!< Timeout */
uint8_t PPt; /*!< Optional Parameters presence indicator */
uint8_t GBt[RFAL_NFCDEP_GB_MAX_LEN]; /*!< General Bytes */
} rfalNfcDepAtrRes;
/*! Structure of transmit I-PDU Buffer format from caller */
typedef struct
{
uint8_t prologue[RFAL_NFCDEP_DEPREQ_HEADER_LEN]; /*!< Prologue space for NFC-DEP header*/
uint8_t inf[RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN]; /*!< INF | Data area of the buffer */
} rfalNfcDepBufFormat;
/*! Structure of APDU Buffer format from caller */
typedef struct
{
uint8_t prologue[RFAL_NFCDEP_DEPREQ_HEADER_LEN]; /*!< Prologue/SoD buffer */
uint8_t pdu[RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN]; /*!< Complete PDU/Payload buffer */
} rfalNfcDepPduBufFormat;
/*! Activation info as Initiator and Target */
typedef union { /* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently , device is only initiatior or target a time. No problem can occur. */
struct {
rfalNfcDepAtrRes ATR_RES; /*!< ATR RES (Initiator mode) */
uint8_t ATR_RESLen; /*!< ATR RES length (Initiator mode) */
}Target; /*!< Target */
struct {
rfalNfcDepAtrReq ATR_REQ; /*!< ATR REQ (Target mode) */
uint8_t ATR_REQLen; /*!< ATR REQ length (Target mode) */
}Initiator; /*!< Initiator */
} rfalNfcDepActivation;
/*! NFC-DEP device Info */
typedef struct {
uint8_t GBLen; /*!< General Bytes length */
uint8_t WT; /*!< WT to be used (ignored in Listen Mode) */
uint32_t FWT; /*!< FWT to be used (1/fc)(ignored Listen Mode) */
uint32_t dFWT; /*!< Delta FWT to be used (1/fc) */
uint8_t LR; /*!< Length Reduction coding the max payload */
uint16_t FS; /*!< Frame Size */
rfalBitRate DSI; /*!< Bit Rate coding from Initiator to Target */
rfalBitRate DRI; /*!< Bit Rate coding from Target to Initiator */
uint8_t DID; /*!< Device ID (RFAL_NFCDEP_DID_NO if no DID) */
uint8_t NAD; /*!< Node ADdress (RFAL_NFCDEP_NAD_NO if no NAD)*/
} rfalNfcDepInfo;
/*! NFC-DEP Device structure */
typedef struct {
rfalNfcDepActivation activation; /*!< Activation Info */
rfalNfcDepInfo info; /*!< NFC-DEP device Info */
} rfalNfcDepDevice;
/*! NFCIP Protocol structure for P2P Target
*
* operParam : derives from NFC-Forum NCI NFC-DEP Operation Parameter
* NCI 1.1 Table 86: NFC-DEP Operation Parameter
* and it's a bit mask composed as:
* [ 0000b
* | Chain SHALL use max. Transport Data Byte[1b]
* | I-PDU with no Transport Data SHALL NOT be sent [1b]
* | NFC-DEP Target SHALL NOT send RTOX request [1b]
* ]
*
*/
typedef struct{
rfalNfcDepCommMode commMode; /*!< Initiator in Active P2P or Passive P2P*/
uint8_t operParam; /*!< NFC-DEP Operation Parameter */
uint8_t* nfcid; /*!< Initiator's NFCID2 or NFCID3 */
uint8_t nfcidLen; /*!< Initiator's NFCID length (NFCID2/3) */
uint8_t DID; /*!< Initiator's Device ID DID */
uint8_t NAD; /*!< Initiator's Node ID NAD */
uint8_t BS; /*!< Initiator's Bit Rates supported in Tx */
uint8_t BR; /*!< Initiator's Bit Rates supported in Rx */
uint8_t LR; /*!< Initiator's Length reduction */
uint8_t* GB; /*!< Initiator's General Bytes (Gi) */
uint8_t GBLen; /*!< Initiator's General Bytes length */
} rfalNfcDepAtrParam;
/*! Structure of parameters to be passed in for nfcDepListenStartActivation */
typedef struct
{
rfalNfcDepBufFormat *rxBuf; /*!< Receive Buffer struct reference */
uint16_t *rxLen; /*!< Receive INF data length in bytes */
bool *isRxChaining; /*!< Received data is not complete */
rfalNfcDepDevice *nfcDepDev; /*!< NFC-DEP device info */
} rfalNfcDepListenActvParam;
/*! NFCIP Protocol structure for P2P Target
*
* operParam : derives from NFC-Forum NCI NFC-DEP Operation Parameter
* NCI 1.1 Table 86: NFC-DEP Operation Parameter
* and it's a bit mask composed as:
* [ 0000b
* | Chain SHALL use max. Transport Data Byte[1b]
* | I-PDU with no Transport Data SHALL NOT be sent [1b]
* | NFC-DEP Target SHALL NOT send RTOX request [1b]
* ]
*
*/
typedef struct{
rfalNfcDepCommMode commMode; /*!< Target in Active P2P or Passive P2P */
uint8_t nfcid3[RFAL_NFCDEP_NFCID3_LEN]; /*!< Target's NFCID3 */
uint8_t bst; /*!< Target's Bit Rates supported in Tx */
uint8_t brt; /*!< Target's Bit Rates supported in Rx */
uint8_t to; /*!< Target's timeout (TO) value */
uint8_t ppt; /*!< Target's Presence optional Params(PPt)*/
uint8_t GBt[RFAL_NFCDEP_GB_MAX_LEN]; /*!< Target's General Bytes (Gt) */
uint8_t GBtLen; /*!< Target's General Bytes length */
uint8_t operParam; /*!< NFC-DEP Operation Parameter */
} rfalNfcDepTargetParam;
/*! Structure of parameters to be passed in for nfcDepStartIpduTransceive */
typedef struct
{
rfalNfcDepBufFormat *txBuf; /*!< Transmit Buffer struct reference */
uint16_t txBufLen; /*!< Transmit Buffer INF field length in bytes */
bool isTxChaining; /*!< Transmit data is not complete */
rfalNfcDepBufFormat *rxBuf; /*!< Receive Buffer struct reference */
uint16_t *rxLen; /*!< Receive INF data length */
bool *isRxChaining; /*!< Received data is not complete */
uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */
uint32_t dFWT; /*!< Delta FWT to be used */
uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */
uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */
} rfalNfcDepTxRxParam;
/*! Structure of parameters used on NFC DEP PDU Transceive */
typedef struct
{
rfalNfcDepPduBufFormat *txBuf; /*!< Transmit Buffer struct reference */
uint16_t txBufLen; /*!< Transmit Buffer INF field length in Bytes*/
rfalNfcDepPduBufFormat *rxBuf; /*!< Receive Buffer struct reference in Bytes */
uint16_t *rxLen; /*!< Received INF data length in Bytes */
rfalNfcDepBufFormat *tmpBuf; /*!< Temp buffer for single PDUs (internal) */
uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */
uint32_t dFWT; /*!< Delta FWT to be used */
uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */
uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */
} rfalNfcDepPduTxRxParam;
/*
* *****************************************************************************
* GLOBAL VARIABLE DECLARATIONS
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
******************************************************************************
* \brief NFCIP Initialize
*
* This method resets all NFC-DEP inner states, counters and context and sets
* default values
*
******************************************************************************
*/
void rfalNfcDepInitialize( void );
/*!
******************************************************************************
* \brief Set deactivating callback
*
* Sets the deactivating callback so that nfcip layer can check if upper layer
* has a deactivation pending, and not perform error recovery upon specific
* errors
*
* \param[in] pFunc : method pointer to deactivation flag check
******************************************************************************
*/
void rfalNfcDepSetDeactivatingCallback( rfalNfcDepDeactCallback pFunc );
/*!
******************************************************************************
* \brief Calculate Response Waiting Time
*
* Calculates the Response Waiting Time (RWT) from the given Waiting Time (WT)
*
* \param[in] wt : the WT value to calculate RWT
*
* \return RWT value in 1/fc
******************************************************************************
*/
uint32_t rfalNfcDepCalculateRWT( uint8_t wt );
/*!
******************************************************************************
* \brief NFC-DEP Initiator ATR (Attribute Request)
*
* This method configures the NFC-DEP layer with given parameters and then
* sends an ATR to the Target with and checks for a valid response response
*
* \param[in] param : parameters to initialize and compose the ATR
* \param[out] atrRes : location to store the ATR_RES
* \param[out] atrResLen : length of the ATR_RES received
*
* \return ERR_NONE : No error
* \return ERR_TIMEOUT : Timeout occurred
* \return ERR_PROTO : Protocol error occurred
******************************************************************************
*/
ReturnCode rfalNfcDepATR( const rfalNfcDepAtrParam* param, rfalNfcDepAtrRes *atrRes, uint8_t* atrResLen );
/*!
******************************************************************************
* \brief NFC-DEP Initiator PSL (Parameter Selection)
*
* This method sends a PSL to the Target with the given parameters and checks
* for a valid response response
*
* The parameters must be coded according to Digital 1.1 16.7.1
*
* \param[in] BRS : the selected Bit Rates for Initiator and Target
* \param[in] FSL : the maximum length of Commands and Responses
*
* \return ERR_NONE : No error
* \return ERR_TIMEOUT : Timeout occurred
* \return ERR_PROTO : Protocol error occurred
******************************************************************************
*/
ReturnCode rfalNfcDepPSL( uint8_t BRS, uint8_t FSL );
/*!
******************************************************************************
* \brief NFC-DEP Initiator DSL (Deselect)
*
* This method checks if the NFCIP module is configured as initiator and if
* so sends a DSL REQ, waits the target's response and checks it
*
* In case of performing as target no action is taken
*
* \return ERR_NONE : No error
* \return ERR_TIMEOUT : Timeout occurred
* \return ERR_MAX_RERUNS : Timeout occurred
* \return ERR_PROTO : Protocol error occurred
******************************************************************************
*/
ReturnCode rfalNfcDepDSL( void );
/*!
******************************************************************************
* \brief NFC-DEP Initiator RLS (Release)
*
* This method checks if the NFCIP module is configured as initiator and if
* so sends a RLS REQ, waits target's response and checks it
*
* In case of performing as target no action is taken
*
* \return ERR_NONE : No error
* \return ERR_TIMEOUT : Timeout occurred
* \return ERR_MAX_RERUNS : Timeout occurred
* \return ERR_PROTO : Protocol error occurred
******************************************************************************
*/
ReturnCode rfalNfcDepRLS( void );
/*!
*****************************************************************************
* \brief NFC-DEP Initiator Handle Activation
*
* This performs a Activation into NFC-DEP layer with the given
* parameters. It sends ATR_REQ and if the higher bit rates are supported by
* both devices it additionally sends PSL
* Once Activated all details of the device are provided on nfcDepDev
*
* \param[in] param : required parameters to initialize and send ATR_REQ
* \param[in] desiredBR : Desired bit rate supported by the Poller
* \param[out] nfcDepDev : NFC-DEP information of the activated Listen device
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error
* \return ERR_PAR : Parity error detected
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error, activation successful
*****************************************************************************
*/
ReturnCode rfalNfcDepInitiatorHandleActivation( rfalNfcDepAtrParam* param, rfalBitRate desiredBR, rfalNfcDepDevice* nfcDepDev );
/*!
******************************************************************************
* \brief Check if buffer contains valid ATR_REQ
*
* This method checks if the given ATR_REQ is valid
*
*
* \param[in] buf : buffer holding Initiator's received request
* \param[in] bufLen : size of the msg contained on the buf in Bytes
* \param[out] nfcid3 : pointer to where the NFCID3 may be outputed,
* nfcid3 has NFCF_SENSF_NFCID3_LEN as length
* Pass NULL if output parameter not desired
*
* \return true : Valid ATR_REQ received, the ATR_RES has been computed in txBuf
* \return false : Invalid protocol request
*
******************************************************************************
*/
bool rfalNfcDepIsAtrReq( const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid3 );
/*!
******************************************************************************
* \brief Check is Target has received ATR
*
* This method checks if the NFCIP module is configured as target and if a
* ATR REQ has been received ( whether is in activation or in data exchange)
*
* \return true : a ATR has already been received
* \return false : no ATR has been received
******************************************************************************
*/
bool rfalNfcDepTargetRcvdATR( void );
/*!
*****************************************************************************
* \brief NFCDEP Start Listen Activation Handling
*
* Start Activation Handling and setup to receive first frame which may
* contain complete or partial DEP-REQ after activation is completed
*
* Pass in ATR_REQ for NFC-DEP to handle ATR_RES. The Activation Handling
* handles ATR_RES and PSL_RES if a PSL_REQ is received
*
* Activation is completed if PSL_RES is sent or if first I-PDU is received
*
* \ref rfalNfcDepListenGetActivationStatus() provide status of the
* ongoing activation
*
* \warning nfcDepGetTransceiveStatus() shall be called right after activation
* is completed (i.e. rfalNfcDepListenGetActivationStatus() return ERR_NONE)
* to check for first received frame.
*
* \param[in] param : Target parameters to be used
* \param[in] atrReq : reference to buffer containing ATR_REQ
* \param[in] atrReqLength: Length of ATR_REQ
* \param[out] rxParam : references to buffer, length and chaining indication
* for first complete LLCP to be received
*
* \return ERR_NONE : ATR_REQ is valid and activation ongoing
* \return ERR_PARAM : ATR_REQ or other params are invalid
* \return ERR_LINK_LOSS : Remote Field is turned off
*****************************************************************************
*/
ReturnCode rfalNfcDepListenStartActivation( const rfalNfcDepTargetParam *param, const uint8_t *atrReq, uint16_t atrReqLength, rfalNfcDepListenActvParam rxParam );
/*!
*****************************************************************************
* \brief Get the current NFC-DEP Activation Status
*
* \return ERR_NONE : Activation has completed successfully
* \return ERR_BUSY : Activation is ongoing
* \return ERR_LINK_LOSS : Remote Field was turned off
*****************************************************************************
*/
ReturnCode rfalNfcDepListenGetActivationStatus( void );
/*!
*****************************************************************************
* \brief Start Transceive
*
* Transceives a complete or partial DEP block
*
* The txBuf contains complete or partial of DEP to be transmitted.
* The Prologue field of the I-PDU is handled internally
*
* If the buffer contains partial LLCP and is not the last block, then
* isTxChaining must be set to true
*
* \param[in] param: reference parameters to be used for the Transceive
*
* \return ERR_PARAM : Bad request
* \return ERR_WRONG_STATE : The module is not in a proper state
* \return ERR_NONE : The Transceive request has been started
*****************************************************************************
*/
ReturnCode rfalNfcDepStartTransceive( const rfalNfcDepTxRxParam *param );
/*!
*****************************************************************************
* \brief Return the Transceive status
*
* Returns the status of the NFC-DEP Transceive
*
* \warning When the other device is performing chaining once a chained
* block is received the error ERR_AGAIN is sent. At this point
* caller must handle the received data immediately.
* When ERR_AGAIN is returned an ACK has already been sent to
* the other device and the next block might be incoming.
* If rfalWorker() is called frequently it will place the next
* block on the given buffer
*
* \return ERR_NONE : Transceive has been completed successfully
* \return ERR_BUSY : Transceive is ongoing
* \return ERR_PROTO : Protocol error occurred
* \return ERR_TIMEOUT : Timeout error occurred
* \return ERR_SLEEP_REQ : Deselect has been received and responded
* \return ERR_NOMEM : The received I-PDU does not fit into the
* receive buffer
* \return ERR_LINK_LOSS : Communication is lost because Reader/Writer
* has turned off its field
* \return ERR_AGAIN : received one chaining block, continue to call
* this method to retrieve the remaining blocks
*****************************************************************************
*/
ReturnCode rfalNfcDepGetTransceiveStatus( void );
/*!
*****************************************************************************
* \brief Start PDU Transceive
*
* This method triggers a NFC-DEP Transceive containing a complete PDU
* It transmits the given message and handles all protocol retransmitions,
* error handling and control messages
*
* The txBuf contains a complete PDU to be transmitted
* The Prologue field will be manipulated by the Transceive
*
* \warning the txBuf will be modified during the transmission
* \warning the maximum RF frame which can be received is limited by param.tmpBuf
*
* \param[in] param: reference parameters to be used for the Transceive
*
* \return ERR_PARAM : Bad request
* \return ERR_WRONG_STATE : The module is not in a proper state
* \return ERR_NONE : The Transceive request has been started
*****************************************************************************
*/
ReturnCode rfalNfcDepStartPduTransceive( rfalNfcDepPduTxRxParam param );
/*!
*****************************************************************************
* \brief Return the PSU Transceive status
*
* Returns the status of the NFC-DEP PDU Transceive
*
*
* \return ERR_NONE : Transceive has been completed successfully
* \return ERR_BUSY : Transceive is ongoing
* \return ERR_PROTO : Protocol error occurred
* \return ERR_TIMEOUT : Timeout error occurred
* \return ERR_SLEEP_REQ : Deselect has been received and responded
* \return ERR_NOMEM : The received I-PDU does not fit into the
* receive buffer
* \return ERR_LINK_LOSS : Communication is lost because Reader/Writer
* has turned off its field
*****************************************************************************
*/
ReturnCode rfalNfcDepGetPduTransceiveStatus( void );
#endif /* RFAL_NFCDEP_H_ */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,464 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfca.h
*
* \author Gustavo Patricio
*
* \brief Provides several NFC-A convenience methods and definitions
*
* It provides a Poller (ISO14443A PCD) interface and as well as
* some NFC-A Listener (ISO14443A PICC) helpers.
*
* The definitions and helpers methods provided by this module are only
* up to ISO14443-3 layer
*
*
* An usage example is provided here: \ref exampleRfalNfca.c
* \example exampleRfalNfca.c
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup NFC-A
* \brief RFAL NFC-A Module
* @{
*
*/
#ifndef RFAL_NFCA_H
#define RFAL_NFCA_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
#include "rfal_t1t.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCA_CASCADE_1_UID_LEN 4U /*!< UID length of cascade level 1 only tag */
#define RFAL_NFCA_CASCADE_2_UID_LEN 7U /*!< UID length of cascade level 2 only tag */
#define RFAL_NFCA_CASCADE_3_UID_LEN 10U /*!< UID length of cascade level 3 only tag */
#define RFAL_NFCA_SENS_RES_PLATFORM_MASK 0x0FU /*!< SENS_RES (ATQA) platform configuration mask Digital 1.1 Table 10 */
#define RFAL_NFCA_SENS_RES_PLATFORM_T1T 0x0CU /*!< SENS_RES (ATQA) T1T platform configuration Digital 1.1 Table 10 */
#define RFAL_NFCA_SEL_RES_CONF_MASK 0x60U /*!< SEL_RES (SAK) platform configuration mask Digital 1.1 Table 19 */
#define RFAL_NFCA_SEL_RES_CONF_T2T 0x00U /*!< SEL_RES (SAK) T2T configuration Digital 1.1 Table 19 */
#define RFAL_NFCA_SEL_RES_CONF_T4T 0x20U /*!< SEL_RES (SAK) T4T configuration Digital 1.1 Table 19 */
#define RFAL_NFCA_SEL_RES_CONF_NFCDEP 0x40U /*!< SEL_RES (SAK) NFC-DEP configuration Digital 1.1 Table 19 */
#define RFAL_NFCA_SEL_RES_CONF_T4T_NFCDEP 0x60U /*!< SEL_RES (SAK) T4T and NFC-DEP configuration Digital 1.1 Table 19 */
/*! NFC-A minimum FDT(listen) = ((n * 128 + (84)) / fc) with n_min = 9 Digital 1.1 6.10.1
* = (1236)/fc
* Relax with 3etu: (3*128)/fc as with multiple NFC-A cards, response may take longer (JCOP cards)
* = (1236 + 384)/fc = 1620 / fc */
#define RFAL_NFCA_FDTMIN 1620U
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*! Checks if device is a T1T given its SENS_RES */
#define rfalNfcaIsSensResT1T( sensRes ) ((((rfalNfcaSensRes*)(sensRes))->platformInfo & RFAL_NFCA_SENS_RES_PLATFORM_MASK) == RFAL_NFCA_SENS_RES_PLATFORM_T1T )
/*! Checks if device is a T2T given its SENS_RES */
#define rfalNfcaIsSelResT2T( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T2T )
/*! Checks if device is a T4T given its SENS_RES */
#define rfalNfcaIsSelResT4T( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T4T )
/*! Checks if device supports NFC-DEP protocol given its SENS_RES */
#define rfalNfcaIsSelResNFCDEP( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_NFCDEP )
/*! Checks if device supports ISO-DEP and NFC-DEP protocol given its SENS_RES */
#define rfalNfcaIsSelResT4TNFCDEP( selRes ) ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == RFAL_NFCA_SEL_RES_CONF_T4T_NFCDEP )
/*! Checks if a NFC-A listener device supports multiple protocols (ISO-DEP and NFC-DEP) */
#define rfalNfcaLisDevIsMultiProto( lisDev ) (((rfalNfcaListenDevice*)(lisDev))->type == RFAL_NFCA_T4T_NFCDEP )
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! NFC-A Listen device types */
typedef enum {
RFAL_NFCA_T1T = 0x01, /* Device configured for T1T Digital 1.1 Table 9 */
RFAL_NFCA_T2T = 0x00, /* Device configured for T2T Digital 1.1 Table 19 */
RFAL_NFCA_T4T = 0x20, /* Device configured for T4T Digital 1.1 Table 19 */
RFAL_NFCA_NFCDEP = 0x40, /* Device configured for NFC-DEP Digital 1.1 Table 19 */
RFAL_NFCA_T4T_NFCDEP = 0x60 /* Device configured for NFC-DEP and T4T Digital 1.1 Table 19 */
} rfalNfcaListenDeviceType;
/*! SENS_RES (ATQA) format Digital 1.1 6.6.3 & Table 7 */
typedef struct
{
uint8_t anticollisionInfo; /*!< SENS_RES Anticollision Information */
uint8_t platformInfo; /*!< SENS_RES Platform Information */
} rfalNfcaSensRes;
/*! SDD_REQ (Anticollision) format Digital 1.1 6.7.1 & Table 11 */
typedef struct
{
uint8_t selCmd; /*!< SDD_REQ SEL_CMD: cascade Level */
uint8_t selPar; /*!< SDD_REQ SEL_PAR: Byte Count[4b] | Bit Count[4b] (NVB: Number of Valid Bits)*/
} rfalNfcaSddReq;
/*! SDD_RES (UID CLn) format Digital 1.1 6.7.2 & Table 15 */
typedef struct
{
uint8_t nfcid1[RFAL_NFCA_CASCADE_1_UID_LEN]; /*!< NFCID1 cascade level NFCID */
uint8_t bcc; /*!< BCC Exclusive-OR over first 4 bytes of SDD_RES */
} rfalNfcaSddRes;
/*! SEL_REQ (Select) format Digital 1.1 6.8.1 & Table 17 */
typedef struct
{
uint8_t selCmd; /*!< SDD_REQ SEL_CMD: cascade Level */
uint8_t selPar; /*!< SDD_REQ SEL_PAR: Byte Count[4b] | Bit Count[4b] (NVB: Number of Valid Bits)*/
uint8_t nfcid1[RFAL_NFCA_CASCADE_1_UID_LEN]; /*!< NFCID1 data */
uint8_t bcc; /*!< Checksum calculated as exclusive-OR over the 4 bytes of NFCID1 CLn */
} rfalNfcaSelReq;
/*! SEL_RES (SAK) format Digital 1.1 6.8.2 & Table 19 */
typedef struct
{
uint8_t sak; /*!< Select Acknowledge */
} rfalNfcaSelRes;
/*! NFC-A listener device (PICC) struct */
typedef struct
{
rfalNfcaListenDeviceType type; /*!< NFC-A Listen device type */
rfalNfcaSensRes sensRes; /*!< SENS_RES (ATQA) */
rfalNfcaSelRes selRes; /*!< SEL_RES (SAK) */
uint8_t nfcId1Len; /*!< NFCID1 Length */
uint8_t nfcId1[RFAL_NFCA_CASCADE_3_UID_LEN]; /*!< NFCID1 (UID) */
#ifdef RFAL_FEATURE_T1T
rfalT1TRidRes ridRes; /*!< RID_RES */
#endif /* RFAL_FEATURE_T1T */
bool isSleep; /*!< Device sleeping flag */
} rfalNfcaListenDevice;
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize NFC-A Poller mode
*
* This methods configures RFAL RF layer to perform as a
* NFC-A Poller/RW (ISO14443A PCD) including all default timings and bit rate
* to 106 kbps
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcaPollerInitialize( void );
/*!
*****************************************************************************
* \brief NFC-A Poller Check Presence
*
* This method checks if a NFC-A Listen device (PICC) is present on the field
* by sending an ALL_REQ (WUPA) or SENS_REQ (REQA)
*
* \param[in] cmd : Indicate if to send an ALL_REQ or a SENS_REQ
* \param[out] sensRes : If received, the SENS_RES
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_RF_COLLISION : Collision detected one or more device in the field
* \return ERR_PAR : Parity error detected, one or more device in the field
* \return ERR_CRC : CRC error detected, one or more device in the field
* \return ERR_FRAMING : Framing error detected, one or more device in the field
* \return ERR_PROTO : Protocol error detected, one or more device in the field
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_NONE : No error, one or more device in the field
*****************************************************************************
*/
ReturnCode rfalNfcaPollerCheckPresence( rfal14443AShortFrameCmd cmd, rfalNfcaSensRes *sensRes );
/*!
*****************************************************************************
* \brief NFC-A Poller Select
*
* This method selects a NFC-A Listener device (PICC)
*
* \param[in] nfcid1 : Listener device NFCID1 to be selected
* \param[in] nfcidLen : Length of the NFCID1 to be selected
* \param[out] selRes : pointer to place the SEL_RES
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error
* \return ERR_PAR : Parity error detected
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error, SEL_RES received
*****************************************************************************
*/
ReturnCode rfalNfcaPollerSelect( const uint8_t *nfcid1, uint8_t nfcidLen, rfalNfcaSelRes *selRes );
/*!
*****************************************************************************
* \brief NFC-A Poller Sleep
*
* This method sends a SLP_REQ (HLTA)
* No response is expected afterwards Digital 1.1 6.9.2.1
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcaPollerSleep( void );
/*!
*****************************************************************************
* \brief NFC-A Technology Detection
*
* This method performs NFC-A Technology Detection as defined in the spec
* given in the compliance mode
*
* \param[in] compMode : compliance mode to be performed
* \param[out] sensRes : location to store the SENS_RES, if received
*
* When compMode is set to ISO compliance a SLP_REQ (HLTA) is not sent
* after detection. When set to EMV a ALL_REQ (WUPA) is sent instead of
* a SENS_REQ (REQA)
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error, one or more device in the field
*****************************************************************************
*/
ReturnCode rfalNfcaPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcaSensRes *sensRes );
/*!
*****************************************************************************
* \brief NFC-A Poller Collision Resolution
*
* Collision resolution for one NFC-A Listener device/card (PICC) as
* defined in Activity 2.1 9.3.4
*
* This method executes anti collision loop and select the device with higher NFCID1
*
* When devLimit = 0 it is configured to perform collision detection only. Once a collision
* is detected the collision resolution is aborted immidiatly. If only one device is found
* with no collisions, it will properly resolved.
*
* \param[in] devLimit : device limit value (CON_DEVICES_LIMIT)
* \param[out] collPending : pointer to collision pending flag (INT_COLL_PEND)
* \param[out] selRes : location to store the last Select Response from listener device (PICC)
* \param[out] nfcId1 : location to store the NFCID1 (UID), ensure RFAL_NFCA_CASCADE_3_UID_LEN
* \param[out] nfcId1Len : pointer to length of NFCID1 (UID)
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_PROTO : Card length invalid
* \return ERR_IGNORE : conDevLimit is 0 and there is a collision
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcaPollerSingleCollisionResolution( uint8_t devLimit, bool *collPending, rfalNfcaSelRes *selRes, uint8_t *nfcId1, uint8_t *nfcId1Len );
/*!
*****************************************************************************
* \brief NFC-A Poller Full Collision Resolution
*
* Performs a full Collision resolution as defined in Activity 2.1 9.3.4
*
* \param[in] compMode : compliance mode to be performed
* \param[in] devLimit : device limit value, and size nfcaDevList
* \param[out] nfcaDevList : NFC-A listener device info
* \param[out] devCnt : Devices found counter
*
* When compMode is set to ISO compliance it assumes that the device is
* not sleeping and therefore no ALL_REQ (WUPA) is sent at the beginning.
* When compMode is set to NFC compliance an additional ALL_REQ (WUPA) is sent
* at the beginning.
*
*
* When devLimit = 0 it is configured to perform collision detection only. Once a collision
* is detected the collision resolution is aborted immidiatly. If only one device is found
* with no collisions, it will properly resolved.
*
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcaPollerFullCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief NFC-A Poller Full Collision Resolution with Sleep
*
* Performs a full Collision resolution similar to rfalNfcaPollerFullCollisionResolution
* but an additional SLP_REQ (HLTA) -> SENS_RES (REQA) is sent regardless if there
* was a collision.
* This proprietary behaviour ensures proper activation of certain devices that suffer
* from influence of Type B commands as foreseen in ISO14443-3 5.2.3 or were somehow
* not detected by the first round of collision resolution
*
* \param[in] devLimit : device limit value, and size nfcaDevList
* \param[out] nfcaDevList : NFC-A listener device info
* \param[out] devCnt : Devices found counter
*
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcaPollerSleepFullCollisionResolution( uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief NFC-A Poller Start Full Collision Resolution
*
* This method starts the full Collision resolution as defined
* in Activity 1.0 or 1.1 9.3.4
*
* \param[in] compMode : compliance mode to be performed
* \param[in] devLimit : device limit value, and size nfcaDevList
* \param[out] nfcaDevList : NFC-A listener device info
* \param[out] devCnt : Devices found counter
*
* When compMode is set to ISO compliance it assumes that the device is
* not sleeping and therefore no ALL_REQ (WUPA) is sent at the beginning.
* When compMode is set to NFC compliance an additional ALL_REQ (WUPA) is sent at
* the beginning.
*
*
* When devLimit = 0 it is configured to perform collision detection only. Once a collision
* is detected the collision resolution is aborted immidiatly. If only one device is found
* with no collisions, it will properly resolved.
*
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcaPollerStartFullCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief NFC-A Get Full Collision Resolution Status
*
* Returns the Collision Resolution status
*
* \return ERR_BUSY : Operation is ongoing
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error
* \return ERR_PAR : Parity error detected
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error, activation successful
*****************************************************************************
*/
ReturnCode rfalNfcaPollerGetFullCollisionResolutionStatus( void );
/*!
*****************************************************************************
* \brief NFC-A Listener is SLP_REQ
*
* Checks if the given buffer contains valid NFC-A SLP_REQ (HALT)
*
* \param[in] buf: buffer containing data
* \param[in] bufLen: length of the data in buffer to be checked
*
* \return true if data in buf contains a SLP_REQ ; false otherwise
*****************************************************************************
*/
bool rfalNfcaListenerIsSleepReq( const uint8_t *buf, uint16_t bufLen );
#endif /* RFAL_NFCA_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,398 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfcb.h
*
* \author Gustavo Patricio
*
* \brief Implementation of NFC-B (ISO14443B) helpers
*
* It provides a NFC-B Poller (ISO14443B PCD) interface and
* also provides some NFC-B Listener (ISO14443B PICC) helpers
*
* The definitions and helpers methods provided by this module are only
* up to ISO14443-3 layer (excluding ATTRIB)
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup NFC-B
* \brief RFAL NFC-B Module
* @{
*
*/
#ifndef RFAL_NFCB_H
#define RFAL_NFCB_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCB_FWTSENSB 7680U /*!< NFC-B FWT(SENSB) Digital 2.0 B.3 */
#define RFAL_NFCB_DFWT 49152U /*!< NFC-B dFWT Delta 2.0 7.9.1.3 & B.3 */
#define RFAL_NFCB_DTPOLL_10 rfalConvMsTo1fc(20) /*!< NFC-B Delta Tb Poll Digital 1.0 A.2 */
#define RFAL_NFCB_DTPOLL_20 rfalConvMsTo1fc(17) /*!< NFC-B Delta Tb Poll Digital 2.1 B.3 */
#define RFAL_NFCB_AFI 0x00U /*!< NFC-B default Application Family Digital 1.1 7.6.1.1 */
#define RFAL_NFCB_PARAM 0x00U /*!< NFC-B default SENSB_REQ PARAM */
#define RFAL_NFCB_CRC_LEN 2U /*!< NFC-B CRC length and CRC_B(AID) Digital 1.1 Table 28 */
#define RFAL_NFCB_NFCID0_LEN 4U /*!< Length of NFC-B NFCID0 */
#define RFAL_NFCB_CMD_LEN 1U /*!< Length of NFC-B Command */
#define RFAL_NFCB_SENSB_RES_LEN 12U /*!< Standard length of SENSB_RES without SFGI byte */
#define RFAL_NFCB_SENSB_RES_EXT_LEN 13U /*!< Extended length of SENSB_RES with SFGI byte */
#define RFAL_NFCB_SENSB_REQ_ADV_FEATURE 0x20U /*!< Bit mask for Advance Feature in SENSB_REQ */
#define RFAL_NFCB_SENSB_RES_FSCI_MASK 0x0FU /*!< Bit mask for FSCI value in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_FSCI_SHIFT 4U /*!< Shift for FSCI value in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_PROTO_RFU_MASK 0x08U /*!< Bit mask for Protocol Type RFU in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK 0x03U /*!< Bit mask for Protocol Type TR2 in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_PROTO_TR2_SHIFT 1U /*!< Shift for Protocol Type TR2 in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK 0x01U /*!< Bit mask Protocol Type ISO14443 Compliant in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_FWI_MASK 0x0FU /*!< Bit mask for FWI value in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_FWI_SHIFT 4U /*!< Bit mask for FWI value in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_ADC_MASK 0x0CU /*!< Bit mask for ADC value in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_ADC_ADV_FEATURE_MASK 0x08U /*!< Bit mask for ADC.Advanced Proto Features in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_ADC_PROPRIETARY_MASK 0x04U /*!< Bit mask for ADC.Proprietary Application in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_FO_DID_MASK 0x01U /*!< Bit mask for DID in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_FO_NAD_MASK 0x02U /*!< Bit mask for DID in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_FO_MASK 0x03U /*!< Bit mask for FO value in SENSB_RES (NAD and DID) */
#define RFAL_NFCB_SENSB_RES_SFGI_MASK 0x0FU /*!< Bit mask for SFGI in SENSB_RES */
#define RFAL_NFCB_SENSB_RES_SFGI_SHIFT 4U /*!< Shift for SFGI in SENSB_RES */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*! Get device's FSCI given its SENSB_RES Digital 1.1 7.6.2 */
#define rfalNfcbGetFSCI( sensbRes ) ((((rfalNfcbSensbRes*)(sensbRes))->protInfo.FsciProType >> RFAL_NFCB_SENSB_RES_FSCI_SHIFT) & RFAL_NFCB_SENSB_RES_FSCI_MASK )
/*! Checks if the given NFC-B device indicates ISO-DEP support */
#define rfalNfcbIsIsoDepSupported( dev ) ( (((rfalNfcbListenDevice*)(dev))->sensbRes.protInfo.FsciProType & RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK) != 0U )
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! SENSB_REQ and ALLB_REQ param Digital 1.1 7.6.1 */
typedef enum
{
RFAL_NFCB_SENS_CMD_ALLB_REQ = 0x08, /*!< ALLB_REQ (WUPB) */
RFAL_NFCB_SENS_CMD_SENSB_REQ = 0x00 /*!< SENSB_REQ (REQB) */
} rfalNfcbSensCmd;
/*! Number of Slots (NI) codes used for NFC-B anti collision Digital 1.1 Table 26 */
typedef enum
{
RFAL_NFCB_SLOT_NUM_1 = 0, /*!< N=0 : 1 slot */
RFAL_NFCB_SLOT_NUM_2 = 1, /*!< N=1 : 2 slots */
RFAL_NFCB_SLOT_NUM_4 = 2, /*!< N=2 : 4 slots */
RFAL_NFCB_SLOT_NUM_8 = 3, /*!< N=3 : 8 slots */
RFAL_NFCB_SLOT_NUM_16 = 4 /*!< N=4 : 16 slots */
}rfalNfcbSlots;
/*! SENSB_RES (ATQB) Application Data Format Digital 1.1 Table 28 */
typedef struct
{
uint8_t AFI; /*!< Application Family Identifier */
uint8_t CRC_B[RFAL_NFCB_CRC_LEN]; /*!< CRC_B of AID */
uint8_t numApps; /*!< Number of Applications */
} rfalNfcbSensbResAppData;
/*! SENSB_RES Protocol Info format Digital 1.1 Table 29 */
typedef struct
{
uint8_t BRC; /*!< Bit Rate Capability */
uint8_t FsciProType; /*!< Frame Size Card Integer [4b] | Protocol Type[4 bits] */
uint8_t FwiAdcFo; /*!< Frame Waiting Integer [4b] | Application Data Coding [2b] | Frame Options [2b] */
uint8_t SFGI; /*!< Optional: Start-Up Frame Guard Time Integer[4b] | RFU [4b] */
} rfalNfcbSensbResProtocolInfo;
/*! SENSB_RES format Digital 1.1 7.6.2 */
typedef struct
{
uint8_t cmd; /*!< SENSB_RES: 50h */
uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFC Identifier (PUPI)*/
rfalNfcbSensbResAppData appData; /*!< Application Data */
rfalNfcbSensbResProtocolInfo protInfo; /*!< Protocol Information */
} rfalNfcbSensbRes;
/*! NFC-B listener device (PICC) struct */
typedef struct
{
uint8_t sensbResLen; /*!< SENSB_RES length */
rfalNfcbSensbRes sensbRes; /*!< SENSB_RES */
bool isSleep; /*!< Device sleeping flag */
}rfalNfcbListenDevice;
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize NFC-B Poller mode
*
* This methods configures RFAL RF layer to perform as a
* NFC-B Poller/RW (ISO14443B PCD) including all default timings
*
* It sets NFC-B parameters (AFI, PARAM) to default values
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcbPollerInitialize( void );
/*!
*****************************************************************************
* \brief Set NFC-B Poller parameters
*
* This methods configures RFAL RF layer to perform as a
* NFCA Poller/RW (ISO14443A PCD) including all default timings
*
* Additionally configures NFC-B specific parameters to be used on the
* following communications
*
* \param[in] AFI : Application Family Identifier to be used
* \param[in] PARAM : PARAM to be used, it announces whether Advanced
* Features or Extended SENSB_RES is supported
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcbPollerInitializeWithParams( uint8_t AFI, uint8_t PARAM );
/*!
*****************************************************************************
* \brief NFC-B Poller Check Presence
*
* This method checks if a NFC-B Listen device (PICC) is present on the field
* by sending an ALLB_REQ (WUPB) or SENSB_REQ (REQB)
*
* \param[in] cmd : Indicate if to send an ALL_REQ or a SENS_REQ
* \param[in] slots : The number of slots to be announced
* \param[out] sensbRes : If received, the SENSB_RES
* \param[out] sensbResLen : If received, the SENSB_RES length
*
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_RF_COLLISION : Collision detected one or more device in the field
* \return ERR_PAR : Parity error detected, one or more device in the field
* \return ERR_CRC : CRC error detected, one or more device in the field
* \return ERR_FRAMING : Framing error detected, one or more device in the field
* \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received
* \return ERR_NONE : No error, SENSB_RES received
*****************************************************************************
*/
ReturnCode rfalNfcbPollerCheckPresence( rfalNfcbSensCmd cmd, rfalNfcbSlots slots, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen );
/*!
*****************************************************************************
* \brief NFC-B Poller Sleep
*
* This function is used to send the SLPB_REQ (HLTB) command to put the PICC with
* the given NFCID0 to state HALT so that they do not reply to further SENSB_REQ
* commands (only to ALLB_REQ)
*
* \param[in] nfcid0 : NFCID of the device to be put to Sleep
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcbPollerSleep( const uint8_t* nfcid0 );
/*!
*****************************************************************************
* \brief NFC-B Poller Slot Marker
*
* This method selects a NFC-B Slot marker frame
*
* \param[in] slotCode : Slot Code [1-15]
* \param[out] sensbRes : If received, the SENSB_RES
* \param[out] sensbResLen : If received, the SENSB_RES length
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error
* \return ERR_PAR : Parity error detected
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error, SEL_RES received
*****************************************************************************
*/
ReturnCode rfalNfcbPollerSlotMarker( uint8_t slotCode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen );
/*!
*****************************************************************************
* \brief NFC-B Technology Detection
*
* This method performs NFC-B Technology Detection as defined in the spec
* given in the compliance mode
*
* \param[in] compMode : compliance mode to be performed
* \param[out] sensbRes : location to store the SENSB_RES, if received
* \param[out] sensbResLen : length of the SENSB_RES, if received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error, one or more device in the field
*****************************************************************************
*/
ReturnCode rfalNfcbPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen );
/*!
*****************************************************************************
* \brief NFC-B Poller Collision Resolution
*
* NFC-B Collision resolution Listener device/card (PICC) as
* defined in Activity 1.1 9.3.5
*
* This function is used to perform collision resolution for detection in case
* of multiple NFC Forum Devices with Technology B detected.
* Target with valid SENSB_RES will be stored in devInfo and nfcbDevCount incremented.
*
* \param[in] compMode : compliance mode to be performed
* \param[in] devLimit : device limit value, and size nfcbDevList
* \param[out] nfcbDevList : NFC-B listener device info
* \param[out] devCnt : devices found counter
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcbPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief NFC-B Poller Collision Resolution Slotted
*
* NFC-B Collision resolution Listener device/card (PICC). The sequence can
* be configured to be according to NFC Forum Activity 1.1 9.3.5, ISO10373
* or EMVCo
*
* This function is used to perform collision resolution for detection in case
* of multiple NFC Forum Devices with Technology B are detected.
* Target with valid SENSB_RES will be stored in devInfo and nfcbDevCount incremented.
*
* This method provides the means to perform a collision resolution loop with specific
* initial and end number of slots. This allows to user to start the loop already with
* greater number of slots, and or limit the end number of slots. At the end a flag
* indicating whether there were collisions pending is returned.
*
* If RFAL_COMPLIANCE_MODE_ISO is used \a initSlots must be set to RFAL_NFCB_SLOT_NUM_1
*
*
* \param[in] compMode : compliance mode to be performed
* \param[in] devLimit : device limit value, and size nfcbDevList
* \param[in] initSlots : number of slots to open initially
* \param[in] endSlots : number of slots when to stop collision resolution
* \param[out] nfcbDevList : NFC-B listener device info
* \param[out] devCnt : devices found counter
* \param[out] colPending : flag indicating whether collision are still pending
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcbPollerSlottedCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbSlots initSlots, rfalNfcbSlots endSlots, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt, bool *colPending );
/*!
*****************************************************************************
* \brief NFC-B TR2 code to FDT
*
* Converts the TR2 code as defined in Digital 1.1 Table 33 Minimum
* TR2 Coding to Frame Delay Time (FDT) in 1/Fc
*
* \param[in] tr2Code : TR2 code as defined in Digital 1.1 Table 33
*
* \return FDT in 1/Fc
*****************************************************************************
*/
uint32_t rfalNfcbTR2ToFDT( uint8_t tr2Code );
#endif /* RFAL_NFCB_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,370 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfcf.h
*
* \author Gustavo Patricio
*
* \brief Implementation of NFC-F Poller (FeliCa PCD) device
*
* The definitions and helpers methods provided by this module are
* aligned with NFC-F (FeliCa - JIS X6319-4)
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup NFC-F
* \brief RFAL NFC-F Module
* @{
*
*/
#ifndef RFAL_NFCF_H
#define RFAL_NFCF_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCF_NFCID2_LEN 8U /*!< NFCID2 (FeliCa IDm) length */
#define RFAL_NFCF_SENSF_RES_LEN_MIN 16U /*!< SENSF_RES minimum length */
#define RFAL_NFCF_SENSF_RES_LEN_MAX 18U /*!< SENSF_RES maximum length */
#define RFAL_NFCF_SENSF_RES_PAD0_LEN 2U /*!< SENSF_RES PAD0 length */
#define RFAL_NFCF_SENSF_RES_PAD1_LEN 2U /*!< SENSF_RES PAD1 length */
#define RFAL_NFCF_SENSF_RES_RD_LEN 2U /*!< SENSF_RES Request Data length */
#define RFAL_NFCF_SENSF_RES_BYTE1 1U /*!< SENSF_RES first byte value */
#define RFAL_NFCF_SENSF_SC_LEN 2U /*!< Felica SENSF_REQ System Code length */
#define RFAL_NFCF_SENSF_PARAMS_SC1_POS 0U /*!< System Code byte1 position in the SENSF_REQ */
#define RFAL_NFCF_SENSF_PARAMS_SC2_POS 1U /*!< System Code byte2 position in the SENSF_REQ */
#define RFAL_NFCF_SENSF_PARAMS_RC_POS 2U /*!< Request Code position in the SENSF_REQ */
#define RFAL_NFCF_SENSF_PARAMS_TSN_POS 3U /*!< Time Slot Number position in the SENSF_REQ */
#define RFAL_NFCF_POLL_MAXCARDS 16U /*!< Max number slots/cards 16 */
#define RFAL_NFCF_CMD_POS 0U /*!< Command/Responce code length */
#define RFAL_NFCF_CMD_LEN 1U /*!< Command/Responce code length */
#define RFAL_NFCF_LENGTH_LEN 1U /*!< LEN field length */
#define RFAL_NFCF_HEADER_LEN (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CMD_LEN) /*!< Header length*/
#define RFAL_NFCF_SENSF_NFCID2_BYTE1_POS 0U /*!< NFCID2 byte1 position */
#define RFAL_NFCF_SENSF_NFCID2_BYTE2_POS 1U /*!< NFCID2 byte2 position */
#define RFAL_NFCF_SENSF_NFCID2_PROT_TYPE_LEN 2U /*!< NFCID2 length for byte 1 and byte 2 indicating NFC-DEP or T3T support */
#define RFAL_NFCF_SENSF_NFCID2_BYTE1_NFCDEP 0x01U /*!< NFCID2 byte1 NFC-DEP support Digital 1.0 Table 44 */
#define RFAL_NFCF_SENSF_NFCID2_BYTE2_NFCDEP 0xFEU /*!< NFCID2 byte2 NFC-DEP support Digital 1.0 Table 44 */
#define RFAL_NFCF_SYSTEMCODE 0xFFFFU /*!< SENSF_RES Default System Code Digital 1.0 6.6.1.1 */
#define RFAL_NFCF_BLOCK_LEN 16U /*!< NFCF T3T Block size T3T 1.0 4.1 */
#define RFAL_NFCF_CHECKUPDATE_RES_ST1_POS 9U /*!< Check|Update Res Status Flag 1 position T3T 1.0 Table 8 */
#define RFAL_NFCF_CHECKUPDATE_RES_ST2_POS 10U /*!< Check|Update Res Status Flag 2 position T3T 1.0 Table 8 */
#define RFAL_NFCF_CHECKUPDATE_RES_NOB_POS 11U /*!< Check|Update Res Number of Blocks position T3T 1.0 Table 8 */
#define RFAL_NFCF_STATUS_FLAG_SUCCESS 0x00U /*!< Check response Number of Blocks position T3T 1.0 Table 11 */
#define RFAL_NFCF_STATUS_FLAG_ERROR 0xFFU /*!< Check response Number of Blocks position T3T 1.0 Table 11 */
#define RFAL_NFCF_BLOCKLISTELEM_LEN 0x80U /*!< Block List Element Length bit (2|3 bytes) T3T 1.0 5.6.1 */
#define RFAL_NFCF_SERVICECODE_RDONLY 0x000BU /*!< NDEF Service Code as Read-Only T3T 1.0 7.2.1 */
#define RFAL_NFCF_SERVICECODE_RDWR 0x0009U /*!< NDEF Service Code as Read and Write T3T 1.0 7.2.1 */
/*! NFC-F Felica command set JIS X6319-4 9.1 */
enum
{
RFAL_NFCF_CMD_POLLING = 0x00, /*!< SENSF_REQ (Felica Poll/REQC command to identify a card ) */
RFAL_NFCF_CMD_POLLING_RES = 0x01, /*!< SENSF_RES (Felica Poll/REQC command response ) */
RFAL_NFCF_CMD_REQUEST_SERVICE = 0x02, /*!< verify the existence of Area and Service */
RFAL_NFCF_CMD_REQUEST_RESPONSE = 0x04, /*!< verify the existence of a card */
RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION = 0x06, /*!< read Block Data from a Service that requires no authentication */
RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION_RES = 0x07, /*!< read Block Data response from a Service with no authentication */
RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION = 0x08, /*!< write Block Data to a Service that requires no authentication */
RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION_RES = 0x09, /*!< write Block Data response to a Service with no authentication */
RFAL_NFCF_CMD_REQUEST_SYSTEM_CODE = 0x0c, /*!< acquire the System Code registered to a card */
RFAL_NFCF_CMD_AUTHENTICATION1 = 0x10, /*!< authenticate a card */
RFAL_NFCF_CMD_AUTHENTICATION2 = 0x12, /*!< allow a card to authenticate a Reader/Writer */
RFAL_NFCF_CMD_READ = 0x14, /*!< read Block Data from a Service that requires authentication */
RFAL_NFCF_CMD_WRITE = 0x16, /*!< write Block Data to a Service that requires authentication */
};
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*! Checks if the given NFC-F device indicates NFC-DEP support */
#define rfalNfcfIsNfcDepSupported( dev ) ( (((rfalNfcfListenDevice*)(dev))->sensfRes.NFCID2[RFAL_NFCF_SENSF_NFCID2_BYTE1_POS] == RFAL_NFCF_SENSF_NFCID2_BYTE1_NFCDEP) && \
(((rfalNfcfListenDevice*)(dev))->sensfRes.NFCID2[RFAL_NFCF_SENSF_NFCID2_BYTE2_POS] == RFAL_NFCF_SENSF_NFCID2_BYTE2_NFCDEP) )
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! NFC-F SENSF_RES format Digital 1.1 8.6.2 */
typedef struct
{
uint8_t CMD; /*!< Command Code: 01h */
uint8_t NFCID2[RFAL_NFCF_NFCID2_LEN]; /*!< NFCID2 */
uint8_t PAD0[RFAL_NFCF_SENSF_RES_PAD0_LEN]; /*!< PAD0 */
uint8_t PAD1[RFAL_NFCF_SENSF_RES_PAD1_LEN]; /*!< PAD1 */
uint8_t MRTIcheck; /*!< MRTIcheck */
uint8_t MRTIupdate; /*!< MRTIupdate */
uint8_t PAD2; /*!< PAD2 */
uint8_t RD[RFAL_NFCF_SENSF_RES_RD_LEN]; /*!< Request Data */
} rfalNfcfSensfRes;
/*! NFC-F poller device (PCD) struct */
typedef struct
{
uint8_t NFCID2[RFAL_NFCF_NFCID2_LEN]; /*!< NFCID2 */
} rfalNfcfPollDevice;
/*! NFC-F listener device (PICC) struct */
typedef struct
{
uint8_t sensfResLen; /*!< SENF_RES length */
rfalNfcfSensfRes sensfRes; /*!< SENF_RES */
} rfalNfcfListenDevice;
typedef uint16_t rfalNfcfServ; /*!< NFC-F Service Code */
/*! NFC-F Block List Element (2 or 3 bytes element) T3T 1.0 5.6.1 */
typedef struct
{
uint8_t conf; /*!< Access Mode | Serv Code List Order */
uint16_t blockNum; /*!< Block Number */
}rfalNfcfBlockListElem;
/*! Check Update Service list and Block list parameter */
typedef struct
{
uint8_t numServ; /*!< Number of Services */
rfalNfcfServ *servList; /*!< Service Code List */
uint8_t numBlock; /*!< Number of Blocks */
rfalNfcfBlockListElem *blockList; /*!< Block Number List */
}rfalNfcfServBlockListParam;
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize NFC-F Poller mode
*
* This methods configures RFAL RF layer to perform as a
* NFC-F Poller/RW (FeliCa PCD) including all default timings
*
* \param[in] bitRate : NFC-F bitrate to be initialize (212 or 424)
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Incorrect bitrate
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcfPollerInitialize( rfalBitRate bitRate );
/*!
*****************************************************************************
* \brief NFC-F Poller Check Presence
*
* This function sends a Poll/SENSF command according to NFC Activity spec
* It detects if a NCF-F device is within range
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_NONE : No error and some NFC-F device was detected
*
*****************************************************************************
*/
ReturnCode rfalNfcfPollerCheckPresence( void );
/*!
*****************************************************************************
* \brief NFC-F Poller Poll
*
* This function sends to all PICCs in field the POLL command with the given
* number of slots.
*
* \param[in] slots : the number of slots to be performed
* \param[in] sysCode : as given in FeliCa poll command
* \param[in] reqCode : FeliCa communication parameters
* \param[out] cardList : Parameter of type rfalFeliCaPollRes which will hold the cards found
* \param[out] devCnt : actual number of cards found
* \param[out] collisions : number of collisions encountered
*
* \warning the list cardList has to be as big as the number of slots for the Poll
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_NONE : No error and some NFC-F device was detected
*
*****************************************************************************
*/
ReturnCode rfalNfcfPollerPoll( rfalFeliCaPollSlots slots, uint16_t sysCode, uint8_t reqCode, rfalFeliCaPollRes *cardList, uint8_t *devCnt, uint8_t *collisions );
/*!
*****************************************************************************
* \brief NFC-F Poller Full Collision Resolution
*
* Performs a full Collision resolution as defined in Activity 1.1 9.3.4
*
* \param[in] compMode : compliance mode to be performed
* \param[in] devLimit : device limit value, and size nfcaDevList
* \param[out] nfcfDevList : NFC-F listener devices list
* \param[out] devCnt : Devices found counter
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcfPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcfListenDevice *nfcfDevList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief NFC-F Poller Check/Read
*
* It computes a Check / Read command accoring to T3T 1.0 and JIS X6319-4 and
* sends it to PICC. If sucessfully, the rxBuf will contain the the number of
* blocks in the first byte followed by the blocks data.
*
* \param[in] nfcid2 : nfcid2 of the device
* \param[in] servBlock : parameter containing the list of Services and
* Blocks to be addressed by this command
* \param[out] rxBuf : buffer to place check/read data
* \param[in] rxBufLen : size of the rxBuf
* \param[out] rcvdLen : length of data placed in rxBuf
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_REQUEST : The request was executed with error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcfPollerCheck( const uint8_t* nfcid2, const rfalNfcfServBlockListParam *servBlock, uint8_t *rxBuf, uint16_t rxBufLen, uint16_t *rcvdLen );
/*!
*****************************************************************************
* \brief NFC-F Poller Update/Write
*
* It computes a Update / Write command accoring to T3T 1.0 and JIS X6319-4 and
* sends it to PICC.
*
* \param[in] nfcid2 : nfcid2 of the device
* \param[in] servBlock : parameter containing the list of Services and
* Blocks to be addressed by this command
* \param[in] txBuf : buffer where the request will be composed
* \param[in] txBufLen : size of txBuf
* \param[in] blockData : data to written on the given block(s)
* \param[out] rxBuf : buffer to place check/read data
* \param[in] rxBufLen : size of the rxBuf
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_REQUEST : The request was executed with error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcfPollerUpdate( const uint8_t* nfcid2, const rfalNfcfServBlockListParam *servBlock, uint8_t *txBuf, uint16_t txBufLen, const uint8_t *blockData, uint8_t *rxBuf, uint16_t rxBufLen);
/*!
*****************************************************************************
* \brief NFC-F Listener is T3T Request
*
* This method checks if the given data is a valid T3T command (Read or Write)
* and in case a valid request has been received it may output the request's NFCID2
*
* \param[in] buf : buffer holding Initiator's received command
* \param[in] bufLen : length of received command in bytes
* \param[out] nfcid2 : pointer to where the NFCID2 may be outputed,
* nfcid2 has NFCF_SENSF_NFCID2_LEN as length
* Pass NULL if output parameter not desired
*
* \return true : Valid T3T command (Read or Write) received
* \return false : Invalid protocol request
*
*****************************************************************************
*/
bool rfalNfcfListenerIsT3TReq( const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid2 );
#endif /* RFAL_NFCF_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,772 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfcv.h
*
* \author Gustavo Patricio
*
* \brief Implementation of NFC-V Poller (ISO15693) device
*
* The definitions and helpers methods provided by this module
* are aligned with NFC-V Digital 2.1
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup NFC-V
* \brief RFAL NFC-V Module
* @{
*
*/
#ifndef RFAL_NFCV_H
#define RFAL_NFCV_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCV_UID_LEN 8U /*!< NFC-V UID length */
#define RFAL_NFCV_MAX_BLOCK_LEN 32U /*!< Max Block size: can be of up to 256 bits ISO 15693 2000 5 */
#define RFAL_NFCV_BNO_LEN 1U /*!< NFC-V Block Number length */
#define RFAL_NFCV_CRC_LEN 2U /*!< NFC-V CRC length */
#define RFAL_NFCV_MAX_GEN_DATA_LEN (RFAL_NFCV_MAX_BLOCK_LEN + RFAL_NFCV_BNO_LEN + RFAL_NFCV_UID_LEN) /*!<Max data */
#define RFAL_NFCV_BLOCKNUM_LEN 1U /*!< Block Number length on normal commands: 8 bits */
#define RFAL_NFCV_BLOCKNUM_EXTENDED_LEN 2U /*!< Block Number length on extended commands: 16 bits */
#define RFAL_NFCV_PARAM_SKIP 0U /*!< Skip proprietary Param Request */
/*! NFC-V RequestFlags ISO15693 2000 7.3.1 */
enum{
RFAL_NFCV_REQ_FLAG_DEFAULT = 0x02U, /*!< Default Request Flags */
RFAL_NFCV_REQ_FLAG_SUB_CARRIER = 0x01U, /*!< Sub Carrier flag */
RFAL_NFCV_REQ_FLAG_DATA_RATE = 0x02U, /*!< Data Rate flag */
RFAL_NFCV_REQ_FLAG_INVENTORY = 0x04U, /*!< Inventory flag */
RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT = 0x08U, /*!< Protocol Extension flag */
RFAL_NFCV_REQ_FLAG_SELECT = 0x10U, /*!< Select flag */
RFAL_NFCV_REQ_FLAG_ADDRESS = 0x20U, /*!< Address flag */
RFAL_NFCV_REQ_FLAG_OPTION = 0x40U, /*!< Option flag */
RFAL_NFCV_REQ_FLAG_RFU = 0x80U, /*!< RFU flag */
RFAL_NFCV_REQ_FLAG_AFI = 0x10U, /*!< AFI flag */
RFAL_NFCV_REQ_FLAG_NB_SLOTS = 0x20U, /*!< Number of Slots flag */
};
/*! NFC-V Response Flags ISO15693 2000 7.4.1 */
enum{
RFAL_NFCV_RES_FLAG_ERROR = 0x01U, /*!< Error flag */
RFAL_NFCV_RES_FLAG_RFU1 = 0x02U, /*!< RFU flag */
RFAL_NFCV_RES_FLAG_RFU2 = 0x04U, /*!< RFU flag */
RFAL_NFCV_RES_FLAG_EXTENSION = 0x08U, /*!< Extension flag */
RFAL_NFCV_RES_FLAG_RFU3 = 0x10U, /*!< RFU flag */
RFAL_NFCV_RES_FLAG_RFU4 = 0x20U, /*!< RFU flag */
RFAL_NFCV_RES_FLAG_RFU5 = 0x40U, /*!< RFU flag */
RFAL_NFCV_RES_FLAG_RFU6 = 0x80U /*!< RFU flag */
};
/*! NFC-V Error code ISO15693 2000 7.4.2 */
enum{
RFAL_NFCV_ERROR_CMD_NOT_SUPPORTED = 0x01U, /*!< The command is not supported, code is not recognised */
RFAL_NFCV_ERROR_CMD_NOT_RECOGNIZED = 0x02U, /*!< The command is not recognised, format error occurred */
RFAL_NFCV_ERROR_OPTION_NOT_SUPPORTED = 0x03U, /*!< The option is not supported */
RFAL_NFCV_ERROR_UNKNOWN = 0x0FU, /*!< Unknown error */
RFAL_NFCV_ERROR_BLOCK_NOT_AVALIABLE = 0x10U, /*!< The specified block is not available */
RFAL_NFCV_ERROR_BLOCK_ALREDY_LOCKED = 0x11U, /*!< The specified block is already locked */
RFAL_NFCV_ERROR_BLOCK_LOCKED = 0x12U, /*!< The specified block is locked */
RFAL_NFCV_ERROR_WRITE_FAILED = 0x13U, /*!< The specified block was not successfully programmed */
RFAL_NFCV_ERROR_BLOCK_FAILED = 0x14U /*!< The specified block was not successfully locked */
};
/*! NFC-V command set ISO15693 2000 9.1 */
enum
{
RFAL_NFCV_CMD_INVENTORY = 0x01U, /*!< INVENTORY_REQ (Inventory) command */
RFAL_NFCV_CMD_SLPV = 0x02U, /*!< SLPV_REQ (Stay quiet) command */
RFAL_NFCV_CMD_READ_SINGLE_BLOCK = 0x20U, /*!< Read single block command */
RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK = 0x21U, /*!< Write single block command */
RFAL_NFCV_CMD_LOCK_BLOCK = 0x22U, /*!< Lock block command */
RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS = 0x23U, /*!< Read multiple blocks command */
RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS = 0x24U, /*!< Write multiple blocks command */
RFAL_NFCV_CMD_SELECT = 0x25U, /*!< Select command */
RFAL_NFCV_CMD_RESET_TO_READY = 0x26U, /*!< Reset To Ready command */
RFAL_NFCV_CMD_GET_SYS_INFO = 0x2BU, /*!< Get System Information command */
RFAL_NFCV_CMD_EXTENDED_READ_SINGLE_BLOCK = 0x30U, /*!< Extended read single block command */
RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK = 0x31U, /*!< Extended write single block command */
RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK = 0x32U, /*!< Extended lock single block command */
RFAL_NFCV_CMD_EXTENDED_READ_MULTIPLE_BLOCK = 0x33U, /*!< Extended read multiple block command */
RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK = 0x34U, /*!< Extended read multiple block command */
RFAL_NFCV_CMD_EXTENDED_GET_SYS_INFO = 0x3BU /*!< Extended Get System Information command */
};
/*! ST25TV/ST25DV command set */
enum
{
RFAL_NFCV_CMD_READ_CONFIGURATION = 0xA0U, /*!< Read configuration command */
RFAL_NFCV_CMD_WRITE_CONFIGURATION = 0xA1U, /*!< Write configuration command */
RFAL_NFCV_CMD_SET_EAS = 0xA2U, /*!< Set EAS command */
RFAL_NFCV_CMD_RESET_EAS = 0xA3U, /*!< Reset EAS command */
RFAL_NFCV_CMD_LOCK_EAS = 0xA4U, /*!< Lock EAS command */
RFAL_NFCV_CMD_ENABLE_EAS = 0xA5U, /*!< Enable EAS command */
RFAL_NFCV_CMD_KILL = 0xA6U, /*!< Kill command */
RFAL_NFCV_CMD_WRITE_EAS_ID = 0xA7U, /*!< Write EAS ID command */
RFAL_NFCV_CMD_WRITE_EAS_CONFIG = 0xA8U, /*!< Write EAS CONFIG command */
RFAL_NFCV_CMD_MANAGE_GPO = 0xA9U, /*!< Manage GPO command */
RFAL_NFCV_CMD_WRITE_MESSAGE = 0xAAU, /*!< Write Message command */
RFAL_NFCV_CMD_READ_MESSAGE_LENGTH = 0xABU, /*!< Read Message Length command */
RFAL_NFCV_CMD_READ_MESSAGE = 0xACU, /*!< Read Message command */
RFAL_NFCV_CMD_READ_DYN_CONFIGURATION = 0xADU, /*!< Read Dynamic Configuration command */
RFAL_NFCV_CMD_WRITE_DYN_CONFIGURATION = 0xAEU, /*!< Write Dynamic Configuration command */
RFAL_NFCV_CMD_WRITE_PASSWORD = 0xB1U, /*!< Write Kill Password / Write Password command */
RFAL_NFCV_CMD_LOCK_KILL = 0xB2U, /*!< Lock Kill command */
RFAL_NFCV_CMD_PRESENT_PASSWORD = 0xB3U, /*!< Present Password command */
RFAL_NFCV_CMD_GET_RANDOM_NUMBER = 0xB4U, /*!< Get Random Number command */
RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK = 0xC0U, /*!< Fast Read single block command */
RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS = 0xC3U, /*!< Fast Read multiple blocks command */
RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK = 0xC4U, /*!< Fast Extended Read single block command */
RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS = 0xC5U, /*!< Fast Extended Read multiple blocks command */
RFAL_NFCV_CMD_FAST_WRITE_MESSAGE = 0xCAU, /*!< Fast Write Message */
RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH = 0xCBU, /*!< Fast Read Message Length */
RFAL_NFCV_CMD_FAST_READ_MESSAGE = 0xCCU, /*!< Fast Read Message */
RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION = 0xCDU, /*!< Fast Read Dynamic configuration */
RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION = 0xCEU /*!< Fast Write Dynamic Configuration */
};
/*! ISO 15693 Get System info parameter request field ISO15693 2018 Table 94 */
enum
{
RFAL_NFCV_SYSINFO_DFSID = 0x01U, /*!< Get System info DFSID flag */
RFAL_NFCV_SYSINFO_AFI = 0x02U, /*!< Get System info AFI flag */
RFAL_NFCV_SYSINFO_MEMSIZE = 0x04U, /*!< Get System info MEMSIZE flag */
RFAL_NFCV_SYSINFO_ICREF = 0x08U, /*!< Get System info ICREF flag */
RFAL_NFCV_SYSINFO_MOI = 0x10U, /*!< Get System info MOI flag */
RFAL_NFCV_SYSINFO_CMDLIST = 0x20U, /*!< Get System info CMDLIST flag */
RFAL_NFCV_SYSINFO_CSI = 0x40U, /*!< Get System info CSI flag */
RFAL_NFCV_SYSINFO_REQ_ALL = 0x7FU /*!< Get System info request of all parameters */
};
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! NFC-V Number of slots Digital 2.0 9.6.1 */
typedef enum
{
RFAL_NFCV_NUM_SLOTS_1 = 0x20, /*!< Number of slots: 1 */
RFAL_NFCV_NUM_SLOTS_16 = 0x00, /*!< Number of slots: 16 */
} rfalNfcvNumSlots;
/*! NFC-V INVENTORY_RES format Digital 2.0 9.6.2 */
typedef struct
{
uint8_t RES_FLAG; /*!< Response Flags */
uint8_t DSFID; /*!< Data Storage Format Identifier */
uint8_t UID[RFAL_NFCV_UID_LEN]; /*!< NFC-V device UID */
uint8_t crc[RFAL_CRC_LEN]; /*!< CRC */
} rfalNfcvInventoryRes;
/*! NFC-V Generic Req format */
typedef struct
{
uint8_t REQ_FLAG; /*!< Request Flags */
uint8_t CMD; /*!< Command code */
union { /* PRQA S 0750 # MISRA 19.2 - Both members are of the same type, just different names. Thus no problem can occur. */
uint8_t UID[RFAL_NFCV_UID_LEN]; /*!< Mask Value */
uint8_t data[RFAL_NFCV_MAX_GEN_DATA_LEN]; /*!< Data */
}payload; /*!< Payload */
} rfalNfcvGenericReq;
/*! NFC-V Generic Response format */
typedef struct
{
uint8_t RES_FLAG; /*!< Response Flags */
uint8_t data[RFAL_NFCV_MAX_GEN_DATA_LEN]; /*!< Data */
} rfalNfcvGenericRes;
/*! NFC-V listener device (VICC) struct */
typedef struct
{
rfalNfcvInventoryRes InvRes; /*!< INVENTORY_RES */
bool isSleep; /*!< Device sleeping flag */
} rfalNfcvListenDevice;
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize NFC-V Poller mode
*
* This methods configures RFAL RF layer to perform as a
* NFC-F Poller/RW (ISO15693) including all default timings
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Incorrect bitrate
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerInitialize( void );
/*!
*****************************************************************************
* \brief NFC-V Poller Check Presence
*
* This method checks if a NFC-V Listen device (VICC) is present on the field
* by sending an Inventory (INVENTORY_REQ)
*
* \param[out] invRes : If received, the INVENTORY_RES
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detectedd
* \return ERR_NONE : No error, one or more device in the field
*****************************************************************************
*/
ReturnCode rfalNfcvPollerCheckPresence( rfalNfcvInventoryRes *invRes );
/*!
*****************************************************************************
* \brief NFC-F Poller Poll
*
* This function sends to all VICCs in field the INVENTORY command with the
* given number of slots
*
* If more than one slot is used the following EOF need to be handled
* by the caller using rfalISO15693TransceiveEOFAnticollision()
*
* \param[in] nSlots : Number of Slots to be sent (1 or 16)
* \param[in] maskLen : Number bits on the Mask value
* \param[in] maskVal : location of the Mask value
* \param[out] invRes : location to place the INVENTORY_RES
* \param[out] rcvdLen : number of bits received (without collision)
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_RF_COLLISION : Collision detected
* \return ERR_CRC : CRC error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerInventory( rfalNfcvNumSlots nSlots, uint8_t maskLen, const uint8_t *maskVal, rfalNfcvInventoryRes *invRes, uint16_t* rcvdLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Full Collision Resolution
*
* Performs a full Collision resolution as defined in Activity 2.0 9.3.7
* Once done, the devCnt will indicate how many (if any) devices have
* been identified and their details are contained on nfcvDevList
*
* \param[in] compMode : compliance mode to be performed
* \param[in] devLimit : device limit value, and size nfcaDevList
* \param[out] nfcvDevList : NFC-v listener devices list
* \param[out] devCnt : Devices found counter
*
* When compMode is set to ISO the function immediately goes to 16 slots improving
* chances to detect more than only one strong card.
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcvListenDevice *nfcvDevList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief NFC-V Poller Full Collision Resolution With Sleep
*
* Performs a full Collision resolution which is different from Activity 2.0 9.3.7.
* The implementation uses SLPV (StayQuiet) command to make sure all cards are found.
* Once done, the devCnt will indicate how many (if any) devices have
* been identified and their details are contained on nfcvDevList
*
* \param[in] devLimit : device limit value, and size nfcaDevList
* \param[out] nfcvDevList : NFC-v listener devices list
* \param[out] devCnt : Devices found counter
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerSleepCollisionResolution( uint8_t devLimit, rfalNfcvListenDevice *nfcvDevList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief NFC-V Poller Sleep
*
* This function is used to send the SLPV_REQ (Stay Quiet) command to put the VICC
* with the given UID to state QUIET so that they do not reply to more Inventory
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to Sleep
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerSleep( uint8_t flags, const uint8_t* uid );
/*!
*****************************************************************************
* \brief NFC-V Poller Select
*
* Selects a device (VICC) by its UID
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be Selected
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerSelect( uint8_t flags, const uint8_t* uid );
/*!
*****************************************************************************
* \brief NFC-V Poller Read Single Block
*
* Reads a Single Block from a device (VICC)
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[in] blockNum : Number of the block to read
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerReadSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Write Single Block
*
* Writes a Single Block from a device (VICC)
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be written
* if UID is provided Addressed mode will be used
* \param[in] blockNum : Number of the block to write
* \param[in] wrData : data to be written on the given block
* \param[in] blockLen : number of bytes of a block
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, const uint8_t* wrData, uint8_t blockLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Read Multiple Blocks
*
* Reads Multiple Blocks from a device (VICC)
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[in] firstBlockNum : first block to be read
* \param[in] numOfBlocks : number of block to read
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Write Multiple Blocks
*
* Reads Multiple Blocks from a device (VICC)
* In order to not limit the length of the Write multiple command, a buffer
* must be provided where the request will be composed and then sent.
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[in] firstBlockNum : first block to be write
* \param[in] numOfBlocks : number of consecutive blocks to write
* \param[in] txBuf : buffer where the request will be composed
* \param[in] txBufLen : length of txBuf
* \param[in] blockLen : number of bytes of a block
* \param[in] wrData : data to be written
* \param[in] wrDataLen : length of the data do be written. Must be
* aligned with number of blocks to write and
* the size of a block
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerWriteMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t *txBuf, uint16_t txBufLen, uint8_t blockLen, const uint8_t* wrData, uint16_t wrDataLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Extended Lock Single Block
*
* Blocks a Single Block from a device (VICC) supporting extended commands
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device
* if UID is provided Addressed mode will be used
* \param[in] blockNum : Number of the block to be locked
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerLockBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum );
/*!
*****************************************************************************
* \brief NFC-V Poller Extended Lock Single Block
*
* Blocks a Single Block from a device (VICC) supporting extended commands
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device
* if UID is provided Addressed mode will be used
* \param[in] blockNum : Number of the block to be locked (16 bits)
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerExtendedLockSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum );
/*!
*****************************************************************************
* \brief NFC-V Poller Extended Read Single Block
*
* Reads a Single Block from a device (VICC) supporting extended commands
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[in] blockNum : Number of the block to read (16 bits)
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerExtendedReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Extended Write Single Block
*
* Writes a Single Block from a device (VICC) supporting extended commands
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device
* if UID is provided Addressed mode will be used
* \param[in] blockNum : Number of the block to write (16 bits)
* \param[in] wrData : data to be written on the given block
* \param[in] blockLen : number of bytes of a block
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerExtendedWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, const uint8_t* wrData, uint8_t blockLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Extended Read Multiple Blocks
*
* Reads Multiple Blocks from a device (VICC) supporting extended commands
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[in] firstBlockNum : first block to be read (16 bits)
* \param[in] numOfBlocks : number of consecutive blocks to read (16 bits)
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerExtendedReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Extended Write Multiple Blocks
*
* Writes Multiple Blocks from a device (VICC) supporting extended commands
* In order to not limit the length of the Write multiple command, a buffer
* must be provided where the request will be composed and then sent.
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[in] firstBlockNum : first block to be write (16 bits)
* \param[in] numOfBlocks : number of consecutive blocks to write (16 bits)
* \param[in] txBuf : buffer where the request will be composed
* \param[in] txBufLen : length of txBuf
* \param[in] blockLen : number of bytes of a block
* \param[in] wrData : data to be written
* \param[in] wrDataLen : length of the data do be written. Must be
* aligned with number of blocks to write and
* the size of a block
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerExtendedWriteMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t *txBuf, uint16_t txBufLen, uint8_t blockLen, const uint8_t* wrData, uint16_t wrDataLen );
/*!
*****************************************************************************
* \brief NFC-V Get System Information
*
* Sends Get System Information command
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerGetSystemInformation( uint8_t flags, const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Extended Get System Information
*
* Sends Extended Get System Information command
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[in] requestField : Get System info parameter request field
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerExtendedGetSystemInformation( uint8_t flags, const uint8_t* uid, uint8_t requestField, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Transceive Request
*
* Performs a generic transceive with an ISO15693 tag
*
* \param[in] cmd : NFC-V command
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] param : Prepend parameter on certain proprietary requests
* For default commands skip: RFAL_NFCV_PARAM_SKIP
* \param[in] uid : UID of the device to be put to be read
* if UID is provided Addressed mode will be used
* \param[in] data : command parameters append after UID
* \param[in] dataLen : command parameters Len
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalNfcvPollerTransceiveReq( uint8_t cmd, uint8_t flags, uint8_t param, const uint8_t* uid, const uint8_t *data, uint16_t dataLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
#endif /* RFAL_NFCV_H */
/**
* @}
*
* @}
*
* @}
*/

1572
lib/ST25RFAL002/include/rfal_rf.h Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,355 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_st25tb.h
*
* \author Gustavo Patricio
*
* \brief Implementation of ST25TB interface
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup ST25TB
* \brief RFAL ST25TB Module
* @{
*
*/
#ifndef RFAL_ST25TB_H
#define RFAL_ST25TB_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
#include "rfal_nfcb.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_ST25TB_CHIP_ID_LEN 1U /*!< ST25TB chip ID length */
#define RFAL_ST25TB_CRC_LEN 2U /*!< ST25TB CRC length */
#define RFAL_ST25TB_UID_LEN 8U /*!< ST25TB Unique ID length */
#define RFAL_ST25TB_BLOCK_LEN 4U /*!< ST25TB Data Block length */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
typedef uint8_t rfalSt25tbUID[RFAL_ST25TB_UID_LEN]; /*!< ST25TB UID type */
typedef uint8_t rfalSt25tbBlock[RFAL_ST25TB_BLOCK_LEN]; /*!< ST25TB Block type */
/*! ST25TB listener device (PICC) struct */
typedef struct
{
uint8_t chipID; /*!< Device's session Chip ID */
rfalSt25tbUID UID; /*!< Device's UID */
bool isDeselected; /*!< Device deselect flag */
}rfalSt25tbListenDevice;
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize ST25TB Poller mode
*
* This methods configures RFAL RF layer to perform as a
* ST25TB Poller/RW including all default timings
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerInitialize( void );
/*!
*****************************************************************************
* \brief ST25TB Poller Check Presence
*
* This method checks if a ST25TB Listen device (PICC) is present on the field
* by sending an Initiate command
*
* \param[out] chipId : if successfully retrieved, the device's chip ID
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_RF_COLLISION : Collision detected one or more device in the field
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerCheckPresence( uint8_t *chipId );
/*!
*****************************************************************************
* \brief ST25TB Poller Collision Resolution
*
* This method performs ST25TB Collision resolution, selects the each device,
* retrieves its UID and then deselects.
* In case only one device is identified the ST25TB device is left in select
* state.
*
* \param[in] devLimit : device limit value, and size st25tbDevList
* \param[out] st25tbDevList : ST35TB listener device info
* \param[out] devCnt : Devices found counter
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_RF_COLLISION : Collision detected one or more device in the field
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerCollisionResolution( uint8_t devLimit, rfalSt25tbListenDevice *st25tbDevList, uint8_t *devCnt );
/*!
*****************************************************************************
* \brief ST25TB Poller Initiate
*
* This method sends an Initiate command
*
* If a single device responds the chip ID will be retrieved
*
* \param[out] chipId : chip ID of the device
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerInitiate( uint8_t *chipId );
/*!
*****************************************************************************
* \brief ST25TB Poller Pcall
*
* This method sends a Pcall command
* If successful the device's chip ID will be retrieved
*
* \param[out] chipId : Chip ID of the device
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerPcall( uint8_t *chipId );
/*!
*****************************************************************************
* \brief ST25TB Poller Slot Marker
*
* This method sends a Slot Marker
*
* If a single device responds the chip ID will be retrieved
*
* \param[in] slotNum : Slot Number
* \param[out] chipIdRes : Chip ID of the device
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerSlotMarker( uint8_t slotNum, uint8_t *chipIdRes );
/*!
*****************************************************************************
* \brief ST25TB Poller Select
*
* This method sends a ST25TB Select command with the given chip ID.
*
* If the device is already in Selected state and receives an incorrect chip
* ID, it goes into Deselected state
*
* \param[in] chipId : chip ID of the device to be selected
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerSelect( uint8_t chipId );
/*!
*****************************************************************************
* \brief ST25TB Get UID
*
* This method sends a Get_UID command
*
* If a single device responds the chip UID will be retrieved
*
* \param[out] UID : UID of the found device
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerGetUID( rfalSt25tbUID *UID );
/*!
*****************************************************************************
* \brief ST25TB Poller Read Block
*
* This method reads a block of the ST25TB
*
* \param[in] blockAddress : address of the block to be read
* \param[out] blockData : location to place the data read from block
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerReadBlock( uint8_t blockAddress, rfalSt25tbBlock *blockData );
/*!
*****************************************************************************
* \brief ST25TB Poller Write Block
*
* This method writes a block of the ST25TB
*
* \param[in] blockAddress : address of the block to be written
* \param[in] blockData : data to be written on the block
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerWriteBlock( uint8_t blockAddress, const rfalSt25tbBlock *blockData );
/*!
*****************************************************************************
* \brief ST25TB Poller Completion
*
* This method sends a completion command to the ST25TB. After the
* completion the card no longer will reply to any command.
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerCompletion( void );
/*!
*****************************************************************************
* \brief ST25TB Poller Reset to Inventory
*
* This method sends a Reset to Inventory command to the ST25TB.
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_TIMEOUT : Timeout error, no listener device detected
* \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalSt25tbPollerResetToInventory( void );
#endif /* RFAL_ST25TB_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,729 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_st25xv.h
*
* \author Gustavo Patricio
*
* \brief NFC-V ST25 NFC-V Tag specific features
*
* This module provides support for ST's specific features available on
* NFC-V (ISO15693) tag families: ST25D, ST25TV, M24LR
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup ST25xV
* \brief RFAL ST25xV Module
* @{
*
*/
#ifndef RFAL_ST25xV_H
#define RFAL_ST25xV_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_nfc.h"
#include "rfal_rf.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCV_BLOCKNUM_M24LR_LEN 2U /*!< Block Number length of MR24LR tags: 16 bits */
#define RFAL_NFCV_ST_IC_MFG_CODE 0x02 /*!< ST IC Mfg code (used for custom commands) */
/*!
*****************************************************************************
* \brief NFC-V Poller Read Single Block (M24LR)
*
* Reads a Single Block from a M24LR tag which has the number of blocks
* bigger than 256 (M24LR16 ; M24LR64)
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* default: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] blockNum : Number of the block to read (16 bits)
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerM24LRReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Read Single Block (M24LR)
*
* Reads a Single Block from a M24LR tag which has the number of blocks
* bigger than 256 (M24LR16 ; M24LR64) using ST Fast mode
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* default: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] blockNum : Number of the block to read (16 bits)
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerM24LRFastReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Write Single Block (M24LR)
*
* Writes a Single Block from a M24LR tag which has the number of blocks
* bigger than 256 (M24LR16 ; M24LR64)
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be written
* if not provided Select mode will be used
* \param[in] blockNum : Number of the block to write (16 bits)
* \param[in] wrData : data to be written on the given block
* \param[in] blockLen : number of bytes of a block
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerM24LRWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, const uint8_t* wrData, uint8_t blockLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Read Multiple Blocks (M24LR)
*
* Reads Multiple Blocks from a device from a M24LR tag which has the number of blocks
* bigger than 256 (M24LR16 ; M24LR64)
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] firstBlockNum : first block to be read (16 bits)
* \param[in] numOfBlocks : number of block to read
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerM24LRReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Read Multiple Blocks (M24LR)
*
* Reads Multiple Blocks from a device from a M24LR tag which has the number of blocks
* bigger than 256 (M24LR16 ; M24LR64) using ST Fast mode
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] firstBlockNum : first block to be read (16 bits)
* \param[in] numOfBlocks : number of block to read
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerM24LRFastReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Read Single Block
*
* Reads a Single Block from a device (VICC) using ST Fast mode
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] blockNum : Number of the block to read
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastReadSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Read Multiple Blocks
*
* Reads Multiple Blocks from a device (VICC) using ST Fast mode
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] firstBlockNum : first block to be read
* \param[in] numOfBlocks : number of block to read
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Extended Read Single Block
*
* Reads a Single Block from a device (VICC) supporting extended commands using ST Fast mode
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] blockNum : Number of the block to read (16 bits)
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastExtendedReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Extended Read Multiple Blocks
*
* Reads Multiple Blocks from a device (VICC) supporting extended commands using ST Fast mode
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] firstBlockNum : first block to be read (16 bits)
* \param[in] numOfBlocks : number of consecutive blocks to read (16 bits)
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastExtReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Read Configuration
*
* Reads static configuration registers at the Pointer address
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] pointer : Pointer address
* \param[out] regValue : Register value
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerReadConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue );
/*!
*****************************************************************************
* \brief NFC-V Poller Write Configuration
*
* Writes static configuration registers at the Pointer address
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] pointer : Pointer address
* \param[in] regValue : Register value
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerWriteConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue );
/*!
*****************************************************************************
* \brief NFC-V Poller Read Dynamic Configuration
*
* Reads dynamic registers at the Pointer address
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] pointer : Pointer address
* \param[out] regValue : Register value
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerReadDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue );
/*!
*****************************************************************************
* \brief NFC-V Poller Write Dynamic Configuration
*
* Writes dynamic registers at the Pointer address
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] pointer : Pointer address
* \param[in] regValue : Register value
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerWriteDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Read Dynamic Configuration
*
* Reads dynamic registers at the Pointer address using ST Fast mode
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] pointer : Pointer address
* \param[out] regValue : Register value
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastReadDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Write Dynamic Configuration
*
* Writes dynamic registers at the Pointer address using ST Fast mode
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] pointer : Pointer address
* \param[in] regValue : Register value
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastWriteDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue );
/*!
*****************************************************************************
* \brief NFC-V Poller Present Password
*
* Sends the Present Password command
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] pwdNum : Password number
* \param[in] pwd : Password
* \param[in] pwdLen : Password length
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerPresentPassword( uint8_t flags, const uint8_t* uid, uint8_t pwdNum, const uint8_t* pwd, uint8_t pwdLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Get Random Number
*
* Returns a 16 bit random number
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerGetRandomNumber( uint8_t flags, const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Read Message length
*
* Sends a Read Message Length message to retrieve the value of MB_LEN_Dyn
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[out] msgLen : Message Length
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerReadMessageLength( uint8_t flags, const uint8_t* uid, uint8_t* msgLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Read Message length
*
* Sends a Fast Read Message Length message to retrieve the value of MB_LEN_Dyn using ST Fast mode.
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[out] msgLen : Message Length
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastReadMsgLength( uint8_t flags, const uint8_t* uid, uint8_t* msgLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Read Message
*
* Reads up to 256 bytes in the Mailbox from the location
* specified by MBpointer and sends back their value in the rxBuf response.
* First MailBox location is '00'. When Number of bytes is set to 00h
* and MBPointer is equals to 00h, the MB_LEN bytes of the full message
* are returned. Otherwise, Read Message command returns (Number of Bytes + 1) bytes
* (i.e. 01h returns 2 bytes, FFh returns 256 bytes).
* An error is reported if (Pointer + Nb of bytes + 1) is greater than the message length.
* RF Reading of the last byte of the mailbox message automatically clears b1
* of MB_CTRL_Dyn HOST_PUT_MSG, and allows RF to put a new message.
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] mbPointer : MPpointer
* \param[in] numBytes : number of bytes
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerReadMessage( uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Read Message
*
* Reads up to 256 bytes in the Mailbox from the location
* specified by MBpointer and sends back their value in the rxBuf response using ST Fast mode.
* First MailBox location is '00'. When Number of bytes is set to 00h
* and MBPointer is equals to 00h, the MB_LEN bytes of the full message
* are returned. Otherwise, Read Message command returns (Number of Bytes + 1) bytes
* (i.e. 01h returns 2 bytes, FFh returns 256 bytes).
* An error is reported if (Pointer + Nb of bytes + 1) is greater than the message length.
* RF Reading of the last byte of the mailbox message automatically clears b1
* of MB_CTRL_Dyn HOST_PUT_MSG, and allows RF to put a new message.
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] mbPointer : MPpointer
* \param[in] numBytes : number of bytes
* \param[out] rxBuf : buffer to store response (also with RES_FLAGS)
* \param[in] rxBufLen : length of rxBuf
* \param[out] rcvLen : number of bytes received
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastReadMessage( uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Write Message
*
* Sends Write message Command
*
* On receiving the Write Message command, the ST25DVxxx puts the data contained
* in the request into the Mailbox buffer, update the MB_LEN_Dyn register, and
* set bit RF_PUT_MSG in MB_CTRL_Dyn register. It then reports if the write operation was successful
* in the response. The ST25DVxxx Mailbox contains up to 256 data bytes which are filled from the
* first location '00'. MSGlength parameter of the command is the number of
* Data bytes minus 1 (00 for 1 byte of data, FFh for 256 bytes of data).
* Write Message could be executed only when Mailbox is accessible by RF.
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] msgLen : MSGLen number of Data bytes minus 1
* \param[in] msgData : Message Data
* \param[out] txBuf : buffer to used to build the Write Message command
* \param[in] txBufLen : length of txBuf
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerWriteMessage( uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen );
/*!
*****************************************************************************
* \brief NFC-V Poller Fast Write Message
*
* Sends Fast Write message Command using ST Fast mode
*
* On receiving the Write Message command, the ST25DVxxx puts the data contained
* in the request into the Mailbox buffer, update the MB_LEN_Dyn register, and
* set bit RF_PUT_MSG in MB_CTRL_Dyn register. It then reports if the write operation was successful
* in the response. The ST25DVxxx Mailbox contains up to 256 data bytes which are filled from the
* first location '00'. MSGlength parameter of the command is the number of
* Data bytes minus 1 (00 for 1 byte of data, FFh for 256 bytes of data).
* Write Message could be executed only when Mailbox is accessible by RF.
*
* \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option
* for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT
* \param[in] uid : UID of the device to be put to be read
* if not provided Select mode will be used
* \param[in] msgLen : MSGLen number of Data bytes minus 1
* \param[in] msgData : Message Data
* \param[out] txBuf : buffer to used to build the Write Message command
* \param[in] txBufLen : length of txBuf
*
* \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode
* \return ERR_PARAM : Invalid parameters
* \return ERR_IO : Generic internal error
* \return ERR_CRC : CRC error detected
* \return ERR_FRAMING : Framing error detected
* \return ERR_PROTO : Protocol error detected
* \return ERR_TIMEOUT : Timeout error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalST25xVPollerFastWriteMessage( uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen );
#endif /* RFAL_ST25xV_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,187 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_t1t.h
*
* \author Gustavo Patricio
*
* \brief Provides NFC-A T1T convenience methods and definitions
*
* This module provides an interface to perform as a NFC-A Reader/Writer
* to handle a Type 1 Tag T1T (Topaz)
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup T1T
* \brief RFAL T1T Module
* @{
*
*/
#ifndef RFAL_T1T_H
#define RFAL_T1T_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_T1T_UID_LEN 4 /*!< T1T UID length of cascade level 1 only tag */
#define RFAL_T1T_HR_LENGTH 2 /*!< T1T HR(Header ROM) length */
#define RFAL_T1T_HR0_NDEF_MASK 0xF0 /*!< T1T HR0 NDEF capability mask T1T 1.2 2.2.2 */
#define RFAL_T1T_HR0_NDEF_SUPPORT 0x10 /*!< T1T HR0 NDEF capable value T1T 1.2 2.2.2 */
/*! NFC-A T1T (Topaz) command set */
typedef enum
{
RFAL_T1T_CMD_RID = 0x78, /*!< T1T Read UID */
RFAL_T1T_CMD_RALL = 0x00, /*!< T1T Read All */
RFAL_T1T_CMD_READ = 0x01, /*!< T1T Read */
RFAL_T1T_CMD_WRITE_E = 0x53, /*!< T1T Write with erase (single byte) */
RFAL_T1T_CMD_WRITE_NE = 0x1A /*!< T1T Write with no erase (single byte) */
} rfalT1Tcmds;
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! NFC-A T1T (Topaz) RID_RES Digital 1.1 10.6.2 & Table 50 */
typedef struct
{
uint8_t hr0; /*!< T1T Header ROM: HR0 */
uint8_t hr1; /*!< T1T Header ROM: HR1 */
uint8_t uid[RFAL_T1T_UID_LEN]; /*!< T1T UID */
} rfalT1TRidRes;
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialize NFC-A T1T Poller mode
*
* This methods configures RFAL RF layer to perform as a
* NFC-A T1T Poller/RW (Topaz) including all default timings
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT1TPollerInitialize( void );
/*!
*****************************************************************************
* \brief NFC-A T1T Poller RID
*
* This method reads the UID of a NFC-A T1T Listener device
*
*
* \param[out] ridRes : pointer to place the RID_RES
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT1TPollerRid( rfalT1TRidRes *ridRes );
/*!
*****************************************************************************
* \brief NFC-A T1T Poller RALL
*
* This method send a Read All command to a NFC-A T1T Listener device
*
*
* \param[in] uid : the UID of the device to read data
* \param[out] rxBuf : pointer to place the read data
* \param[in] rxBufLen : size of rxBuf
* \param[out] rxRcvdLen : actual received data
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT1TPollerRall( const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rxRcvdLen );
/*!
*****************************************************************************
* \brief NFC-A T1T Poller Write
*
* This method writes the given data on the address of a NFC-A T1T Listener device
*
*
* \param[in] uid : the UID of the device to read data
* \param[in] address : address to write the data
* \param[in] data : the data to be written
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT1TPollerWrite( const uint8_t* uid, uint8_t address, uint8_t data );
#endif /* RFAL_T1T_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,153 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_t2t.h
*
* \author Gustavo Patricio
*
* \brief Provides NFC-A T2T convenience methods and definitions
*
* This module provides an interface to perform as a NFC-A Reader/Writer
* to handle a Type 2 Tag T2T
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup T2T
* \brief RFAL T2T Module
* @{
*
*/
#ifndef RFAL_T2T_H
#define RFAL_T2T_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_T2T_BLOCK_LEN 4U /*!< T2T block length */
#define RFAL_T2T_READ_DATA_LEN (4U * RFAL_T2T_BLOCK_LEN) /*!< T2T READ data length */
#define RFAL_T2T_WRITE_DATA_LEN RFAL_T2T_BLOCK_LEN /*!< T2T WRITE data length */
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief NFC-A T2T Poller Read
*
* This method sends a Read command to a NFC-A T2T Listener device
*
*
* \param[in] blockNum : Number of the block to read
* \param[out] rxBuf : pointer to place the read data
* \param[in] rxBufLen : size of rxBuf (RFAL_T2T_READ_DATA_LEN)
* \param[out] rcvLen : actual received data
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT2TPollerRead( uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
/*!
*****************************************************************************
* \brief NFC-A T2T Poller Write
*
* This method sends a Write command to a NFC-A T2T Listener device
*
*
* \param[in] blockNum : Number of the block to write
* \param[in] wrData : data to be written on the given block
* size must be of RFAL_T2T_WRITE_DATA_LEN
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT2TPollerWrite( uint8_t blockNum, const uint8_t* wrData );
/*!
*****************************************************************************
* \brief NFC-A T2T Poller Sector Select
*
* This method sends a Sector Select commands to a NFC-A T2T Listener device
*
* \param[in] sectorNum : Sector Number
*
* \return ERR_WRONG_STATE : RFAL not initialized or mode not set
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT2TPollerSectorSelect( uint8_t sectorNum );
#endif /* RFAL_T2T_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,365 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_t4t.h
*
* \author Gustavo Patricio
*
* \brief Provides convenience methods and definitions for T4T (ISO7816-4)
*
* This module provides an interface to exchange T4T APDUs according to
* NFC Forum T4T and ISO7816-4
*
* This implementation was based on the following specs:
* - ISO/IEC 7816-4 3rd Edition 2013-04-15
* - NFC Forum T4T Technical Specification 1.0 2017-08-28
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-AL
* \brief RFAL Abstraction Layer
* @{
*
* \addtogroup T4T
* \brief RFAL T4T Module
* @{
*
*/
#ifndef RFAL_T4T_H
#define RFAL_T4T_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "rfal_rf.h"
#include "rfal_isoDep.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_T4T_MAX_CAPDU_PROLOGUE_LEN 4U /*!< Command-APDU prologue length (CLA INS P1 P2) */
#define RFAL_T4T_LE_LEN 1U /*!< Le Expected Response Length (short field coding) */
#define RFAL_T4T_LC_LEN 1U /*!< Lc Data field length (short field coding) */
#define RFAL_T4T_MAX_RAPDU_SW1SW2_LEN 2U /*!< SW1 SW2 length */
#define RFAL_T4T_CLA 0x00U /*!< Class byte (contains 00h because secure message are not used) */
#define RFAL_T4T_ISO7816_P1_SELECT_BY_DF_NAME 0x04U /*!< P1 value for Select by name */
#define RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID 0x00U /*!< P1 value for Select by file identifier */
#define RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE 0x00U /*!< b2b1 P2 value for First or only occurence */
#define RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE 0x00U /*!< b4b3 P2 value for Return FCI template */
#define RFAL_T4T_ISO7816_P2_SELECT_NO_RESPONSE_DATA 0x0CU /*!< b4b3 P2 value for No responce data */
#define RFAL_T4T_ISO7816_STATUS_COMPLETE 0x9000U /*!< Command completed \ Normal processing - No further qualification*/
/*
******************************************************************************
* GLOBAL VARIABLES
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! NFC-A T4T Command-APDU structure */
typedef struct
{
uint8_t CLA; /*!< Class byte */
uint8_t INS; /*!< Instruction byte */
uint8_t P1; /*!< Parameter byte 1 */
uint8_t P2; /*!< Parameter byte 2 */
uint8_t Lc; /*!< Data field length */
bool LcFlag; /*!< Lc flag (append Lc when true) */
uint8_t Le; /*!< Expected Response Length */
bool LeFlag; /*!< Le flag (append Le when true) */
rfalIsoDepApduBufFormat *cApduBuf; /*!< Command-APDU buffer (Tx) */
uint16_t *cApduLen; /*!< Command-APDU Length */
}rfalT4tCApduParam;
/*! NFC-A T4T Response-APDU structure */
typedef struct
{
rfalIsoDepApduBufFormat *rApduBuf; /*!< Response-APDU buffer (Rx) */
uint16_t rcvdLen; /*!< Full response length */
uint16_t rApduBodyLen; /*!< Response body length */
uint16_t statusWord; /*!< R-APDU Status Word SW1|SW2 */
}rfalT4tRApduParam;
/*! NFC-A T4T command set T4T 1.0 & ISO7816-4 2013 Table 4 */
typedef enum
{
RFAL_T4T_INS_SELECT = 0xA4U, /*!< T4T Select */
RFAL_T4T_INS_READBINARY = 0xB0U, /*!< T4T ReadBinary */
RFAL_T4T_INS_UPDATEBINARY = 0xD6U, /*!< T4T UpdateBinay */
RFAL_T4T_INS_READBINARY_ODO = 0xB1U, /*!< T4T ReadBinary using ODO */
RFAL_T4T_INS_UPDATEBINARY_ODO = 0xD7U /*!< T4T UpdateBinay using ODO */
} rfalT4tCmds;
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief T4T Compose APDU
*
* This method computes a C-APDU according to NFC Forum T4T and ISO7816-4.
*
* If C-APDU contains data to be sent, it must be placed inside the buffer
* rfalT4tTxRxApduParam.txRx.cApduBuf.apdu and signaled by Lc
*
* To transceive the formed APDU the ISO-DEP layer shall be used
*
* \see rfalIsoDepStartApduTransceive()
* \see rfalIsoDepGetApduTransceiveStatus()
* \see rfalT4TPollerParseRAPDU()
*
* \warning The ISO-DEP module is used to perform the tranceive. Usually
* activation has been done via ISO-DEP activatiavtion. If not
* please call rfalIsoDepInitialize() before.
*
* \param[in,out] apduParam : APDU parameters
* apduParam.cApduLen will contain the APDU length
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerComposeCAPDU( const rfalT4tCApduParam *apduParam );
/*!
*****************************************************************************
* \brief T4T Parse R-APDU
*
* This method parses a R-APDU according to NFC Forum T4T and ISO7816-4.
* It will extract the data length and check if the Satus word is expected.
*
* \param[in,out] apduParam : APDU parameters
* apduParam.rApduBodyLen will contain the data length
* apduParam.statusWord will contain the SW1 and SW2
*
* \return ERR_REQUEST : Status word (SW1 SW2) different from 9000
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerParseRAPDU( rfalT4tRApduParam *apduParam );
/*!
*****************************************************************************
* \brief T4T Compose Select Application APDU
*
* This method computes a Select Application APDU according to NFC Forum T4T
*
* To transceive the formed APDU the ISO-DEP layer shall be used
*
* \see rfalIsoDepStartApduTransceive()
* \see rfalIsoDepGetApduTransceiveStatus()
*
* \param[out] cApduBuf : buffer where the C-APDU will be placed
* \param[in] aid : Application ID to be used
* \param[in] aidLen : Application ID length
* \param[out] cApduLen : Composed C-APDU length
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerComposeSelectAppl( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* aid, uint8_t aidLen, uint16_t *cApduLen );
/*!
*****************************************************************************
* \brief T4T Compose Select File APDU
*
* This method computes a Select File APDU according to NFC Forum T4T
*
* To transceive the formed APDU the ISO-DEP layer shall be used
*
* \see rfalIsoDepStartApduTransceive()
* \see rfalIsoDepGetApduTransceiveStatus()
*
* \param[out] cApduBuf : buffer where the C-APDU will be placed
* \param[in] fid : File ID to be used
* \param[in] fidLen : File ID length
* \param[out] cApduLen : Composed C-APDU length
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerComposeSelectFile( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* fid, uint8_t fidLen, uint16_t *cApduLen );
/*!
*****************************************************************************
* \brief T4T Compose Select File APDU for Mapping Version 1
*
* This method computes a Select File APDU according to NFC Forum T4TOP_v1.0
*
* To transceive the formed APDU the ISO-DEP layer shall be used
*
* \see rfalIsoDepStartApduTransceive()
* \see rfalIsoDepGetApduTransceiveStatus()
*
* \param[out] cApduBuf : buffer where the C-APDU will be placed
* \param[in] fid : File ID to be used
* \param[in] fidLen : File ID length
* \param[out] cApduLen : Composed C-APDU length
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerComposeSelectFileV1Mapping( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* fid, uint8_t fidLen, uint16_t *cApduLen );
/*!
*****************************************************************************
* \brief T4T Compose Read Data APDU
*
* This method computes a Read Data APDU according to NFC Forum T4T
*
* To transceive the formed APDU the ISO-DEP layer shall be used
*
* \see rfalIsoDepStartApduTransceive()
* \see rfalIsoDepGetApduTransceiveStatus()
*
* \param[out] cApduBuf : buffer where the C-APDU will be placed
* \param[in] offset : File offset
* \param[in] expLen : Expected length (Le)
* \param[out] cApduLen : Composed C-APDU length
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerComposeReadData( rfalIsoDepApduBufFormat *cApduBuf, uint16_t offset, uint8_t expLen, uint16_t *cApduLen );
/*!
*****************************************************************************
* \brief T4T Compose Read Data ODO APDU
*
* This method computes a Read Data ODO APDU according to NFC Forum T4T
*
* To transceive the formed APDU the ISO-DEP layer shall be used
*
* \see rfalIsoDepStartApduTransceive()
* \see rfalIsoDepGetApduTransceiveStatus()
*
* \param[out] cApduBuf : buffer where the C-APDU will be placed
* \param[in] offset : File offset
* \param[in] expLen : Expected length (Le)
* \param[out] cApduLen : Composed C-APDU length
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerComposeReadDataODO( rfalIsoDepApduBufFormat *cApduBuf, uint32_t offset, uint8_t expLen, uint16_t *cApduLen );
/*!
*****************************************************************************
* \brief T4T Compose Write Data APDU
*
* This method computes a Write Data APDU according to NFC Forum T4T
*
* To transceive the formed APDU the ISO-DEP layer shall be used
*
* \see rfalIsoDepStartApduTransceive()
* \see rfalIsoDepGetApduTransceiveStatus()
*
* \param[out] cApduBuf : buffer where the C-APDU will be placed
* \param[in] offset : File offset
* \param[in] data : Data to be written
* \param[in] dataLen : Data length to be written (Lc)
* \param[out] cApduLen : Composed C-APDU length
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerComposeWriteData( rfalIsoDepApduBufFormat *cApduBuf, uint16_t offset, const uint8_t* data, uint8_t dataLen, uint16_t *cApduLen );
/*!
*****************************************************************************
* \brief T4T Compose Write Data ODO APDU
*
* This method computes a Write Data ODO sAPDU according to NFC Forum T4T
*
* To transceive the formed APDU the ISO-DEP layer shall be used
*
* \see rfalIsoDepStartApduTransceive()
* \see rfalIsoDepGetApduTransceiveStatus()
*
* \param[out] cApduBuf : buffer where the C-APDU will be placed
* \param[in] offset : File offset
* \param[in] data : Data to be written
* \param[in] dataLen : Data length to be written (Lc)
* \param[out] cApduLen : Composed C-APDU length
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_PROTO : Protocol error
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode rfalT4TPollerComposeWriteDataODO( rfalIsoDepApduBufFormat *cApduBuf, uint32_t offset, const uint8_t* data, uint8_t dataLen, uint16_t *cApduLen );
#endif /* RFAL_T4T_H */
/**
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,49 @@
#include "platform.h"
#include <assert.h>
HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) {
HAL_StatusTypeDef ret;
if (txBuf && rxBuf) {
ret = HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)txBuf, rxBuf, len, HAL_MAX_DELAY);
} else if (txBuf) {
ret = HAL_SPI_Transmit(&hspi3, (uint8_t*)txBuf, len, HAL_MAX_DELAY);
} else if (rxBuf) {
ret = HAL_SPI_Receive(&hspi3, (uint8_t*)rxBuf, len, HAL_MAX_DELAY);
}
if(ret != HAL_OK) {
exit(250);
}
return ret;
}
void platformProtectST25RComm()
{
if (HAL_SPI_DeInit(&hspi3) != HAL_OK) {
Error_Handler();
}
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi3) != HAL_OK) {
Error_Handler();
}
}
void platformUnprotectST25RComm()
{
}

142
lib/ST25RFAL002/platform.h Normal file
View file

@ -0,0 +1,142 @@
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include <cmsis_os2.h>
#include "stm32l4xx_hal.h"
#include "timer.h"
#include "math.h"
#include "spi.h"
#include "main.h"
HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len);
void platformProtectST25RComm();
void platformUnprotectST25RComm();
#define ST25R_SS_PIN NFC_CS_Pin
#define ST25R_SS_PORT NFC_CS_GPIO_Port
#define ST25R_INT_PIN RFID_PULL_Pin
#define ST25R_INT_PORT RFID_PULL_GPIO_Port
#define RFAL_FEATURE_LISTEN_MODE true /*!< Enable/Disable RFAL support for Listen Mode */
#define RFAL_FEATURE_WAKEUP_MODE true /*!< Enable/Disable RFAL support for the Wake-Up mode */
#define RFAL_FEATURE_LOWPOWER_MODE true /*!< Enable/Disable RFAL support for the Low Power mode */
#define RFAL_FEATURE_NFCA true /*!< Enable/Disable RFAL support for NFC-A (ISO14443A) */
#define RFAL_FEATURE_NFCB true /*!< Enable/Disable RFAL support for NFC-B (ISO14443B) */
#define RFAL_FEATURE_NFCF true /*!< Enable/Disable RFAL support for NFC-F (FeliCa) */
#define RFAL_FEATURE_NFCV true /*!< Enable/Disable RFAL support for NFC-V (ISO15693) */
#define RFAL_FEATURE_T1T true /*!< Enable/Disable RFAL support for T1T (Topaz) */
#define RFAL_FEATURE_T2T true /*!< Enable/Disable RFAL support for T2T (MIFARE Ultralight) */
#define RFAL_FEATURE_T4T true /*!< Enable/Disable RFAL support for T4T */
#define RFAL_FEATURE_ST25TB true /*!< Enable/Disable RFAL support for ST25TB */
#define RFAL_FEATURE_ST25xV true /*!< Enable/Disable RFAL support for ST25TV/ST25DV */
#define RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG false /*!< Enable/Disable Analog Configs to be dynamically updated (RAM) */
#define RFAL_FEATURE_DPO false /*!< Enable/Disable RFAL Dynamic Power Output upport */
#define RFAL_FEATURE_ISO_DEP true /*!< Enable/Disable RFAL support for ISO-DEP (ISO14443-4) */
#define RFAL_FEATURE_ISO_DEP_POLL true /*!< Enable/Disable RFAL support for Poller mode (PCD) ISO-DEP (ISO14443-4) */
#define RFAL_FEATURE_ISO_DEP_LISTEN true /*!< Enable/Disable RFAL support for Listen mode (PICC) ISO-DEP (ISO14443-4) */
#define RFAL_FEATURE_NFC_DEP true /*!< Enable/Disable RFAL support for NFC-DEP (NFCIP1/P2P) */
#define RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN 256U /*!< ISO-DEP I-Block max length. Please use values as defined by rfalIsoDepFSx */
#define RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN 254U /*!< NFC-DEP Block/Payload length. Allowed values: 64, 128, 192, 254 */
#define RFAL_FEATURE_NFC_RF_BUF_LEN 256U /*!< RF buffer length used by RFAL NFC layer */
#define RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN 512U /*!< ISO-DEP APDU max length. */
#define RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN 512U /*!< NFC-DEP PDU max length. */
#define platformProtectST25RIrqStatus() platformProtectST25RComm() /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */
#define platformUnprotectST25RIrqStatus() platformUnprotectST25RComm() /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */
#define platformGpioSet( port, pin ) HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET) /*!< Turns the given GPIO High */
#define platformGpioClear( port, pin ) HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET) /*!< Turns the given GPIO Low */
#define platformGpioToogle( port, pin ) HAL_GPIO_TogglePin(port, pin) /*!< Toogles the given GPIO */
#define platformGpioIsHigh( port, pin ) (HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET) /*!< Checks if the given LED is High */
#define platformGpioIsLow( port, pin ) (!platformGpioIsHigh(port, pin)) /*!< Checks if the given LED is Low */
#define platformTimerCreate( t ) timerCalculateTimer(t) /*!< Create a timer with the given time (ms) */
#define platformTimerIsExpired( timer ) timerIsExpired(timer) /*!< Checks if the given timer is expired */
#define platformDelay( t ) osDelay( t ) /*!< Performs a delay for the given time (ms) */
#define platformGetSysTick() osKernelGetTickCount() /*!< Get System Tick (1 tick = 1 ms) */
#define platformAssert( exp ) assert_param( exp ) /*!< Asserts whether the given expression is true*/
#define platformErrorHandle() Error_Handler() /*!< Global error handle\trap */
#define platformSpiSelect() platformGpioClear( ST25R_SS_PORT, ST25R_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Select */
#define platformSpiDeselect() platformGpioSet( ST25R_SS_PORT, ST25R_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Deselect */
#define platformI2CTx( txBuf, len, last, txOnly ) /*!< I2C Transmit */
#define platformI2CRx( txBuf, len ) /*!< I2C Receive */
#define platformI2CStart() /*!< I2C Start condition */
#define platformI2CStop() /*!< I2C Stop condition */
#define platformI2CRepeatStart() /*!< I2C Repeat Start */
#define platformI2CSlaveAddrWR(add) /*!< I2C Slave address for Write operation */
#define platformI2CSlaveAddrRD(add) /*!< I2C Slave address for Read operation */
#define platformLog(...) /*!< Log method */
/*
******************************************************************************
* RFAL OPTIONAL MACROS (Do not change)
******************************************************************************
*/
#ifndef platformProtectST25RIrqStatus
#define platformProtectST25RIrqStatus() /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */
#endif /* platformProtectST25RIrqStatus */
#ifndef platformUnprotectST25RIrqStatus
#define platformUnprotectST25RIrqStatus() /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */
#endif /* platformUnprotectST25RIrqStatus */
#ifndef platformProtectWorker
#define platformProtectWorker() /* Protect RFAL Worker/Task/Process from concurrent execution on multi thread platforms */
#endif /* platformProtectWorker */
#ifndef platformUnprotectWorker
#define platformUnprotectWorker() /* Unprotect RFAL Worker/Task/Process from concurrent execution on multi thread platforms */
#endif /* platformUnprotectWorker */
#ifndef platformIrqST25RPinInitialize
#define platformIrqST25RPinInitialize() /*!< Initializes ST25R IRQ pin */
#endif /* platformIrqST25RPinInitialize */
#ifndef platformIrqST25RSetCallback
#define platformIrqST25RSetCallback( cb ) /*!< Sets ST25R ISR callback */
#endif /* platformIrqST25RSetCallback */
#ifndef platformLedsInitialize
#define platformLedsInitialize() /*!< Initializes the pins used as LEDs to outputs */
#endif /* platformLedsInitialize */
#ifndef platformLedOff
#define platformLedOff( port, pin ) /*!< Turns the given LED Off */
#endif /* platformLedOff */
#ifndef platformLedOn
#define platformLedOn( port, pin ) /*!< Turns the given LED On */
#endif /* platformLedOn */
#ifndef platformLedToogle
#define platformLedToogle( port, pin ) /*!< Toggles the given LED */
#endif /* platformLedToogle */
#ifndef platformGetSysTick
#define platformGetSysTick() /*!< Get System Tick (1 tick = 1 ms) */
#endif /* platformGetSysTick */
#ifndef platformTimerDestroy
#define platformTimerDestroy( timer ) /*!< Stops and released the given timer */
#endif /* platformTimerDestroy */
#ifndef platformAssert
#define platformAssert( exp ) /*!< Asserts whether the given expression is true */
#endif /* platformAssert */
#ifndef platformErrorHandle
#define platformErrorHandle() /*!< Global error handler or trap */
#endif /* platformErrorHandle */

View file

@ -0,0 +1,479 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_analogConfig.c
*
* \author bkam
*
* \brief Funcitons to manage and set analog settings.
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_analogConfig.h"
#include "rfal_chip.h"
#include "st_errno.h"
#include "platform.h"
#include "utils.h"
/* Check whether the Default Analog settings are to be used or custom ones */
#ifdef RFAL_ANALOG_CONFIG_CUSTOM
extern const uint8_t* rfalAnalogConfigCustomSettings;
extern const uint16_t rfalAnalogConfigCustomSettingsLength;
#else
#include "rfal_analogConfigTbl.h"
#endif
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
#define RFAL_TEST_REG 0x0080U /*!< Test Register indicator */
/*
******************************************************************************
* MACROS
******************************************************************************
*/
/*
******************************************************************************
* LOCAL DATA TYPES
******************************************************************************
*/
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
static uint8_t gRfalAnalogConfig[RFAL_ANALOG_CONFIG_TBL_SIZE]; /*!< Analog Configuration Settings List */
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
/*! Struct for Analog Config Look Up Table Update */
typedef struct {
const uint8_t *currentAnalogConfigTbl; /*!< Reference to start of current Analog Configuration */
uint16_t configTblSize; /*!< Total size of Analog Configuration */
bool ready; /*!< Indicate if Look Up Table is complete and ready for use */
} rfalAnalogConfigMgmt;
static rfalAnalogConfigMgmt gRfalAnalogConfigMgmt; /*!< Analog Configuration LUT management */
/*
******************************************************************************
* LOCAL TABLES
******************************************************************************
*/
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static rfalAnalogConfigNum rfalAnalogConfigSearch( rfalAnalogConfigId configId, uint16_t *configOffset );
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
static void rfalAnalogConfigPtrUpdate( const uint8_t* analogConfigTbl );
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
/*
******************************************************************************
* GLOBAL VARIABLE DEFINITIONS
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
void rfalAnalogConfigInitialize( void )
{
/* Use default Analog configuration settings in Flash by default. */
/* Check whether the Default Analog settings are to be used or custom ones */
#ifdef RFAL_ANALOG_CONFIG_CUSTOM
gRfalAnalogConfigMgmt.currentAnalogConfigTbl = (const uint8_t *)&rfalAnalogConfigCustomSettings;
gRfalAnalogConfigMgmt.configTblSize = rfalAnalogConfigCustomSettingsLength;
#else
gRfalAnalogConfigMgmt.currentAnalogConfigTbl = (const uint8_t *)&rfalAnalogConfigDefaultSettings;
gRfalAnalogConfigMgmt.configTblSize = sizeof(rfalAnalogConfigDefaultSettings);
#endif
gRfalAnalogConfigMgmt.ready = true;
} /* rfalAnalogConfigInitialize() */
bool rfalAnalogConfigIsReady( void )
{
return gRfalAnalogConfigMgmt.ready;
}
ReturnCode rfalAnalogConfigListWriteRaw( const uint8_t *configTbl, uint16_t configTblSize )
{
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
/* Check if the Configuration Table exceed the Table size */
if ( configTblSize >= RFAL_ANALOG_CONFIG_TBL_SIZE )
{
rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */
return ERR_NOMEM;
}
/* Check for invalid parameters */
if( (configTbl == NULL) || (configTblSize == 0U) )
{
return ERR_PARAM;
}
/* NOTE: Function does not check for the validity of the Table contents (conf IDs, conf sets, register address) */
ST_MEMCPY( gRfalAnalogConfig, configTbl, configTblSize );
/* Update the total size of configuration settings */
gRfalAnalogConfigMgmt.configTblSize = configTblSize;
rfalAnalogConfigPtrUpdate(gRfalAnalogConfig);
return ERR_NONE;
#else
// If Analog Configuration Update is to be disabled
NO_WARNING(configTbl);
NO_WARNING(configTblSize);
return ERR_REQUEST;
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
}
ReturnCode rfalAnalogConfigListWrite( uint8_t more, const rfalAnalogConfig *config )
{
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
rfalAnalogConfigId configId;
rfalAnalogConfigNum numConfig;
uint8_t configSize;
if (true == gRfalAnalogConfigMgmt.ready)
{ /* First Update to the Configuration list. */
gRfalAnalogConfigMgmt.ready = false; // invalidate the config List
gRfalAnalogConfigMgmt.configTblSize = 0; // Clear the config List
}
configId = GETU16(config->id);
/* Check validity of the Configuration ID. */
if ( (RFAL_ANALOG_CONFIG_TECH_RFU <= RFAL_ANALOG_CONFIG_ID_GET_TECH(configId))
||((RFAL_ANALOG_CONFIG_BITRATE_6780 < RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId)) && (RFAL_ANALOG_CONFIG_BITRATE_1OF4 > RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId)))
||(RFAL_ANALOG_CONFIG_BITRATE_1OF256 < RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId))
)
{
rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */
return ERR_PARAM;
}
numConfig = config->num;
configSize = (uint8_t)(sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + (numConfig * sizeof(rfalAnalogConfigRegAddrMaskVal)));
/* Check if the Configuration Set exceed the Table size. */
if ( RFAL_ANALOG_CONFIG_TBL_SIZE <= (gRfalAnalogConfigMgmt.configTblSize + configSize) )
{
rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */
return ERR_NOMEM;
}
/* NOTE: Function does not check for the validity of the Register Address. */
ST_MEMCPY(&gRfalAnalogConfig[gRfalAnalogConfigMgmt.configTblSize], (const uint8_t*)config, configSize);
/* Increment the total size of configuration settings. */
gRfalAnalogConfigMgmt.configTblSize += configSize;
/* Check if it is the last Analog Configuration to load. */
if (RFAL_ANALOG_CONFIG_UPDATE_LAST == more)
{ /* Update the Analog Configuration to the new settings. */
rfalAnalogConfigPtrUpdate(gRfalAnalogConfig);
}
return ERR_NONE;
#else
// If Analog Configuration Update is to be disabled
NO_WARNING(config);
NO_WARNING(more);
return ERR_DISABLED;
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
} /* rfalAnalogConfigListUpdate() */
ReturnCode rfalAnalogConfigListReadRaw( uint8_t *tblBuf, uint16_t tblBufLen, uint16_t *configTblSize )
{
/* Check if the the current table will fit into the given buffer */
if( tblBufLen < gRfalAnalogConfigMgmt.configTblSize )
{
return ERR_NOMEM;
}
/* Check for invalid parameters */
if( configTblSize == NULL )
{
return ERR_PARAM;
}
/* Copy the whole Table to the given buffer */
if( gRfalAnalogConfigMgmt.configTblSize > 0U ) /* MISRA 21.18 */
{
ST_MEMCPY( tblBuf, gRfalAnalogConfigMgmt.currentAnalogConfigTbl, gRfalAnalogConfigMgmt.configTblSize );
}
*configTblSize = gRfalAnalogConfigMgmt.configTblSize;
return ERR_NONE;
}
ReturnCode rfalAnalogConfigListRead( rfalAnalogConfigOffset *configOffset, uint8_t *more, rfalAnalogConfig *config, rfalAnalogConfigNum numConfig )
{
uint16_t configSize;
rfalAnalogConfigOffset offset = *configOffset;
rfalAnalogConfigNum numConfigSet;
/* Check if the number of register-mask-value settings for the respective Configuration ID will fit into the buffer passed in. */
if (gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset + sizeof(rfalAnalogConfigId)] > numConfig)
{
return ERR_NOMEM;
}
/* Get the number of Configuration set */
numConfigSet = gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset + sizeof(rfalAnalogConfigId)];
/* Pass Configuration Register-Mask-Value sets */
configSize = (sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + (uint16_t)(numConfigSet * sizeof(rfalAnalogConfigRegAddrMaskVal)));
ST_MEMCPY( (uint8_t*) config
, &gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset]
, configSize
);
*configOffset = offset + configSize;
/* Check if it is the last Analog Configuration in the Table.*/
*more = (uint8_t)((*configOffset >= gRfalAnalogConfigMgmt.configTblSize) ? RFAL_ANALOG_CONFIG_UPDATE_LAST
: RFAL_ANALOG_CONFIG_UPDATE_MORE);
return ERR_NONE;
} /* rfalAnalogConfigListRead() */
ReturnCode rfalSetAnalogConfig( rfalAnalogConfigId configId )
{
rfalAnalogConfigOffset configOffset = 0;
rfalAnalogConfigNum numConfigSet;
const rfalAnalogConfigRegAddrMaskVal *configTbl;
ReturnCode retCode = ERR_NONE;
rfalAnalogConfigNum i;
if (true != gRfalAnalogConfigMgmt.ready)
{
return ERR_REQUEST;
}
/* Search LUT for the specific Configuration ID. */
while(true)
{
numConfigSet = rfalAnalogConfigSearch(configId, &configOffset);
if( RFAL_ANALOG_CONFIG_LUT_NOT_FOUND == numConfigSet )
{
break;
}
configTbl = (rfalAnalogConfigRegAddrMaskVal *)( (uint32_t)gRfalAnalogConfigMgmt.currentAnalogConfigTbl + (uint32_t)configOffset);
/* Increment the offset to the next index to search from. */
configOffset += (uint16_t)(numConfigSet * sizeof(rfalAnalogConfigRegAddrMaskVal));
if ((gRfalAnalogConfigMgmt.configTblSize + 1U) < configOffset)
{ /* Error check make sure that the we do not access outside the configuration Table Size */
return ERR_NOMEM;
}
for ( i = 0; i < numConfigSet; i++)
{
if( (GETU16(configTbl[i].addr) & RFAL_TEST_REG) != 0U )
{
EXIT_ON_ERR(retCode, rfalChipChangeTestRegBits( (GETU16(configTbl[i].addr) & ~RFAL_TEST_REG), configTbl[i].mask, configTbl[i].val) );
}
else
{
EXIT_ON_ERR(retCode, rfalChipChangeRegBits( GETU16(configTbl[i].addr), configTbl[i].mask, configTbl[i].val) );
}
}
} /* while(found Analog Config Id) */
return retCode;
} /* rfalSetAnalogConfig() */
uint16_t rfalAnalogConfigGenModeID( rfalMode md, rfalBitRate br, uint16_t dir )
{
uint16_t id;
/* Assign Poll/Listen Mode */
id = ((md >= RFAL_MODE_LISTEN_NFCA) ? RFAL_ANALOG_CONFIG_LISTEN : RFAL_ANALOG_CONFIG_POLL);
/* Assign Technology */
switch( md )
{
case RFAL_MODE_POLL_NFCA:
case RFAL_MODE_POLL_NFCA_T1T:
case RFAL_MODE_LISTEN_NFCA:
id |= RFAL_ANALOG_CONFIG_TECH_NFCA;
break;
case RFAL_MODE_POLL_NFCB:
case RFAL_MODE_POLL_B_PRIME:
case RFAL_MODE_POLL_B_CTS:
case RFAL_MODE_LISTEN_NFCB:
id |= RFAL_ANALOG_CONFIG_TECH_NFCB;
break;
case RFAL_MODE_POLL_NFCF:
case RFAL_MODE_LISTEN_NFCF:
id |= RFAL_ANALOG_CONFIG_TECH_NFCF;
break;
case RFAL_MODE_POLL_NFCV:
case RFAL_MODE_POLL_PICOPASS:
id |= RFAL_ANALOG_CONFIG_TECH_NFCV;
break;
case RFAL_MODE_POLL_ACTIVE_P2P:
case RFAL_MODE_LISTEN_ACTIVE_P2P:
id |= RFAL_ANALOG_CONFIG_TECH_AP2P;
break;
default:
id = RFAL_ANALOG_CONFIG_TECH_CHIP;
break;
}
/* Assign Bitrate */
id |= (((((uint16_t)(br) >= (uint16_t)RFAL_BR_52p97) ? (uint16_t)(br) : ((uint16_t)(br)+1U)) << RFAL_ANALOG_CONFIG_BITRATE_SHIFT) & RFAL_ANALOG_CONFIG_BITRATE_MASK);
/* Assign Direction */
id |= ((dir<<RFAL_ANALOG_CONFIG_DIRECTION_SHIFT) & RFAL_ANALOG_CONFIG_DIRECTION_MASK);
return id;
} /* rfalAnalogConfigGenModeID() */
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Update the link to Analog Configuration LUT
*
* Update the link to the Analog Configuration LUT for the subsequent search
* of Analog Settings.
*
* \param[in] analogConfigTbl: reference to the start of the new Analog Configuration Table
*
*****************************************************************************
*/
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
static void rfalAnalogConfigPtrUpdate( const uint8_t* analogConfigTbl )
{
gRfalAnalogConfigMgmt.currentAnalogConfigTbl = analogConfigTbl;
gRfalAnalogConfigMgmt.ready = true;
} /* rfalAnalogConfigPtrUpdate() */
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
/*!
*****************************************************************************
* \brief Search the Analog Configuration LUT for a specific Configuration ID.
*
* Search the Analog Configuration LUT for the Configuration ID.
*
* \param[in] configId: Configuration ID to search for.
* \param[in] configOffset: Configuration Offset in Table
*
* \return number of Configuration Sets
* \return #RFAL_ANALOG_CONFIG_LUT_NOT_FOUND in case Configuration ID is not found.
*****************************************************************************
*/
static rfalAnalogConfigNum rfalAnalogConfigSearch( rfalAnalogConfigId configId, uint16_t *configOffset )
{
rfalAnalogConfigId foundConfigId;
rfalAnalogConfigId configIdMaskVal;
const uint8_t *configTbl;
const uint8_t *currentConfigTbl;
uint16_t i;
currentConfigTbl = gRfalAnalogConfigMgmt.currentAnalogConfigTbl;
configIdMaskVal = ((RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK | RFAL_ANALOG_CONFIG_BITRATE_MASK)
|((RFAL_ANALOG_CONFIG_TECH_CHIP == RFAL_ANALOG_CONFIG_ID_GET_TECH(configId)) ? (RFAL_ANALOG_CONFIG_TECH_MASK | RFAL_ANALOG_CONFIG_CHIP_SPECIFIC_MASK) : configId)
|((RFAL_ANALOG_CONFIG_NO_DIRECTION == RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(configId)) ? RFAL_ANALOG_CONFIG_DIRECTION_MASK : configId)
);
/* When specific ConfigIDs are to be used, override search mask */
if( (RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(configId) == RFAL_ANALOG_CONFIG_DPO) )
{
configIdMaskVal = (RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK | RFAL_ANALOG_CONFIG_TECH_MASK | RFAL_ANALOG_CONFIG_BITRATE_MASK | RFAL_ANALOG_CONFIG_DIRECTION_MASK);
}
i = *configOffset;
while (i < gRfalAnalogConfigMgmt.configTblSize)
{
configTbl = &currentConfigTbl[i];
foundConfigId = GETU16(configTbl);
if (configId == (foundConfigId & configIdMaskVal))
{
*configOffset = (uint16_t)(i + sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum));
return configTbl[sizeof(rfalAnalogConfigId)];
}
/* If Config Id does not match, increment to next Configuration Id */
i += (uint16_t)( sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum)
+ (configTbl[sizeof(rfalAnalogConfigId)] * sizeof(rfalAnalogConfigRegAddrMaskVal) )
);
} /* for */
return RFAL_ANALOG_CONFIG_LUT_NOT_FOUND;
} /* rfalAnalogConfigSearch() */

View file

@ -0,0 +1,86 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_crc.c
*
* \author Oliver Regenfelder
*
* \brief CRC calculation implementation
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_crc.h"
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static uint16_t rfalCrcUpdateCcitt(uint16_t crcSeed, uint8_t dataByte);
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
uint16_t rfalCrcCalculateCcitt(uint16_t preloadValue, const uint8_t* buf, uint16_t length)
{
uint16_t crc = preloadValue;
uint16_t index;
for (index = 0; index < length; index++)
{
crc = rfalCrcUpdateCcitt(crc, buf[index]);
}
return crc;
}
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
static uint16_t rfalCrcUpdateCcitt(uint16_t crcSeed, uint8_t dataByte)
{
uint16_t crc = crcSeed;
uint8_t dat = dataByte;
dat ^= (uint8_t)(crc & 0xFFU);
dat ^= (dat << 4);
crc = (crc >> 8)^(((uint16_t) dat) << 8)^(((uint16_t) dat) << 3)^(((uint16_t) dat) >> 4);
return crc;
}

259
lib/ST25RFAL002/source/rfal_dpo.c Executable file
View file

@ -0,0 +1,259 @@
/******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* $Revision: $
* LANGUAGE: ISO C99
*/
/*! \file rfal_dpo.c
*
* \author Martin Zechleitner
*
* \brief Functions to manage and set dynamic power settings.
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_dpoTbl.h"
#include "rfal_dpo.h"
#include "platform.h"
#include "rfal_rf.h"
#include "rfal_chip.h"
#include "rfal_analogConfig.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_DPO
#define RFAL_FEATURE_DPO false /* Dynamic Power Module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_DPO
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
#define RFAL_DPO_ANALOGCONFIG_SHIFT 13U
#define RFAL_DPO_ANALOGCONFIG_MASK 0x6000U
/*
******************************************************************************
* LOCAL DATA TYPES
******************************************************************************
*/
static bool gRfalDpoIsEnabled = false;
static uint8_t* gRfalCurrentDpo;
static uint8_t gRfalDpoTableEntries;
static uint8_t gRfalDpo[RFAL_DPO_TABLE_SIZE_MAX];
static uint8_t gRfalDpoTableEntry;
static rfalDpoMeasureFunc gRfalDpoMeasureCallback = NULL;
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
void rfalDpoInitialize( void )
{
/* Use the default Dynamic Power values */
gRfalCurrentDpo = (uint8_t*) rfalDpoDefaultSettings;
gRfalDpoTableEntries = (sizeof(rfalDpoDefaultSettings) / RFAL_DPO_TABLE_PARAMETER);
ST_MEMCPY( gRfalDpo, gRfalCurrentDpo, sizeof(rfalDpoDefaultSettings) );
/* by default use amplitude measurement */
gRfalDpoMeasureCallback = rfalChipMeasureAmplitude;
/* by default DPO is disabled */
gRfalDpoIsEnabled = false;
gRfalDpoTableEntry = 0;
}
void rfalDpoSetMeasureCallback( rfalDpoMeasureFunc pMeasureFunc )
{
gRfalDpoMeasureCallback = pMeasureFunc;
}
/*******************************************************************************/
ReturnCode rfalDpoTableWrite( rfalDpoEntry* powerTbl, uint8_t powerTblEntries )
{
uint8_t entry = 0;
/* check if the table size parameter is too big */
if( (powerTblEntries * RFAL_DPO_TABLE_PARAMETER) > RFAL_DPO_TABLE_SIZE_MAX)
{
return ERR_NOMEM;
}
/* check if the first increase entry is 0xFF */
if( (powerTblEntries == 0) || (powerTbl == NULL) )
{
return ERR_PARAM;
}
/* check if the entries of the dynamic power table are valid */
for (entry = 0; entry < powerTblEntries; entry++)
{
if(powerTbl[entry].inc < powerTbl[entry].dec)
{
return ERR_PARAM;
}
}
/* copy the data set */
ST_MEMCPY( gRfalDpo, powerTbl, (powerTblEntries * RFAL_DPO_TABLE_PARAMETER) );
gRfalCurrentDpo = gRfalDpo;
gRfalDpoTableEntries = powerTblEntries;
if(gRfalDpoTableEntry > powerTblEntries)
{
/* is always greater then zero, otherwise we already returned ERR_PARAM */
gRfalDpoTableEntry = (powerTblEntries - 1);
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalDpoTableRead( rfalDpoEntry* tblBuf, uint8_t tblBufEntries, uint8_t* tableEntries )
{
/* wrong request */
if( (tblBuf == NULL) || (tblBufEntries < gRfalDpoTableEntries) || (tableEntries == NULL) )
{
return ERR_PARAM;
}
/* Copy the whole Table to the given buffer */
ST_MEMCPY( tblBuf, gRfalCurrentDpo, (tblBufEntries * RFAL_DPO_TABLE_PARAMETER) );
*tableEntries = gRfalDpoTableEntries;
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalDpoAdjust( void )
{
uint8_t refValue = 0;
uint16_t modeID;
rfalBitRate br;
rfalDpoEntry* dpoTable = (rfalDpoEntry*) gRfalCurrentDpo;
/* Check if the Power Adjustment is disabled and *
* if the callback to the measurement method is properly set */
if( (gRfalCurrentDpo == NULL) || (!gRfalDpoIsEnabled) || (gRfalDpoMeasureCallback == NULL) )
{
return ERR_PARAM;
}
/* Ensure that the current mode is Passive Poller */
if( !rfalIsModePassivePoll( rfalGetMode() ) )
{
return ERR_WRONG_STATE;
}
/* Ensure a proper measure reference value */
if( ERR_NONE != gRfalDpoMeasureCallback( &refValue ) )
{
return ERR_IO;
}
if( refValue >= dpoTable[gRfalDpoTableEntry].inc )
{ /* Increase the output power */
/* the top of the table represents the highest amplitude value*/
if( gRfalDpoTableEntry == 0 )
{
/* maximum driver value has been reached */
}
else
{
/* go up in the table to decrease the driver resistance */
gRfalDpoTableEntry--;
}
}
else if(refValue <= dpoTable[gRfalDpoTableEntry].dec)
{ /* decrease the output power */
/* The bottom is the highest possible value */
if( (gRfalDpoTableEntry + 1) >= gRfalDpoTableEntries)
{
/* minimum driver value has been reached */
}
else
{
/* go down in the table to increase the driver resistance */
gRfalDpoTableEntry++;
}
}
else
{
/* Fall through to always write dpo and its associated analog configs */
}
/* Get the new value for RFO resistance form the table and apply the new RFO resistance setting */
rfalChipSetRFO( dpoTable[gRfalDpoTableEntry].rfoRes );
/* Apply the DPO Analog Config according to this treshold */
/* Technology field is being extended for DPO: 2msb are used for treshold step (only 4 allowed) */
rfalGetBitRate( &br, NULL ); /* Obtain current Tx bitrate */
modeID = rfalAnalogConfigGenModeID( rfalGetMode(), br, RFAL_ANALOG_CONFIG_DPO ); /* Generate Analog Config mode ID */
modeID |= ((gRfalDpoTableEntry << RFAL_DPO_ANALOGCONFIG_SHIFT) & RFAL_DPO_ANALOGCONFIG_MASK); /* Add DPO treshold step|level */
rfalSetAnalogConfig( modeID ); /* Apply DPO Analog Config */
return ERR_NONE;
}
/*******************************************************************************/
rfalDpoEntry* rfalDpoGetCurrentTableEntry( void )
{
rfalDpoEntry* dpoTable = (rfalDpoEntry*) gRfalCurrentDpo;
return &dpoTable[gRfalDpoTableEntry];
}
/*******************************************************************************/
void rfalDpoSetEnabled( bool enable )
{
gRfalDpoIsEnabled = enable;
}
/*******************************************************************************/
bool rfalDpoIsEnabled( void )
{
return gRfalDpoIsEnabled;
}
#endif /* RFAL_FEATURE_DPO */

View file

@ -0,0 +1,533 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_iso15693_2.c
*
* \author Ulrich Herrmann
*
* \brief Implementation of ISO-15693-2
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_iso15693_2.h"
#include "rfal_crc.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_NFCV
#define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_NFCV
/*
******************************************************************************
* LOCAL MACROS
******************************************************************************
*/
#define ISO_15693_DEBUG(...) /*!< Macro for the log method */
/*
******************************************************************************
* LOCAL DEFINES
******************************************************************************
*/
#define ISO15693_DAT_SOF_1_4 0x21 /* LSB constants */
#define ISO15693_DAT_EOF_1_4 0x04
#define ISO15693_DAT_00_1_4 0x02
#define ISO15693_DAT_01_1_4 0x08
#define ISO15693_DAT_10_1_4 0x20
#define ISO15693_DAT_11_1_4 0x80
#define ISO15693_DAT_SOF_1_256 0x81
#define ISO15693_DAT_EOF_1_256 0x04
#define ISO15693_DAT_SLOT0_1_256 0x02
#define ISO15693_DAT_SLOT1_1_256 0x08
#define ISO15693_DAT_SLOT2_1_256 0x20
#define ISO15693_DAT_SLOT3_1_256 0x80
#define ISO15693_PHY_DAT_MANCHESTER_1 0xaaaa
#define ISO15693_PHY_BIT_BUFFER_SIZE 1000 /*!< size of the receiving buffer. Might be adjusted if longer datastreams are expected. */
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
static iso15693PhyConfig_t iso15693PhyConfig; /*!< current phy configuration */
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static ReturnCode iso15693PhyVCDCode1Of4(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen);
static ReturnCode iso15693PhyVCDCode1Of256(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen);
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
ReturnCode iso15693PhyConfigure(const iso15693PhyConfig_t* config, const struct iso15693StreamConfig ** needed_stream_config )
{
static struct iso15693StreamConfig stream_config = { /* MISRA 8.9 */
.useBPSK = 0, /* 0: subcarrier, 1:BPSK */
.din = 5, /* 2^5*fc = 423750 Hz: divider for the in subcarrier frequency */
.dout = 7, /*!< 2^7*fc = 105937 : divider for the in subcarrier frequency */
.report_period_length = 3, /*!< 8=2^3 the length of the reporting period */
};
/* make a copy of the configuration */
ST_MEMCPY( (uint8_t*)&iso15693PhyConfig, (const uint8_t*)config, sizeof(iso15693PhyConfig_t));
if ( config->speedMode <= 3U)
{ /* If valid speed mode adjust report period accordingly */
stream_config.report_period_length = (3U - (uint8_t)config->speedMode);
}
else
{ /* If invalid default to normal (high) speed */
stream_config.report_period_length = 3;
}
*needed_stream_config = &stream_config;
return ERR_NONE;
}
ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t* config)
{
ST_MEMCPY(config, &iso15693PhyConfig, sizeof(iso15693PhyConfig_t));
return ERR_NONE;
}
ReturnCode iso15693VCDCode(uint8_t* buffer, uint16_t length, bool sendCrc, bool sendFlags, bool picopassMode,
uint16_t *subbit_total_length, uint16_t *offset,
uint8_t* outbuf, uint16_t outBufSize, uint16_t* actOutBufSize)
{
ReturnCode err = ERR_NONE;
uint8_t eof, sof;
uint8_t transbuf[2];
uint16_t crc = 0;
ReturnCode (*txFunc)(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen);
uint8_t crc_len;
uint8_t* outputBuf;
uint16_t outputBufSize;
crc_len = (uint8_t)((sendCrc)?2:0);
*actOutBufSize = 0;
if (ISO15693_VCD_CODING_1_4 == iso15693PhyConfig.coding)
{
sof = ISO15693_DAT_SOF_1_4;
eof = ISO15693_DAT_EOF_1_4;
txFunc = iso15693PhyVCDCode1Of4;
*subbit_total_length = (
( 1U /* SOF */
+ ((length + (uint16_t)crc_len) * 4U)
+ 1U) /* EOF */
);
if (outBufSize < 5U) { /* 5 should be safe: enough for sof + 1byte data in 1of4 */
return ERR_NOMEM;
}
}
else
{
sof = ISO15693_DAT_SOF_1_256;
eof = ISO15693_DAT_EOF_1_256;
txFunc = iso15693PhyVCDCode1Of256;
*subbit_total_length = (
( 1U /* SOF */
+ ((length + (uint16_t)crc_len) * 64U)
+ 1U) /* EOF */
);
if (*offset != 0U)
{
if (outBufSize < 64U) { /* 64 should be safe: enough a single byte data in 1of256 */
return ERR_NOMEM;
}
}
else
{
if (outBufSize < 65U) { /* At beginning of a frame we need at least 65 bytes to start: enough for sof + 1byte data in 1of256 */
return ERR_NOMEM;
}
}
}
if (length == 0U)
{
*subbit_total_length = 1;
}
if ((length != 0U) && (0U == *offset) && sendFlags && !picopassMode)
{
/* set high datarate flag */
buffer[0] |= (uint8_t)ISO15693_REQ_FLAG_HIGH_DATARATE;
/* clear sub-carrier flag - we only support single sub-carrier */
buffer[0] = (uint8_t)(buffer[0] & ~ISO15693_REQ_FLAG_TWO_SUBCARRIERS); /* MISRA 10.3 */
}
outputBuf = outbuf; /* MISRA 17.8: Use intermediate variable */
outputBufSize = outBufSize; /* MISRA 17.8: Use intermediate variable */
/* Send SOF if at 0 offset */
if ((length != 0U) && (0U == *offset))
{
*outputBuf = sof;
(*actOutBufSize)++;
outputBufSize--;
outputBuf++;
}
while ((*offset < length) && (err == ERR_NONE))
{
uint16_t filled_size;
/* send data */
err = txFunc(buffer[*offset], outputBuf, outputBufSize, &filled_size);
(*actOutBufSize) += filled_size;
outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */
outputBufSize -= filled_size;
if (err == ERR_NONE) {
(*offset)++;
}
}
if (err != ERR_NONE) {
return ERR_AGAIN;
}
while ((err == ERR_NONE) && sendCrc && (*offset < (length + 2U)))
{
uint16_t filled_size;
if (0U==crc)
{
crc = rfalCrcCalculateCcitt( (uint16_t) ((picopassMode) ? 0xE012U : 0xFFFFU), /* In PicoPass Mode a different Preset Value is used */
((picopassMode) ? (buffer + 1U) : buffer), /* CMD byte is not taken into account in PicoPass mode */
((picopassMode) ? (length - 1U) : length)); /* CMD byte is not taken into account in PicoPass mode */
crc = (uint16_t)((picopassMode) ? crc : ~crc);
}
/* send crc */
transbuf[0] = (uint8_t)(crc & 0xffU);
transbuf[1] = (uint8_t)((crc >> 8) & 0xffU);
err = txFunc(transbuf[*offset - length], outputBuf, outputBufSize, &filled_size);
(*actOutBufSize) += filled_size;
outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */
outputBufSize -= filled_size;
if (err == ERR_NONE) {
(*offset)++;
}
}
if (err != ERR_NONE) {
return ERR_AGAIN;
}
if ((!sendCrc && (*offset == length))
|| (sendCrc && (*offset == (length + 2U))))
{
*outputBuf = eof;
(*actOutBufSize)++;
outputBufSize--;
outputBuf++;
}
else
{
return ERR_AGAIN;
}
return err;
}
ReturnCode iso15693VICCDecode(const uint8_t *inBuf,
uint16_t inBufLen,
uint8_t* outBuf,
uint16_t outBufLen,
uint16_t* outBufPos,
uint16_t* bitsBeforeCol,
uint16_t ignoreBits,
bool picopassMode )
{
ReturnCode err = ERR_NONE;
uint16_t crc;
uint16_t mp; /* Current bit position in manchester bit inBuf*/
uint16_t bp; /* Current bit position in outBuf */
*bitsBeforeCol = 0;
*outBufPos = 0;
/* first check for valid SOF. Since it starts with 3 unmodulated pulses it is 0x17. */
if ((inBuf[0] & 0x1fU) != 0x17U)
{
ISO_15693_DEBUG("0x%x\n", iso15693PhyBitBuffer[0]);
return ERR_FRAMING;
}
ISO_15693_DEBUG("SOF\n");
if (outBufLen == 0U)
{
return ERR_NONE;
}
mp = 5; /* 5 bits were SOF, now manchester starts: 2 bits per payload bit */
bp = 0;
ST_MEMSET(outBuf,0,outBufLen);
if (inBufLen == 0U)
{
return ERR_CRC;
}
for ( ; mp < ((inBufLen * 8U) - 2U); mp+=2U )
{
bool isEOF = false;
uint8_t man;
man = (inBuf[mp/8U] >> (mp%8U)) & 0x1U;
man |= ((inBuf[(mp+1U)/8U] >> ((mp+1U)%8U)) & 0x1U) << 1;
if (1U == man)
{
bp++;
}
if (2U == man)
{
outBuf[bp/8U] = (uint8_t)(outBuf[bp/8U] | (1U <<(bp%8U))); /* MISRA 10.3 */
bp++;
}
if ((bp%8U) == 0U)
{ /* Check for EOF */
ISO_15693_DEBUG("ceof %hhx %hhx\n", inBuf[mp/8U], inBuf[mp/8+1]);
if ( ((inBuf[mp/8U] & 0xe0U) == 0xa0U)
&&(inBuf[(mp/8U)+1U] == 0x03U))
{ /* Now we know that it was 10111000 = EOF */
ISO_15693_DEBUG("EOF\n");
isEOF = true;
}
}
if ( ((0U == man) || (3U == man)) && !isEOF )
{
if (bp >= ignoreBits)
{
err = ERR_RF_COLLISION;
}
else
{
/* ignored collision: leave as 0 */
bp++;
}
}
if ( (bp >= (outBufLen * 8U)) || (err == ERR_RF_COLLISION) || isEOF )
{ /* Don't write beyond the end */
break;
}
}
*outBufPos = (bp / 8U);
*bitsBeforeCol = bp;
if (err != ERR_NONE)
{
return err;
}
if ((bp%8U) != 0U)
{
return ERR_CRC;
}
if (*outBufPos > 2U)
{
/* finally, check crc */
ISO_15693_DEBUG("Calculate CRC, val: 0x%x, outBufLen: ", *outBuf);
ISO_15693_DEBUG("0x%x ", *outBufPos - 2);
crc = rfalCrcCalculateCcitt(((picopassMode) ? 0xE012U : 0xFFFFU), outBuf, *outBufPos - 2U);
crc = (uint16_t)((picopassMode) ? crc : ~crc);
if (((crc & 0xffU) == outBuf[*outBufPos-2U]) &&
(((crc >> 8U) & 0xffU) == outBuf[*outBufPos-1U]))
{
err = ERR_NONE;
ISO_15693_DEBUG("OK\n");
}
else
{
ISO_15693_DEBUG("error! Expected: 0x%x, got ", crc);
ISO_15693_DEBUG("0x%hhx 0x%hhx\n", outBuf[*outBufPos-2], outBuf[*outBufPos-1]);
err = ERR_CRC;
}
}
else
{
err = ERR_CRC;
}
return err;
}
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Perform 1 of 4 coding and send coded data
*
* This function takes \a length bytes from \a buffer, perform 1 of 4 coding
* (see ISO15693-2 specification) and sends the data using stream mode.
*
* \param[in] sendSof : send SOF prior to data.
* \param[in] buffer : data to send.
* \param[in] length : number of bytes to send.
*
* \return ERR_IO : Error during communication.
* \return ERR_NONE : No error.
*
*****************************************************************************
*/
static ReturnCode iso15693PhyVCDCode1Of4(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen)
{
uint8_t tmp;
ReturnCode err = ERR_NONE;
uint16_t a;
uint8_t* outbuf = outbuffer;
*outBufLen = 0;
if (maxOutBufLen < 4U) {
return ERR_NOMEM;
}
tmp = data;
for (a = 0; a < 4U; a++)
{
switch (tmp & 0x3U)
{
case 0:
*outbuf = ISO15693_DAT_00_1_4;
break;
case 1:
*outbuf = ISO15693_DAT_01_1_4;
break;
case 2:
*outbuf = ISO15693_DAT_10_1_4;
break;
case 3:
*outbuf = ISO15693_DAT_11_1_4;
break;
default:
/* MISRA 16.4: mandatory default statement */
break;
}
outbuf++;
(*outBufLen)++;
tmp >>= 2;
}
return err;
}
/*!
*****************************************************************************
* \brief Perform 1 of 256 coding and send coded data
*
* This function takes \a length bytes from \a buffer, perform 1 of 256 coding
* (see ISO15693-2 specification) and sends the data using stream mode.
* \note This function sends SOF prior to the data.
*
* \param[in] sendSof : send SOF prior to data.
* \param[in] buffer : data to send.
* \param[in] length : number of bytes to send.
*
* \return ERR_IO : Error during communication.
* \return ERR_NONE : No error.
*
*****************************************************************************
*/
static ReturnCode iso15693PhyVCDCode1Of256(const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen)
{
uint8_t tmp;
ReturnCode err = ERR_NONE;
uint16_t a;
uint8_t* outbuf = outbuffer;
*outBufLen = 0;
if (maxOutBufLen < 64U) {
return ERR_NOMEM;
}
tmp = data;
for (a = 0; a < 64U; a++)
{
switch (tmp)
{
case 0:
*outbuf = ISO15693_DAT_SLOT0_1_256;
break;
case 1:
*outbuf = ISO15693_DAT_SLOT1_1_256;
break;
case 2:
*outbuf = ISO15693_DAT_SLOT2_1_256;
break;
case 3:
*outbuf = ISO15693_DAT_SLOT3_1_256;
break;
default:
*outbuf = 0;
break;
}
outbuf++;
(*outBufLen)++;
tmp -= 4U;
}
return err;
}
#endif /* RFAL_FEATURE_NFCV */

File diff suppressed because it is too large Load diff

1926
lib/ST25RFAL002/source/rfal_nfc.c Executable file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,853 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfca.c
*
* \author Gustavo Patricio
*
* \brief Provides several NFC-A convenience methods and definitions
*
* It provides a Poller (ISO14443A PCD) interface and as well as
* some NFC-A Listener (ISO14443A PICC) helpers.
*
* The definitions and helpers methods provided by this module are only
* up to ISO14443-3 layer
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_nfca.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_NFCA
#define RFAL_FEATURE_NFCA false /* NFC-A module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_NFCA
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCA_SLP_FWT rfalConvMsTo1fc(1) /*!< Check 1ms for any modulation ISO14443-3 6.4.3 */
#define RFAL_NFCA_SLP_CMD 0x50U /*!< SLP cmd (byte1) Digital 1.1 6.9.1 & Table 20 */
#define RFAL_NFCA_SLP_BYTE2 0x00U /*!< SLP byte2 Digital 1.1 6.9.1 & Table 20 */
#define RFAL_NFCA_SLP_CMD_POS 0U /*!< SLP cmd position Digital 1.1 6.9.1 & Table 20 */
#define RFAL_NFCA_SLP_BYTE2_POS 1U /*!< SLP byte2 position Digital 1.1 6.9.1 & Table 20 */
#define RFAL_NFCA_SDD_CT 0x88U /*!< Cascade Tag value Digital 1.1 6.7.2 */
#define RFAL_NFCA_SDD_CT_LEN 1U /*!< Cascade Tag length */
#define RFAL_NFCA_SLP_REQ_LEN 2U /*!< SLP_REQ length */
#define RFAL_NFCA_SEL_CMD_LEN 1U /*!< SEL_CMD length */
#define RFAL_NFCA_SEL_PAR_LEN 1U /*!< SEL_PAR length */
#define RFAL_NFCA_SEL_SELPAR rfalNfcaSelPar(7U, 0U)/*!< SEL_PAR on Select is always with 4 data/nfcid */
#define RFAL_NFCA_BCC_LEN 1U /*!< BCC length */
#define RFAL_NFCA_SDD_REQ_LEN (RFAL_NFCA_SEL_CMD_LEN + RFAL_NFCA_SEL_PAR_LEN) /*!< SDD_REQ length */
#define RFAL_NFCA_SDD_RES_LEN (RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_BCC_LEN) /*!< SDD_RES length */
#define RFAL_NFCA_T_RETRANS 5U /*!< t RETRANSMISSION [3, 33]ms EMVCo 2.6 A.5 */
#define RFAL_NFCA_N_RETRANS 2U /*!< Number of retries EMVCo 2.6 9.6.1.3 */
/*! SDD_REQ (Select) Cascade Levels */
enum
{
RFAL_NFCA_SEL_CASCADE_L1 = 0, /*!< SDD_REQ Cascade Level 1 */
RFAL_NFCA_SEL_CASCADE_L2 = 1, /*!< SDD_REQ Cascade Level 2 */
RFAL_NFCA_SEL_CASCADE_L3 = 2 /*!< SDD_REQ Cascade Level 3 */
};
/*! SDD_REQ (Select) request Cascade Level command Digital 1.1 Table 15 */
enum
{
RFAL_NFCA_CMD_SEL_CL1 = 0x93, /*!< SDD_REQ command Cascade Level 1 */
RFAL_NFCA_CMD_SEL_CL2 = 0x95, /*!< SDD_REQ command Cascade Level 2 */
RFAL_NFCA_CMD_SEL_CL3 = 0x97, /*!< SDD_REQ command Cascade Level 3 */
};
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define rfalNfcaSelPar( nBy, nbi ) (uint8_t)((((nBy)<<4U) & 0xF0U) | ((nbi)&0x0FU) ) /*!< Calculates SEL_PAR with the bytes/bits to be sent */
#define rfalNfcaCLn2SELCMD( cl ) (uint8_t)((uint8_t)(RFAL_NFCA_CMD_SEL_CL1) + (2U*(cl))) /*!< Calculates SEL_CMD with the given cascade level */
#define rfalNfcaNfcidLen2CL( len ) ((len) / 5U) /*!< Calculates cascade level by the NFCID length */
#define rfalNfcaRunBlocking( e, fn ) do{ (e)=(fn); rfalWorker(); }while( (e) == ERR_BUSY ) /*!< Macro used for the blocking methods */
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! Colission Resolution states */
typedef enum{
RFAL_NFCA_CR_IDLE, /*!< IDLE state */
RFAL_NFCA_CR_CL, /*!< New Cascading Level state */
RFAL_NFCA_CR_SDD, /*!< Perform anticollsion state */
RFAL_NFCA_CR_SEL, /*!< Perform CL Selection state */
RFAL_NFCA_CR_DONE /*!< Collision Resolution done state */
}colResState;
/*! Colission Resolution context */
typedef struct{
uint8_t devLimit; /*!< Device limit to be used */
rfalComplianceMode compMode; /*!< Compliancy mode to be used */
rfalNfcaListenDevice* nfcaDevList; /*!< Location of the device list */
uint8_t* devCnt; /*!< Location of the device counter */
bool collPending; /*!< Collision pending flag */
bool* collPend; /*!< Location of collision pending flag (Single CR) */
rfalNfcaSelReq selReq; /*!< SelReqused during anticollision (Single CR) */
rfalNfcaSelRes* selRes; /*!< Location to place of the SEL_RES(SAK) (Single CR) */
uint8_t* nfcId1; /*!< Location to place the NFCID1 (Single CR) */
uint8_t* nfcId1Len; /*!< Location to place the NFCID1 length (Single CR) */
uint8_t cascadeLv; /*!< Current Cascading Level (Single CR) */
colResState state; /*!< Single Collision Resolution state (Single CR) */
uint8_t bytesTxRx; /*!< TxRx bytes used during anticollision loop (Single CR) */
uint8_t bitsTxRx; /*!< TxRx bits used during anticollision loop (Single CR) */
uint16_t rxLen;
uint32_t tmrFDT; /*!< FDT timer used between SED_REQs (Single CR) */
uint8_t retries; /*!< Retries to be performed upon a timeout error (Single CR)*/
uint8_t backtrackCnt; /*!< Backtrack retries (Single CR) */
bool doBacktrack; /*!< Backtrack flag (Single CR) */
}colResParams;
/*! RFAL NFC-A instance */
typedef struct{
colResParams CR; /*!< Collision Resolution context */
} rfalNfca;
/*! SLP_REQ (HLTA) format Digital 1.1 6.9.1 & Table 20 */
typedef struct
{
uint8_t frame[RFAL_NFCA_SLP_REQ_LEN]; /*!< SLP: 0x50 0x00 */
} rfalNfcaSlpReq;
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
static rfalNfca gNfca; /*!< RFAL NFC-A instance */
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static uint8_t rfalNfcaCalculateBcc( const uint8_t* buf, uint8_t bufLen );
static ReturnCode rfalNfcaPollerStartSingleCollisionResolution( uint8_t devLimit, bool *collPending, rfalNfcaSelRes *selRes, uint8_t *nfcId1, uint8_t *nfcId1Len );
static ReturnCode rfalNfcaPollerGetSingleCollisionResolutionStatus( void );
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
static uint8_t rfalNfcaCalculateBcc( const uint8_t* buf, uint8_t bufLen )
{
uint8_t i;
uint8_t BCC;
BCC = 0;
/* BCC is XOR over first 4 bytes of the SDD_RES Digital 1.1 6.7.2 */
for(i = 0; i < bufLen; i++)
{
BCC ^= buf[i];
}
return BCC;
}
/*******************************************************************************/
static ReturnCode rfalNfcaPollerStartSingleCollisionResolution( uint8_t devLimit, bool *collPending, rfalNfcaSelRes *selRes, uint8_t *nfcId1, uint8_t *nfcId1Len )
{
/* Check parameters */
if( (collPending == NULL) || (selRes == NULL) || (nfcId1 == NULL) || (nfcId1Len == NULL) )
{
return ERR_PARAM;
}
/* Initialize output parameters */
*collPending = false; /* Activity 1.1 9.3.4.6 */
*nfcId1Len = 0;
ST_MEMSET( nfcId1, 0x00, RFAL_NFCA_CASCADE_3_UID_LEN );
/* Save parameters */
gNfca.CR.devLimit = devLimit;
gNfca.CR.collPend = collPending;
gNfca.CR.selRes = selRes;
gNfca.CR.nfcId1 = nfcId1;
gNfca.CR.nfcId1Len = nfcId1Len;
platformTimerDestroy( gNfca.CR.tmrFDT );
gNfca.CR.tmrFDT = 0U;
gNfca.CR.retries = RFAL_NFCA_N_RETRANS;
gNfca.CR.cascadeLv = (uint8_t)RFAL_NFCA_SEL_CASCADE_L1;
gNfca.CR.state = RFAL_NFCA_CR_CL;
gNfca.CR.doBacktrack = false;
gNfca.CR.backtrackCnt = 3U;
return ERR_NONE;
}
/*******************************************************************************/
static ReturnCode rfalNfcaPollerGetSingleCollisionResolutionStatus( void )
{
ReturnCode ret;
uint8_t collBit = 1U; /* standards mandate or recommend collision bit to be set to One. */
/* Check if FDT timer is still running */
if( !platformTimerIsExpired( gNfca.CR.tmrFDT ) && (gNfca.CR.tmrFDT != 0U) )
{
return ERR_BUSY;
}
/*******************************************************************************/
/* Go through all Cascade Levels Activity 1.1 9.3.4 */
if( gNfca.CR.cascadeLv > (uint8_t)RFAL_NFCA_SEL_CASCADE_L3 )
{
return ERR_INTERNAL;
}
switch( gNfca.CR.state )
{
/*******************************************************************************/
case RFAL_NFCA_CR_CL:
/* Initialize the SDD_REQ to send for the new cascade level */
ST_MEMSET( (uint8_t*)&gNfca.CR.selReq, 0x00, sizeof(rfalNfcaSelReq) );
gNfca.CR.bytesTxRx = RFAL_NFCA_SDD_REQ_LEN;
gNfca.CR.bitsTxRx = 0U;
gNfca.CR.state = RFAL_NFCA_CR_SDD;
/* fall through */
/*******************************************************************************/
case RFAL_NFCA_CR_SDD: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */
/* Calculate SEL_CMD and SEL_PAR with the bytes/bits to be sent */
gNfca.CR.selReq.selCmd = rfalNfcaCLn2SELCMD( gNfca.CR.cascadeLv );
gNfca.CR.selReq.selPar = rfalNfcaSelPar(gNfca.CR.bytesTxRx, gNfca.CR.bitsTxRx);
/* Send SDD_REQ (Anticollision frame) */
ret = rfalISO14443ATransceiveAnticollisionFrame( (uint8_t*)&gNfca.CR.selReq, &gNfca.CR.bytesTxRx, &gNfca.CR.bitsTxRx, &gNfca.CR.rxLen, RFAL_NFCA_FDTMIN );
/* Retry upon timeout EMVCo 2.6 9.6.1.3 */
if( (ret == ERR_TIMEOUT) && (gNfca.CR.devLimit==0U) && (gNfca.CR.retries != 0U) )
{
gNfca.CR.retries--;
platformTimerDestroy( gNfca.CR.tmrFDT );
gNfca.CR.tmrFDT = platformTimerCreate( RFAL_NFCA_T_RETRANS );
break;
}
/* Covert rxLen into bytes */
gNfca.CR.rxLen = rfalConvBitsToBytes( gNfca.CR.rxLen );
if( (ret == ERR_TIMEOUT) && (gNfca.CR.backtrackCnt != 0U) && (!gNfca.CR.doBacktrack)
&& !((RFAL_NFCA_SDD_REQ_LEN == gNfca.CR.bytesTxRx) && (0U == gNfca.CR.bitsTxRx)) )
{
/* In multiple card scenarios it may always happen that some
* collisions of a weaker tag go unnoticed. If then a later
* collision is recognized and the strong tag has a 0 at the
* collision position then no tag will respond. Catch this
* corner case and then try with the bit being sent as zero. */
rfalNfcaSensRes sensRes;
ret = ERR_RF_COLLISION;
rfalNfcaPollerCheckPresence( RFAL_14443A_SHORTFRAME_CMD_REQA, &sensRes );
/* Algorithm below does a post-increment, decrement to go back to current position */
if (0U == gNfca.CR.bitsTxRx)
{
gNfca.CR.bitsTxRx = 7;
gNfca.CR.bytesTxRx--;
}
else
{
gNfca.CR.bitsTxRx--;
}
collBit = (uint8_t)( ((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] & (1U << gNfca.CR.bitsTxRx) );
collBit = (uint8_t)((0U==collBit)?1U:0U); // invert the collision bit
gNfca.CR.doBacktrack = true;
gNfca.CR.backtrackCnt--;
}
else
{
gNfca.CR.doBacktrack = false;
}
if( ret == ERR_RF_COLLISION )
{
/* Check received length */
if( (gNfca.CR.bytesTxRx + ((gNfca.CR.bitsTxRx != 0U) ? 1U : 0U)) > (RFAL_NFCA_SDD_RES_LEN + RFAL_NFCA_SDD_REQ_LEN) )
{
return ERR_PROTO;
}
if( ((gNfca.CR.bytesTxRx + ((gNfca.CR.bitsTxRx != 0U) ? 1U : 0U)) > (RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_SDD_REQ_LEN)) && (gNfca.CR.backtrackCnt != 0U) )
{ /* Collision in BCC: Anticollide only UID part */
gNfca.CR.backtrackCnt--;
gNfca.CR.bytesTxRx = RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_SDD_REQ_LEN - 1U;
gNfca.CR.bitsTxRx = 7;
collBit = (uint8_t)( ((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] & (1U << gNfca.CR.bitsTxRx) ); /* Not a real collision, extract the actual bit for the subsequent code */
}
if( (gNfca.CR.devLimit == 0U) && !(*gNfca.CR.collPend) )
{
/* Activity 1.0 & 1.1 9.3.4.12: If CON_DEVICES_LIMIT has a value of 0, then
* NFC Forum Device is configured to perform collision detection only */
*gNfca.CR.collPend = true;
return ERR_IGNORE;
}
*gNfca.CR.collPend = true;
/* Set and select the collision bit, with the number of bytes/bits successfully TxRx */
if (collBit != 0U)
{
((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] = (uint8_t)(((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] | (1U << gNfca.CR.bitsTxRx)); /* MISRA 10.3 */
}
else
{
((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] = (uint8_t)(((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] & ~(1U << gNfca.CR.bitsTxRx)); /* MISRA 10.3 */
}
gNfca.CR.bitsTxRx++;
/* Check if number of bits form a byte */
if( gNfca.CR.bitsTxRx == RFAL_BITS_IN_BYTE )
{
gNfca.CR.bitsTxRx = 0;
gNfca.CR.bytesTxRx++;
}
break;
}
/*******************************************************************************/
/* Check if Collision loop has failed */
if( ret != ERR_NONE )
{
return ret;
}
/* If collisions are to be reported check whether the response is complete */
if( (gNfca.CR.devLimit == 0U) && (gNfca.CR.rxLen != sizeof(rfalNfcaSddRes)) )
{
return ERR_PROTO;
}
/* Check if the received BCC match */
if( gNfca.CR.selReq.bcc != rfalNfcaCalculateBcc( gNfca.CR.selReq.nfcid1, RFAL_NFCA_CASCADE_1_UID_LEN ) )
{
return ERR_PROTO;
}
/*******************************************************************************/
/* Anticollision OK, Select this Cascade Level */
gNfca.CR.selReq.selPar = RFAL_NFCA_SEL_SELPAR;
gNfca.CR.retries = RFAL_NFCA_N_RETRANS;
gNfca.CR.state = RFAL_NFCA_CR_SEL;
break;
/*******************************************************************************/
case RFAL_NFCA_CR_SEL:
/* Send SEL_REQ (Select command) - Retry upon timeout EMVCo 2.6 9.6.1.3 */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&gNfca.CR.selReq, sizeof(rfalNfcaSelReq), (uint8_t*)gNfca.CR.selRes, sizeof(rfalNfcaSelRes), &gNfca.CR.rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCA_FDTMIN );
/* Retry upon timeout EMVCo 2.6 9.6.1.3 */
if( (ret == ERR_TIMEOUT) && (gNfca.CR.devLimit==0U) && (gNfca.CR.retries != 0U) )
{
gNfca.CR.retries--;
platformTimerDestroy( gNfca.CR.tmrFDT );
gNfca.CR.tmrFDT = platformTimerCreate( RFAL_NFCA_T_RETRANS );
break;
}
if( ret != ERR_NONE )
{
return ret;
}
/* Ensure proper response length */
if( gNfca.CR.rxLen != sizeof(rfalNfcaSelRes) )
{
return ERR_PROTO;
}
/*******************************************************************************/
/* Check cascade byte, if cascade tag then go next cascade level */
if( *gNfca.CR.selReq.nfcid1 == RFAL_NFCA_SDD_CT )
{
/* Cascade Tag present, store nfcid1 bytes (excluding cascade tag) and continue for next CL */
ST_MEMCPY( &gNfca.CR.nfcId1[*gNfca.CR.nfcId1Len], &((uint8_t*)&gNfca.CR.selReq.nfcid1)[RFAL_NFCA_SDD_CT_LEN], (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN) );
*gNfca.CR.nfcId1Len += (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN);
/* Go to next cascade level */
gNfca.CR.state = RFAL_NFCA_CR_CL;
gNfca.CR.cascadeLv++;
}
else
{
/* UID Selection complete, Stop Cascade Level loop */
ST_MEMCPY( &gNfca.CR.nfcId1[*gNfca.CR.nfcId1Len], (uint8_t*)&gNfca.CR.selReq.nfcid1, RFAL_NFCA_CASCADE_1_UID_LEN );
*gNfca.CR.nfcId1Len += RFAL_NFCA_CASCADE_1_UID_LEN;
gNfca.CR.state = RFAL_NFCA_CR_DONE;
break; /* Only flag operation complete on the next execution */
}
break;
/*******************************************************************************/
case RFAL_NFCA_CR_DONE:
return ERR_NONE;
/*******************************************************************************/
default:
return ERR_WRONG_STATE;
}
return ERR_BUSY;
}
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
ReturnCode rfalNfcaPollerInitialize( void )
{
ReturnCode ret;
EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCA, RFAL_BR_106, RFAL_BR_106 ) );
rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC );
rfalSetGT( RFAL_GT_NFCA );
rfalSetFDTListen( RFAL_FDT_LISTEN_NFCA_POLLER );
rfalSetFDTPoll( RFAL_FDT_POLL_NFCA_POLLER );
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcaPollerCheckPresence( rfal14443AShortFrameCmd cmd, rfalNfcaSensRes *sensRes )
{
ReturnCode ret;
uint16_t rcvLen;
/* Digital 1.1 6.10.1.3 For Commands ALL_REQ, SENS_REQ, SDD_REQ, and SEL_REQ, the NFC Forum Device *
* MUST treat receipt of a Listen Frame at a time after FDT(Listen, min) as a Timeour Error */
ret = rfalISO14443ATransceiveShortFrame( cmd, (uint8_t*)sensRes, (uint8_t)rfalConvBytesToBits(sizeof(rfalNfcaSensRes)), &rcvLen, RFAL_NFCA_FDTMIN );
if( (ret == ERR_RF_COLLISION) || (ret == ERR_CRC) || (ret == ERR_NOMEM) || (ret == ERR_FRAMING) || (ret == ERR_PAR) )
{
ret = ERR_NONE;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalNfcaPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcaSensRes *sensRes )
{
ReturnCode ret;
EXIT_ON_ERR( ret, rfalNfcaPollerCheckPresence( ((compMode == RFAL_COMPLIANCE_MODE_EMV) ? RFAL_14443A_SHORTFRAME_CMD_WUPA : RFAL_14443A_SHORTFRAME_CMD_REQA), sensRes ) );
/* Send SLP_REQ as Activity 1.1 9.2.3.6 and EMVCo 2.6 9.2.1.3 */
if( compMode != RFAL_COMPLIANCE_MODE_ISO)
{
rfalNfcaPollerSleep();
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcaPollerSingleCollisionResolution( uint8_t devLimit, bool *collPending, rfalNfcaSelRes *selRes, uint8_t *nfcId1, uint8_t *nfcId1Len )
{
ReturnCode ret;
EXIT_ON_ERR( ret, rfalNfcaPollerStartSingleCollisionResolution( devLimit, collPending, selRes, nfcId1, nfcId1Len ) );
rfalNfcaRunBlocking( ret, rfalNfcaPollerGetSingleCollisionResolutionStatus() );
return ret;
}
/*******************************************************************************/
ReturnCode rfalNfcaPollerStartFullCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt )
{
ReturnCode ret;
rfalNfcaSensRes sensRes;
uint16_t rcvLen;
if( (nfcaDevList == NULL) || (devCnt == NULL) )
{
return ERR_PARAM;
}
*devCnt = 0;
ret = ERR_NONE;
/*******************************************************************************/
/* Send ALL_REQ before Anticollision if a Sleep was sent before Activity 1.1 9.3.4.1 and EMVco 2.6 9.3.2.1 */
if( compMode != RFAL_COMPLIANCE_MODE_ISO )
{
ret = rfalISO14443ATransceiveShortFrame( RFAL_14443A_SHORTFRAME_CMD_WUPA, (uint8_t*)&nfcaDevList->sensRes, (uint8_t)rfalConvBytesToBits(sizeof(rfalNfcaSensRes)), &rcvLen, RFAL_NFCA_FDTMIN );
if(ret != ERR_NONE)
{
if( (compMode == RFAL_COMPLIANCE_MODE_EMV) || ((ret != ERR_RF_COLLISION) && (ret != ERR_CRC) && (ret != ERR_FRAMING) && (ret != ERR_PAR)) )
{
return ret;
}
}
/* Check proper SENS_RES/ATQA size */
if( (ret == ERR_NONE) && (rfalConvBytesToBits(sizeof(rfalNfcaSensRes)) != rcvLen) )
{
return ERR_PROTO;
}
}
/*******************************************************************************/
/* Store the SENS_RES from Technology Detection or from WUPA */
sensRes = nfcaDevList->sensRes;
if( devLimit > 0U ) /* MISRA 21.18 */
{
ST_MEMSET( nfcaDevList, 0x00, (sizeof(rfalNfcaListenDevice) * devLimit) );
}
/* Restore the prev SENS_RES, assuming that the SENS_RES received is from first device
* When only one device is detected it's not woken up then we'll have no SENS_RES (ATQA) */
nfcaDevList->sensRes = sensRes;
/* Save parameters */
gNfca.CR.devCnt = devCnt;
gNfca.CR.devLimit = devLimit;
gNfca.CR.nfcaDevList = nfcaDevList;
gNfca.CR.compMode = compMode;
#if RFAL_FEATURE_T1T
/*******************************************************************************/
/* Only check for T1T if previous SENS_RES was received without a transmission *
* error. When collisions occur bits in the SENS_RES may look like a T1T */
/* If T1T Anticollision is not supported Activity 1.1 9.3.4.3 */
if( rfalNfcaIsSensResT1T( &nfcaDevList->sensRes ) && (devLimit != 0U) && (ret == ERR_NONE) && (compMode != RFAL_COMPLIANCE_MODE_EMV) )
{
/* RID_REQ shall be performed Activity 1.1 9.3.4.24 */
rfalT1TPollerInitialize();
EXIT_ON_ERR( ret, rfalT1TPollerRid( &nfcaDevList->ridRes ) );
*devCnt = 1U;
nfcaDevList->isSleep = false;
nfcaDevList->type = RFAL_NFCA_T1T;
nfcaDevList->nfcId1Len = RFAL_NFCA_CASCADE_1_UID_LEN;
ST_MEMCPY( &nfcaDevList->nfcId1, &nfcaDevList->ridRes.uid, RFAL_NFCA_CASCADE_1_UID_LEN );
return ERR_NONE;
}
#endif /* RFAL_FEATURE_T1T */
return rfalNfcaPollerStartSingleCollisionResolution( devLimit, &gNfca.CR.collPending, &nfcaDevList->selRes, (uint8_t*)&nfcaDevList->nfcId1, &nfcaDevList->nfcId1Len );
}
/*******************************************************************************/
ReturnCode rfalNfcaPollerGetFullCollisionResolutionStatus( void )
{
ReturnCode ret;
uint8_t newDevType;
if( (gNfca.CR.nfcaDevList == NULL) || (gNfca.CR.devCnt == NULL) )
{
return ERR_WRONG_STATE;
}
/*******************************************************************************/
/* Check whether a T1T has already been detected */
if( rfalNfcaIsSensResT1T( &gNfca.CR.nfcaDevList->sensRes ) && (gNfca.CR.nfcaDevList->type == RFAL_NFCA_T1T) )
{
/* T1T doesn't support Anticollision */
return ERR_NONE;
}
/*******************************************************************************/
EXIT_ON_ERR( ret, rfalNfcaPollerGetSingleCollisionResolutionStatus() );
/* Assign Listen Device */
newDevType = ((uint8_t)gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].selRes.sak) & RFAL_NFCA_SEL_RES_CONF_MASK; /* MISRA 10.8 */
/* PRQA S 4342 1 # MISRA 10.5 - Guaranteed that no invalid enum values are created: see guard_eq_RFAL_NFCA_T2T, .... */
gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].type = (rfalNfcaListenDeviceType) newDevType;
gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].isSleep = false;
(*gNfca.CR.devCnt)++;
/* If a collision was detected and device counter is lower than limit Activity 1.1 9.3.4.21 */
if( (*gNfca.CR.devCnt < gNfca.CR.devLimit) && (gNfca.CR.collPending) )
{
/* Put this device to Sleep Activity 1.1 9.3.4.22 */
rfalNfcaPollerSleep();
gNfca.CR.nfcaDevList[(*gNfca.CR.devCnt - 1U)].isSleep = true;
/* Send a new SENS_REQ to check for other cards Activity 1.1 9.3.4.23 */
ret = rfalNfcaPollerCheckPresence( RFAL_14443A_SHORTFRAME_CMD_REQA, &gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].sensRes );
if( ret == ERR_TIMEOUT )
{
/* No more devices found, exit */
gNfca.CR.collPending = false;
}
else
{
/* Another device found, continue loop */
gNfca.CR.collPending = true;
}
}
else
{
/* Exit loop */
gNfca.CR.collPending = false;
}
/*******************************************************************************/
/* Check if collision resolution shall continue */
if( (*gNfca.CR.devCnt < gNfca.CR.devLimit) && (gNfca.CR.collPending) )
{
EXIT_ON_ERR( ret, rfalNfcaPollerStartSingleCollisionResolution( gNfca.CR.devLimit,
&gNfca.CR.collPending,
&gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].selRes,
(uint8_t*)&gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].nfcId1,
&gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].nfcId1Len ) );
return ERR_BUSY;
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcaPollerFullCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt )
{
ReturnCode ret;
EXIT_ON_ERR( ret, rfalNfcaPollerStartFullCollisionResolution( compMode, devLimit, nfcaDevList, devCnt ) );
rfalNfcaRunBlocking( ret, rfalNfcaPollerGetFullCollisionResolutionStatus() );
return ret;
}
ReturnCode rfalNfcaPollerSleepFullCollisionResolution( uint8_t devLimit, rfalNfcaListenDevice *nfcaDevList, uint8_t *devCnt )
{
bool firstRound;
uint8_t tmpDevCnt;
ReturnCode ret;
if( (nfcaDevList == NULL) || (devCnt == NULL) )
{
return ERR_PARAM;
}
/* Only use ALL_REQ (WUPA) on the first round */
firstRound = true;
*devCnt = 0;
/* Perform collision resolution until no new device is found */
do
{
tmpDevCnt = 0;
ret = rfalNfcaPollerFullCollisionResolution( (firstRound ? RFAL_COMPLIANCE_MODE_NFC : RFAL_COMPLIANCE_MODE_ISO), (devLimit - *devCnt), &nfcaDevList[*devCnt], &tmpDevCnt );
if( (ret == ERR_NONE) && (tmpDevCnt > 0U) )
{
*devCnt += tmpDevCnt;
/* Check whether to seacrh for more devices */
if( *devCnt < devLimit )
{
/* Set last found device to sleep (all others are slept already) */
rfalNfcaPollerSleep();
nfcaDevList[((*devCnt)-1U)].isSleep = true;
/* Check if any other device is present */
ret = rfalNfcaPollerCheckPresence( RFAL_14443A_SHORTFRAME_CMD_REQA, &nfcaDevList[*devCnt].sensRes );
if( ret == ERR_NONE )
{
firstRound = false;
continue;
}
}
}
break;
}
while( true );
return ((*devCnt > 0U) ? ERR_NONE : ret);
}
/*******************************************************************************/
ReturnCode rfalNfcaPollerSelect( const uint8_t *nfcid1, uint8_t nfcidLen, rfalNfcaSelRes *selRes )
{
uint8_t i;
uint8_t cl;
uint8_t nfcidOffset;
uint16_t rxLen;
ReturnCode ret;
rfalNfcaSelReq selReq;
if( (nfcid1 == NULL) || (nfcidLen > RFAL_NFCA_CASCADE_3_UID_LEN) || (selRes == NULL) )
{
return ERR_PARAM;
}
/* Calculate Cascate Level */
cl = rfalNfcaNfcidLen2CL( nfcidLen );
nfcidOffset = 0;
/*******************************************************************************/
/* Go through all Cascade Levels Activity 1.1 9.4.4 */
for( i = RFAL_NFCA_SEL_CASCADE_L1; i <= cl; i++ )
{
/* Assign SEL_CMD according to the CLn and SEL_PAR*/
selReq.selCmd = rfalNfcaCLn2SELCMD(i);
selReq.selPar = RFAL_NFCA_SEL_SELPAR;
/* Compute NFCID/Data on the SEL_REQ command Digital 1.1 Table 18 */
if( cl != i )
{
*selReq.nfcid1 = RFAL_NFCA_SDD_CT;
ST_MEMCPY( &selReq.nfcid1[RFAL_NFCA_SDD_CT_LEN], &nfcid1[nfcidOffset], (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN) );
nfcidOffset += (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN);
}
else
{
ST_MEMCPY( selReq.nfcid1, &nfcid1[nfcidOffset], RFAL_NFCA_CASCADE_1_UID_LEN );
}
/* Calculate nfcid's BCC */
selReq.bcc = rfalNfcaCalculateBcc( (uint8_t*)&selReq.nfcid1, sizeof(selReq.nfcid1) );
/*******************************************************************************/
/* Send SEL_REQ */
EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&selReq, sizeof(rfalNfcaSelReq), (uint8_t*)selRes, sizeof(rfalNfcaSelRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCA_FDTMIN ) );
/* Ensure proper response length */
if( rxLen != sizeof(rfalNfcaSelRes) )
{
return ERR_PROTO;
}
}
/* REMARK: Could check if NFCID1 is complete */
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcaPollerSleep( void )
{
rfalNfcaSlpReq slpReq;
uint8_t rxBuf; /* dummy buffer, just to perform Rx */
slpReq.frame[RFAL_NFCA_SLP_CMD_POS] = RFAL_NFCA_SLP_CMD;
slpReq.frame[RFAL_NFCA_SLP_BYTE2_POS] = RFAL_NFCA_SLP_BYTE2;
rfalTransceiveBlockingTxRx( (uint8_t*)&slpReq, sizeof(rfalNfcaSlpReq), &rxBuf, sizeof(rxBuf), NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCA_SLP_FWT );
/* ISO14443-3 6.4.3 HLTA - If PICC responds with any modulation during 1 ms this response shall be interpreted as not acknowledge
Digital 2.0 6.9.2.1 & EMVCo 3.0 5.6.2.1 - consider the HLTA command always acknowledged
No check to be compliant with NFC and EMVCo, and to improve interoprability (Kovio RFID Tag)
*/
return ERR_NONE;
}
/*******************************************************************************/
bool rfalNfcaListenerIsSleepReq( const uint8_t *buf, uint16_t bufLen )
{
/* Check if length and payload match */
if( (bufLen != sizeof(rfalNfcaSlpReq)) || (buf[RFAL_NFCA_SLP_CMD_POS] != RFAL_NFCA_SLP_CMD) || (buf[RFAL_NFCA_SLP_BYTE2_POS] != RFAL_NFCA_SLP_BYTE2) )
{
return false;
}
return true;
}
/* If the guards here don't compile then the code above cannot work anymore. */
extern uint8_t guard_eq_RFAL_NFCA_T2T[((RFAL_NFCA_SEL_RES_CONF_MASK&(uint8_t)RFAL_NFCA_T2T) == (uint8_t)RFAL_NFCA_T2T)?1:(-1)];
extern uint8_t guard_eq_RFAL_NFCA_T4T[((RFAL_NFCA_SEL_RES_CONF_MASK&(uint8_t)RFAL_NFCA_T4T) == (uint8_t)RFAL_NFCA_T4T)?1:(-1)];
extern uint8_t guard_eq_RFAL_NFCA_NFCDEP[((RFAL_NFCA_SEL_RES_CONF_MASK&(uint8_t)RFAL_NFCA_NFCDEP) == (uint8_t)RFAL_NFCA_NFCDEP)?1:(-1)];
extern uint8_t guard_eq_RFAL_NFCA_T4T_NFCDEP[((RFAL_NFCA_SEL_RES_CONF_MASK&(uint8_t)RFAL_NFCA_T4T_NFCDEP) == (uint8_t)RFAL_NFCA_T4T_NFCDEP)?1:(-1)];
#endif /* RFAL_FEATURE_NFCA */

View file

@ -0,0 +1,504 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfcb.c
*
* \author Gustavo Patricio
*
* \brief Implementation of NFC-B (ISO14443B) helpers
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_nfcb.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_NFCB
#define RFAL_FEATURE_NFCB false /* NFC-B module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_NFCB
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCB_SENSB_REQ_EXT_SENSB_RES_SUPPORTED 0x10U /*!< Bit mask for Extended SensB Response support in SENSB_REQ */
#define RFAL_NFCB_SENSB_RES_PROT_TYPE_RFU 0x08U /*!< Bit mask for Protocol Type RFU in SENSB_RES */
#define RFAL_NFCB_SLOT_MARKER_SC_SHIFT 4U /*!< Slot Code position on SLOT_MARKER APn */
#define RFAL_NFCB_SLOTMARKER_SLOTCODE_MIN 1U /*!< SLOT_MARKER Slot Code minimum Digital 1.1 Table 37 */
#define RFAL_NFCB_SLOTMARKER_SLOTCODE_MAX 16U /*!< SLOT_MARKER Slot Code maximum Digital 1.1 Table 37 */
#define RFAL_NFCB_ACTIVATION_FWT (RFAL_NFCB_FWTSENSB + RFAL_NFCB_DTPOLL_20) /*!< FWT(SENSB) + dTbPoll Digital 2.0 7.9.1.3 */
/*! Advanced and Extended bit mask in Parameter of SENSB_REQ */
#define RFAL_NFCB_SENSB_REQ_PARAM (RFAL_NFCB_SENSB_REQ_ADV_FEATURE | RFAL_NFCB_SENSB_REQ_EXT_SENSB_RES_SUPPORTED)
/*! NFC-B commands definition */
enum
{
RFAL_NFCB_CMD_SENSB_REQ = 0x05, /*!< SENSB_REQ (REQB) & SLOT_MARKER Digital 1.1 Table 24 */
RFAL_NFCB_CMD_SENSB_RES = 0x50, /*!< SENSB_RES (ATQB) & SLOT_MARKER Digital 1.1 Table 27 */
RFAL_NFCB_CMD_SLPB_REQ = 0x50, /*!< SLPB_REQ (HLTB command) Digital 1.1 Table 38 */
RFAL_NFCB_CMD_SLPB_RES = 0x00 /*!< SLPB_RES (HLTB Answer) Digital 1.1 Table 39 */
};
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define rfalNfcbNI2NumberOfSlots( ni ) (uint8_t)(1U << (ni)) /*!< Converts the Number of slots Identifier to slot number */
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! ALLB_REQ (WUPB) and SENSB_REQ (REQB) Command Format Digital 1.1 7.6.1 */
typedef struct
{
uint8_t cmd; /*!< xxxxB_REQ: 05h */
uint8_t AFI; /*!< NFC Identifier */
uint8_t PARAM; /*!< Application Data */
} rfalNfcbSensbReq;
/*! SLOT_MARKER Command format Digital 1.1 7.7.1 */
typedef struct
{
uint8_t APn; /*!< Slot number 2..16 | 0101b */
} rfalNfcbSlotMarker;
/*! SLPB_REQ (HLTB) Command Format Digital 1.1 7.8.1 */
typedef struct
{
uint8_t cmd; /*!< SLPB_REQ: 50h */
uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFC Identifier (PUPI)*/
} rfalNfcbSlpbReq;
/*! SLPB_RES (HLTB) Response Format Digital 1.1 7.8.2 */
typedef struct
{
uint8_t cmd; /*!< SLPB_RES: 00h */
} rfalNfcbSlpbRes;
/*! RFAL NFC-B instance */
typedef struct
{
uint8_t AFI; /*!< AFI to be used */
uint8_t PARAM; /*!< PARAM to be used */
} rfalNfcb;
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static ReturnCode rfalNfcbCheckSensbRes( const rfalNfcbSensbRes *sensbRes, uint8_t sensbResLen );
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
static rfalNfcb gRfalNfcb; /*!< RFAL NFC-B Instance */
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
static ReturnCode rfalNfcbCheckSensbRes( const rfalNfcbSensbRes *sensbRes, uint8_t sensbResLen )
{
/* Check response length */
if( ( (sensbResLen != RFAL_NFCB_SENSB_RES_LEN) && (sensbResLen != RFAL_NFCB_SENSB_RES_EXT_LEN) ) )
{
return ERR_PROTO;
}
/* Check SENSB_RES and Protocol Type Digital 1.1 7.6.2.19 */
if( ((sensbRes->protInfo.FsciProType & RFAL_NFCB_SENSB_RES_PROT_TYPE_RFU) != 0U) || (sensbRes->cmd != (uint8_t)RFAL_NFCB_CMD_SENSB_RES) )
{
return ERR_PROTO;
}
return ERR_NONE;
}
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
ReturnCode rfalNfcbPollerInitialize( void )
{
ReturnCode ret;
EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCB, RFAL_BR_106, RFAL_BR_106 ) );
rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC );
rfalSetGT( RFAL_GT_NFCB );
rfalSetFDTListen( RFAL_FDT_LISTEN_NFCB_POLLER );
rfalSetFDTPoll( RFAL_FDT_POLL_NFCB_POLLER );
gRfalNfcb.AFI = RFAL_NFCB_AFI;
gRfalNfcb.PARAM = RFAL_NFCB_PARAM;
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcbPollerInitializeWithParams( uint8_t AFI, uint8_t PARAM )
{
ReturnCode ret;
EXIT_ON_ERR( ret, rfalNfcbPollerInitialize() );
gRfalNfcb.AFI = AFI;
gRfalNfcb.PARAM = (PARAM & RFAL_NFCB_SENSB_REQ_PARAM);
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcbPollerCheckPresence( rfalNfcbSensCmd cmd, rfalNfcbSlots slots, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen )
{
uint16_t rxLen;
ReturnCode ret;
rfalNfcbSensbReq sensbReq;
/* Check if the command requested and given the slot number are valid */
if( ((RFAL_NFCB_SENS_CMD_SENSB_REQ != cmd) && (RFAL_NFCB_SENS_CMD_ALLB_REQ != cmd)) ||
(slots > RFAL_NFCB_SLOT_NUM_16) || (sensbRes == NULL) || (sensbResLen == NULL) )
{
return ERR_PARAM;
}
*sensbResLen = 0;
ST_MEMSET(sensbRes, 0x00, sizeof(rfalNfcbSensbRes) );
/* Compute SENSB_REQ */
sensbReq.cmd = RFAL_NFCB_CMD_SENSB_REQ;
sensbReq.AFI = gRfalNfcb.AFI;
sensbReq.PARAM = (((uint8_t)gRfalNfcb.PARAM & RFAL_NFCB_SENSB_REQ_PARAM) | (uint8_t)cmd | (uint8_t)slots);
/* Send SENSB_REQ and disable AGC to detect collisions */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&sensbReq, sizeof(rfalNfcbSensbReq), (uint8_t*)sensbRes, sizeof(rfalNfcbSensbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_FWTSENSB );
*sensbResLen = (uint8_t)rxLen;
/* Check if a transmission error was detected */
if( (ret == ERR_CRC) || (ret == ERR_FRAMING) )
{
/* Invalidate received frame as an error was detected (CollisionResolution checks if valid) */
*sensbResLen = 0;
return ERR_NONE;
}
if( ret == ERR_NONE )
{
return rfalNfcbCheckSensbRes( sensbRes, *sensbResLen );
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalNfcbPollerSleep( const uint8_t* nfcid0 )
{
uint16_t rxLen;
ReturnCode ret;
rfalNfcbSlpbReq slpbReq;
rfalNfcbSlpbRes slpbRes;
if( nfcid0 == NULL )
{
return ERR_PARAM;
}
/* Compute SLPB_REQ */
slpbReq.cmd = RFAL_NFCB_CMD_SLPB_REQ;
ST_MEMCPY( slpbReq.nfcid0, nfcid0, RFAL_NFCB_NFCID0_LEN );
EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&slpbReq, sizeof(rfalNfcbSlpbReq), (uint8_t*)&slpbRes, sizeof(rfalNfcbSlpbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_ACTIVATION_FWT ));
/* Check SLPB_RES */
if( (rxLen != sizeof(rfalNfcbSlpbRes)) || (slpbRes.cmd != (uint8_t)RFAL_NFCB_CMD_SLPB_RES) )
{
return ERR_PROTO;
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcbPollerSlotMarker( uint8_t slotCode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen )
{
ReturnCode ret;
rfalNfcbSlotMarker slotMarker;
uint16_t rxLen;
/* Check parameters */
if( (sensbRes == NULL) || (sensbResLen == NULL) ||
(slotCode < RFAL_NFCB_SLOTMARKER_SLOTCODE_MIN) ||
(slotCode > RFAL_NFCB_SLOTMARKER_SLOTCODE_MAX) )
{
return ERR_PARAM;
}
/* Compose and send SLOT_MARKER with disabled AGC to detect collisions */
slotMarker.APn = ((slotCode << RFAL_NFCB_SLOT_MARKER_SC_SHIFT) | (uint8_t)RFAL_NFCB_CMD_SENSB_REQ);
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&slotMarker, sizeof(rfalNfcbSlotMarker), (uint8_t*)sensbRes, sizeof(rfalNfcbSensbRes), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCB_ACTIVATION_FWT );
*sensbResLen = (uint8_t)rxLen;
/* Check if a transmission error was detected */
if( (ret == ERR_CRC) || (ret == ERR_FRAMING) )
{
return ERR_RF_COLLISION;
}
if( ret == ERR_NONE )
{
return rfalNfcbCheckSensbRes( sensbRes, *sensbResLen );
}
return ret;
}
ReturnCode rfalNfcbPollerTechnologyDetection( rfalComplianceMode compMode, rfalNfcbSensbRes *sensbRes, uint8_t *sensbResLen )
{
NO_WARNING(compMode);
return rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_SENSB_REQ, RFAL_NFCB_SLOT_NUM_1, sensbRes, sensbResLen );
}
/*******************************************************************************/
ReturnCode rfalNfcbPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt )
{
bool colPending; /* dummy */
return rfalNfcbPollerSlottedCollisionResolution( compMode, devLimit, RFAL_NFCB_SLOT_NUM_1, RFAL_NFCB_SLOT_NUM_16, nfcbDevList, devCnt, &colPending );
}
/*******************************************************************************/
ReturnCode rfalNfcbPollerSlottedCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcbSlots initSlots, rfalNfcbSlots endSlots, rfalNfcbListenDevice *nfcbDevList, uint8_t *devCnt, bool *colPending )
{
ReturnCode ret;
uint8_t slotsNum;
uint8_t slotCode;
uint8_t curDevCnt;
/* Check parameters. In ISO | Activity 1.0 mode the initial slots must be 1 as continuation of Technology Detection */
if( (nfcbDevList == NULL) || (devCnt == NULL) || (colPending == NULL) || (initSlots > RFAL_NFCB_SLOT_NUM_16) ||
(endSlots > RFAL_NFCB_SLOT_NUM_16) || ((compMode == RFAL_COMPLIANCE_MODE_ISO) && (initSlots != RFAL_NFCB_SLOT_NUM_1)) )
{
return ERR_PARAM;
}
/* Initialise as no error in case Activity 1.0 where the previous SENSB_RES from technology detection should be used */
ret = ERR_NONE;
*devCnt = 0;
curDevCnt = 0;
*colPending = false;
/* Send ALLB_REQ Activity 1.1 9.3.5.2 and 9.3.5.3 (Symbol 1 and 2) */
if( compMode != RFAL_COMPLIANCE_MODE_ISO )
{
ret = rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_ALLB_REQ, initSlots, &nfcbDevList->sensbRes, &nfcbDevList->sensbResLen );
if( (ret != ERR_NONE) && (initSlots == RFAL_NFCB_SLOT_NUM_1) )
{
return ret;
}
}
/* Check if there was a transmission error on WUPB EMVCo 2.6 9.3.3.1 */
if( (compMode == RFAL_COMPLIANCE_MODE_EMV) && (nfcbDevList->sensbResLen == 0U) )
{
return ERR_FRAMING;
}
for( slotsNum = (uint8_t)initSlots; slotsNum <= (uint8_t)endSlots; slotsNum++ )
{
do {
/* Activity 1.1 9.3.5.23 - Symbol 22 */
if( (compMode == RFAL_COMPLIANCE_MODE_NFC) && (curDevCnt != 0U) )
{
rfalNfcbPollerSleep( nfcbDevList[((*devCnt) - (uint8_t)1U)].sensbRes.nfcid0 );
nfcbDevList[((*devCnt) - (uint8_t)1U)].isSleep = true;
}
/* Send SENSB_REQ with number of slots if not the first Activity 1.1 9.3.5.24 - Symbol 23 */
if( (slotsNum != (uint8_t)initSlots) || *colPending )
{
/* PRQA S 4342 1 # MISRA 10.5 - Layout of rfalNfcbSlots and above loop guarantee that no invalid enum values are created. */
ret = rfalNfcbPollerCheckPresence( RFAL_NFCB_SENS_CMD_SENSB_REQ, (rfalNfcbSlots)slotsNum, &nfcbDevList[*devCnt].sensbRes, &nfcbDevList[*devCnt].sensbResLen );
}
/* Activity 1.1 9.3.5.6 - Symbol 5 */
slotCode = 0;
curDevCnt = 0;
*colPending = false;
do{
/* Activity 1.1 9.3.5.26 - Symbol 25 */
if( slotCode != 0U )
{
ret = rfalNfcbPollerSlotMarker( slotCode, &nfcbDevList[*devCnt].sensbRes, &nfcbDevList[*devCnt].sensbResLen );
}
/* Activity 1.1 9.3.5.7 and 9.3.5.8 - Symbol 6 */
if( ret != ERR_TIMEOUT )
{
/* Activity 1.1 9.3.5.8 - Symbol 7 */
if( (rfalNfcbCheckSensbRes( &nfcbDevList[*devCnt].sensbRes, nfcbDevList[*devCnt].sensbResLen) == ERR_NONE) && (ret == ERR_NONE) )
{
nfcbDevList[*devCnt].isSleep = false;
if( compMode == RFAL_COMPLIANCE_MODE_EMV )
{
(*devCnt)++;
return ret;
}
else if( compMode == RFAL_COMPLIANCE_MODE_ISO )
{
/* Activity 1.0 9.3.5.8 - Symbol 7 */
(*devCnt)++;
curDevCnt++;
/* Activity 1.0 9.3.5.10 - Symbol 9 */
if( (*devCnt >= devLimit) || (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) )
{
return ret;
}
/* Activity 1.0 9.3.5.11 - Symbol 10 */
rfalNfcbPollerSleep( nfcbDevList[*devCnt-1U].sensbRes.nfcid0 );
nfcbDevList[*devCnt-1U].isSleep = true;
}
else if( compMode == RFAL_COMPLIANCE_MODE_NFC )
{
/* Activity 1.1 9.3.5.10 and 9.3.5.11 - Symbol 9 and Symbol 11*/
if(curDevCnt != 0U)
{
rfalNfcbPollerSleep( nfcbDevList[(*devCnt) - (uint8_t)1U].sensbRes.nfcid0 );
nfcbDevList[(*devCnt) - (uint8_t)1U].isSleep = true;
}
/* Activity 1.1 9.3.5.12 - Symbol 11 */
(*devCnt)++;
curDevCnt++;
/* Activity 1.1 9.3.5.6 - Symbol 13 */
if( (*devCnt >= devLimit) || (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) )
{
return ret;
}
}
else
{
/* MISRA 15.7 - Empty else */
}
}
else
{
/* If deviceLimit is set to 0 the NFC Forum Device is configured to perform collision detection only Activity 1.0 and 1.1 9.3.5.5 - Symbol 4 */
if( (devLimit == 0U) && (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1) )
{
return ERR_RF_COLLISION;
}
/* Activity 1.1 9.3.5.9 - Symbol 8 */
*colPending = true;
}
}
/* Activity 1.1 9.3.5.15 - Symbol 14 */
slotCode++;
}
while( slotCode < rfalNfcbNI2NumberOfSlots(slotsNum) );
/* Activity 1.1 9.3.5.17 - Symbol 16 */
if( !(*colPending) )
{
return ERR_NONE;
}
/* Activity 1.1 9.3.5.18 - Symbol 17 */
} while (curDevCnt != 0U); /* If a collision is detected and card(s) were found on this loop keep the same number of available slots */
}
return ERR_NONE;
}
/*******************************************************************************/
uint32_t rfalNfcbTR2ToFDT( uint8_t tr2Code )
{
/*******************************************************************************/
/* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */
/*! TR2 Table according to Digital 1.1 Table 33 */
const uint16_t rfalNfcbTr2Table[] = { 1792, 3328, 5376, 9472 };
/*******************************************************************************/
return rfalNfcbTr2Table[ (tr2Code & RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK) ];
}
#endif /* RFAL_FEATURE_NFCB */

View file

@ -0,0 +1,546 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfcf.c
*
* \author Gustavo Patricio
*
* \brief Implementation of NFC-F Poller (FeliCa PCD) device
*
* The definitions and helpers methods provided by this module are
* aligned with NFC-F (FeliCa - JIS X6319-4)
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_nfcf.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_NFCF
#define RFAL_FEATURE_NFCF false /* NFC-F module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_NFCF
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCF_SENSF_REQ_LEN_MIN 5U /*!< SENSF_RES minimum length */
#define RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN 15U /*!< Minimum length for a Check Command T3T 5.4.1 */
#define RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN 31U /*!< Minimum length for an Update Command T3T 5.5.1 */
#define RFAL_NFCF_CHECK_RES_MIN_LEN 11U /*!< CHECK Response minimum length T3T 1.0 Table 8 */
#define RFAL_NFCF_UPDATE_RES_MIN_LEN 11U /*!< UPDATE Response minimum length T3T 1.0 Table 8 */
#define RFAL_NFCF_CHECK_REQ_MAX_LEN 86U /*!< Max length of a Check request T3T 1.0 Table 7 */
#define RFAL_NFCF_CHECK_REQ_MAX_SERV 15U /*!< Max Services number on Check request T3T 1.0 5.4.1.5 */
#define RFAL_NFCF_CHECK_REQ_MAX_BLOCK 15U /*!< Max Blocks number on Check request T3T 1.0 5.4.1.10 */
#define RFAL_NFCF_UPDATE_REQ_MAX_SERV 15U /*!< Max Services number Update request T3T 1.0 5.4.1.5 */
#define RFAL_NFCF_UPDATE_REQ_MAX_BLOCK 13U /*!< Max Blocks number on Update request T3T 1.0 5.4.1.10 */
/*! MRT Check | Uupdate = (Tt3t x ((A+1) + n (B+1)) x 4^E) + dRWTt3t T3T 5.8
Max values used: A = 7 ; B = 7 ; E = 3 ; n = 15 (NFC Forum n = 15, JIS n = 32)
*/
#define RFAL_NFCF_MRT_CHECK_UPDATE ((4096 * (8 + (15 * 8)) * 64 ) + 16)
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define rfalNfcfSlots2CardNum( s ) ((uint8_t)(s)+1U) /*!< Converts Time Slot Number (TSN) into num of slots */
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! Structure/Buffer to hold the SENSF_RES with LEN byte prepended */
typedef struct{
uint8_t LEN; /*!< NFC-F LEN byte */
rfalNfcfSensfRes SENSF_RES; /*!< SENSF_RES */
} rfalNfcfSensfResBuf;
/*! Greedy collection for NFCF GRE_POLL_F Activity 1.0 Table 10 */
typedef struct{
uint8_t pollFound; /*!< Number of devices found by the Poll */
uint8_t pollCollision; /*!< Number of collisions detected */
rfalFeliCaPollRes POLL_F[RFAL_NFCF_POLL_MAXCARDS]; /*!< GRE_POLL_F Activity 1.0 Table 10 */
} rfalNfcfGreedyF;
/*! NFC-F SENSF_REQ format Digital 1.1 8.6.1 */
typedef struct
{
uint8_t CMD; /*!< Command code: 00h */
uint8_t SC[RFAL_NFCF_SENSF_SC_LEN]; /*!< System Code */
uint8_t RC; /*!< Request Code */
uint8_t TSN; /*!< Time Slot Number */
} rfalNfcfSensfReq;
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
static rfalNfcfGreedyF gRfalNfcfGreedyF; /*!< Activity's NFCF Greedy collection */
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static void rfalNfcfComputeValidSENF( rfalNfcfListenDevice *outDevInfo, uint8_t *curDevIdx, uint8_t devLimit, bool overwrite, bool *nfcDepFound );
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
/*******************************************************************************/
static void rfalNfcfComputeValidSENF( rfalNfcfListenDevice *outDevInfo, uint8_t *curDevIdx, uint8_t devLimit, bool overwrite, bool *nfcDepFound )
{
uint8_t tmpIdx;
bool duplicate;
const rfalNfcfSensfResBuf *sensfBuf;
rfalNfcfSensfResBuf sensfCopy;
/*******************************************************************************/
/* Go through all responses check if valid and duplicates */
/*******************************************************************************/
while( (gRfalNfcfGreedyF.pollFound > 0U) && ((*curDevIdx) < devLimit) )
{
duplicate = false;
gRfalNfcfGreedyF.pollFound--;
/* MISRA 11.3 - Cannot point directly into different object type, use local copy */
ST_MEMCPY( (uint8_t*)&sensfCopy, (uint8_t*)&gRfalNfcfGreedyF.POLL_F[gRfalNfcfGreedyF.pollFound], sizeof(rfalNfcfSensfResBuf) );
/* Point to received SENSF_RES */
sensfBuf = &sensfCopy;
/* Check for devices that are already in device list */
for( tmpIdx = 0; tmpIdx < (*curDevIdx); tmpIdx++ )
{
if( ST_BYTECMP( sensfBuf->SENSF_RES.NFCID2, outDevInfo[tmpIdx].sensfRes.NFCID2, RFAL_NFCF_NFCID2_LEN ) == 0 )
{
duplicate = true;
break;
}
}
/* If is a duplicate skip this (and not to overwrite)*/
if(duplicate && !overwrite)
{
continue;
}
/* Check if response length is OK */
if( (( sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) < RFAL_NFCF_SENSF_RES_LEN_MIN) || ((sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) > RFAL_NFCF_SENSF_RES_LEN_MAX) )
{
continue;
}
/* Check if the response is a SENSF_RES / Polling response */
if( sensfBuf->SENSF_RES.CMD != (uint8_t)RFAL_NFCF_CMD_POLLING_RES )
{
continue;
}
/* Check if is an overwrite request or new device*/
if(duplicate && overwrite)
{
/* overwrite deviceInfo/GRE_SENSF_RES with SENSF_RES */
outDevInfo[tmpIdx].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN);
ST_MEMCPY( &outDevInfo[tmpIdx].sensfRes, &sensfBuf->SENSF_RES, outDevInfo[tmpIdx].sensfResLen );
continue;
}
else
{
/* fill deviceInfo/GRE_SENSF_RES with new SENSF_RES */
outDevInfo[(*curDevIdx)].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN);
ST_MEMCPY( &outDevInfo[(*curDevIdx)].sensfRes, &sensfBuf->SENSF_RES, outDevInfo[(*curDevIdx)].sensfResLen );
}
/* Check if this device supports NFC-DEP and signal it (ACTIVITY 1.1 9.3.6.63) */
*nfcDepFound = rfalNfcfIsNfcDepSupported( &outDevInfo[(*curDevIdx)] );
(*curDevIdx)++;
}
}
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
ReturnCode rfalNfcfPollerInitialize( rfalBitRate bitRate )
{
ReturnCode ret;
if( (bitRate != RFAL_BR_212) && (bitRate != RFAL_BR_424) )
{
return ERR_PARAM;
}
EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCF, bitRate, bitRate ) );
rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC );
rfalSetGT( RFAL_GT_NFCF );
rfalSetFDTListen( RFAL_FDT_LISTEN_NFCF_POLLER );
rfalSetFDTPoll( RFAL_FDT_POLL_NFCF_POLLER );
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcfPollerPoll( rfalFeliCaPollSlots slots, uint16_t sysCode, uint8_t reqCode, rfalFeliCaPollRes *cardList, uint8_t *devCnt, uint8_t *collisions )
{
return rfalFeliCaPoll( slots, sysCode, reqCode, cardList, rfalNfcfSlots2CardNum(slots), devCnt, collisions );
}
/*******************************************************************************/
ReturnCode rfalNfcfPollerCheckPresence( void )
{
gRfalNfcfGreedyF.pollFound = 0;
gRfalNfcfGreedyF.pollCollision = 0;
/* ACTIVITY 1.0 & 1.1 - 9.2.3.17 SENSF_REQ must be with number of slots equal to 4
* SC must be 0xFFFF
* RC must be 0x00 (No system code info required) */
return rfalFeliCaPoll( RFAL_FELICA_4_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_NO_REQUEST, gRfalNfcfGreedyF.POLL_F, rfalNfcfSlots2CardNum(RFAL_FELICA_4_SLOTS), &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision );
}
/*******************************************************************************/
ReturnCode rfalNfcfPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcfListenDevice *nfcfDevList, uint8_t *devCnt )
{
ReturnCode ret;
bool nfcDepFound;
if( (nfcfDevList == NULL) || (devCnt == NULL) )
{
return ERR_PARAM;
}
*devCnt = 0;
nfcDepFound = false;
/*******************************************************************************************/
/* ACTIVITY 1.0 - 9.3.6.3 Copy valid SENSF_RES in GRE_POLL_F into GRE_SENSF_RES */
/* ACTIVITY 1.0 - 9.3.6.6 The NFC Forum Device MUST remove all entries from GRE_SENSF_RES[]*/
/* ACTIVITY 1.1 - 9.3.63.59 Populate GRE_SENSF_RES with data from GRE_POLL_F */
/* */
/* CON_DEVICES_LIMIT = 0 Just check if devices from Tech Detection exceeds -> always true */
/* Allow the number of slots open on Technology Detection */
/*******************************************************************************************/
rfalNfcfComputeValidSENF( nfcfDevList, devCnt, ((devLimit == 0U) ? rfalNfcfSlots2CardNum( RFAL_FELICA_4_SLOTS ) : devLimit), false, &nfcDepFound );
/*******************************************************************************/
/* ACTIVITY 1.0 - 9.3.6.4 */
/* ACTIVITY 1.1 - 9.3.63.60 Check if devices found are lower than the limit */
/* and send a SENSF_REQ if so */
/*******************************************************************************/
if( *devCnt < devLimit )
{
/* ACTIVITY 1.0 - 9.3.6.5 Copy valid SENSF_RES and then to remove it
* ACTIVITY 1.1 - 9.3.6.65 Copy and filter duplicates
* For now, due to some devices keep generating different nfcid2, we use 1.0
* Phones detected: Samsung Galaxy Nexus,Samsung Galaxy S3,Samsung Nexus S */
*devCnt = 0;
ret = rfalNfcfPollerPoll( RFAL_FELICA_16_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_NO_REQUEST, gRfalNfcfGreedyF.POLL_F, &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision );
if( ret == ERR_NONE )
{
rfalNfcfComputeValidSENF( nfcfDevList, devCnt, devLimit, false, &nfcDepFound );
}
/*******************************************************************************/
/* ACTIVITY 1.1 - 9.3.6.63 Check if any device supports NFC DEP */
/*******************************************************************************/
if( nfcDepFound && (compMode == RFAL_COMPLIANCE_MODE_NFC) )
{
ret = rfalNfcfPollerPoll( RFAL_FELICA_16_SLOTS, RFAL_NFCF_SYSTEMCODE, RFAL_FELICA_POLL_RC_SYSTEM_CODE, gRfalNfcfGreedyF.POLL_F, &gRfalNfcfGreedyF.pollFound, &gRfalNfcfGreedyF.pollCollision );
if( ret == ERR_NONE )
{
rfalNfcfComputeValidSENF( nfcfDevList, devCnt, devLimit, true, &nfcDepFound );
}
}
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcfPollerCheck( const uint8_t* nfcid2, const rfalNfcfServBlockListParam *servBlock, uint8_t *rxBuf, uint16_t rxBufLen, uint16_t *rcvdLen )
{
uint8_t txBuf[RFAL_NFCF_CHECK_REQ_MAX_LEN];
uint8_t msgIt;
uint8_t i;
ReturnCode ret;
const uint8_t *checkRes;
/* Check parameters */
if( (nfcid2 == NULL) || (rxBuf == NULL) || (servBlock == NULL) ||
(servBlock->numBlock == 0U) || (servBlock->numBlock > RFAL_NFCF_CHECK_REQ_MAX_BLOCK) ||
(servBlock->numServ == 0U) || (servBlock->numServ > RFAL_NFCF_CHECK_REQ_MAX_SERV) ||
(rxBufLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECK_RES_MIN_LEN)) )
{
return ERR_PARAM;
}
msgIt = 0;
/*******************************************************************************/
/* Compose CHECK command/request */
txBuf[msgIt++] = RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION; /* Command Code */
ST_MEMCPY( &txBuf[msgIt], nfcid2, RFAL_NFCF_NFCID2_LEN ); /* NFCID2 */
msgIt += RFAL_NFCF_NFCID2_LEN;
txBuf[msgIt++] = servBlock->numServ; /* NoS */
for( i = 0; i < servBlock->numServ; i++)
{
txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 0U) & 0xFFU); /* Service Code */
txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 8U) & 0xFFU);
}
txBuf[msgIt++] = servBlock->numBlock; /* NoB */
for( i = 0; i < servBlock->numBlock; i++)
{
txBuf[msgIt++] = servBlock->blockList[i].conf; /* Block list element conf (Flag|Access|Service) */
if( (servBlock->blockList[i].conf & 0x80U) != 0U ) /* Check if 2 or 3 byte block list element */
{
txBuf[msgIt++] = (uint8_t)(servBlock->blockList[i].blockNum & 0xFFU); /* 1byte Block Num */
}
else
{
txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 0U) & 0xFFU); /* 2byte Block Num */
txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 8U) & 0xFFU);
}
}
/*******************************************************************************/
/* Transceive CHECK command/request */
ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, rxBuf, rxBufLen, rcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCF_MRT_CHECK_UPDATE );
if( ret == ERR_NONE )
{
/* Skip LEN byte */
checkRes = (rxBuf + RFAL_NFCF_LENGTH_LEN);
/* Check response length */
if( *rcvdLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_ST2_POS) )
{
ret = ERR_PROTO;
}
/* Check for a valid response */
else if( (checkRes[RFAL_NFCF_CMD_POS] != (uint8_t)RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION_RES) ||
(checkRes[RFAL_NFCF_CHECKUPDATE_RES_ST1_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) ||
(checkRes[RFAL_NFCF_CHECKUPDATE_RES_ST2_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) )
{
ret = ERR_REQUEST;
}
/* CHECK succesfull, remove header */
else
{
(*rcvdLen) -= (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_NOB_POS);
if( *rcvdLen > 0U )
{
ST_MEMMOVE( rxBuf, &checkRes[RFAL_NFCF_CHECKUPDATE_RES_NOB_POS], (*rcvdLen) );
}
}
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalNfcfPollerUpdate( const uint8_t* nfcid2, const rfalNfcfServBlockListParam *servBlock, uint8_t *txBuf, uint16_t txBufLen, const uint8_t *blockData, uint8_t *rxBuf, uint16_t rxBufLen )
{
uint8_t i;
uint16_t msgIt;
uint16_t rcvdLen;
uint16_t auxLen;
const uint8_t *updateRes;
ReturnCode ret;
/* Check parameters */
if( (nfcid2 == NULL) || (rxBuf == NULL) || (servBlock == NULL) || (txBuf == NULL) ||
(servBlock->numBlock == 0U) || (servBlock->numBlock > RFAL_NFCF_UPDATE_REQ_MAX_BLOCK) ||
(servBlock->numServ == 0U) || (servBlock->numServ > RFAL_NFCF_UPDATE_REQ_MAX_SERV) ||
(rxBufLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_UPDATE_RES_MIN_LEN)) )
{
return ERR_PARAM;
}
/* Calculate required txBuffer lenth */
auxLen = (uint16_t)( RFAL_NFCF_CMD_LEN + RFAL_NFCF_NFCID2_LEN + ( servBlock->numServ * sizeof(rfalNfcfServ) ) +
(servBlock->numBlock * sizeof(rfalNfcfBlockListElem)) + (uint16_t)((uint16_t)servBlock->numBlock * RFAL_NFCF_BLOCK_LEN) );
/* Check whether the provided buffer is sufficient for this request */
if( txBufLen < auxLen )
{
return ERR_PARAM;
}
msgIt = 0;
/*******************************************************************************/
/* Compose UPDATE command/request */
txBuf[msgIt++] = RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION; /* Command Code */
ST_MEMCPY( &txBuf[msgIt], nfcid2, RFAL_NFCF_NFCID2_LEN ); /* NFCID2 */
msgIt += RFAL_NFCF_NFCID2_LEN;
txBuf[msgIt++] = servBlock->numServ; /* NoS */
for( i = 0; i < servBlock->numServ; i++)
{
txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 0U) & 0xFFU); /* Service Code */
txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 8U) & 0xFFU);
}
txBuf[msgIt++] = servBlock->numBlock; /* NoB */
for( i = 0; i < servBlock->numBlock; i++)
{
txBuf[msgIt++] = servBlock->blockList[i].conf; /* Block list element conf (Flag|Access|Service) */
if( (servBlock->blockList[i].conf & 0x80U) != 0U ) /* Check if 2 or 3 byte block list element */
{
txBuf[msgIt++] = (uint8_t)(servBlock->blockList[i].blockNum & 0xFFU); /* 1byte Block Num */
}
else
{
txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 0U) & 0xFFU); /* 2byte Block Num */
txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 8U) & 0xFFU);
}
}
auxLen = ((uint16_t)servBlock->numBlock * RFAL_NFCF_BLOCK_LEN);
ST_MEMCPY( &txBuf[msgIt], blockData, auxLen ); /* Block Data */
msgIt += auxLen;
/*******************************************************************************/
/* Transceive UPDATE command/request */
ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, rxBuf, rxBufLen, &rcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCF_MRT_CHECK_UPDATE );
if( ret == ERR_NONE )
{
/* Skip LEN byte */
updateRes = (rxBuf + RFAL_NFCF_LENGTH_LEN);
/* Check response length */
if( rcvdLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_ST2_POS) )
{
ret = ERR_PROTO;
}
/* Check for a valid response */
else if( (updateRes[RFAL_NFCF_CMD_POS] != (uint8_t)RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION_RES) ||
(updateRes[RFAL_NFCF_CHECKUPDATE_RES_ST1_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) ||
(updateRes[RFAL_NFCF_CHECKUPDATE_RES_ST2_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) )
{
ret = ERR_REQUEST;
}
else
{
/* MISRA 15.7 - Empty else */
}
}
return ret;
}
/*******************************************************************************/
bool rfalNfcfListenerIsT3TReq( const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid2 )
{
/* Check cmd byte */
switch( *buf )
{
case RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION:
if( bufLen < RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN )
{
return false;
}
break;
case RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION:
if( bufLen < RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN )
{
return false;
}
break;
default:
return false;
}
/* Output NFID2 if requested */
if( nfcid2 != NULL )
{
ST_MEMCPY( nfcid2, &buf[RFAL_NFCF_CMD_LEN], RFAL_NFCF_NFCID2_LEN );
}
return true;
}
#endif /* RFAL_FEATURE_NFCF */

View file

@ -0,0 +1,870 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_nfcv.c
*
* \author Gustavo Patricio
*
* \brief Implementation of NFC-V Poller (ISO15693) device
*
* The definitions and helpers methods provided by this module are
* aligned with NFC-V (ISO15693)
*
* The definitions and helpers methods provided by this module
* are aligned with NFC-V Digital 2.1
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_nfcv.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_NFCV
#define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_NFCV
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_NFCV_INV_REQ_FLAG 0x06U /*!< INVENTORY_REQ INV_FLAG Digital 2.1 9.6.1 */
#define RFAL_NFCV_MASKVAL_MAX_LEN 8U /*!< Mask value max length: 64 bits (UID length) */
#define RFAL_NFCV_MASKVAL_MAX_1SLOT_LEN 64U /*!< Mask value max length in 1 Slot mode in bits Digital 2.1 9.6.1.6 */
#define RFAL_NFCV_MASKVAL_MAX_16SLOT_LEN 60U /*!< Mask value max length in 16 Slot mode in bits Digital 2.1 9.6.1.6 */
#define RFAL_NFCV_MAX_SLOTS 16U /*!< NFC-V max number of Slots */
#define RFAL_NFCV_INV_REQ_HEADER_LEN 3U /*!< INVENTORY_REQ header length (INV_FLAG, CMD, MASK_LEN) */
#define RFAL_NFCV_INV_RES_LEN 10U /*!< INVENTORY_RES length */
#define RFAL_NFCV_WR_MUL_REQ_HEADER_LEN 4U /*!< Write Multiple header length (INV_FLAG, CMD, [UID], BNo, Bno) */
#define RFAL_NFCV_CMD_LEN 1U /*!< Commandbyte length */
#define RFAL_NFCV_FLAG_POS 0U /*!< Flag byte position */
#define RFAL_NFCV_FLAG_LEN 1U /*!< Flag byte length */
#define RFAL_NFCV_DATASTART_POS 1U /*!< Position of start of data */
#define RFAL_NFCV_DSFI_LEN 1U /*!< DSFID length */
#define RFAL_NFCV_SLPREQ_REQ_FLAG 0x22U /*!< SLPV_REQ request flags Digital 2.0 (Candidate) 9.7.1.1 */
#define RFAL_NFCV_RES_FLAG_NOERROR 0x00U /*!< RES_FLAG indicating no error (checked during activation) */
#define RFAL_NFCV_MAX_COLL_SUPPORTED 16U /*!< Maximum number of collisions supported by the Anticollision loop */
#define RFAL_NFCV_FDT_MAX rfalConvMsTo1fc(20) /*!< Maximum Wait time FDTV,EOF and MAX2 Digital 2.1 B.5*/
#define RFAL_NFCV_FDT_MAX1 4394U /*!< Read alike command FWT FDTV,LISTEN,MAX1 Digital 2.0 B.5 */
/*! Time from special frame to EOF
* ISO15693 2009 10.4.2 : 20ms
* NFC Forum defines Digital 2.0 9.7.4 : FDTV,EOF = [10 ; 20]ms
*/
#define RFAL_NFCV_FDT_EOF 20U
/*! Time between slots - ISO 15693 defines t3min depending on modulation depth and data rate.
* With only high-bitrate supported, AM modulation and a length of 12 bytes (96bits) for INV_RES we get:
* - ISO t3min = 96/26 ms + 300us = 4 ms
* - NFC Forum defines FDTV,INVENT_NORES = (4394 + 2048)/fc. Digital 2.0 B.5*/
#define RFAL_NFCV_FDT_V_INVENT_NORES 4U
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*! Checks if a valid INVENTORY_RES is valid Digital 2.2 9.6.2.1 & 9.6.2.3 */
#define rfalNfcvCheckInvRes( f, l ) (((l)==rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN)) && ((f)==RFAL_NFCV_RES_FLAG_NOERROR))
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! NFC-V INVENTORY_REQ format Digital 2.0 9.6.1 */
typedef struct
{
uint8_t INV_FLAG; /*!< Inventory Flags */
uint8_t CMD; /*!< Command code: 01h */
uint8_t MASK_LEN; /*!< Mask Value Length */
uint8_t MASK_VALUE[RFAL_NFCV_MASKVAL_MAX_LEN]; /*!< Mask Value */
} rfalNfcvInventoryReq;
/*! NFC-V SLP_REQ format Digital 2.0 (Candidate) 9.7.1 */
typedef struct
{
uint8_t REQ_FLAG; /*!< Request Flags */
uint8_t CMD; /*!< Command code: 02h */
uint8_t UID[RFAL_NFCV_UID_LEN]; /*!< Mask Value */
} rfalNfcvSlpvReq;
/*! Container for a collision found during Anticollision loop */
typedef struct
{
uint8_t maskLen;
uint8_t maskVal[RFAL_NFCV_MASKVAL_MAX_LEN];
}rfalNfcvCollision;
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static ReturnCode rfalNfcvParseError( uint8_t err );
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
static ReturnCode rfalNfcvParseError( uint8_t err )
{
switch(err)
{
case RFAL_NFCV_ERROR_CMD_NOT_SUPPORTED:
case RFAL_NFCV_ERROR_OPTION_NOT_SUPPORTED:
return ERR_NOTSUPP;
case RFAL_NFCV_ERROR_CMD_NOT_RECOGNIZED:
return ERR_PROTO;
case RFAL_NFCV_ERROR_WRITE_FAILED:
return ERR_WRITE;
default:
return ERR_REQUEST;
}
}
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
ReturnCode rfalNfcvPollerInitialize( void )
{
ReturnCode ret;
EXIT_ON_ERR( ret, rfalSetMode( RFAL_MODE_POLL_NFCV, RFAL_BR_26p48, RFAL_BR_26p48 ) );
rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC );
rfalSetGT( RFAL_GT_NFCV );
rfalSetFDTListen( RFAL_FDT_LISTEN_NFCV_POLLER );
rfalSetFDTPoll( RFAL_FDT_POLL_NFCV_POLLER );
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerCheckPresence( rfalNfcvInventoryRes *invRes )
{
ReturnCode ret;
/* INVENTORY_REQ with 1 slot and no Mask Activity 2.0 (Candidate) 9.2.3.32 */
ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_1, 0, NULL, invRes, NULL );
if( (ret == ERR_RF_COLLISION) || (ret == ERR_CRC) ||
(ret == ERR_FRAMING) || (ret == ERR_PROTO) )
{
ret = ERR_NONE;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerInventory( rfalNfcvNumSlots nSlots, uint8_t maskLen, const uint8_t *maskVal, rfalNfcvInventoryRes *invRes, uint16_t* rcvdLen )
{
ReturnCode ret;
rfalNfcvInventoryReq invReq;
uint16_t rxLen;
if( ((maskVal == NULL) && (maskLen != 0U)) || (invRes == NULL) )
{
return ERR_PARAM;
}
invReq.INV_FLAG = (RFAL_NFCV_INV_REQ_FLAG | (uint8_t)nSlots);
invReq.CMD = RFAL_NFCV_CMD_INVENTORY;
invReq.MASK_LEN = (uint8_t)MIN( maskLen, ((nSlots == RFAL_NFCV_NUM_SLOTS_1) ? RFAL_NFCV_MASKVAL_MAX_1SLOT_LEN : RFAL_NFCV_MASKVAL_MAX_16SLOT_LEN) ); /* Digital 2.0 9.6.1.6 */
if( (rfalConvBitsToBytes(invReq.MASK_LEN) > 0U) && (maskVal != NULL) ) /* MISRA 21.18 & 1.3 */
{
ST_MEMCPY( invReq.MASK_VALUE, maskVal, rfalConvBitsToBytes(invReq.MASK_LEN) );
}
ret = rfalISO15693TransceiveAnticollisionFrame( (uint8_t*)&invReq, (uint8_t)(RFAL_NFCV_INV_REQ_HEADER_LEN + rfalConvBitsToBytes(invReq.MASK_LEN)), (uint8_t*)invRes, sizeof(rfalNfcvInventoryRes), &rxLen );
/* Check for optional output parameter */
if( rcvdLen != NULL )
{
*rcvdLen = rxLen;
}
if( ret == ERR_NONE )
{
/* Check for valid INVENTORY_RES Digital 2.2 9.6.2.1 & 9.6.2.3 */
if( !rfalNfcvCheckInvRes( invRes->RES_FLAG, rxLen ) )
{
return ERR_PROTO;
}
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerCollisionResolution( rfalComplianceMode compMode, uint8_t devLimit, rfalNfcvListenDevice *nfcvDevList, uint8_t *devCnt )
{
ReturnCode ret;
uint8_t slotNum;
uint16_t rcvdLen;
uint8_t colIt;
uint8_t colCnt;
uint8_t colPos;
bool colPending;
rfalNfcvCollision colFound[RFAL_NFCV_MAX_COLL_SUPPORTED];
if( (nfcvDevList == NULL) || (devCnt == NULL) )
{
return ERR_PARAM;
}
/* Initialize parameters */
*devCnt = 0;
colIt = 0;
colCnt = 0;
colPending = false;
ST_MEMSET(colFound, 0x00, (sizeof(rfalNfcvCollision)*RFAL_NFCV_MAX_COLL_SUPPORTED) );
if( devLimit > 0U ) /* MISRA 21.18 */
{
ST_MEMSET(nfcvDevList, 0x00, (sizeof(rfalNfcvListenDevice)*devLimit) );
}
NO_WARNING(colPending); /* colPending is not exposed externally, in future it might become exposed/ouput parameter */
if( compMode == RFAL_COMPLIANCE_MODE_NFC )
{
/* Send INVENTORY_REQ with one slot Activity 2.1 9.3.7.1 (Symbol 0) */
ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &nfcvDevList->InvRes, NULL );
if( ret == ERR_TIMEOUT ) /* Exit if no device found Activity 2.1 9.3.7.2 (Symbol 1) */
{
return ERR_NONE;
}
if( ret == ERR_NONE ) /* Device found without transmission error/collision Activity 2.1 9.3.7.3 (Symbol 2) */
{
(*devCnt)++;
return ERR_NONE;
}
/* A Collision has been identified Activity 2.1 9.3.7.4 (Symbol 3) */
colPending = true;
colCnt = 1;
/* Check if the Collision Resolution is set to perform only Collision detection Activity 2.1 9.3.7.5 (Symbol 4)*/
if( devLimit == 0U )
{
return ERR_RF_COLLISION;
}
platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES);
/*******************************************************************************/
/* Collisions pending, Anticollision loop must be executed */
/*******************************************************************************/
}
else
{
/* Advance to 16 slots below without mask. Will give a good chance to identify multiple cards */
colPending = true;
colCnt = 1;
}
/* Execute until all collisions are resolved Activity 2.1 9.3.7.18 (Symbol 17) */
do
{
/* Activity 2.1 9.3.7.7 (Symbol 6 / 7) */
colPending = false;
slotNum = 0;
do
{
if( slotNum == 0U )
{
/* Send INVENTORY_REQ with 16 slots Activity 2.1 9.3.7.9 (Symbol 8) */
ret = rfalNfcvPollerInventory( RFAL_NFCV_NUM_SLOTS_16, colFound[colIt].maskLen, colFound[colIt].maskVal, &nfcvDevList[(*devCnt)].InvRes, &rcvdLen );
}
else
{
ret = rfalISO15693TransceiveEOFAnticollision( (uint8_t*)&nfcvDevList[(*devCnt)].InvRes, sizeof(rfalNfcvInventoryRes), &rcvdLen );
}
slotNum++;
/*******************************************************************************/
if( ret != ERR_TIMEOUT )
{
if( rcvdLen < rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN) )
{ /* If only a partial frame was received make sure the FDT_V_INVENT_NORES is fulfilled */
platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES);
}
/* Check if response is a correct frame (no TxRx error) Activity 2.1 9.3.7.11 (Symbol 10)*/
if( (ret == ERR_NONE) || (ret == ERR_PROTO) )
{
/* Check if the device found is already on the list and its response is a valid INVENTORY_RES */
if( rfalNfcvCheckInvRes( nfcvDevList[(*devCnt)].InvRes.RES_FLAG, rcvdLen ) )
{
/* Activity 2.1 9.3.7.12 (Symbol 11) */
(*devCnt)++;
}
}
else /* Treat everything else as collision */
{
/* Activity 2.1 9.3.7.17 (Symbol 16) */
colPending = true;
/*******************************************************************************/
/* Ensure that this collision still fits on the container */
if( colCnt < RFAL_NFCV_MAX_COLL_SUPPORTED )
{
/* Store this collision on the container to be resolved later */
/* Activity 2.1 9.3.7.17 (Symbol 16): add the collision information
* (MASK_VAL + SN) to the list containing the collision information */
ST_MEMCPY(colFound[colCnt].maskVal, colFound[colIt].maskVal, RFAL_NFCV_UID_LEN);
colPos = colFound[colIt].maskLen;
colFound[colCnt].maskVal[(colPos/RFAL_BITS_IN_BYTE)] &= (uint8_t)((1U << (colPos % RFAL_BITS_IN_BYTE)) - 1U);
colFound[colCnt].maskVal[(colPos/RFAL_BITS_IN_BYTE)] |= (uint8_t)((slotNum-1U) << (colPos % RFAL_BITS_IN_BYTE));
colFound[colCnt].maskVal[((colPos/RFAL_BITS_IN_BYTE)+1U)] = (uint8_t)((slotNum-1U) >> (RFAL_BITS_IN_BYTE - (colPos % RFAL_BITS_IN_BYTE)));
colFound[colCnt].maskLen = (colFound[colIt].maskLen + 4U);
colCnt++;
}
}
}
else
{
/* Timeout */
platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES);
}
/* Check if devices found have reached device limit Activity 2.1 9.3.7.13 (Symbol 12) */
if( *devCnt >= devLimit )
{
return ERR_NONE;
}
} while( slotNum < RFAL_NFCV_MAX_SLOTS ); /* Slot loop */
colIt++;
} while( colIt < colCnt ); /* Collisions found loop */
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerSleepCollisionResolution( uint8_t devLimit, rfalNfcvListenDevice *nfcvDevList, uint8_t *devCnt )
{
uint8_t tmpDevCnt;
ReturnCode ret;
uint8_t i;
if( (nfcvDevList == NULL) || (devCnt == NULL) )
{
return ERR_PARAM;
}
*devCnt = 0;
do
{
tmpDevCnt = 0;
ret = rfalNfcvPollerCollisionResolution( RFAL_COMPLIANCE_MODE_ISO, (devLimit - *devCnt), &nfcvDevList[*devCnt], &tmpDevCnt );
for( i = *devCnt; i < (*devCnt + tmpDevCnt); i++ )
{
rfalNfcvPollerSleep( 0x00, nfcvDevList[i].InvRes.UID );
nfcvDevList[i].isSleep = true;
}
*devCnt += tmpDevCnt;
}
while( (ret == ERR_NONE) && (tmpDevCnt > 0U) && (*devCnt < devLimit) );
return ret;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerSleep( uint8_t flags, const uint8_t* uid )
{
ReturnCode ret;
rfalNfcvSlpvReq slpReq;
uint8_t rxBuf; /* dummy buffer, just to perform Rx */
if( uid == NULL )
{
return ERR_PARAM;
}
/* Compute SLPV_REQ */
slpReq.REQ_FLAG = (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS); /* Should be with UID according Digital 2.0 (Candidate) 9.7.1.1 */
slpReq.CMD = RFAL_NFCV_CMD_SLPV;
ST_MEMCPY( slpReq.UID, uid, RFAL_NFCV_UID_LEN );
/* NFC Forum device SHALL wait at least FDTVpp to consider the SLPV acknowledged (FDTVpp = FDTVpoll) Digital 2.0 (Candidate) 9.7 9.8.2 */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&slpReq, sizeof(rfalNfcvSlpvReq), &rxBuf, sizeof(rxBuf), NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCV_FDT_MAX1 );
if( ret != ERR_TIMEOUT )
{
return ret;
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerSelect( uint8_t flags, const uint8_t* uid )
{
uint16_t rcvLen;
rfalNfcvGenericRes res;
if( uid == NULL )
{
return ERR_PARAM;
}
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_SELECT, flags, RFAL_NFCV_PARAM_SKIP, uid, NULL, 0U, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerReadSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t bn;
bn = blockNum;
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, &bn, sizeof(uint8_t), rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, const uint8_t* wrData, uint8_t blockLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_MAX_BLOCK_LEN)];
uint8_t dataLen;
uint16_t rcvLen;
rfalNfcvGenericRes res;
/* Check for valid parameters */
if( (blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (wrData == NULL) )
{
return ERR_PARAM;
}
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = blockNum; /* Set Block Number (8 bits) */
ST_MEMCPY( &data[dataLen], wrData, blockLen ); /* Append Block data to write */
dataLen += blockLen;
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerLockBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum )
{
uint16_t rcvLen;
rfalNfcvGenericRes res;
uint8_t bn;
bn = blockNum;
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_LOCK_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, &bn, sizeof(uint8_t), (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_BLOCKNUM_LEN)];
uint8_t dataLen;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = firstBlockNum; /* Set first Block Number */
data[dataLen++] = numOfBlocks; /* Set number of blocks to read */
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerWriteMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t *txBuf, uint16_t txBufLen, uint8_t blockLen, const uint8_t* wrData, uint16_t wrDataLen )
{
ReturnCode ret;
uint16_t rcvLen;
uint16_t reqLen;
rfalNfcvGenericRes res;
uint16_t msgIt;
/* Calculate required buffer length */
reqLen = (uint16_t)((uid != NULL) ? (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen) : (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen));
if( (reqLen > txBufLen) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || ((((uint16_t)numOfBlocks) * (uint16_t)blockLen) != wrDataLen) || (numOfBlocks == 0U) || (wrData == NULL) )
{
return ERR_PARAM;
}
msgIt = 0;
/* Compute Request Command */
txBuf[msgIt++] = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS)));
txBuf[msgIt++] = RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS;
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
if( uid != NULL )
{
txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS;
ST_MEMCPY( &txBuf[msgIt], uid, RFAL_NFCV_UID_LEN );
msgIt += (uint8_t)RFAL_NFCV_UID_LEN;
}
txBuf[msgIt++] = firstBlockNum;
txBuf[msgIt++] = (numOfBlocks - 1U);
if( wrDataLen > 0U ) /* MISRA 21.18 */
{
ST_MEMCPY( &txBuf[msgIt], wrData, wrDataLen );
msgIt += wrDataLen;
}
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCV_FDT_MAX );
if( ret != ERR_NONE )
{
return ret;
}
/* Check if the response minimum length has been received */
if( rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN )
{
return ERR_PROTO;
}
/* Check if an error has been signalled */
if( (res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U )
{
return rfalNfcvParseError( *res.data );
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN];
uint8_t dataLen;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */
data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU);
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_READ_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, const uint8_t* wrData, uint8_t blockLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_MAX_BLOCK_LEN)];
uint8_t dataLen;
uint16_t rcvLen;
rfalNfcvGenericRes res;
/* Check for valid parameters */
if( (blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) )
{
return ERR_PARAM;
}
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */
data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU);
ST_MEMCPY( &data[dataLen], wrData, blockLen ); /* Append Block data to write */
dataLen += blockLen;
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedLockSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum )
{
uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN];
uint8_t dataLen;
uint16_t rcvLen;
rfalNfcvGenericRes res;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */
data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU);
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN)];
uint8_t dataLen;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)((firstBlockNum >> 0U) & 0xFFU);
data[dataLen++] = (uint8_t)((firstBlockNum >> 8U) & 0xFFU);
data[dataLen++] = (uint8_t)((numOfBlocks >> 0U) & 0xFFU);
data[dataLen++] = (uint8_t)((numOfBlocks >> 8U) & 0xFFU);
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_READ_MULTIPLE_BLOCK, flags, RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedWriteMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t *txBuf, uint16_t txBufLen, uint8_t blockLen, const uint8_t* wrData, uint16_t wrDataLen )
{
ReturnCode ret;
uint16_t rcvLen;
uint16_t reqLen;
rfalNfcvGenericRes res;
uint16_t msgIt;
uint16_t nBlocks;
/* Calculate required buffer length */
reqLen = ((uid != NULL) ? (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen) : (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen) );
if( (reqLen > txBufLen) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (( (uint16_t)numOfBlocks * (uint16_t)blockLen) != wrDataLen) || (numOfBlocks == 0U) )
{
return ERR_PARAM;
}
msgIt = 0;
nBlocks = (numOfBlocks - 1U);
/* Compute Request Command */
txBuf[msgIt++] = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS)));
txBuf[msgIt++] = RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK;
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
if( uid != NULL )
{
txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS;
ST_MEMCPY( &txBuf[msgIt], uid, RFAL_NFCV_UID_LEN );
msgIt += (uint8_t)RFAL_NFCV_UID_LEN;
}
txBuf[msgIt++] = (uint8_t)((firstBlockNum >> 0) & 0xFFU);
txBuf[msgIt++] = (uint8_t)((firstBlockNum >> 8) & 0xFFU);
txBuf[msgIt++] = (uint8_t)((nBlocks >> 0) & 0xFFU);
txBuf[msgIt++] = (uint8_t)((nBlocks >> 8) & 0xFFU);
if( wrDataLen > 0U ) /* MISRA 21.18 */
{
ST_MEMCPY( &txBuf[msgIt], wrData, wrDataLen );
msgIt += wrDataLen;
}
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCV_FDT_MAX );
if( ret != ERR_NONE )
{
return ret;
}
/* Check if the response minimum length has been received */
if( rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN )
{
return ERR_PROTO;
}
/* Check if an error has been signalled */
if( (res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U )
{
return rfalNfcvParseError( *res.data );
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerGetSystemInformation( uint8_t flags, const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_GET_SYS_INFO, flags, RFAL_NFCV_PARAM_SKIP, uid, NULL, 0U, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerExtendedGetSystemInformation( uint8_t flags, const uint8_t* uid, uint8_t requestField, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_EXTENDED_GET_SYS_INFO, flags, requestField, uid, NULL, 0U, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalNfcvPollerTransceiveReq( uint8_t cmd, uint8_t flags, uint8_t param, const uint8_t* uid, const uint8_t *data, uint16_t dataLen, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
ReturnCode ret;
rfalNfcvGenericReq req;
uint8_t msgIt;
rfalBitRate rxBR;
bool fastMode;
msgIt = 0;
fastMode = false;
/* Check for valid parameters */
if( (rxBuf == NULL) || (rcvLen == NULL) || ((dataLen > 0U) && (data == NULL)) ||
(dataLen > ((uid != NULL) ? RFAL_NFCV_MAX_GEN_DATA_LEN : (RFAL_NFCV_MAX_GEN_DATA_LEN - RFAL_NFCV_UID_LEN))) )
{
return ERR_PARAM;
}
/* Check if the command is an ST's Fast command */
if( (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK) ||
(cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS) ||
(cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_MESSAGE) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH) ||
(cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MESSAGE) || (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION) ||
(cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION) )
{
/* Store current Rx bit rate and move to fast mode */
rfalGetBitRate( NULL, &rxBR );
rfalSetBitRate( RFAL_BR_KEEP, RFAL_BR_52p97 );
fastMode = true;
}
/* Compute Request Command */
req.REQ_FLAG = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS)));
req.CMD = cmd;
/* Prepend parameter on ceratin proprietary requests: IC Manuf, Parameters */
if( param != RFAL_NFCV_PARAM_SKIP )
{
req.payload.data[msgIt++] = param;
}
/* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */
if( uid != NULL )
{
req.REQ_FLAG |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS;
ST_MEMCPY( &req.payload.data[msgIt], uid, RFAL_NFCV_UID_LEN );
msgIt += RFAL_NFCV_UID_LEN;
}
if( dataLen > 0U )
{
ST_MEMCPY( &req.payload.data[msgIt], data, dataLen);
msgIt += (uint8_t)dataLen;
}
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&req, (RFAL_NFCV_CMD_LEN + RFAL_NFCV_FLAG_LEN +(uint16_t)msgIt), rxBuf, rxBufLen, rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_NFCV_FDT_MAX );
/* If the Option Flag is set in certain commands an EOF needs to be sent after 20ms to retrieve the VICC response ISO15693-3 2009 10.4.2 & 10.4.3 & 10.4.5 */
if( ((flags & (uint8_t)RFAL_NFCV_REQ_FLAG_OPTION) != 0U) && ((cmd == (uint8_t)RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS) ||
(cmd == (uint8_t)RFAL_NFCV_CMD_LOCK_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK) ||
(cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK) || (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK)) )
{
ret = rfalISO15693TransceiveEOF( rxBuf, (uint8_t)rxBufLen, rcvLen );
}
/* Restore Rx BitRate */
if( fastMode )
{
rfalSetBitRate( RFAL_BR_KEEP, rxBR );
}
if( ret != ERR_NONE )
{
return ret;
}
/* Check if the response minimum length has been received */
if( (*rcvLen) < (uint8_t)RFAL_NFCV_FLAG_LEN )
{
return ERR_PROTO;
}
/* Check if an error has been signalled */
if( (rxBuf[RFAL_NFCV_FLAG_POS] & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U )
{
return rfalNfcvParseError( rxBuf[RFAL_NFCV_DATASTART_POS] );
}
return ERR_NONE;
}
#endif /* RFAL_FEATURE_NFCV */

View file

@ -0,0 +1,561 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_st25tb.c
*
* \author Gustavo Patricio
*
* \brief Implementation of ST25TB interface
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_st25tb.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_ST25TB
#define RFAL_FEATURE_ST25TB false /* ST25TB module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_ST25TB
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_ST25TB_CMD_LEN 1U /*!< ST25TB length of a command */
#define RFAL_ST25TB_SLOTS 16U /*!< ST25TB number of slots */
#define RFAL_ST25TB_SLOTNUM_MASK 0x0FU /*!< ST25TB Slot Number bit mask on SlotMarker */
#define RFAL_ST25TB_SLOTNUM_SHIFT 4U /*!< ST25TB Slot Number shift on SlotMarker */
#define RFAL_ST25TB_INITIATE_CMD1 0x06U /*!< ST25TB Initiate command byte1 */
#define RFAL_ST25TB_INITIATE_CMD2 0x00U /*!< ST25TB Initiate command byte2 */
#define RFAL_ST25TB_PCALL_CMD1 0x06U /*!< ST25TB Pcall16 command byte1 */
#define RFAL_ST25TB_PCALL_CMD2 0x04U /*!< ST25TB Pcall16 command byte2 */
#define RFAL_ST25TB_SELECT_CMD 0x0EU /*!< ST25TB Select command */
#define RFAL_ST25TB_GET_UID_CMD 0x0BU /*!< ST25TB Get UID command */
#define RFAL_ST25TB_COMPLETION_CMD 0x0FU /*!< ST25TB Completion command */
#define RFAL_ST25TB_RESET_INV_CMD 0x0CU /*!< ST25TB Reset to Inventory command */
#define RFAL_ST25TB_READ_BLOCK_CMD 0x08U /*!< ST25TB Read Block command */
#define RFAL_ST25TB_WRITE_BLOCK_CMD 0x09U /*!< ST25TB Write Block command */
#define RFAL_ST25TB_T0 2157U /*!< ST25TB t0 159 us ST25TB RF characteristics */
#define RFAL_ST25TB_T1 2048U /*!< ST25TB t1 151 us ST25TB RF characteristics */
#define RFAL_ST25TB_FWT (RFAL_ST25TB_T0 + RFAL_ST25TB_T1) /*!< ST25TB FWT = T0 + T1 */
#define RFAL_ST25TB_TW rfalConvMsTo1fc(7U) /*!< ST25TB TW : Programming time for write max 7ms */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! Initiate Request */
typedef struct
{
uint8_t cmd1; /*!< Initiate Request cmd1: 0x06 */
uint8_t cmd2; /*!< Initiate Request cmd2: 0x00 */
} rfalSt25tbInitiateReq;
/*! Pcall16 Request */
typedef struct
{
uint8_t cmd1; /*!< Pcal16 Request cmd1: 0x06 */
uint8_t cmd2; /*!< Pcal16 Request cmd2: 0x04 */
} rfalSt25tbPcallReq;
/*! Select Request */
typedef struct
{
uint8_t cmd; /*!< Select Request cmd: 0x0E */
uint8_t chipId; /*!< Chip ID */
} rfalSt25tbSelectReq;
/*! Read Block Request */
typedef struct
{
uint8_t cmd; /*!< Select Request cmd: 0x08 */
uint8_t address; /*!< Block address */
} rfalSt25tbReadBlockReq;
/*! Write Block Request */
typedef struct
{
uint8_t cmd; /*!< Select Request cmd: 0x09 */
uint8_t address; /*!< Block address */
rfalSt25tbBlock data; /*!< Block Data */
} rfalSt25tbWriteBlockReq;
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief ST25TB Poller Do Collision Resolution
*
* This method performs ST25TB Collision resolution loop for each slot
*
* \param[in] devLimit : device limit value, and size st25tbDevList
* \param[out] st25tbDevList : ST35TB listener device info
* \param[out] devCnt : Devices found counter
*
* \return colPending : true if a collision was detected
*****************************************************************************
*/
static bool rfalSt25tbPollerDoCollisionResolution( uint8_t devLimit, rfalSt25tbListenDevice *st25tbDevList, uint8_t *devCnt );
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static bool rfalSt25tbPollerDoCollisionResolution( uint8_t devLimit, rfalSt25tbListenDevice *st25tbDevList, uint8_t *devCnt )
{
uint8_t i;
uint8_t chipId;
ReturnCode ret;
bool col;
col = false;
for(i = 0; i < RFAL_ST25TB_SLOTS; i++)
{
platformDelay(1); /* Wait t2: Answer to new request delay */
if( i==0U )
{
/* Step 2: Send Pcall16 */
ret = rfalSt25tbPollerPcall( &chipId );
}
else
{
/* Step 3-17: Send Pcall16 */
ret = rfalSt25tbPollerSlotMarker( i, &chipId );
}
if( ret == ERR_NONE )
{
/* Found another device */
st25tbDevList[*devCnt].chipID = chipId;
st25tbDevList[*devCnt].isDeselected = false;
/* Select Device, retrieve its UID */
ret = rfalSt25tbPollerSelect( chipId );
/* By Selecting this device, the previous gets Deselected */
if( (*devCnt) > 0U )
{
st25tbDevList[(*devCnt)-1U].isDeselected = true;
}
if( ERR_NONE == ret )
{
rfalSt25tbPollerGetUID( &st25tbDevList[*devCnt].UID );
}
if( ERR_NONE == ret )
{
(*devCnt)++;
}
}
else if( (ret == ERR_CRC) || (ret == ERR_FRAMING) )
{
col = true;
}
else
{
/* MISRA 15.7 - Empty else */
}
if( *devCnt >= devLimit )
{
break;
}
}
return col;
}
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
ReturnCode rfalSt25tbPollerInitialize( void )
{
return rfalNfcbPollerInitialize();
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerCheckPresence( uint8_t *chipId )
{
ReturnCode ret;
uint8_t chipIdRes;
chipIdRes = 0x00;
/* Send Initiate Request */
ret = rfalSt25tbPollerInitiate( &chipIdRes );
/* Check if a transmission error was detected */
if( (ret == ERR_CRC) || (ret == ERR_FRAMING) )
{
return ERR_NONE;
}
/* Copy chip ID if requested */
if( chipId != NULL )
{
*chipId = chipIdRes;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerInitiate( uint8_t *chipId )
{
ReturnCode ret;
uint16_t rxLen;
rfalSt25tbInitiateReq initiateReq;
uint8_t rxBuf[RFAL_ST25TB_CHIP_ID_LEN + RFAL_ST25TB_CRC_LEN]; /* In case we receive less data that CRC, RF layer will not remove the CRC from buffer */
/* Compute Initiate Request */
initiateReq.cmd1 = RFAL_ST25TB_INITIATE_CMD1;
initiateReq.cmd2 = RFAL_ST25TB_INITIATE_CMD2;
/* Send Initiate Request */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&initiateReq, sizeof(rfalSt25tbInitiateReq), (uint8_t*)rxBuf, sizeof(rxBuf), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT );
/* Check for valid Select Response */
if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN) )
{
return ERR_PROTO;
}
/* Copy chip ID if requested */
if( chipId != NULL )
{
*chipId = *rxBuf;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerPcall( uint8_t *chipId )
{
ReturnCode ret;
uint16_t rxLen;
rfalSt25tbPcallReq pcallReq;
/* Compute Pcal16 Request */
pcallReq.cmd1 = RFAL_ST25TB_PCALL_CMD1;
pcallReq.cmd2 = RFAL_ST25TB_PCALL_CMD2;
/* Send Pcal16 Request */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&pcallReq, sizeof(rfalSt25tbPcallReq), (uint8_t*)chipId, RFAL_ST25TB_CHIP_ID_LEN, &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT );
/* Check for valid Select Response */
if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN) )
{
return ERR_PROTO;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerSlotMarker( uint8_t slotNum, uint8_t *chipIdRes )
{
ReturnCode ret;
uint16_t rxLen;
uint8_t slotMarker;
if( (slotNum == 0U) || (slotNum > 15U) )
{
return ERR_PARAM;
}
/* Compute SlotMarker */
slotMarker = ( ((slotNum & RFAL_ST25TB_SLOTNUM_MASK) << RFAL_ST25TB_SLOTNUM_SHIFT) | RFAL_ST25TB_PCALL_CMD1 );
/* Send SlotMarker */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&slotMarker, RFAL_ST25TB_CMD_LEN, (uint8_t*)chipIdRes, RFAL_ST25TB_CHIP_ID_LEN, &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT );
/* Check for valid ChipID Response */
if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN) )
{
return ERR_PROTO;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerSelect( uint8_t chipId )
{
ReturnCode ret;
uint16_t rxLen;
rfalSt25tbSelectReq selectReq;
uint8_t chipIdRes;
/* Compute Select Request */
selectReq.cmd = RFAL_ST25TB_SELECT_CMD;
selectReq.chipId = chipId;
/* Send Select Request */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&selectReq, sizeof(rfalSt25tbSelectReq), (uint8_t*)&chipIdRes, RFAL_ST25TB_CHIP_ID_LEN, &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT );
/* Check for valid Select Response */
if( (ret == ERR_NONE) && ((rxLen != RFAL_ST25TB_CHIP_ID_LEN) || (chipIdRes != chipId)) )
{
return ERR_PROTO;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerGetUID( rfalSt25tbUID *UID )
{
ReturnCode ret;
uint16_t rxLen;
uint8_t getUidReq;
/* Compute Get UID Request */
getUidReq = RFAL_ST25TB_GET_UID_CMD;
/* Send Select Request */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&getUidReq, RFAL_ST25TB_CMD_LEN, (uint8_t*)UID, sizeof(rfalSt25tbUID), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT );
/* Check for valid UID Response */
if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_UID_LEN) )
{
return ERR_PROTO;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerCollisionResolution( uint8_t devLimit, rfalSt25tbListenDevice *st25tbDevList, uint8_t *devCnt )
{
uint8_t chipId;
ReturnCode ret;
bool detected; /* collision or device was detected */
if( (st25tbDevList == NULL) || (devCnt == NULL) || (devLimit == 0U) )
{
return ERR_PARAM;
}
*devCnt = 0;
/* Step 1: Send Initiate */
ret = rfalSt25tbPollerInitiate( &chipId );
if( ret == ERR_NONE )
{
/* If only 1 answer is detected */
st25tbDevList[*devCnt].chipID = chipId;
st25tbDevList[*devCnt].isDeselected = false;
/* Retrieve its UID and keep it Selected*/
ret = rfalSt25tbPollerSelect( chipId );
if( ERR_NONE == ret )
{
ret = rfalSt25tbPollerGetUID( &st25tbDevList[*devCnt].UID );
}
if( ERR_NONE == ret )
{
(*devCnt)++;
}
}
/* Always proceed to Pcall16 anticollision as phase differences of tags can lead to no tag recognized, even if there is one */
if( *devCnt < devLimit )
{
/* Multiple device responses */
do
{
detected = rfalSt25tbPollerDoCollisionResolution( devLimit, st25tbDevList, devCnt );
}
while( (detected == true) && (*devCnt < devLimit) );
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerReadBlock( uint8_t blockAddress, rfalSt25tbBlock *blockData )
{
ReturnCode ret;
uint16_t rxLen;
rfalSt25tbReadBlockReq readBlockReq;
/* Compute Read Block Request */
readBlockReq.cmd = RFAL_ST25TB_READ_BLOCK_CMD;
readBlockReq.address = blockAddress;
/* Send Read Block Request */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&readBlockReq, sizeof(rfalSt25tbReadBlockReq), (uint8_t*)blockData, sizeof(rfalSt25tbBlock), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT );
/* Check for valid UID Response */
if( (ret == ERR_NONE) && (rxLen != RFAL_ST25TB_BLOCK_LEN) )
{
return ERR_PROTO;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerWriteBlock( uint8_t blockAddress, const rfalSt25tbBlock *blockData )
{
ReturnCode ret;
uint16_t rxLen;
rfalSt25tbWriteBlockReq writeBlockReq;
rfalSt25tbBlock tmpBlockData;
/* Compute Write Block Request */
writeBlockReq.cmd = RFAL_ST25TB_WRITE_BLOCK_CMD;
writeBlockReq.address = blockAddress;
ST_MEMCPY( &writeBlockReq.data, blockData, RFAL_ST25TB_BLOCK_LEN );
/* Send Write Block Request */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&writeBlockReq, sizeof(rfalSt25tbWriteBlockReq), tmpBlockData, RFAL_ST25TB_BLOCK_LEN, &rxLen, RFAL_TXRX_FLAGS_DEFAULT, (RFAL_ST25TB_FWT + RFAL_ST25TB_TW) );
/* Check if there was any error besides timeout */
if( ret != ERR_TIMEOUT )
{
/* Check if an unexpected answer was received */
if( ret == ERR_NONE )
{
return ERR_PROTO;
}
/* Check whether a transmission error occurred */
if( (ret != ERR_CRC) && (ret != ERR_FRAMING) && (ret != ERR_NOMEM) && (ret != ERR_RF_COLLISION) )
{
return ret;
}
/* If a transmission error occurred (maybe noise while commiting data) wait maximum programming time and verify data afterwards */
rfalSetGT( (RFAL_ST25TB_FWT + RFAL_ST25TB_TW) );
rfalFieldOnAndStartGT();
}
ret = rfalSt25tbPollerReadBlock(blockAddress, &tmpBlockData);
if( ret == ERR_NONE )
{
if( ST_BYTECMP( &tmpBlockData, blockData, RFAL_ST25TB_BLOCK_LEN ) == 0 )
{
return ERR_NONE;
}
return ERR_PROTO;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerCompletion( void )
{
uint8_t completionReq;
/* Compute Completion Request */
completionReq = RFAL_ST25TB_COMPLETION_CMD;
/* Send Completion Request, no response is expected */
return rfalTransceiveBlockingTxRx( (uint8_t*)&completionReq, RFAL_ST25TB_CMD_LEN, NULL, 0, NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT );
}
/*******************************************************************************/
ReturnCode rfalSt25tbPollerResetToInventory( void )
{
uint8_t resetInvReq;
/* Compute Completion Request */
resetInvReq = RFAL_ST25TB_RESET_INV_CMD;
/* Send Completion Request, no response is expected */
return rfalTransceiveBlockingTxRx( (uint8_t*)&resetInvReq, RFAL_ST25TB_CMD_LEN, NULL, 0, NULL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25TB_FWT );
}
#endif /* RFAL_FEATURE_ST25TB */

View file

@ -0,0 +1,529 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_st25xv.c
*
* \author Gustavo Patricio
*
* \brief NFC-V ST25 NFC-V Tag specific features
*
* This module provides support for ST's specific features available on
* NFC-V (ISO15693) tag families: ST25D, ST25TV, M24LR
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_st25xv.h"
#include "rfal_nfcv.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_ST25xV
#define RFAL_FEATURE_ST25xV false /* ST25xV module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_ST25xV
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_ST25xV_READ_CONFIG_LEN 2U /*!< READ CONFIGURATION length */
#define RFAL_ST25xV_READ_MSG_LEN_LEN 2U /*!< READ MESSAGE LENGTH length */
#define RFAL_ST25xV_CONF_POINTER_LEN 1U /*!< READ/WRITE CONFIGURATION Pointer length */
#define RFAL_ST25xV_CONF_REGISTER_LEN 1U /*!< READ/WRITE CONFIGURATION Register length */
#define RFAL_ST25xV_PWDNUM_LEN 1U /*!< Password Number length */
#define RFAL_ST25xV_PWD_LEN 8U /*!< Password length */
#define RFAL_ST25xV_MBPOINTER_LEN 1U /*!< Read Message MBPointer length */
#define RFAL_ST25xV_NUMBYTES_LEN 1U /*!< Read Message Number of Bytes length */
#define RFAL_ST25TV02K_TBOOT_RF 1U /*!< RF Boot time (Minimum time from carrier generation to first data) */
#define RFAL_ST25TV02K_TRF_OFF 2U /*!< RF OFF time */
#define RFAL_ST25xV_FDT_POLL_MAX rfalConvMsTo1fc(20) /*!< Maximum Wait time FDTV,EOF 20 ms Digital 2.1 B.5 */
#define RFAL_NFCV_FLAG_POS 0U /*!< Flag byte position */
#define RFAL_NFCV_FLAG_LEN 1U /*!< Flag byte length */
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static ReturnCode rfalST25xVPollerGenericReadConfiguration(uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue );
static ReturnCode rfalST25xVPollerGenericWriteConfiguration( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue );
static ReturnCode rfalST25xVPollerGenericReadMessageLength( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t* msgLen );
static ReturnCode rfalST25xVPollerGenericReadMessage( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen );
static ReturnCode rfalST25xVPollerGenericWriteMessage( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen );
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
static ReturnCode rfalST25xVPollerGenericReadConfiguration(uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue )
{
ReturnCode ret;
uint8_t p;
uint16_t rcvLen;
rfalNfcvGenericRes res;
if( regValue == NULL )
{
return ERR_PARAM;
}
p = pointer;
ret = rfalNfcvPollerTransceiveReq( cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, &p, sizeof(uint8_t), (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
if( ret == ERR_NONE )
{
if( rcvLen < RFAL_ST25xV_READ_CONFIG_LEN )
{
ret = ERR_PROTO;
}
else
{
*regValue = res.data[0];
}
}
return ret;
}
/*******************************************************************************/
static ReturnCode rfalST25xVPollerGenericWriteConfiguration( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue )
{
uint8_t data[RFAL_ST25xV_CONF_POINTER_LEN + RFAL_ST25xV_CONF_REGISTER_LEN];
uint8_t dataLen;
uint16_t rcvLen;
rfalNfcvGenericRes res;
dataLen = 0U;
data[dataLen++] = pointer;
data[dataLen++] = regValue;
return rfalNfcvPollerTransceiveReq( cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
}
/*******************************************************************************/
static ReturnCode rfalST25xVPollerGenericReadMessageLength( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t* msgLen )
{
ReturnCode ret;
uint16_t rcvLen;
rfalNfcvGenericRes res;
if( msgLen == NULL )
{
return ERR_PARAM;
}
ret = rfalNfcvPollerTransceiveReq( cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, NULL, 0, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
if( ret == ERR_NONE )
{
if( rcvLen < RFAL_ST25xV_READ_MSG_LEN_LEN )
{
ret = ERR_PROTO;
}
else
{
*msgLen = res.data[0];
}
}
return ret;
}
/*******************************************************************************/
static ReturnCode rfalST25xVPollerGenericReadMessage( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[RFAL_ST25xV_MBPOINTER_LEN + RFAL_ST25xV_NUMBYTES_LEN];
uint8_t dataLen;
dataLen = 0;
/* Compute Request Data */
data[dataLen++] = mbPointer;
data[dataLen++] = numBytes;
return rfalNfcvPollerTransceiveReq( cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
static ReturnCode rfalST25xVPollerGenericWriteMessage( uint8_t cmd, uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen )
{
ReturnCode ret;
uint8_t reqFlag;
uint16_t msgIt;
rfalBitRate rxBR;
bool fastMode;
rfalNfcvGenericRes res;
uint16_t rcvLen;
/* Calculate required Tx buf length: Mfg Code UID MSGLen MSGLen+1 */
msgIt = (uint16_t)( msgLen + sizeof(flags) + sizeof(cmd) + 1U + ((uid != NULL) ? RFAL_NFCV_UID_LEN : 0U) + 1U + 1U );
/* Note: MSGlength parameter of the command is the number of Data bytes minus - 1 (00 for 1 byte of data, FFh for 256 bytes of data) */
/* Check for valid parameters */
if( (txBuf == NULL) || (msgData == NULL) || (txBufLen < msgIt) )
{
return ERR_PARAM;
}
msgIt = 0;
fastMode = false;
/* Check if the command is an ST's Fast command */
if( cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_MESSAGE )
{
/* Store current Rx bit rate and move to fast mode */
rfalGetBitRate( NULL, &rxBR );
rfalSetBitRate( RFAL_BR_KEEP, RFAL_BR_52p97 );
fastMode = true;
}
/* Compute Request Command */
reqFlag = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS) & ~((uint32_t)RFAL_NFCV_REQ_FLAG_SELECT)));
reqFlag |= (( uid != NULL ) ? (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS : (uint8_t)RFAL_NFCV_REQ_FLAG_SELECT);
txBuf[msgIt++] = reqFlag;
txBuf[msgIt++] = cmd;
txBuf[msgIt++] = RFAL_NFCV_ST_IC_MFG_CODE;
if( uid != NULL )
{
ST_MEMCPY( &txBuf[msgIt], uid, RFAL_NFCV_UID_LEN );
msgIt += RFAL_NFCV_UID_LEN;
}
txBuf[msgIt++] = msgLen;
ST_MEMCPY( &txBuf[msgIt], msgData, (uint16_t)(msgLen +(uint16_t) 1U) ); /* Message Data contains (MSGLength + 1) bytes */
msgIt += (uint16_t)(msgLen + (uint16_t)1U);
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx( txBuf, msgIt, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_ST25xV_FDT_POLL_MAX );
/* Restore Rx BitRate */
if( fastMode )
{
rfalSetBitRate( RFAL_BR_KEEP, rxBR );
}
if( ret != ERR_NONE )
{
return ret;
}
/* Check if the response minimum length has been received */
if( rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN )
{
return ERR_PROTO;
}
/* Check if an error has been signalled */
if( (res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U )
{
return ERR_PROTO;
}
return ERR_NONE;
}
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
ReturnCode rfalST25xVPollerM24LRReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[RFAL_NFCV_BLOCKNUM_M24LR_LEN];
uint8_t dataLen;
dataLen = 0;
/* Compute Request Data */
data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */
data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_SINGLE_BLOCK, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerM24LRWriteSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, const uint8_t* wrData, uint8_t blockLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_MAX_BLOCK_LEN)];
uint8_t dataLen;
uint16_t rcvLen;
rfalNfcvGenericRes res;
/* Check for valid parameters */
if( (blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (wrData == NULL) )
{
return ERR_PARAM;
}
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */
data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */
ST_MEMCPY( &data[dataLen], wrData, blockLen ); /* Append Block data to write */
dataLen += blockLen;
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerM24LRReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_BLOCKNUM_M24LR_LEN)];
uint8_t dataLen;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)firstBlockNum; /* Set M24LR Block Number (16 bits) LSB */
data[dataLen++] = (uint8_t)(firstBlockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */
data[dataLen++] = numOfBlocks; /* Set number of blocks to read */
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_PARAM_SKIP, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastReadSingleBlock( uint8_t flags, const uint8_t* uid, uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t bn;
bn = blockNum;
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, &bn, sizeof(uint8_t), rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerM24LRFastReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[RFAL_NFCV_BLOCKNUM_M24LR_LEN];
uint8_t dataLen;
dataLen = 0;
/* Compute Request Data */
data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */
data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerM24LRFastReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_BLOCKNUM_M24LR_LEN)];
uint8_t dataLen;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)firstBlockNum; /* Set M24LR Block Number (16 bits) LSB */
data[dataLen++] = (uint8_t)(firstBlockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */
data[dataLen++] = numOfBlocks; /* Set number of blocks to read */
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS, (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint8_t firstBlockNum, uint8_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_BLOCKNUM_LEN)];
uint8_t dataLen;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = firstBlockNum; /* Set first Block Number */
data[dataLen++] = numOfBlocks; /* Set number of blocks to read */
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastExtendedReadSingleBlock( uint8_t flags, const uint8_t* uid, uint16_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN];
uint8_t dataLen;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */
data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU);
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastExtReadMultipleBlocks( uint8_t flags, const uint8_t* uid, uint16_t firstBlockNum, uint16_t numOfBlocks, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN)];
uint8_t dataLen;
dataLen = 0U;
/* Compute Request Data */
data[dataLen++] = (uint8_t)((firstBlockNum >> 0U) & 0xFFU);
data[dataLen++] = (uint8_t)((firstBlockNum >> 8U) & 0xFFU);
data[dataLen++] = (uint8_t)((numOfBlocks >> 0U) & 0xFFU);
data[dataLen++] = (uint8_t)((numOfBlocks >> 8U) & 0xFFU);
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerReadConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue )
{
return rfalST25xVPollerGenericReadConfiguration(RFAL_NFCV_CMD_READ_CONFIGURATION, flags, uid, pointer, regValue );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerWriteConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue )
{
return rfalST25xVPollerGenericWriteConfiguration( RFAL_NFCV_CMD_WRITE_CONFIGURATION, flags, uid, pointer, regValue);
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerReadDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue )
{
return rfalST25xVPollerGenericReadConfiguration(RFAL_NFCV_CMD_READ_DYN_CONFIGURATION, flags, uid, pointer, regValue );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerWriteDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue )
{
return rfalST25xVPollerGenericWriteConfiguration( RFAL_NFCV_CMD_WRITE_DYN_CONFIGURATION, flags, uid, pointer, regValue);
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastReadDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t* regValue )
{
return rfalST25xVPollerGenericReadConfiguration(RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION, flags, uid, pointer, regValue );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastWriteDynamicConfiguration( uint8_t flags, const uint8_t* uid, uint8_t pointer, uint8_t regValue )
{
return rfalST25xVPollerGenericWriteConfiguration( RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION, flags, uid, pointer, regValue);
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerPresentPassword( uint8_t flags, const uint8_t* uid, uint8_t pwdNum, const uint8_t *pwd, uint8_t pwdLen)
{
uint8_t data[RFAL_ST25xV_PWDNUM_LEN + RFAL_ST25xV_PWD_LEN];
uint8_t dataLen;
uint16_t rcvLen;
rfalNfcvGenericRes res;
if( (pwdLen > RFAL_ST25xV_PWD_LEN) || (pwd == NULL) )
{
return ERR_PARAM;
}
dataLen = 0U;
data[dataLen++] = pwdNum;
if( pwdLen > 0U )
{
ST_MEMCPY(&data[dataLen], pwd, pwdLen);
}
dataLen += pwdLen;
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_PRESENT_PASSWORD, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, (uint8_t*)&res, sizeof(rfalNfcvGenericRes), &rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerGetRandomNumber( uint8_t flags, const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
rfalFieldOff();
platformDelay(RFAL_ST25TV02K_TRF_OFF);
rfalNfcvPollerInitialize();
rfalFieldOnAndStartGT();
platformDelay(RFAL_ST25TV02K_TBOOT_RF);
return rfalNfcvPollerTransceiveReq( RFAL_NFCV_CMD_GET_RANDOM_NUMBER, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, NULL, 0U, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerWriteMessage( uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen )
{
return rfalST25xVPollerGenericWriteMessage( RFAL_NFCV_CMD_WRITE_MESSAGE, flags, uid, msgLen, msgData, txBuf, txBufLen);
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastWriteMessage( uint8_t flags, const uint8_t* uid, uint8_t msgLen, const uint8_t* msgData, uint8_t* txBuf, uint16_t txBufLen )
{
return rfalST25xVPollerGenericWriteMessage( RFAL_NFCV_CMD_FAST_WRITE_MESSAGE, flags, uid, msgLen, msgData, txBuf, txBufLen);
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerReadMessageLength( uint8_t flags, const uint8_t* uid, uint8_t* msgLen )
{
return rfalST25xVPollerGenericReadMessageLength(RFAL_NFCV_CMD_READ_MESSAGE_LENGTH, flags, uid, msgLen);
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastReadMsgLength( uint8_t flags, const uint8_t* uid, uint8_t* msgLen )
{
return rfalST25xVPollerGenericReadMessageLength(RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH, flags, uid, msgLen);
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerReadMessage( uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
return rfalST25xVPollerGenericReadMessage(RFAL_NFCV_CMD_READ_MESSAGE, flags, uid, mbPointer, numBytes, rxBuf, rxBufLen, rcvLen );
}
/*******************************************************************************/
ReturnCode rfalST25xVPollerFastReadMessage( uint8_t flags, const uint8_t* uid, uint8_t mbPointer, uint8_t numBytes, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
return rfalST25xVPollerGenericReadMessage(RFAL_NFCV_CMD_FAST_READ_MESSAGE, flags, uid, mbPointer, numBytes, rxBuf, rxBufLen, rcvLen );
}
#endif /* RFAL_FEATURE_ST25xV */

220
lib/ST25RFAL002/source/rfal_t1t.c Executable file
View file

@ -0,0 +1,220 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_t1t.c
*
* \author Gustavo Patricio
*
* \brief Provides NFC-A T1T convenience methods and definitions
*
* This module provides an interface to perform as a NFC-A Reader/Writer
* to handle a Type 1 Tag T1T (Topaz)
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_t1t.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_T1T
#define RFAL_FEATURE_T1T false /* T1T module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_T1T
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_T1T_DRD_READ (1236U*2U) /*!< DRD for Reads with n=9 => 1236/fc ~= 91 us T1T 1.2 4.4.2 */
#define RFAL_T1T_DRD_WRITE 36052U /*!< DRD for Write with n=281 => 36052/fc ~= 2659 us T1T 1.2 4.4.2 */
#define RFAL_T1T_DRD_WRITE_E 70996U /*!< DRD for Write/Erase with n=554 => 70996/fc ~= 5236 us T1T 1.2 4.4.2 */
#define RFAL_T1T_RID_RES_HR0_VAL 0x10U /*!< HR0 indicating NDEF support Digital 2.0 (Candidate) 11.6.2.1 */
#define RFAL_T1T_RID_RES_HR0_MASK 0xF0U /*!< HR0 most significant nibble mask */
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! NFC-A T1T (Topaz) RID_REQ Digital 1.1 10.6.1 & Table 49 */
typedef struct
{
uint8_t cmd; /*!< T1T cmd: RID */
uint8_t add; /*!< ADD: undefined value */
uint8_t data; /*!< DATA: undefined value */
uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID-echo: undefined value */
} rfalT1TRidReq;
/*! NFC-A T1T (Topaz) RALL_REQ T1T 1.2 Table 4 */
typedef struct
{
uint8_t cmd; /*!< T1T cmd: RALL */
uint8_t add1; /*!< ADD: 0x00 */
uint8_t add0; /*!< ADD: 0x00 */
uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID */
} rfalT1TRallReq;
/*! NFC-A T1T (Topaz) WRITE_REQ T1T 1.2 Table 4 */
typedef struct
{
uint8_t cmd; /*!< T1T cmd: RALL */
uint8_t add; /*!< ADD */
uint8_t data; /*!< DAT */
uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID */
} rfalT1TWriteReq;
/*! NFC-A T1T (Topaz) WRITE_RES T1T 1.2 Table 4 */
typedef struct
{
uint8_t add; /*!< ADD */
uint8_t data; /*!< DAT */
} rfalT1TWriteRes;
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
ReturnCode rfalT1TPollerInitialize( void )
{
ReturnCode ret;
EXIT_ON_ERR(ret, rfalSetMode( RFAL_MODE_POLL_NFCA_T1T, RFAL_BR_106, RFAL_BR_106 ) );
rfalSetErrorHandling( RFAL_ERRORHANDLING_NFC );
rfalSetGT( RFAL_GT_NONE ); /* T1T should only be initialized after NFC-A mode, therefore the GT has been fulfilled */
rfalSetFDTListen( RFAL_FDT_LISTEN_NFCA_POLLER ); /* T1T uses NFC-A FDT Listen with n=9 Digital 1.1 10.7.2 */
rfalSetFDTPoll( RFAL_FDT_POLL_NFCA_T1T_POLLER );
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalT1TPollerRid( rfalT1TRidRes *ridRes )
{
ReturnCode ret;
rfalT1TRidReq ridReq;
uint16_t rcvdLen;
if( ridRes == NULL )
{
return ERR_PARAM;
}
/* Compute RID command and set Undefined Values to 0x00 Digital 1.1 10.6.1 */
ST_MEMSET( &ridReq, 0x00, sizeof(rfalT1TRidReq) );
ridReq.cmd = (uint8_t)RFAL_T1T_CMD_RID;
EXIT_ON_ERR( ret, rfalTransceiveBlockingTxRx( (uint8_t*)&ridReq, sizeof(rfalT1TRidReq), (uint8_t*)ridRes, sizeof(rfalT1TRidRes), &rcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_T1T_DRD_READ ) );
/* Check expected RID response length and the HR0 Digital 2.0 (Candidate) 11.6.2.1 */
if( (rcvdLen != sizeof(rfalT1TRidRes)) || ((ridRes->hr0 & RFAL_T1T_RID_RES_HR0_MASK) != RFAL_T1T_RID_RES_HR0_VAL) )
{
return ERR_PROTO;
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalT1TPollerRall( const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rxRcvdLen )
{
rfalT1TRallReq rallReq;
if( (rxBuf == NULL) || (uid == NULL) || (rxRcvdLen == NULL) )
{
return ERR_PARAM;
}
/* Compute RALL command and set Add to 0x00 */
ST_MEMSET( &rallReq, 0x00, sizeof(rfalT1TRallReq) );
rallReq.cmd = (uint8_t)RFAL_T1T_CMD_RALL;
ST_MEMCPY(rallReq.uid, uid, RFAL_T1T_UID_LEN);
return rfalTransceiveBlockingTxRx( (uint8_t*)&rallReq, sizeof(rfalT1TRallReq), (uint8_t*)rxBuf, rxBufLen, rxRcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_T1T_DRD_READ );
}
/*******************************************************************************/
ReturnCode rfalT1TPollerWrite( const uint8_t* uid, uint8_t address, uint8_t data )
{
rfalT1TWriteReq writeReq;
rfalT1TWriteRes writeRes;
uint16_t rxRcvdLen;
ReturnCode err;
if( uid == NULL )
{
return ERR_PARAM;
}
writeReq.cmd = (uint8_t)RFAL_T1T_CMD_WRITE_E;
writeReq.add = address;
writeReq.data = data;
ST_MEMCPY(writeReq.uid, uid, RFAL_T1T_UID_LEN);
err = rfalTransceiveBlockingTxRx( (uint8_t*)&writeReq, sizeof(rfalT1TWriteReq), (uint8_t*)&writeRes, sizeof(rfalT1TWriteRes), &rxRcvdLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_T1T_DRD_WRITE_E );
if( err == ERR_NONE )
{
if( (writeReq.add != writeRes.add) || (writeReq.data != writeRes.data) || (rxRcvdLen != sizeof(rfalT1TWriteRes)) )
{
return ERR_PROTO;
}
}
return err;
}
#endif /* RFAL_FEATURE_T1T */

242
lib/ST25RFAL002/source/rfal_t2t.c Executable file
View file

@ -0,0 +1,242 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_t2t.c
*
* \author
*
* \brief Provides NFC-A T2T convenience methods and definitions
*
* This module provides an interface to perform as a NFC-A Reader/Writer
* to handle a Type 2 Tag T2T
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_t2t.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_T2T
#define RFAL_FEATURE_T2T false /* T2T module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_T2T
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_FDT_POLL_READ_MAX rfalConvMsTo1fc(5U) /*!< Maximum Wait time for Read command as defined in TS T2T 1.0 table 18 */
#define RFAL_FDT_POLL_WRITE_MAX rfalConvMsTo1fc(10U) /*!< Maximum Wait time for Write command as defined in TS T2T 1.0 table 18 */
#define RFAL_FDT_POLL_SL_MAX rfalConvMsTo1fc(1U) /*!< Maximum Wait time for Sector Select as defined in TS T2T 1.0 table 18 */
#define RFAL_T2T_ACK_NACK_LEN 1U /*!< Len of NACK in bytes (4 bits) */
#define RFAL_T2T_ACK 0x0AU /*!< ACK value */
#define RFAL_T2T_ACK_MASK 0x0FU /*!< ACK value */
#define RFAL_T2T_SECTOR_SELECT_P1_BYTE2 0xFFU /*!< Sector Select Packet 1 byte 2 */
#define RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN 3U /*!< Sector Select RFU length */
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*! NFC-A T2T command set T2T 1.0 5.1 */
typedef enum
{
RFAL_T2T_CMD_READ = 0x30, /*!< T2T Read */
RFAL_T2T_CMD_WRITE = 0xA2, /*!< T2T Write */
RFAL_T2T_CMD_SECTOR_SELECT = 0xC2 /*!< T2T Sector Select */
} rfalT2Tcmds;
/*! NFC-A T2T READ T2T 1.0 5.2 and table 11 */
typedef struct
{
uint8_t code; /*!< Command code */
uint8_t blNo; /*!< Block number */
} rfalT2TReadReq;
/*! NFC-A T2T WRITE T2T 1.0 5.3 and table 12 */
typedef struct
{
uint8_t code; /*!< Command code */
uint8_t blNo; /*!< Block number */
uint8_t data[RFAL_T2T_WRITE_DATA_LEN]; /*!< Data */
} rfalT2TWriteReq;
/*! NFC-A T2T SECTOR SELECT Packet 1 T2T 1.0 5.4 and table 13 */
typedef struct
{
uint8_t code; /*!< Command code */
uint8_t byte2; /*!< Sector Select Packet 1 byte 2 */
} rfalT2TSectorSelectP1Req;
/*! NFC-A T2T SECTOR SELECT Packet 2 T2T 1.0 5.4 and table 13 */
typedef struct
{
uint8_t secNo; /*!< Block number */
uint8_t rfu[RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN]; /*!< Sector Select Packet RFU */
} rfalT2TSectorSelectP2Req;
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
ReturnCode rfalT2TPollerRead( uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t *rcvLen )
{
ReturnCode ret;
rfalT2TReadReq req;
if( (rxBuf == NULL) || (rcvLen == NULL) )
{
return ERR_PARAM;
}
req.code = (uint8_t)RFAL_T2T_CMD_READ;
req.blNo = blockNum;
/* Transceive Command */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&req, sizeof(rfalT2TReadReq), rxBuf, rxBufLen, rcvLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_READ_MAX );
/* T2T 1.0 5.2.1.7 The Reader/Writer SHALL treat a NACK in response to a READ Command as a Protocol Error */
if( (ret == ERR_INCOMPLETE_BYTE) && (*rcvLen == RFAL_T2T_ACK_NACK_LEN) && ((*rxBuf & RFAL_T2T_ACK_MASK) != RFAL_T2T_ACK) )
{
return ERR_PROTO;
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalT2TPollerWrite( uint8_t blockNum, const uint8_t* wrData )
{
ReturnCode ret;
rfalT2TWriteReq req;
uint8_t res;
uint16_t rxLen;
req.code = (uint8_t)RFAL_T2T_CMD_WRITE;
req.blNo = blockNum;
ST_MEMCPY(req.data, wrData, RFAL_T2T_WRITE_DATA_LEN);
/* Transceive WRITE Command */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&req, sizeof(rfalT2TWriteReq), &res, sizeof(uint8_t), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_READ_MAX );
/* Check for a valid ACK */
if( (ret == ERR_INCOMPLETE_BYTE) || (ret == ERR_NONE) )
{
ret = ERR_PROTO;
if( (rxLen == RFAL_T2T_ACK_NACK_LEN) && ((res & RFAL_T2T_ACK_MASK) == RFAL_T2T_ACK) )
{
ret = ERR_NONE;
}
}
return ret;
}
/*******************************************************************************/
ReturnCode rfalT2TPollerSectorSelect( uint8_t sectorNum )
{
rfalT2TSectorSelectP1Req p1Req;
rfalT2TSectorSelectP2Req p2Req;
ReturnCode ret;
uint8_t res;
uint16_t rxLen;
/* Compute SECTOR SELECT Packet 1 */
p1Req.code = (uint8_t)RFAL_T2T_CMD_SECTOR_SELECT;
p1Req.byte2 = RFAL_T2T_SECTOR_SELECT_P1_BYTE2;
/* Transceive SECTOR SELECT Packet 1 */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&p1Req, sizeof(rfalT2TSectorSelectP1Req), &res, sizeof(uint8_t), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_SL_MAX );
/* Check and report any transmission error */
if( (ret != ERR_INCOMPLETE_BYTE) && (ret != ERR_NONE) )
{
return ret;
}
/* Ensure that an ACK was received */
if( (ret != ERR_INCOMPLETE_BYTE) || (rxLen != RFAL_T2T_ACK_NACK_LEN) || ((res & RFAL_T2T_ACK_MASK) != RFAL_T2T_ACK) )
{
return ERR_PROTO;
}
/* Compute SECTOR SELECT Packet 2 */
p2Req.secNo = sectorNum;
ST_MEMSET( &p2Req.rfu, 0x00, RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN );
/* Transceive SECTOR SELECT Packet 2 */
ret = rfalTransceiveBlockingTxRx( (uint8_t*)&p2Req, sizeof(rfalT2TSectorSelectP2Req), &res, sizeof(uint8_t), &rxLen, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FDT_POLL_SL_MAX );
/* T2T 1.0 5.4.1.14 The Reader/Writer SHALL treat any response received before the end of PATT2T,SL,MAX as a Protocol Error */
if( (ret == ERR_NONE) || (ret == ERR_INCOMPLETE_BYTE) )
{
return ERR_PROTO;
}
/* T2T 1.0 5.4.1.13 The Reader/Writer SHALL treat the transmission of the SECTOR SELECT Command Packet 2 as being successful when it receives no response until PATT2T,SL,MAX. */
if( ret == ERR_TIMEOUT )
{
return ERR_NONE;
}
return ret;
}
#endif /* RFAL_FEATURE_T2T */

398
lib/ST25RFAL002/source/rfal_t4t.c Executable file
View file

@ -0,0 +1,398 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_t4t.h
*
* \author Gustavo Patricio
*
* \brief Provides convenience methods and definitions for T4T (ISO7816-4)
*
* This module provides an interface to exchange T4T APDUs according to
* NFC Forum T4T and ISO7816-4
*
* This implementation was based on the following specs:
* - ISO/IEC 7816-4 3rd Edition 2013-04-15
* - NFC Forum T4T Technical Specification 1.0 2017-08-28
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_t4t.h"
#include "utils.h"
/*
******************************************************************************
* ENABLE SWITCH
******************************************************************************
*/
#ifndef RFAL_FEATURE_T4T
#define RFAL_FEATURE_T4T false /* T4T module configuration missing. Disabled by default */
#endif
#if RFAL_FEATURE_T4T
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_T4T_OFFSET_DO 0x54U /*!< Tag value for offset BER-TLV data object */
#define RFAL_T4T_LENGTH_DO 0x03U /*!< Len value for offset BER-TLV data object */
#define RFAL_T4T_DATA_DO 0x53U /*!< Tag value for data BER-TLV data object */
#define RFAL_T4T_MAX_LC 255U /*!< Maximum Lc value for short Lc coding */
/*
******************************************************************************
* GLOBAL TYPES
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
ReturnCode rfalT4TPollerComposeCAPDU( const rfalT4tCApduParam *apduParam )
{
uint8_t hdrLen;
uint16_t msgIt;
if( (apduParam == NULL) || (apduParam->cApduBuf == NULL) || (apduParam->cApduLen == NULL) )
{
return ERR_PARAM;
}
msgIt = 0;
*(apduParam->cApduLen) = 0;
/*******************************************************************************/
/* Compute Command-APDU according to the format T4T 1.0 5.1.2 & ISO7816-4 2013 Table 1 */
/* Check if Data is present */
if( apduParam->LcFlag )
{
if( apduParam->Lc == 0U )
{
/* Extented field coding not supported */
return ERR_PARAM;
}
/* Check whether requested Lc fits */
if( (uint16_t)apduParam->Lc > (uint16_t)(RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN - RFAL_T4T_LE_LEN) )
{
return ERR_PARAM; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */
}
/* Calculate the header length a place the data/body where it should be */
hdrLen = RFAL_T4T_MAX_CAPDU_PROLOGUE_LEN + RFAL_T4T_LC_LEN;
/* make sure not to exceed buffer size */
if( ((uint16_t)hdrLen + (uint16_t)apduParam->Lc + (apduParam->LeFlag ? RFAL_T4T_LC_LEN : 0U)) > RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN )
{
return ERR_NOMEM; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */
}
ST_MEMMOVE( &apduParam->cApduBuf->apdu[hdrLen], apduParam->cApduBuf->apdu, apduParam->Lc );
}
/* Prepend the ADPDU's header */
apduParam->cApduBuf->apdu[msgIt++] = apduParam->CLA;
apduParam->cApduBuf->apdu[msgIt++] = apduParam->INS;
apduParam->cApduBuf->apdu[msgIt++] = apduParam->P1;
apduParam->cApduBuf->apdu[msgIt++] = apduParam->P2;
/* Check if Data field length is to be added */
if( apduParam->LcFlag )
{
apduParam->cApduBuf->apdu[msgIt++] = apduParam->Lc;
msgIt += apduParam->Lc;
}
/* Check if Expected Response Length is to be added */
if( apduParam->LeFlag )
{
apduParam->cApduBuf->apdu[msgIt++] = apduParam->Le;
}
*(apduParam->cApduLen) = msgIt;
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode rfalT4TPollerParseRAPDU( rfalT4tRApduParam *apduParam )
{
if( (apduParam == NULL) || (apduParam->rApduBuf == NULL) )
{
return ERR_PARAM;
}
if( apduParam->rcvdLen < RFAL_T4T_MAX_RAPDU_SW1SW2_LEN )
{
return ERR_PROTO;
}
apduParam->rApduBodyLen = (apduParam->rcvdLen - (uint16_t)RFAL_T4T_MAX_RAPDU_SW1SW2_LEN);
apduParam->statusWord = GETU16( (&apduParam->rApduBuf->apdu[ apduParam->rApduBodyLen ]) );
/* Check SW1 SW2 T4T 1.0 5.1.3 NOTE */
if( apduParam->statusWord == RFAL_T4T_ISO7816_STATUS_COMPLETE )
{
return ERR_NONE;
}
return ERR_REQUEST;
}
/*******************************************************************************/
ReturnCode rfalT4TPollerComposeSelectAppl( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* aid, uint8_t aidLen, uint16_t *cApduLen )
{
rfalT4tCApduParam cAPDU;
/* CLA INS P1 P2 Lc Data Le */
/* 00h A4h 00h 00h 07h AID 00h */
cAPDU.CLA = RFAL_T4T_CLA;
cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT;
cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_DF_NAME;
cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE;
cAPDU.Lc = aidLen;
cAPDU.Le = 0x00;
cAPDU.LcFlag = true;
cAPDU.LeFlag = true;
cAPDU.cApduBuf = cApduBuf;
cAPDU.cApduLen = cApduLen;
if( aidLen > 0U )
{
ST_MEMCPY( cAPDU.cApduBuf->apdu, aid, aidLen );
}
return rfalT4TPollerComposeCAPDU( &cAPDU );
}
/*******************************************************************************/
ReturnCode rfalT4TPollerComposeSelectFile( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* fid, uint8_t fidLen, uint16_t *cApduLen )
{
rfalT4tCApduParam cAPDU;
/* CLA INS P1 P2 Lc Data Le */
/* 00h A4h 00h 0Ch 02h FID - */
cAPDU.CLA = RFAL_T4T_CLA;
cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT;
cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID;
cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | RFAL_T4T_ISO7816_P2_SELECT_NO_RESPONSE_DATA;
cAPDU.Lc = fidLen;
cAPDU.Le = 0x00;
cAPDU.LcFlag = true;
cAPDU.LeFlag = false;
cAPDU.cApduBuf = cApduBuf;
cAPDU.cApduLen = cApduLen;
if( fidLen > 0U )
{
ST_MEMCPY( cAPDU.cApduBuf->apdu, fid, fidLen );
}
return rfalT4TPollerComposeCAPDU( &cAPDU );
}
/*******************************************************************************/
ReturnCode rfalT4TPollerComposeSelectFileV1Mapping( rfalIsoDepApduBufFormat *cApduBuf, const uint8_t* fid, uint8_t fidLen, uint16_t *cApduLen )
{
rfalT4tCApduParam cAPDU;
/* CLA INS P1 P2 Lc Data Le */
/* 00h A4h 00h 00h 02h FID - */
cAPDU.CLA = RFAL_T4T_CLA;
cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT;
cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID;
cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE;
cAPDU.Lc = fidLen;
cAPDU.Le = 0x00;
cAPDU.LcFlag = true;
cAPDU.LeFlag = false;
cAPDU.cApduBuf = cApduBuf;
cAPDU.cApduLen = cApduLen;
if( fidLen > 0U )
{
ST_MEMCPY( cAPDU.cApduBuf->apdu, fid, fidLen );
}
return rfalT4TPollerComposeCAPDU( &cAPDU );
}
/*******************************************************************************/
ReturnCode rfalT4TPollerComposeReadData( rfalIsoDepApduBufFormat *cApduBuf, uint16_t offset, uint8_t expLen, uint16_t *cApduLen )
{
rfalT4tCApduParam cAPDU;
/* CLA INS P1 P2 Lc Data Le */
/* 00h B0h [Offset] - - len */
cAPDU.CLA = RFAL_T4T_CLA;
cAPDU.INS = (uint8_t)RFAL_T4T_INS_READBINARY;
cAPDU.P1 = (uint8_t)((offset >> 8U) & 0xFFU);
cAPDU.P2 = (uint8_t)((offset >> 0U) & 0xFFU);
cAPDU.Le = expLen;
cAPDU.LcFlag = false;
cAPDU.LeFlag = true;
cAPDU.cApduBuf = cApduBuf;
cAPDU.cApduLen = cApduLen;
return rfalT4TPollerComposeCAPDU( &cAPDU );
}
/*******************************************************************************/
ReturnCode rfalT4TPollerComposeReadDataODO( rfalIsoDepApduBufFormat *cApduBuf, uint32_t offset, uint8_t expLen, uint16_t *cApduLen )
{
rfalT4tCApduParam cAPDU;
uint8_t dataIt;
/* CLA INS P1 P2 Lc Data Le */
/* 00h B1h 00h 00h Lc 54 03 xxyyzz len */
/* [Offset] */
cAPDU.CLA = RFAL_T4T_CLA;
cAPDU.INS = (uint8_t)RFAL_T4T_INS_READBINARY_ODO;
cAPDU.P1 = 0x00U;
cAPDU.P2 = 0x00U;
cAPDU.Le = expLen;
cAPDU.LcFlag = true;
cAPDU.LeFlag = true;
cAPDU.cApduBuf = cApduBuf;
cAPDU.cApduLen = cApduLen;
dataIt = 0U;
cApduBuf->apdu[dataIt++] = RFAL_T4T_OFFSET_DO;
cApduBuf->apdu[dataIt++] = RFAL_T4T_LENGTH_DO;
cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 16U);
cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 8U);
cApduBuf->apdu[dataIt++] = (uint8_t)(offset);
cAPDU.Lc = dataIt;
return rfalT4TPollerComposeCAPDU( &cAPDU );
}
/*******************************************************************************/
ReturnCode rfalT4TPollerComposeWriteData( rfalIsoDepApduBufFormat *cApduBuf, uint16_t offset, const uint8_t* data, uint8_t dataLen, uint16_t *cApduLen )
{
rfalT4tCApduParam cAPDU;
/* CLA INS P1 P2 Lc Data Le */
/* 00h D6h [Offset] len Data - */
cAPDU.CLA = RFAL_T4T_CLA;
cAPDU.INS = (uint8_t)RFAL_T4T_INS_UPDATEBINARY;
cAPDU.P1 = (uint8_t)((offset >> 8U) & 0xFFU);
cAPDU.P2 = (uint8_t)((offset >> 0U) & 0xFFU);
cAPDU.Lc = dataLen;
cAPDU.LcFlag = true;
cAPDU.LeFlag = false;
cAPDU.cApduBuf = cApduBuf;
cAPDU.cApduLen = cApduLen;
if( dataLen > 0U )
{
ST_MEMCPY( cAPDU.cApduBuf->apdu, data, dataLen );
}
return rfalT4TPollerComposeCAPDU( &cAPDU );
}
/*******************************************************************************/
ReturnCode rfalT4TPollerComposeWriteDataODO( rfalIsoDepApduBufFormat *cApduBuf, uint32_t offset, const uint8_t* data, uint8_t dataLen, uint16_t *cApduLen )
{
rfalT4tCApduParam cAPDU;
uint8_t dataIt;
/* CLA INS P1 P2 Lc Data Le */
/* 00h D7h 00h 00h len 54 03 xxyyzz 53 Ld data - */
/* [offset] [data] */
cAPDU.CLA = RFAL_T4T_CLA;
cAPDU.INS = (uint8_t)RFAL_T4T_INS_UPDATEBINARY_ODO;
cAPDU.P1 = 0x00U;
cAPDU.P2 = 0x00U;
cAPDU.LcFlag = true;
cAPDU.LeFlag = false;
cAPDU.cApduBuf = cApduBuf;
cAPDU.cApduLen = cApduLen;
dataIt = 0U;
cApduBuf->apdu[dataIt++] = RFAL_T4T_OFFSET_DO;
cApduBuf->apdu[dataIt++] = RFAL_T4T_LENGTH_DO;
cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 16U);
cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 8U);
cApduBuf->apdu[dataIt++] = (uint8_t)(offset);
cApduBuf->apdu[dataIt++] = RFAL_T4T_DATA_DO;
cApduBuf->apdu[dataIt++] = dataLen;
if( (((uint32_t)dataLen + (uint32_t)dataIt) >= RFAL_T4T_MAX_LC) || (((uint32_t)dataLen + (uint32_t)dataIt) >= RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN) )
{
return (ERR_NOMEM);
}
if( dataLen > 0U )
{
ST_MEMCPY( &cAPDU.cApduBuf->apdu[dataIt], data, dataLen );
}
dataIt += dataLen;
cAPDU.Lc = dataIt;
return rfalT4TPollerComposeCAPDU( &cAPDU );
}
#endif /* RFAL_FEATURE_T4T */

View file

@ -0,0 +1,594 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_analogConfig.h
*
* \author bkam
*
* \brief ST25R3916 Analog Configuration Settings
*
*/
#ifndef ST25R3916_ANALOGCONFIG_H
#define ST25R3916_ANALOGCONFIG_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_analogConfig.h"
#include "st25r3916_com.h"
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*! Macro for Configuration Setting with only one register-mask-value set:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1] */
#define MODE_ENTRY_1_REG(MODE, R0, M0, V0) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 1, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0)
/*! Macro for Configuration Setting with only two register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1] */
#define MODE_ENTRY_2_REG(MODE, R0, M0, V0, R1, M1, V1) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 2, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1)
/*! Macro for Configuration Setting with only three register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_3_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 3, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2)
/*! Macro for Configuration Setting with only four register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_4_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 4, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3)
/*! Macro for Configuration Setting with only five register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_5_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 5, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4)
/*! Macro for Configuration Setting with only six register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_6_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 6, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5)
/*! Macro for Configuration Setting with only seven register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_7_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 7, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6)
/*! Macro for Configuration Setting with only eight register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_8_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 8, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7)
/*! Macro for Configuration Setting with only nine register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_9_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 9, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8)
/*! Macro for Configuration Setting with only ten register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_10_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU),10, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \
, (uint8_t)((uint16_t)(R9) >> 8U), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9)
/*! Macro for Configuration Setting with eleven register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_11_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU),11, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \
, (uint8_t)((uint16_t)(R9) >> 8U), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \
, (uint8_t)((uint16_t)(R10) >> 8U), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10)
/*! Macro for Configuration Setting with twelve register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_12_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10, R11, M11, V11) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU),12, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \
, (uint8_t)((uint16_t)(R9) >> 8U), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \
, (uint8_t)((uint16_t)(R10) >> 8U), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \
, (uint8_t)((uint16_t)(R11) >> 8U), (uint8_t)((R11) & 0xFFU), (uint8_t)(M11), (uint8_t)(V11)
/*! Macro for Configuration Setting with thirteen register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_13_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10, R11, M11, V11, R12, M12, V12) \
(uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU),13, (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \
, (uint8_t)((uint16_t)(R9) >> 8U), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \
, (uint8_t)((uint16_t)(R10) >> 8U), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \
, (uint8_t)((uint16_t)(R11) >> 8U), (uint8_t)((R11) & 0xFFU), (uint8_t)(M11), (uint8_t)(V11) \
, (uint8_t)((uint16_t)(R12) >> 8U), (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12)
/*! Macro for Configuration Setting with fourteen register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_14_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10, R11, M11, V11, R12, M12, V12, R13, M13, V13, R14, M14, V14, R15, M15, V15) \
(uint8_t)((uint16_t)(MODE) >> 8), (uint8_t)((MODE) & 0xFFU),14, (uint8_t)((uint16_t)(R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \
, (uint8_t)((uint16_t)(R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \
, (uint8_t)((uint16_t)(R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \
, (uint8_t)((uint16_t)(R11) >> 8), (uint8_t)((R11) & 0xFFU), (uint8_t)(M11), (uint8_t)(V11) \
, (uint8_t)((uint16_t)(R12) >> 8), (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12) \
, (uint8_t)((uint16_t)(R13) >> 8), (uint8_t)((R13) & 0xFFU), (uint8_t)(M13), (uint8_t)(V13)
/*! Macro for Configuration Setting with fifteen register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_15_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10, R11, M11, V11, R12, M12, V12, R13, M13, V13, R14, M14, V14, R15, M15, V15) \
(uint8_t)((uint16_t)(MODE) >> 8), (uint8_t)((MODE) & 0xFFU),15, (uint8_t)((uint16_t)(R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \
, (uint8_t)((uint16_t)(R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \
, (uint8_t)((uint16_t)(R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \
, (uint8_t)((uint16_t)(R11) >> 8), (uint8_t)((R11) & 0xFFU), (uint8_t)(M11), (uint8_t)(V11) \
, (uint8_t)((uint16_t)(R12) >> 8), (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12) \
, (uint8_t)((uint16_t)(R13) >> 8), (uint8_t)((R13) & 0xFFU), (uint8_t)(M13), (uint8_t)(V13) \
, (uint8_t)((uint16_t)(R14) >> 8), (uint8_t)((R14) & 0xFFU), (uint8_t)(M14), (uint8_t)(V14)
/*! Macro for Configuration Setting with sixteen register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_16_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10, R11, M11, V11, R12, M12, V12, R13, M13, V13, R14, M14, V14, R15, M15, V15) \
(uint8_t)((uint16_t)(MODE) >> 8), (uint8_t)((MODE) & 0xFFU),16, (uint8_t)((uint16_t)(R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \
, (uint8_t)((uint16_t)(R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \
, (uint8_t)((uint16_t)(R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \
, (uint8_t)((uint16_t)(R11) >> 8), (uint8_t)((R11) & 0xFFU), (uint8_t)(M11), (uint8_t)(V11) \
, (uint8_t)((uint16_t)(R12) >> 8), (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12) \
, (uint8_t)((uint16_t)(R13) >> 8), (uint8_t)((R13) & 0xFFU), (uint8_t)(M13), (uint8_t)(V13) \
, (uint8_t)((uint16_t)(R14) >> 8), (uint8_t)((R14) & 0xFFU), (uint8_t)(M14), (uint8_t)(V14) \
, (uint8_t)((uint16_t)(R15) >> 8), (uint8_t)((R15) & 0xFFU), (uint8_t)(M15), (uint8_t)(V15)
/*! Macro for Configuration Setting with seventeen register-mask-value sets:
* - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */
#define MODE_ENTRY_17_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6, R7, M7, V7, R8, M8, V8, R9, M9, V9, R10, M10, V10, R11, M11, V11, R12, M12, V12, R13, M13, V13, R14, M14, V14, R15, M15, V15, R16, M16, V16) \
(uint8_t)((uint16_t)(MODE) >> 8), (uint8_t)((MODE) & 0xFFU),17, (uint8_t)((uint16_t)(R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) \
, (uint8_t)((uint16_t)(R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) \
, (uint8_t)((uint16_t)(R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) \
, (uint8_t)((uint16_t)(R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) \
, (uint8_t)((uint16_t)(R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) \
, (uint8_t)((uint16_t)(R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) \
, (uint8_t)((uint16_t)(R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) \
, (uint8_t)((uint16_t)(R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) \
, (uint8_t)((uint16_t)(R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) \
, (uint8_t)((uint16_t)(R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) \
, (uint8_t)((uint16_t)(R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), (uint8_t)(V10) \
, (uint8_t)((uint16_t)(R11) >> 8), (uint8_t)((R11) & 0xFFU), (uint8_t)(M11), (uint8_t)(V11) \
, (uint8_t)((uint16_t)(R12) >> 8), (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12) \
, (uint8_t)((uint16_t)(R13) >> 8), (uint8_t)((R13) & 0xFFU), (uint8_t)(M13), (uint8_t)(V13) \
, (uint8_t)((uint16_t)(R14) >> 8), (uint8_t)((R14) & 0xFFU), (uint8_t)(M14), (uint8_t)(V14) \
, (uint8_t)((uint16_t)(R15) >> 8), (uint8_t)((R15) & 0xFFU), (uint8_t)(M15), (uint8_t)(V15) \
, (uint8_t)((uint16_t)(R16) >> 8), (uint8_t)((R16) & 0xFFU), (uint8_t)(M16), (uint8_t)(V16)
/*
******************************************************************************
* GLOBAL DATA TYPES
******************************************************************************
*/
/* PRQA S 3406 1 # MISRA 8.6 - Externally generated table included by the library */ /* PRQA S 1514 1 # MISRA 8.9 - Externally generated table included by the library */
const uint8_t rfalAnalogConfigDefaultSettings[] = {
/****** Default Analog Configuration for Chip-Specific Reset ******/
MODE_ENTRY_17_REG( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_INIT)
, ST25R3916_REG_IO_CONF1, (ST25R3916_REG_IO_CONF1_out_cl_mask | ST25R3916_REG_IO_CONF1_lf_clk_off), 0x07 /* Disable MCU_CLK */
, ST25R3916_REG_IO_CONF2, (ST25R3916_REG_IO_CONF2_miso_pd1 | ST25R3916_REG_IO_CONF2_miso_pd2 ), 0x18 /* SPI Pull downs */
, ST25R3916_REG_IO_CONF2, ST25R3916_REG_IO_CONF2_aat_en, ST25R3916_REG_IO_CONF2_aat_en /* Enable AAT */
, ST25R3916_REG_TX_DRIVER, ST25R3916_REG_TX_DRIVER_d_res_mask, 0x00 /* Set RFO resistance Active Tx */
, ST25R3916_REG_RES_AM_MOD, 0xFF, 0x80 /* Use minimum non-overlap */
, ST25R3916_REG_FIELD_THRESHOLD_ACTV, ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask, ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_105mV /* Lower activation threshold (higher than deactivation)*/
, ST25R3916_REG_FIELD_THRESHOLD_ACTV, ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask, ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_105mV /* Lower activation threshold (higher than deactivation)*/
, ST25R3916_REG_FIELD_THRESHOLD_DEACTV, ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_mask, ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_75mV /* Lower deactivation threshold */
, ST25R3916_REG_FIELD_THRESHOLD_DEACTV, ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_mask, ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_75mV /* Lower deactivation threshold */
, ST25R3916_REG_AUX_MOD, ST25R3916_REG_AUX_MOD_lm_ext, 0x00 /* Disable External Load Modulation */
, ST25R3916_REG_AUX_MOD, ST25R3916_REG_AUX_MOD_lm_dri, ST25R3916_REG_AUX_MOD_lm_dri /* Use internal Load Modulation */
, ST25R3916_REG_PASSIVE_TARGET, ST25R3916_REG_PASSIVE_TARGET_fdel_mask, (5U<<ST25R3916_REG_PASSIVE_TARGET_fdel_shift) /* Adjust the FDT to be aligned with the bitgrid */
, ST25R3916_REG_PT_MOD, (ST25R3916_REG_PT_MOD_ptm_res_mask | ST25R3916_REG_PT_MOD_pt_res_mask), 0x5f /* Reduce RFO resistance in Modulated state */
, ST25R3916_REG_EMD_SUP_CONF, ST25R3916_REG_EMD_SUP_CONF_rx_start_emv, ST25R3916_REG_EMD_SUP_CONF_rx_start_emv_on /* Enable start on first 4 bits */
, ST25R3916_REG_ANT_TUNE_A, 0xFF, 0x82 /* Set Antenna Tuning (Poller): ANTL */
, ST25R3916_REG_ANT_TUNE_B, 0xFF, 0x82 /* Set Antenna Tuning (Poller): ANTL */
, 0x84U, 0x10, 0x10 /* Avoid chip internal overheat protection */
)
/****** Default Analog Configuration for Chip-Specific Poll Common ******/
, MODE_ENTRY_9_REG( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */
, ST25R3916_REG_TX_DRIVER, ST25R3916_REG_TX_DRIVER_am_mod_mask, ST25R3916_REG_TX_DRIVER_am_mod_12percent /* Set Modulation index */
, ST25R3916_REG_AUX_MOD, (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), 0x00 /* Use AM via regulator */
, ST25R3916_REG_ANT_TUNE_A, 0xFF, 0x82 /* Set Antenna Tuning (Poller): ANTL */
, ST25R3916_REG_ANT_TUNE_B, 0xFF, 0x82 /* Set Antenna Tuning (Poller): ANTL */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x00 /* Disable Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x00 /* Disable Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x00 /* Disable Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x00 /* Disable Undershoot Protection */
)
/****** Default Analog Configuration for Poll NFC-A Rx Common ******/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */
)
/****** Default Analog Configuration for Poll NFC-A Tx 106 ******/
, MODE_ENTRY_5_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_106 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am, ST25R3916_REG_MODE_tr_am_ook /* Use OOK */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x40 /* Set default Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x03 /* Set default Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x40 /* Set default Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x03 /* Set default Undershoot Protection */
)
/****** Default Analog Configuration for Poll NFC-A Rx 106 ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_106 | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, 0xFF, 0x08
, ST25R3916_REG_RX_CONF2, 0xFF, 0x2D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x51
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
/****** Default Analog Configuration for Poll NFC-A Tx 212 ******/
, MODE_ENTRY_7_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_212 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */
, ST25R3916_REG_AUX_MOD, (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), 0x88 /* Use Resistive AM */
, ST25R3916_REG_RES_AM_MOD, ST25R3916_REG_RES_AM_MOD_md_res_mask, 0x7F /* Set Resistive modulation */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x40 /* Set default Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x03 /* Set default Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x40 /* Set default Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x03 /* Set default Undershoot Protection */
)
/****** Default Analog Configuration for Poll NFC-A Rx 212 ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_212 | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, 0xFF, 0x02
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x14
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
/****** Default Analog Configuration for Poll NFC-A Tx 424 ******/
, MODE_ENTRY_7_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_424 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */
, ST25R3916_REG_AUX_MOD, (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), 0x88 /* Use Resistive AM */
, ST25R3916_REG_RES_AM_MOD, ST25R3916_REG_RES_AM_MOD_md_res_mask, 0x7F /* Set Resistive modulation */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x40 /* Set default Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x03 /* Set default Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x40 /* Set default Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x03 /* Set default Undershoot Protection */
)
/****** Default Analog Configuration for Poll NFC-A Rx 424 ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_424 | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, 0xFF, 0x42
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x54
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
/****** Default Analog Configuration for Poll NFC-A Tx 848 ******/
, MODE_ENTRY_7_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_848 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */
, ST25R3916_REG_TX_DRIVER, ST25R3916_REG_TX_DRIVER_am_mod_mask, ST25R3916_REG_TX_DRIVER_am_mod_40percent /* Set Modulation index */
, ST25R3916_REG_AUX_MOD, (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), 0x00 /* Use AM via regulator */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x00 /* Disable Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x00 /* Disable Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x00 /* Disable Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x00 /* Disable Undershoot Protection */
)
/****** Default Analog Configuration for Poll NFC-A Rx 848 ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_848 | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, 0xFF, 0x42
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x44
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
/****** Default Analog Configuration for Poll NFC-A Anticolision setting ******/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_ANTICOL)
, ST25R3916_REG_CORR_CONF1, ST25R3916_REG_CORR_CONF1_corr_s6, 0x00 /* Set collision detection level different from data */
)
#ifdef RFAL_USE_COHE
/****** Default Analog Configuration for Poll NFC-B Rx Common ******/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, ST25R3916_REG_AUX_dis_corr_coherent /* Use Coherent Receiver */
)
#else
/****** Default Analog Configuration for Poll NFC-B Rx Common ******/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */
)
#endif /*RFAL_USE_COHE*/
/****** Default Analog Configuration for Poll NFC-B Rx 106 ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_106 | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, 0xFF, 0x04
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x1B
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
/****** Default Analog Configuration for Poll NFC-B Rx 212 ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_212 | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, 0xFF, 0x02
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x14
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
/****** Default Analog Configuration for Poll NFC-B Rx 424 ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_424 | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, 0xFF, 0x42
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x54
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
/****** Default Analog Configuration for Poll NFC-B Rx 848 ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_848 | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, 0xFF, 0x42
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x44
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
#ifdef RFAL_USE_COHE
/****** Default Analog Configuration for Poll NFC-F Rx Common ******/
, MODE_ENTRY_7_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, ST25R3916_REG_AUX_dis_corr_coherent /* Use Pulse Receiver */
, ST25R3916_REG_RX_CONF1, 0xFF, 0x13
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x54
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
#else
/****** Default Analog Configuration for Poll NFC-F Rx Common ******/
, MODE_ENTRY_7_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */
, ST25R3916_REG_RX_CONF1, 0xFF, 0x13
, ST25R3916_REG_RX_CONF2, 0xFF, 0x3D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x54
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x00
)
#endif /*RFAL_USE_COHE*/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | RFAL_ANALOG_CONFIG_BITRATE_1OF4 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am, ST25R3916_REG_MODE_tr_am_ook /* Use OOK */
)
#ifdef RFAL_USE_COHE
/****** Default Analog Configuration for Poll NFC-V Rx Common ******/
, MODE_ENTRY_7_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, ST25R3916_REG_AUX_dis_corr_coherent /* Use Pulse Receiver */
, ST25R3916_REG_RX_CONF1, 0xFF, 0x13
, ST25R3916_REG_RX_CONF2, 0xFF, 0x2D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x13
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x01
)
#else
/****** Default Analog Configuration for Poll NFC-V Rx Common ******/
, MODE_ENTRY_7_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */
, ST25R3916_REG_RX_CONF1, 0xFF, 0x13
, ST25R3916_REG_RX_CONF2, 0xFF, 0x2D
, ST25R3916_REG_RX_CONF3, 0xFF, 0x00
, ST25R3916_REG_RX_CONF4, 0xFF, 0x00
, ST25R3916_REG_CORR_CONF1, 0xFF, 0x13
, ST25R3916_REG_CORR_CONF2, 0xFF, 0x01
)
#endif /*RFAL_USE_COHE*/
/****** Default Analog Configuration for Poll AP2P Tx 106 ******/
, MODE_ENTRY_5_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_106 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_ook /* Use OOK modulation */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x40 /* Set default Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x03 /* Set default Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x40 /* Set default Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x03 /* Set default Undershoot Protection */
)
/****** Default Analog Configuration for Poll AP2P Tx 212 ******/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_212 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */
)
/****** Default Analog Configuration for Poll AP2P Tx 424 ******/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_424 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */
)
/****** Default Analog Configuration for Chip-Specific Listen On ******/
, MODE_ENTRY_6_REG( (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_ON)
, ST25R3916_REG_ANT_TUNE_A, 0xFF, 0x00 /* Set Antenna Tuning (Listener): ANTL */
, ST25R3916_REG_ANT_TUNE_B, 0xFF, 0xff /* Set Antenna Tuning (Listener): ANTL */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x00 /* Disable Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x00 /* Disable Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x00 /* Disable Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x00 /* Disable Undershoot Protection */
)
/****** Default Analog Configuration for Listen AP2P Tx Common ******/
, MODE_ENTRY_7_REG( (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_ANT_TUNE_A, 0xFF, 0x82 /* Set Antenna Tuning (Poller): ANTL */
, ST25R3916_REG_ANT_TUNE_B, 0xFF, 0x82 /* Set Antenna Tuning (Poller): ANTL */
, ST25R3916_REG_TX_DRIVER, ST25R3916_REG_TX_DRIVER_am_mod_mask, ST25R3916_REG_TX_DRIVER_am_mod_12percent /* Set Modulation index */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x00 /* Disable Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x00 /* Disable Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x00 /* Disable Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x00 /* Disable Undershoot Protection */
)
/****** Default Analog Configuration for Listen AP2P Rx Common ******/
, MODE_ENTRY_3_REG( (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)
, ST25R3916_REG_RX_CONF1, ST25R3916_REG_RX_CONF1_lp_mask, ST25R3916_REG_RX_CONF1_lp_1200khz /* Set Rx filter configuration */
, ST25R3916_REG_RX_CONF1, ST25R3916_REG_RX_CONF1_hz_mask, ST25R3916_REG_RX_CONF1_hz_12_200khz /* Set Rx filter configuration */
, ST25R3916_REG_RX_CONF2, ST25R3916_REG_RX_CONF2_amd_sel, ST25R3916_REG_RX_CONF2_amd_sel_mixer /* AM demodulator: mixer */
)
/****** Default Analog Configuration for Listen AP2P Tx 106 ******/
, MODE_ENTRY_5_REG( (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_106 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_ook /* Use OOK modulation */
, ST25R3916_REG_OVERSHOOT_CONF1, 0xFF, 0x40 /* Set default Overshoot Protection */
, ST25R3916_REG_OVERSHOOT_CONF2, 0xFF, 0x03 /* Set default Overshoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF1, 0xFF, 0x40 /* Set default Undershoot Protection */
, ST25R3916_REG_UNDERSHOOT_CONF2, 0xFF, 0x03 /* Set default Undershoot Protection */
)
/****** Default Analog Configuration for Listen AP2P Tx 212 ******/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_212 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */
)
/****** Default Analog Configuration for Listen AP2P Tx 424 ******/
, MODE_ENTRY_1_REG( (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_424 | RFAL_ANALOG_CONFIG_TX)
, ST25R3916_REG_MODE, ST25R3916_REG_MODE_tr_am , ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */
)
};
#endif /* ST25R3916_ANALOGCONFIG_H */

View file

@ -0,0 +1,63 @@
/******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* $Revision: $
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Martin Zechleitner
*
* \brief RF Dynamic Power Table default values
*/
#ifndef ST25R3916_DPO_H
#define ST25R3916_DPO_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_dpo.h"
/*
******************************************************************************
* GLOBAL DATA TYPES
******************************************************************************
*/
/*! Default DPO table */
const uint8_t rfalDpoDefaultSettings [] = {
0x00, 255, 200,
0x01, 210, 150,
0x02, 160, 100,
0x03, 110, 50,
};
#endif /* ST25R3916_DPO_H */

View file

@ -0,0 +1,113 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Gustavo Patricio
*
* \brief RFAL Features/Capabilities Definition for ST25R3916
*/
#ifndef RFAL_FEATURES_H
#define RFAL_FEATURES_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define RFAL_SUPPORT_MODE_POLL_NFCA true /*!< RFAL Poll NFCA mode support switch */
#define RFAL_SUPPORT_MODE_POLL_NFCB true /*!< RFAL Poll NFCB mode support switch */
#define RFAL_SUPPORT_MODE_POLL_NFCF true /*!< RFAL Poll NFCF mode support switch */
#define RFAL_SUPPORT_MODE_POLL_NFCV true /*!< RFAL Poll NFCV mode support switch */
#define RFAL_SUPPORT_MODE_POLL_ACTIVE_P2P true /*!< RFAL Poll AP2P mode support switch */
#define RFAL_SUPPORT_MODE_LISTEN_NFCA true /*!< RFAL Listen NFCA mode support switch */
#define RFAL_SUPPORT_MODE_LISTEN_NFCB false /*!< RFAL Listen NFCB mode support switch */
#define RFAL_SUPPORT_MODE_LISTEN_NFCF true /*!< RFAL Listen NFCF mode support switch */
#define RFAL_SUPPORT_MODE_LISTEN_ACTIVE_P2P true /*!< RFAL Listen AP2P mode support switch */
/*******************************************************************************/
/*! RFAL supported Card Emulation (CE) */
#define RFAL_SUPPORT_CE ( RFAL_SUPPORT_MODE_LISTEN_NFCA || RFAL_SUPPORT_MODE_LISTEN_NFCB || RFAL_SUPPORT_MODE_LISTEN_NFCF )
/*! RFAL supported Reader/Writer (RW) */
#define RFAL_SUPPORT_RW ( RFAL_SUPPORT_MODE_POLL_NFCA || RFAL_SUPPORT_MODE_POLL_NFCB || RFAL_SUPPORT_MODE_POLL_NFCF || RFAL_SUPPORT_MODE_POLL_NFCV )
/*! RFAL support for Active P2P (AP2P) */
#define RFAL_SUPPORT_AP2P ( RFAL_SUPPORT_MODE_POLL_ACTIVE_P2P || RFAL_SUPPORT_MODE_LISTEN_ACTIVE_P2P )
/*******************************************************************************/
#define RFAL_SUPPORT_BR_RW_106 true /*!< RFAL RW 106 Bit Rate support switch */
#define RFAL_SUPPORT_BR_RW_212 true /*!< RFAL RW 212 Bit Rate support switch */
#define RFAL_SUPPORT_BR_RW_424 true /*!< RFAL RW 424 Bit Rate support switch */
#define RFAL_SUPPORT_BR_RW_848 true /*!< RFAL RW 848 Bit Rate support switch */
#define RFAL_SUPPORT_BR_RW_1695 false /*!< RFAL RW 1695 Bit Rate support switch */
#define RFAL_SUPPORT_BR_RW_3390 false /*!< RFAL RW 3390 Bit Rate support switch */
#define RFAL_SUPPORT_BR_RW_6780 false /*!< RFAL RW 6780 Bit Rate support switch */
#define RFAL_SUPPORT_BR_RW_13560 false /*!< RFAL RW 6780 Bit Rate support switch */
/*******************************************************************************/
#define RFAL_SUPPORT_BR_AP2P_106 true /*!< RFAL AP2P 106 Bit Rate support switch */
#define RFAL_SUPPORT_BR_AP2P_212 true /*!< RFAL AP2P 212 Bit Rate support switch */
#define RFAL_SUPPORT_BR_AP2P_424 true /*!< RFAL AP2P 424 Bit Rate support switch */
#define RFAL_SUPPORT_BR_AP2P_848 false /*!< RFAL AP2P 848 Bit Rate support switch */
/*******************************************************************************/
#define RFAL_SUPPORT_BR_CE_A_106 true /*!< RFAL CE A 106 Bit Rate support switch */
#define RFAL_SUPPORT_BR_CE_A_212 false /*!< RFAL CE A 212 Bit Rate support switch */
#define RFAL_SUPPORT_BR_CE_A_424 false /*!< RFAL CE A 424 Bit Rate support switch */
#define RFAL_SUPPORT_BR_CE_A_848 false /*!< RFAL CE A 848 Bit Rate support switch */
/*******************************************************************************/
#define RFAL_SUPPORT_BR_CE_B_106 false /*!< RFAL CE B 106 Bit Rate support switch */
#define RFAL_SUPPORT_BR_CE_B_212 false /*!< RFAL CE B 212 Bit Rate support switch */
#define RFAL_SUPPORT_BR_CE_B_424 false /*!< RFAL CE B 424 Bit Rate support switch */
#define RFAL_SUPPORT_BR_CE_B_848 false /*!< RFAL CE B 848 Bit Rate support switch */
/*******************************************************************************/
#define RFAL_SUPPORT_BR_CE_F_212 true /*!< RFAL CE F 212 Bit Rate support switch */
#define RFAL_SUPPORT_BR_CE_F_424 true /*!< RFAL CE F 424 Bit Rate support switch */
#endif /* RFAL_FEATURES_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,794 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Gustavo Patricio
*
* \brief ST25R3916 high level interface
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "st25r3916.h"
#include "st25r3916_com.h"
#include "st25r3916_led.h"
#include "st25r3916_irq.h"
#include "utils.h"
/*
******************************************************************************
* LOCAL DEFINES
******************************************************************************
*/
#define ST25R3916_SUPPLY_THRESHOLD 3600U /*!< Power supply measure threshold between 3.3V or 5V */
#define ST25R3916_NRT_MAX 0xFFFFU /*!< Max Register value of NRT */
#define ST25R3916_TOUT_MEASURE_VDD 100U /*!< Max duration time of Measure Power Supply command Datasheet: 25us */
#define ST25R3916_TOUT_MEASURE_AMPLITUDE 10U /*!< Max duration time of Measure Amplitude command Datasheet: 25us */
#define ST25R3916_TOUT_MEASURE_PHASE 10U /*!< Max duration time of Measure Phase command Datasheet: 25us */
#define ST25R3916_TOUT_MEASURE_CAPACITANCE 10U /*!< Max duration time of Measure Capacitance command Datasheet: 25us */
#define ST25R3916_TOUT_CALIBRATE_CAP_SENSOR 4U /*!< Max duration Calibrate Capacitive Sensor command Datasheet: 3ms */
#define ST25R3916_TOUT_ADJUST_REGULATORS 6U /*!< Max duration time of Adjust Regulators command Datasheet: 5ms */
#define ST25R3916_TOUT_CA 10U /*!< Max duration time of Collision Avoidance command */
#define ST25R3916_TEST_REG_PATTERN 0x33U /*!< Register Read Write test pattern used during selftest */
#define ST25R3916_TEST_WU_TOUT 12U /*!< Timeout used on WU timer during self test */
#define ST25R3916_TEST_TMR_TOUT 20U /*!< Timeout used during self test */
#define ST25R3916_TEST_TMR_TOUT_DELTA 2U /*!< Timeout used during self test */
#define ST25R3916_TEST_TMR_TOUT_8FC (ST25R3916_TEST_TMR_TOUT * 16950U) /*!< Timeout in 8/fc */
/*
******************************************************************************
* LOCAL CONSTANTS
******************************************************************************
*/
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
static uint32_t gST25R3916NRT_64fcs;
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*
******************************************************************************
* LOCAL FUNCTION
******************************************************************************
*/
ReturnCode st25r3916ExecuteCommandAndGetResult( uint8_t cmd, uint8_t resReg, uint8_t tout, uint8_t* result )
{
/* Clear and enable Direct Command interrupt */
st25r3916GetInterrupt( ST25R3916_IRQ_MASK_DCT );
st25r3916EnableInterrupts( ST25R3916_IRQ_MASK_DCT );
st25r3916ExecuteCommand( cmd );
st25r3916WaitForInterruptsTimed( ST25R3916_IRQ_MASK_DCT, tout );
st25r3916DisableInterrupts( ST25R3916_IRQ_MASK_DCT );
/* After execution read out the result if the pointer is not NULL */
if( result != NULL )
{
st25r3916ReadRegister( resReg, result);
}
return ERR_NONE;
}
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
ReturnCode st25r3916Initialize( void )
{
uint16_t vdd_mV;
ReturnCode ret;
/* Set default state on the ST25R3916 */
st25r3916ExecuteCommand( ST25R3916_CMD_SET_DEFAULT );
#ifndef RFAL_USE_I2C
/* Increase MISO driving level as SPI can go up to 10MHz */
st25r3916WriteRegister(ST25R3916_REG_IO_CONF2, ST25R3916_REG_IO_CONF2_io_drv_lvl);
#endif /* RFAL_USE_I2C */
if( !st25r3916CheckChipID( NULL ) )
{
platformErrorHandle();
return ERR_HW_MISMATCH;
}
st25r3916InitInterrupts();
st25r3916ledInit();
gST25R3916NRT_64fcs = 0;
#ifndef RFAL_USE_I2C
/* Enable pull downs on MISO line */
st25r3916SetRegisterBits(ST25R3916_REG_IO_CONF2, ( ST25R3916_REG_IO_CONF2_miso_pd1 | ST25R3916_REG_IO_CONF2_miso_pd2 ) );
#endif /* RFAL_USE_I2C */
/* Disable internal overheat protection */
st25r3916ChangeTestRegisterBits( 0x04, 0x10, 0x10 );
#ifdef ST25R_SELFTEST
/******************************************************************************
* Check communication interface:
* - write a pattern in a register
* - reads back the register value
* - return ERR_IO in case the read value is different
*/
st25r3916WriteRegister( ST25R3916_REG_BIT_RATE, ST25R3916_TEST_REG_PATTERN );
if( !st25r3916CheckReg( ST25R3916_REG_BIT_RATE, (ST25R3916_REG_BIT_RATE_rxrate_mask | ST25R3916_REG_BIT_RATE_txrate_mask), ST25R3916_TEST_REG_PATTERN ) )
{
platformErrorHandle();
return ERR_IO;
}
/* Restore default value */
st25r3916WriteRegister( ST25R3916_REG_BIT_RATE, 0x00 );
/*
* Check IRQ Handling:
* - use the Wake-up timer to trigger an IRQ
* - wait the Wake-up timer interrupt
* - return ERR_TIMEOUT when the Wake-up timer interrupt is not received
*/
st25r3916WriteRegister( ST25R3916_REG_WUP_TIMER_CONTROL, ST25R3916_REG_WUP_TIMER_CONTROL_wur|ST25R3916_REG_WUP_TIMER_CONTROL_wto);
st25r3916EnableInterrupts( ST25R3916_IRQ_MASK_WT );
st25r3916ExecuteCommand( ST25R3916_CMD_START_WUP_TIMER );
if(st25r3916WaitForInterruptsTimed(ST25R3916_IRQ_MASK_WT, ST25R3916_TEST_WU_TOUT) == 0U )
{
platformErrorHandle();
return ERR_TIMEOUT;
}
st25r3916DisableInterrupts( ST25R3916_IRQ_MASK_WT );
st25r3916WriteRegister( ST25R3916_REG_WUP_TIMER_CONTROL, 0U );
/*******************************************************************************/
#endif /* ST25R_SELFTEST */
/* Enable Oscillator and wait until it gets stable */
ret = st25r3916OscOn();
if( ret != ERR_NONE )
{
platformErrorHandle();
return ret;
}
/* Measure VDD and set sup3V bit according to Power supplied */
vdd_mV = st25r3916MeasureVoltage( ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd );
st25r3916ChangeRegisterBits( ST25R3916_REG_IO_CONF2, ST25R3916_REG_IO_CONF2_sup3V, ((vdd_mV < ST25R3916_SUPPLY_THRESHOLD) ? ST25R3916_REG_IO_CONF2_sup3V_3V : ST25R3916_REG_IO_CONF2_sup3V_5V) );
/* Make sure Transmitter and Receiver are disabled */
st25r3916TxRxOff();
#ifdef ST25R_SELFTEST_TIMER
/******************************************************************************
* Check SW timer operation :
* - use the General Purpose timer to measure an amount of time
* - test whether an interrupt is seen when less time was given
* - test whether an interrupt is seen when sufficient time was given
*/
st25r3916EnableInterrupts( ST25R3916_IRQ_MASK_GPE );
st25r3916SetStartGPTimer( (uint16_t)ST25R3916_TEST_TMR_TOUT_8FC, ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger);
if( st25r3916WaitForInterruptsTimed( ST25R3916_IRQ_MASK_GPE, (ST25R3916_TEST_TMR_TOUT - ST25R3916_TEST_TMR_TOUT_DELTA)) != 0U )
{
platformErrorHandle();
return ERR_SYSTEM;
}
/* Stop all activities to stop the GP timer */
st25r3916ExecuteCommand( ST25R3916_CMD_STOP );
st25r3916ClearAndEnableInterrupts( ST25R3916_IRQ_MASK_GPE );
st25r3916SetStartGPTimer( (uint16_t)ST25R3916_TEST_TMR_TOUT_8FC, ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger );
if(st25r3916WaitForInterruptsTimed( ST25R3916_IRQ_MASK_GPE, (ST25R3916_TEST_TMR_TOUT + ST25R3916_TEST_TMR_TOUT_DELTA)) == 0U )
{
platformErrorHandle();
return ERR_SYSTEM;
}
/* Stop all activities to stop the GP timer */
st25r3916ExecuteCommand( ST25R3916_CMD_STOP );
/*******************************************************************************/
#endif /* ST25R_SELFTEST_TIMER */
/* After reset all interrupts are enabled, so disable them at first */
st25r3916DisableInterrupts( ST25R3916_IRQ_MASK_ALL );
/* And clear them, just to be sure */
st25r3916ClearInterrupts();
return ERR_NONE;
}
/*******************************************************************************/
void st25r3916Deinitialize( void )
{
st25r3916DisableInterrupts( ST25R3916_IRQ_MASK_ALL );
/* Disabe Tx and Rx, Keep OSC On */
st25r3916TxRxOff();
return;
}
/*******************************************************************************/
ReturnCode st25r3916OscOn( void )
{
/* Check if oscillator is already turned on and stable */
/* Use ST25R3916_REG_OP_CONTROL_en instead of ST25R3916_REG_AUX_DISPLAY_osc_ok to be on the safe side */
if( !st25r3916CheckReg( ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en, ST25R3916_REG_OP_CONTROL_en ) )
{
/* Clear any eventual previous oscillator IRQ */
st25r3916GetInterrupt( ST25R3916_IRQ_MASK_OSC );
/* Enable oscillator frequency stable interrupt */
st25r3916EnableInterrupts( ST25R3916_IRQ_MASK_OSC );
/* Enable oscillator and regulator output */
st25r3916SetRegisterBits( ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en );
/* Wait for the oscillator interrupt */
st25r3916WaitForInterruptsTimed( ST25R3916_IRQ_MASK_OSC, ST25R3916_TOUT_OSC_STABLE );
st25r3916DisableInterrupts( ST25R3916_IRQ_MASK_OSC );
}
if( !st25r3916CheckReg( ST25R3916_REG_AUX_DISPLAY, ST25R3916_REG_AUX_DISPLAY_osc_ok, ST25R3916_REG_AUX_DISPLAY_osc_ok ) )
{
return ERR_SYSTEM;
}
return ERR_NONE;
}
/*******************************************************************************/
uint8_t st25r3916MeasurePowerSupply( uint8_t mpsv )
{
uint8_t result;
/* Set the source of direct command: Measure Power Supply Voltage */
st25r3916ChangeRegisterBits( ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_mpsv_mask, mpsv );
/* Execute command: Measure Power Supply Voltage */
st25r3916ExecuteCommandAndGetResult( ST25R3916_CMD_MEASURE_VDD, ST25R3916_REG_AD_RESULT, ST25R3916_TOUT_MEASURE_VDD, &result);
return result;
}
/*******************************************************************************/
uint16_t st25r3916MeasureVoltage( uint8_t mpsv )
{
uint8_t result;
uint16_t mV;
result = st25r3916MeasurePowerSupply(mpsv);
/* Convert cmd output into mV (each step represents 23.4 mV )*/
mV = ((uint16_t)result) * 23U;
mV += (((((uint16_t)result) * 4U) + 5U) / 10U);
return mV;
}
/*******************************************************************************/
ReturnCode st25r3916AdjustRegulators( uint16_t* result_mV )
{
uint8_t result;
/* Reset logic and set regulated voltages to be defined by result of Adjust Regulators command */
st25r3916SetRegisterBits( ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_reg_s );
st25r3916ClrRegisterBits( ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_reg_s );
/* Execute Adjust regulators cmd and retrieve result */
st25r3916ExecuteCommandAndGetResult( ST25R3916_CMD_ADJUST_REGULATORS, ST25R3916_REG_REGULATOR_RESULT, ST25R3916_TOUT_ADJUST_REGULATORS, &result );
/* Calculate result in mV */
result >>= ST25R3916_REG_REGULATOR_RESULT_reg_shift;
if( result_mV != NULL )
{
if( st25r3916CheckReg( ST25R3916_REG_IO_CONF2, ST25R3916_REG_IO_CONF2_sup3V, ST25R3916_REG_IO_CONF2_sup3V ) )
{
result = MIN( result, (uint8_t)(result-5U) );/* In 3.3V mode [0,4] are not used */
*result_mV = 2400U; /* Minimum regulated voltage 2.4V in case of 3.3V supply */
}
else
{
*result_mV = 3600U; /* Minimum regulated voltage 3.6V in case of 5V supply */
}
*result_mV += (uint16_t)result * 100U; /* 100mV steps in both 3.3V and 5V supply */
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916MeasureAmplitude( uint8_t* result )
{
return st25r3916ExecuteCommandAndGetResult( ST25R3916_CMD_MEASURE_AMPLITUDE, ST25R3916_REG_AD_RESULT, ST25R3916_TOUT_MEASURE_AMPLITUDE, result );
}
/*******************************************************************************/
ReturnCode st25r3916MeasurePhase( uint8_t* result )
{
return st25r3916ExecuteCommandAndGetResult( ST25R3916_CMD_MEASURE_PHASE, ST25R3916_REG_AD_RESULT, ST25R3916_TOUT_MEASURE_PHASE, result );
}
/*******************************************************************************/
ReturnCode st25r3916MeasureCapacitance( uint8_t* result )
{
return st25r3916ExecuteCommandAndGetResult( ST25R3916_CMD_MEASURE_CAPACITANCE, ST25R3916_REG_AD_RESULT, ST25R3916_TOUT_MEASURE_CAPACITANCE, result );
}
/*******************************************************************************/
ReturnCode st25r3916CalibrateCapacitiveSensor( uint8_t* result )
{
ReturnCode ret;
uint8_t res;
/* Clear Manual calibration values to enable automatic calibration mode */
st25r3916ClrRegisterBits( ST25R3916_REG_CAP_SENSOR_CONTROL, ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal_mask );
/* Execute automatic calibration */
ret = st25r3916ExecuteCommandAndGetResult( ST25R3916_CMD_CALIBRATE_C_SENSOR, ST25R3916_REG_CAP_SENSOR_RESULT, ST25R3916_TOUT_CALIBRATE_CAP_SENSOR, &res );
/* Check wether the calibration was successull */
if( ((res & ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_end) != ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_end) ||
((res & ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_err) == ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_err) || (ret != ERR_NONE) )
{
return ERR_IO;
}
if( result != NULL )
{
(*result) = (uint8_t)(res >> ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_shift);
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916SetBitrate(uint8_t txrate, uint8_t rxrate)
{
uint8_t reg;
st25r3916ReadRegister( ST25R3916_REG_BIT_RATE, &reg );
if( rxrate != ST25R3916_BR_DO_NOT_SET )
{
if(rxrate > ST25R3916_BR_848)
{
return ERR_PARAM;
}
reg = (uint8_t)(reg & ~ST25R3916_REG_BIT_RATE_rxrate_mask); /* MISRA 10.3 */
reg |= rxrate << ST25R3916_REG_BIT_RATE_rxrate_shift;
}
if( txrate != ST25R3916_BR_DO_NOT_SET )
{
if(txrate > ST25R3916_BR_6780)
{
return ERR_PARAM;
}
reg = (uint8_t)(reg & ~ST25R3916_REG_BIT_RATE_txrate_mask); /* MISRA 10.3 */
reg |= txrate<<ST25R3916_REG_BIT_RATE_txrate_shift;
}
return st25r3916WriteRegister( ST25R3916_REG_BIT_RATE, reg );
}
/*******************************************************************************/
ReturnCode st25r3916PerformCollisionAvoidance( uint8_t FieldONCmd, uint8_t pdThreshold, uint8_t caThreshold, uint8_t nTRFW )
{
uint8_t treMask;
uint32_t irqs;
ReturnCode err;
if( (FieldONCmd != ST25R3916_CMD_INITIAL_RF_COLLISION) && (FieldONCmd != ST25R3916_CMD_RESPONSE_RF_COLLISION_N) )
{
return ERR_PARAM;
}
err = ERR_INTERNAL;
/* Check if new thresholds are to be applied */
if( (pdThreshold != ST25R3916_THRESHOLD_DO_NOT_SET) || (caThreshold != ST25R3916_THRESHOLD_DO_NOT_SET) )
{
treMask = 0;
if(pdThreshold != ST25R3916_THRESHOLD_DO_NOT_SET)
{
treMask |= ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask;
}
if(caThreshold != ST25R3916_THRESHOLD_DO_NOT_SET)
{
treMask |= ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask;
}
/* Set Detection Threshold and|or Collision Avoidance Threshold */
st25r3916ChangeRegisterBits( ST25R3916_REG_FIELD_THRESHOLD_ACTV, treMask, (pdThreshold & ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask) | (caThreshold & ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask ) );
}
/* Set n x TRFW */
st25r3916ChangeRegisterBits( ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_n_mask, nTRFW );
/*******************************************************************************/
/* Enable and clear CA specific interrupts and execute command */
st25r3916GetInterrupt( (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON) );
st25r3916EnableInterrupts( (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON) );
st25r3916ExecuteCommand( FieldONCmd );
/*******************************************************************************/
/* Wait for initial APON interrupt, indicating anticollision avoidance done and ST25R3916's
* field is now on, or a CAC indicating a collision */
irqs = st25r3916WaitForInterruptsTimed( ( ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_APON ), ST25R3916_TOUT_CA );
if( (ST25R3916_IRQ_MASK_CAC & irqs) != 0U ) /* Collision occurred */
{
err = ERR_RF_COLLISION;
}
else if( (ST25R3916_IRQ_MASK_APON & irqs) != 0U )
{
/* After APON wait for CAT interrupt, indication field was switched on minimum guard time has been fulfilled */
irqs = st25r3916WaitForInterruptsTimed( ( ST25R3916_IRQ_MASK_CAT ), ST25R3916_TOUT_CA );
if( (ST25R3916_IRQ_MASK_CAT & irqs) != 0U ) /* No Collision detected, Field On */
{
err = ERR_NONE;
}
}
else
{
/* MISRA 15.7 - Empty else */
}
/* Clear any previous External Field events and disable CA specific interrupts */
st25r3916GetInterrupt( (ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_EON) );
st25r3916DisableInterrupts( (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON) );
return err;
}
/*******************************************************************************/
void st25r3916SetNumTxBits( uint16_t nBits )
{
st25r3916WriteRegister( ST25R3916_REG_NUM_TX_BYTES2, (uint8_t)((nBits >> 0) & 0xFFU) );
st25r3916WriteRegister( ST25R3916_REG_NUM_TX_BYTES1, (uint8_t)((nBits >> 8) & 0xFFU) );
}
/*******************************************************************************/
uint16_t st25r3916GetNumFIFOBytes( void )
{
uint8_t reg;
uint16_t result;
st25r3916ReadRegister( ST25R3916_REG_FIFO_STATUS2, &reg );
reg = ((reg & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >> ST25R3916_REG_FIFO_STATUS2_fifo_b_shift);
result = ((uint16_t)reg << 8);
st25r3916ReadRegister( ST25R3916_REG_FIFO_STATUS1, &reg );
result |= (((uint16_t)reg) & 0x00FFU);
return result;
}
/*******************************************************************************/
uint8_t st25r3916GetNumFIFOLastBits( void )
{
uint8_t reg;
st25r3916ReadRegister( ST25R3916_REG_FIFO_STATUS2, &reg );
return ((reg & ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask) >> ST25R3916_REG_FIFO_STATUS2_fifo_lb_shift);
}
/*******************************************************************************/
uint32_t st25r3916GetNoResponseTime( void )
{
return gST25R3916NRT_64fcs;
}
/*******************************************************************************/
ReturnCode st25r3916SetNoResponseTime( uint32_t nrt_64fcs )
{
ReturnCode err;
uint8_t nrt_step;
uint32_t tmpNRT;
tmpNRT = nrt_64fcs; /* MISRA 17.8 */
err = ERR_NONE;
gST25R3916NRT_64fcs = tmpNRT; /* Store given NRT value in 64/fc into local var */
nrt_step = ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step_64fc; /* Set default NRT in steps of 64/fc */
if( tmpNRT > ST25R3916_NRT_MAX ) /* Check if the given NRT value fits using 64/fc steps */
{
nrt_step = ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step_4096_fc; /* If not, change NRT set to 4096/fc */
tmpNRT = ((tmpNRT + 63U) / 64U); /* Calculate number of steps in 4096/fc */
if( tmpNRT > ST25R3916_NRT_MAX ) /* Check if the NRT value fits using 64/fc steps */
{
tmpNRT = ST25R3916_NRT_MAX; /* Assign the maximum possible */
err = ERR_PARAM; /* Signal parameter error */
}
gST25R3916NRT_64fcs = (64U * tmpNRT);
}
/* Set the ST25R3916 NRT step units and the value */
st25r3916ChangeRegisterBits( ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step, nrt_step );
st25r3916WriteRegister( ST25R3916_REG_NO_RESPONSE_TIMER1, (uint8_t)(tmpNRT >> 8U) );
st25r3916WriteRegister( ST25R3916_REG_NO_RESPONSE_TIMER2, (uint8_t)(tmpNRT & 0xFFU) );
return err;
}
/*******************************************************************************/
ReturnCode st25r3916SetStartNoResponseTimer( uint32_t nrt_64fcs )
{
ReturnCode err;
err = st25r3916SetNoResponseTime( nrt_64fcs );
if(err == ERR_NONE)
{
st25r3916ExecuteCommand( ST25R3916_CMD_START_NO_RESPONSE_TIMER );
}
return err;
}
/*******************************************************************************/
void st25r3916SetGPTime( uint16_t gpt_8fcs )
{
st25r3916WriteRegister( ST25R3916_REG_GPT1, (uint8_t)(gpt_8fcs >> 8) );
st25r3916WriteRegister( ST25R3916_REG_GPT2, (uint8_t)(gpt_8fcs & 0xFFU) );
}
/*******************************************************************************/
ReturnCode st25r3916SetStartGPTimer( uint16_t gpt_8fcs, uint8_t trigger_source )
{
st25r3916SetGPTime( gpt_8fcs );
st25r3916ChangeRegisterBits( ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_gptc_mask, trigger_source );
/* If there's no trigger source, start GPT immediately */
if( trigger_source == ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger )
{
st25r3916ExecuteCommand( ST25R3916_CMD_START_GP_TIMER );
}
return ERR_NONE;
}
/*******************************************************************************/
bool st25r3916CheckChipID( uint8_t *rev )
{
uint8_t ID;
ID = 0;
st25r3916ReadRegister( ST25R3916_REG_IC_IDENTITY, &ID );
/* Check if IC Identity Register contains ST25R3916's IC type code */
if( (ID & ST25R3916_REG_IC_IDENTITY_ic_type_mask) != ST25R3916_REG_IC_IDENTITY_ic_type_st25r3916 )
{
return false;
}
if(rev != NULL)
{
*rev = (ID & ST25R3916_REG_IC_IDENTITY_ic_rev_mask);
}
return true;
}
/*******************************************************************************/
ReturnCode st25r3916GetRegsDump( t_st25r3916Regs* regDump )
{
uint8_t regIt;
if(regDump == NULL)
{
return ERR_PARAM;
}
/* Dump Registers on space A */
for( regIt = ST25R3916_REG_IO_CONF1; regIt <= ST25R3916_REG_IC_IDENTITY; regIt++ )
{
st25r3916ReadRegister(regIt, &regDump->RsA[regIt] );
}
regIt = 0;
/* Read non-consecutive Registers on space B */
st25r3916ReadRegister( ST25R3916_REG_EMD_SUP_CONF, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_SUBC_START_TIME, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_P2P_RX_CONF, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_CORR_CONF1, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_CORR_CONF2, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_SQUELCH_TIMER, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_FIELD_ON_GT, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_AUX_MOD, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_TX_DRIVER_TIMING, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_RES_AM_MOD, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_TX_DRIVER_STATUS, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_REGULATOR_RESULT, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_OVERSHOOT_CONF1, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_OVERSHOOT_CONF2, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_UNDERSHOOT_CONF1, &regDump->RsB[regIt++] );
st25r3916ReadRegister( ST25R3916_REG_UNDERSHOOT_CONF2, &regDump->RsB[regIt++] );
return ERR_NONE;
}
/*******************************************************************************/
bool st25r3916IsCmdValid( uint8_t cmd )
{
if( !((cmd >= ST25R3916_CMD_SET_DEFAULT) && (cmd <= ST25R3916_CMD_RESPONSE_RF_COLLISION_N)) &&
!((cmd >= ST25R3916_CMD_GOTO_SENSE) && (cmd <= ST25R3916_CMD_GOTO_SLEEP)) &&
!((cmd >= ST25R3916_CMD_MASK_RECEIVE_DATA) && (cmd <= ST25R3916_CMD_MEASURE_AMPLITUDE)) &&
!((cmd >= ST25R3916_CMD_RESET_RXGAIN) && (cmd <= ST25R3916_CMD_ADJUST_REGULATORS)) &&
!((cmd >= ST25R3916_CMD_CALIBRATE_DRIVER_TIMING) && (cmd <= ST25R3916_CMD_START_PPON2_TIMER)) &&
(cmd != ST25R3916_CMD_SPACE_B_ACCESS) && (cmd != ST25R3916_CMD_STOP_NRT) )
{
return false;
}
return true;
}
/*******************************************************************************/
ReturnCode st25r3916StreamConfigure(const struct st25r3916StreamConfig *config)
{
uint8_t smd;
uint8_t mode;
smd = 0;
if( config->useBPSK != 0U )
{
mode = ST25R3916_REG_MODE_om_bpsk_stream;
if( (config->din<2U) || (config->din>4U) ) /* not in fc/4 .. fc/16 */
{
return ERR_PARAM;
}
smd |= ((4U - config->din) << ST25R3916_REG_STREAM_MODE_scf_shift);
}
else
{
mode = ST25R3916_REG_MODE_om_subcarrier_stream;
if( (config->din<3U) || (config->din>6U) ) /* not in fc/8 .. fc/64 */
{
return ERR_PARAM;
}
smd |= ((6U - config->din) << ST25R3916_REG_STREAM_MODE_scf_shift);
if( config->report_period_length == 0U )
{
return ERR_PARAM;
}
}
if( (config->dout<1U) || (config->dout>7U) ) /* not in fc/2 .. fc/128 */
{
return ERR_PARAM;
}
smd |= (7U - config->dout) << ST25R3916_REG_STREAM_MODE_stx_shift;
if( config->report_period_length > 3U )
{
return ERR_PARAM;
}
smd |= (config->report_period_length << ST25R3916_REG_STREAM_MODE_scp_shift);
st25r3916WriteRegister(ST25R3916_REG_STREAM_MODE, smd);
st25r3916ChangeRegisterBits(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_mask, mode);
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916GetRSSI( uint16_t *amRssi, uint16_t *pmRssi )
{
/*******************************************************************************/
/* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */
/*< ST25R3916 RSSI Display Reg values: 0 1 2 3 4 5 6 7 8 9 a b c d e f */
static const uint16_t st25r3916Rssi2mV[] = { 0 ,20 ,27 ,37 ,52 ,72 ,99 ,136 ,190 ,262 ,357 ,500 ,686 ,950, 1150, 1150 };
/* ST25R3916 2/3 stage gain reduction [dB] 0 0 0 0 0 3 6 9 12 15 18 na na na na na */
static const uint16_t st25r3916Gain2Percent[] = { 100, 100, 100, 100, 100, 141, 200, 281, 398, 562, 794, 1, 1, 1, 1, 1 };
/*******************************************************************************/
uint8_t rssi;
uint8_t gainRed;
st25r3916ReadRegister( ST25R3916_REG_RSSI_RESULT, &rssi );
st25r3916ReadRegister( ST25R3916_REG_GAIN_RED_STATE, &gainRed );
if( amRssi != NULL )
{
*amRssi = (uint16_t) ( ( (uint32_t)st25r3916Rssi2mV[ (rssi >> ST25R3916_REG_RSSI_RESULT_rssi_am_shift) ] * (uint32_t)st25r3916Gain2Percent[ (gainRed >> ST25R3916_REG_GAIN_RED_STATE_gs_am_shift) ] ) / 100U );
}
if( pmRssi != NULL )
{
*pmRssi = (uint16_t) ( ( (uint32_t)st25r3916Rssi2mV[ (rssi & ST25R3916_REG_RSSI_RESULT_rssi_pm_mask) ] * (uint32_t)st25r3916Gain2Percent[ (gainRed & ST25R3916_REG_GAIN_RED_STATE_gs_pm_mask) ] ) / 100U );
}
return ERR_NONE;
}

View file

@ -0,0 +1,609 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Gustavo Patricio
*
* \brief ST25R3916 high level interface
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-HAL
* \brief RFAL Hardware Abstraction Layer
* @{
*
* \addtogroup ST25R3916
* \brief RFAL ST25R3916 Driver
* @{
*
* \addtogroup ST25R3916_Driver
* \brief RFAL ST25R3916 Driver
* @{
*
*/
#ifndef ST25R3916_H
#define ST25R3916_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
#include "st_errno.h"
#include "st25r3916_com.h"
/*
******************************************************************************
* GLOBAL DATATYPES
******************************************************************************
*/
/*! Struct to represent all regs on ST25R3916 */
typedef struct{
uint8_t RsA[(ST25R3916_REG_IC_IDENTITY+1U)]; /*!< Registers contained on ST25R3916 space A (Rs-A) */
uint8_t RsB[ST25R3916_SPACE_B_REG_LEN]; /*!< Registers contained on ST25R3916 space B (Rs-B) */
}t_st25r3916Regs;
/*! Parameters how the stream mode should work */
struct st25r3916StreamConfig {
uint8_t useBPSK; /*!< 0: subcarrier, 1:BPSK */
uint8_t din; /*!< Divider for the in subcarrier frequency: fc/2^din */
uint8_t dout; /*!< Divider for the in subcarrier frequency fc/2^dout */
uint8_t report_period_length; /*!< Length of the reporting period 2^report_period_length*/
};
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
/* ST25R3916 direct commands */
#define ST25R3916_CMD_SET_DEFAULT 0xC1U /*!< Puts the chip in default state (same as after power-up) */
#define ST25R3916_CMD_STOP 0xC2U /*!< Stops all activities and clears FIFO */
#define ST25R3916_CMD_TRANSMIT_WITH_CRC 0xC4U /*!< Transmit with CRC */
#define ST25R3916_CMD_TRANSMIT_WITHOUT_CRC 0xC5U /*!< Transmit without CRC */
#define ST25R3916_CMD_TRANSMIT_REQA 0xC6U /*!< Transmit REQA */
#define ST25R3916_CMD_TRANSMIT_WUPA 0xC7U /*!< Transmit WUPA */
#define ST25R3916_CMD_INITIAL_RF_COLLISION 0xC8U /*!< NFC transmit with Initial RF Collision Avoidance */
#define ST25R3916_CMD_RESPONSE_RF_COLLISION_N 0xC9U /*!< NFC transmit with Response RF Collision Avoidance */
#define ST25R3916_CMD_GOTO_SENSE 0xCDU /*!< Passive target logic to Sense/Idle state */
#define ST25R3916_CMD_GOTO_SLEEP 0xCEU /*!< Passive target logic to Sleep/Halt state */
#define ST25R3916_CMD_MASK_RECEIVE_DATA 0xD0U /*!< Mask receive data */
#define ST25R3916_CMD_UNMASK_RECEIVE_DATA 0xD1U /*!< Unmask receive data */
#define ST25R3916_CMD_AM_MOD_STATE_CHANGE 0xD2U /*!< AM Modulation state change */
#define ST25R3916_CMD_MEASURE_AMPLITUDE 0xD3U /*!< Measure singal amplitude on RFI inputs */
#define ST25R3916_CMD_RESET_RXGAIN 0xD5U /*!< Reset RX Gain */
#define ST25R3916_CMD_ADJUST_REGULATORS 0xD6U /*!< Adjust regulators */
#define ST25R3916_CMD_CALIBRATE_DRIVER_TIMING 0xD8U /*!< Starts the sequence to adjust the driver timing */
#define ST25R3916_CMD_MEASURE_PHASE 0xD9U /*!< Measure phase between RFO and RFI signal */
#define ST25R3916_CMD_CLEAR_RSSI 0xDAU /*!< Clear RSSI bits and restart the measurement */
#define ST25R3916_CMD_CLEAR_FIFO 0xDBU /*!< Clears FIFO, Collision and IRQ status */
#define ST25R3916_CMD_TRANSPARENT_MODE 0xDCU /*!< Transparent mode */
#define ST25R3916_CMD_CALIBRATE_C_SENSOR 0xDDU /*!< Calibrate the capacitive sensor */
#define ST25R3916_CMD_MEASURE_CAPACITANCE 0xDEU /*!< Measure capacitance */
#define ST25R3916_CMD_MEASURE_VDD 0xDFU /*!< Measure power supply voltage */
#define ST25R3916_CMD_START_GP_TIMER 0xE0U /*!< Start the general purpose timer */
#define ST25R3916_CMD_START_WUP_TIMER 0xE1U /*!< Start the wake-up timer */
#define ST25R3916_CMD_START_MASK_RECEIVE_TIMER 0xE2U /*!< Start the mask-receive timer */
#define ST25R3916_CMD_START_NO_RESPONSE_TIMER 0xE3U /*!< Start the no-response timer */
#define ST25R3916_CMD_START_PPON2_TIMER 0xE4U /*!< Start PPon2 timer */
#define ST25R3916_CMD_STOP_NRT 0xE8U /*!< Stop No Response Timer */
#define ST25R3916_CMD_SPACE_B_ACCESS 0xFBU /*!< Enable R/W access to the test registers */
#define ST25R3916_CMD_TEST_ACCESS 0xFCU /*!< Enable R/W access to the test registers */
#define ST25R3916_THRESHOLD_DO_NOT_SET 0xFFU /*!< Indicates not to change this Threshold */
#define ST25R3916_BR_DO_NOT_SET 0xFFU /*!< Indicates not to change this Bit Rate */
#define ST25R3916_BR_106 0x00U /*!< ST25R3916 Bit Rate 106 kbit/s (fc/128) */
#define ST25R3916_BR_212 0x01U /*!< ST25R3916 Bit Rate 212 kbit/s (fc/64) */
#define ST25R3916_BR_424 0x02U /*!< ST25R3916 Bit Rate 424 kbit/s (fc/32) */
#define ST25R3916_BR_848 0x03U /*!< ST25R3916 Bit Rate 848 kbit/s (fc/16) */
#define ST25R3916_BR_1695 0x04U /*!< ST25R3916 Bit Rate 1696 kbit/s (fc/8) */
#define ST25R3916_BR_3390 0x05U /*!< ST25R3916 Bit Rate 3390 kbit/s (fc/4) */
#define ST25R3916_BR_6780 0x07U /*!< ST25R3916 Bit Rate 6780 kbit/s (fc/2) */
#define ST25R3916_FIFO_DEPTH 512U /*!< Depth of FIFO */
#define ST25R3916_TOUT_OSC_STABLE 10U /*!< Max timeout for Oscillator to get stable DS: 700us */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*! Enables the Transmitter (Field On) and Receiver */
#define st25r3916TxRxOn() st25r3916SetRegisterBits( ST25R3916_REG_OP_CONTROL, (ST25R3916_REG_OP_CONTROL_rx_en | ST25R3916_REG_OP_CONTROL_tx_en ) )
/*! Disables the Transmitter (Field Off) and Receiver */
#define st25r3916TxRxOff() st25r3916ClrRegisterBits( ST25R3916_REG_OP_CONTROL, (ST25R3916_REG_OP_CONTROL_rx_en | ST25R3916_REG_OP_CONTROL_tx_en ) )
/*! Disables the Transmitter (Field Off) */
#define st25r3916TxOff() st25r3916ClrRegisterBits( ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_tx_en )
/*! Checks if General Purpose Timer is still running by reading gpt_on flag */
#define st25r3916IsGPTRunning( ) st25r3916CheckReg( ST25R3916_REG_NFCIP1_BIT_RATE, ST25R3916_REG_NFCIP1_BIT_RATE_gpt_on, ST25R3916_REG_NFCIP1_BIT_RATE_gpt_on )
/*! Checks if External Filed is detected by reading ST25R3916 External Field Detector output */
#define st25r3916IsExtFieldOn() st25r3916CheckReg( ST25R3916_REG_AUX_DISPLAY, ST25R3916_REG_AUX_DISPLAY_efd_o, ST25R3916_REG_AUX_DISPLAY_efd_o )
/*! Checks if Transmitter is enabled (Field On) */
#define st25r3916IsTxEnabled() st25r3916CheckReg( ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_tx_en, ST25R3916_REG_OP_CONTROL_tx_en )
/*! Checks if NRT is in EMV mode */
#define st25r3916IsNRTinEMV() st25r3916CheckReg( ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv, ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv_on )
/*! Checks if last FIFO byte is complete */
#define st25r3916IsLastFIFOComplete() st25r3916CheckReg( ST25R3916_REG_FIFO_STATUS2, ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask, 0 )
/*! Checks if the Oscillator is enabled */
#define st25r3916IsOscOn() st25r3916CheckReg( ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en, ST25R3916_REG_OP_CONTROL_en )
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Initialise ST25R3916 driver
*
* This function initialises the ST25R3916 driver.
*
* \return ERR_NONE : Operation successful
* \return ERR_HW_MISMATCH : Expected HW do not match or communication error
* \return ERR_IO : Error during communication selftest. Check communication interface
* \return ERR_TIMEOUT : Timeout during IRQ selftest. Check IRQ handling
* \return ERR_SYSTEM : Failure during oscillator activation or timer error
*
*****************************************************************************
*/
ReturnCode st25r3916Initialize( void );
/*!
*****************************************************************************
* \brief Deinitialize ST25R3916 driver
*
* Calling this function deinitializes the ST25R3916 driver.
*
*****************************************************************************
*/
void st25r3916Deinitialize( void );
/*!
*****************************************************************************
* \brief Turn on Oscillator and Regulator
*
* This function turn on oscillator and regulator and waits for the
* oscillator to become stable
*
* \return ERR_SYSTEM : Failure dusring Oscillator activation
* \return ERR_NONE : No error, Oscillator is active and stable, Regulator is on
*
*****************************************************************************
*/
ReturnCode st25r3916OscOn( void );
/*!
*****************************************************************************
* \brief Sets the bitrate
*
* This function sets the bitrates for rx and tx
*
* \param txrate : speed is 2^txrate * 106 kb/s
* 0xff : don't set txrate (ST25R3916_BR_DO_NOT_SET)
* \param rxrate : speed is 2^rxrate * 106 kb/s
* 0xff : don't set rxrate (ST25R3916_BR_DO_NOT_SET)
*
* \return ERR_PARAM: At least one bit rate was invalid
* \return ERR_NONE : No error, both bit rates were set
*
*****************************************************************************
*/
ReturnCode st25r3916SetBitrate( uint8_t txrate, uint8_t rxrate );
/*!
*****************************************************************************
* \brief Adjusts supply regulators according to the current supply voltage
*
* This function the power level is measured in maximum load conditions and
* the regulated voltage reference is set to 250mV below this level.
* Execution of this function lasts arround 5ms.
*
* The regulated voltages will be set to the result of Adjust Regulators
*
* \param [out] result_mV : Result of calibration in milliVolts
*
* \return ERR_IO : Error during communication with ST25R3916
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916AdjustRegulators( uint16_t* result_mV );
/*!
*****************************************************************************
* \brief Measure Amplitude
*
* This function measured the amplitude on the RFI inputs and stores the
* result in parameter \a result.
*
* \param[out] result: result of RF measurement.
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916MeasureAmplitude( uint8_t* result );
/*!
*****************************************************************************
* \brief Measure Power Supply
*
* This function executes Measure Power Supply and returns the raw value
*
* \param[in] mpsv : one of ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd
* ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_rf
* ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_a
* ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_d
* ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_am
*
* \return the measured voltage in raw format.
*
*****************************************************************************
*/
uint8_t st25r3916MeasurePowerSupply( uint8_t mpsv );
/*!
*****************************************************************************
* \brief Measure Voltage
*
* This function measures the voltage on one of VDD and VDD_* and returns
* the result in mV
*
* \param[in] mpsv : one of ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd
* ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_rf
* ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_a
* ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_d
* or ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_am
*
* \return the measured voltage in mV
*
*****************************************************************************
*/
uint16_t st25r3916MeasureVoltage( uint8_t mpsv );
/*!
*****************************************************************************
* \brief Measure Phase
*
* This function performs a Phase measurement.
* The result is stored in the \a result parameter.
*
* \param[out] result: 8 bit long result of the measurement.
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916MeasurePhase( uint8_t* result );
/*!
*****************************************************************************
* \brief Measure Capacitance
*
* This function performs the capacitance measurement and stores the
* result in parameter \a result.
*
* \param[out] result: 8 bit long result of RF measurement.
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916MeasureCapacitance( uint8_t* result );
/*!
*****************************************************************************
* \brief Calibrates Capacitive Sensor
*
* This function performs automatic calibration of the capacitive sensor
* and stores the result in parameter \a result.
*
* \warning To avoid interference with Xtal oscillator and reader magnetic
* field, it is strongly recommended to perform calibration
* in Power-down mode only.
* This method does not modify the Oscillator nor transmitter state,
* these should be configured before by user.
*
* \param[out] result: 5 bit long result of the calibration.
* Binary weighted, step 0.1 pF, max 3.1 pF
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_IO : The calibration was not successful
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916CalibrateCapacitiveSensor( uint8_t* result );
/*!
*****************************************************************************
* \brief Get NRT time
*
* This returns the last value set on the NRT
*
* \warning it does not read chip register, just the sw var that contains the
* last value set before
*
* \return the value of the NRT in 64/fc
*/
uint32_t st25r3916GetNoResponseTime( void );
/*!
*****************************************************************************
* \brief Set NRT time
*
* This function sets the No Response Time with the given value
*
* \param [in] nrt_64fcs : no response time in steps of 64/fc (4.72us)
*
* \return ERR_PARAM : Invalid parameter (time is too large)
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916SetNoResponseTime( uint32_t nrt_64fcs );
/*!
*****************************************************************************
* \brief Set and Start NRT
*
* This function sets the No Response Time with the given value and
* immediately starts it
* Used when needs to add more time before timeout without performing Tx
*
* \param [in] nrt_64fcs : no response time in steps of 64/fc (4.72us)
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916SetStartNoResponseTimer( uint32_t nrt_64fcs );
/*!
*****************************************************************************
* \brief Set GPT time
*
* This function sets the General Purpose Timer time registers
*
* \param [in] gpt_8fcs : general purpose timer timeout in steps of 8/fc (590ns)
*
*****************************************************************************
*/
void st25r3916SetGPTime( uint16_t gpt_8fcs );
/*!
*****************************************************************************
* \brief Set and Start GPT
*
* This function sets the General Purpose Timer with the given timeout and
* immediately starts it ONLY if the trigger source is not set to none.
*
* \param [in] gpt_8fcs : general purpose timer timeout in steps of8/fc (590ns)
* \param [in] trigger_source : no trigger, start of Rx, end of Rx, end of Tx in NFC mode
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916SetStartGPTimer( uint16_t gpt_8fcs, uint8_t trigger_source );
/*!
*****************************************************************************
* \brief Sets the number Tx Bits
*
* Sets ST25R3916 internal registers with correct number of complete bytes and
* bits to be sent
*
* \param [in] nBits : number of bits to be set/transmitted
*
*****************************************************************************
*/
void st25r3916SetNumTxBits( uint16_t nBits );
/*!
*****************************************************************************
* \brief Get amount of bytes in FIFO
*
* Gets the number of bytes currently in the FIFO
*
* \return the number of bytes currently in the FIFO
*
*****************************************************************************
*/
uint16_t st25r3916GetNumFIFOBytes( void );
/*!
*****************************************************************************
* \brief Get amount of bits of the last FIFO byte if incomplete
*
* Gets the number of bits of the last FIFO byte if incomplete
*
* \return the number of bits of the last FIFO byte if incomplete, 0 if
* the last byte is complete
*
*****************************************************************************
*/
uint8_t st25r3916GetNumFIFOLastBits( void );
/*!
*****************************************************************************
* \brief Perform Collision Avoidance
*
* Performs Collision Avoidance with the given threshold and with the
* n number of TRFW
*
* \param[in] FieldONCmd : Field ON command to be executed ST25R3916_CMD_INITIAL_RF_COLLISION
* or ST25R3916_CMD_RESPONSE_RF_COLLISION_N
* \param[in] pdThreshold : Peer Detection Threshold (ST25R3916_REG_FIELD_THRESHOLD_trg_xx)
* 0xff : don't set Threshold (ST25R3916_THRESHOLD_DO_NOT_SET)
* \param[in] caThreshold : Collision Avoidance Threshold (ST25R3916_REG_FIELD_THRESHOLD_rfe_xx)
* 0xff : don't set Threshold (ST25R3916_THRESHOLD_DO_NOT_SET)
* \param[in] nTRFW : Number of TRFW
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_RF_COLLISION : Collision detected
* \return ERR_NONE : No collision detected
*
*****************************************************************************
*/
ReturnCode st25r3916PerformCollisionAvoidance( uint8_t FieldONCmd, uint8_t pdThreshold, uint8_t caThreshold, uint8_t nTRFW );
/*!
*****************************************************************************
* \brief Check Identity
*
* Checks if the chip ID is as expected.
*
* 5 bit IC type code for ST25R3916: 00101
* The 3 lsb contain the IC revision code
*
* \param[out] rev : the IC revision code
*
* \return true when IC type is as expected
* \return false otherwise
*/
bool st25r3916CheckChipID( uint8_t *rev );
/*!
*****************************************************************************
* \brief Retrieves all internal registers from ST25R3916
*
* \param[out] regDump : pointer to the struct/buffer where the reg dump
* will be written
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*****************************************************************************
*/
ReturnCode st25r3916GetRegsDump( t_st25r3916Regs* regDump );
/*!
*****************************************************************************
* \brief Check if command is valid
*
* Checks if the given command is a valid ST25R3916 command
*
* \param[in] cmd: Command to check
*
* \return true if is a valid command
* \return false otherwise
*
*****************************************************************************
*/
bool st25r3916IsCmdValid( uint8_t cmd );
/*!
*****************************************************************************
* \brief Configure the stream mode of ST25R3916
*
* This function initializes the stream with the given parameters
*
* \param[in] config : all settings for bitrates, type, etc.
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error, stream mode driver initialized
*
*****************************************************************************
*/
ReturnCode st25r3916StreamConfigure( const struct st25r3916StreamConfig *config );
/*!
*****************************************************************************
* \brief Executes a direct command and returns the result
*
* This function executes the direct command given by \a cmd waits for
* \a sleeptime for I_dct and returns the result read from register \a resreg.
* The value of cmd is not checked.
*
* \param[in] cmd : direct command to execute
* \param[in] resReg: address of the register containing the result
* \param[in] tout : time in milliseconds to wait before reading the result
* \param[out] result: result
*
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916ExecuteCommandAndGetResult( uint8_t cmd, uint8_t resReg, uint8_t tout, uint8_t* result );
/*!
*****************************************************************************
* \brief Gets the RSSI values
*
* This function gets the RSSI value of the previous reception taking into
* account the gain reductions that were used.
* RSSI value for both AM and PM channel can be retrieved.
*
* \param[out] amRssi: the RSSI on the AM channel expressed in mV
* \param[out] pmRssi: the RSSI on the PM channel expressed in mV
*
* \return ERR_PARAM : Invalid parameter
* \return ERR_NONE : No error
*
*****************************************************************************
*/
ReturnCode st25r3916GetRSSI( uint16_t *amRssi, uint16_t *pmRssi );
#endif /* ST25R3916_H */
/**
* @}
*
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,329 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file st25r3916_aat.c
*
* \author
*
* \brief ST25R3916 Antenna Tuning
*
* The antenna tuning algorithm tries to find the optimal settings for
* the AAT_A and AAT_B registers, which are connected to variable capacitors
* to tune the antenna matching.
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "st25r3916_aat.h"
#include "utils.h"
#include "st_errno.h"
#include "st25r3916.h"
#include "st25r3916_com.h"
#include "platform.h"
#include "rfal_chip.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define ST25R3916_AAT_CAP_DELAY_MAX 10 /*!< Max Variable Capacitor settle delay */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define st25r3916AatLog(...) /* platformLog(__VA_ARGS__) */ /*!< Logging macro */
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static ReturnCode aatHillClimb(const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus);
static int32_t aatGreedyDescent(uint32_t *f_min, const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus, int32_t previousDir);
static int32_t aatSteepestDescent(uint32_t *f_min, const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus, int32_t previousDir, int32_t previousDir2);
static ReturnCode aatMeasure(uint8_t serCap, uint8_t parCap, uint8_t *amplitude, uint8_t *phase, uint16_t *measureCnt);
static uint32_t aatCalcF(const struct st25r3916AatTuneParams *tuningParams, uint8_t amplitude, uint8_t phase);
static ReturnCode aatStepDacVals(const struct st25r3916AatTuneParams *tuningParams,uint8_t *a, uint8_t *b, int32_t dir);
/*******************************************************************************/
ReturnCode st25r3916AatTune(const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus)
{
ReturnCode err;
const struct st25r3916AatTuneParams *tp = tuningParams;
struct st25r3916AatTuneResult *ts = tuningStatus;
struct st25r3916AatTuneParams defaultTuningParams =
{
.aat_a_min=0,
.aat_a_max=255,
.aat_a_start=127,
.aat_a_stepWidth=32,
.aat_b_min=0,
.aat_b_max=255,
.aat_b_start=127,
.aat_b_stepWidth=32,
.phaTarget=128,
.phaWeight=2,
.ampTarget=196,
.ampWeight=1,
.doDynamicSteps=true,
.measureLimit=50,
};
struct st25r3916AatTuneResult defaultTuneResult;
if ((NULL != tp) && (
(tp->aat_a_min > tp->aat_a_max )
|| (tp->aat_a_start < tp->aat_a_min )
|| (tp->aat_a_start > tp->aat_a_max )
|| (tp->aat_b_min > tp->aat_b_max )
|| (tp->aat_b_start < tp->aat_b_min )
|| (tp->aat_b_start > tp->aat_b_max )
))
{
return ERR_PARAM;
}
if (NULL == tp)
{ /* Start from current caps with default params */
st25r3916ReadRegister(ST25R3916_REG_ANT_TUNE_A, &defaultTuningParams.aat_a_start);
st25r3916ReadRegister(ST25R3916_REG_ANT_TUNE_B, &defaultTuningParams.aat_b_start);
tp = &defaultTuningParams;
}
if (NULL == ts){ts = &defaultTuneResult;}
ts->measureCnt = 0; /* Clear current measure count */
err = aatHillClimb(tp, ts);
return err;
}
/*******************************************************************************/
static ReturnCode aatHillClimb(const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus)
{
ReturnCode err = ERR_NONE;
uint32_t f_min;
int32_t direction, gdirection;
uint8_t amp,phs;
struct st25r3916AatTuneParams tp = *tuningParams; // local copy to obey const
tuningStatus->aat_a = tuningParams->aat_a_start;
tuningStatus->aat_b = tuningParams->aat_b_start;
/* Get a proper start value */
aatMeasure(tuningStatus->aat_a,tuningStatus->aat_b,&amp,&phs,&tuningStatus->measureCnt);
f_min = aatCalcF(&tp, amp, phs);
direction = 0;
st25r3916AatLog("%d %d: %d***\n",tuningStatus->aat_a,tuningStatus->aat_b,f_min);
do {
direction = 0; /* Initially and after reducing step sizes we don't have a previous direction */
do {
/* With the greedy step below always executed aftwards the -direction does never need to be investigated */
direction = aatSteepestDescent(&f_min, &tp, tuningStatus, direction, -direction);
if (tuningStatus->measureCnt > tp.measureLimit)
{
err = ERR_OVERRUN;
break;
}
do
{
gdirection = aatGreedyDescent(&f_min, &tp, tuningStatus, direction);
if (tuningStatus->measureCnt > tp.measureLimit) {
err = ERR_OVERRUN;
break;
}
} while (0 != gdirection);
} while (0 != direction);
tp.aat_a_stepWidth /= 2U; /* Reduce step sizes */
tp.aat_b_stepWidth /= 2U;
} while (tp.doDynamicSteps && ((tp.aat_a_stepWidth>0U) || (tp.aat_b_stepWidth>0U)));
return err;
}
/*******************************************************************************/
static int32_t aatSteepestDescent(uint32_t *f_min, const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus, int32_t previousDir, int32_t previousDir2)
{
int32_t i;
uint8_t amp,phs;
uint32_t f;
int32_t bestdir = 0; /* Negative direction: decrease, Positive: increase. (-)1: aat_a, (-)2: aat_b */
for (i = -2; i <= 2; i++)
{
uint8_t a = tuningStatus->aat_a , b = tuningStatus->aat_b;
if ((0==i) || (i==-previousDir) || (i==-previousDir2))
{ /* Skip no direction and avoid going backwards */
continue;
}
if (0U!=aatStepDacVals(tuningParams, &a, &b, i))
{ /* If stepping did not change the value, omit this direction */
continue;
}
aatMeasure(a,b,&amp,&phs,&tuningStatus->measureCnt);
f = aatCalcF(tuningParams, amp, phs);
st25r3916AatLog("%d : %d %d: %d",i,a, b, f);
if (f < *f_min)
{ /* Value is better than all previous ones */
st25r3916AatLog("*");
*f_min = f;
bestdir = i;
}
st25r3916AatLog("\n");
}
if (0!=bestdir)
{ /* Walk into the best direction */
aatStepDacVals(tuningParams, &tuningStatus->aat_a, &tuningStatus->aat_b, bestdir);
}
return bestdir;
}
/*******************************************************************************/
static int32_t aatGreedyDescent(uint32_t *f_min, const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus, int32_t previousDir)
{
uint8_t amp,phs;
uint32_t f;
uint8_t a = tuningStatus->aat_a , b = tuningStatus->aat_b;
if (0U != aatStepDacVals(tuningParams, &a, &b, previousDir))
{ /* If stepping did not change the value, omit this direction */
return 0;
}
aatMeasure(a,b,&amp,&phs,&tuningStatus->measureCnt);
f = aatCalcF(tuningParams, amp, phs);
st25r3916AatLog("g : %d %d: %d",a, b, f);
if (f < *f_min)
{ /* Value is better than previous one */
st25r3916AatLog("*\n");
tuningStatus->aat_a = a;
tuningStatus->aat_b = b;
*f_min = f;
return previousDir;
}
st25r3916AatLog("\n");
return 0;
}
/*******************************************************************************/
static uint32_t aatCalcF(const struct st25r3916AatTuneParams *tuningParams, uint8_t amplitude, uint8_t phase)
{
/* f(amp, pha) = (ampWeight * |amp - ampTarget|) + (phaWeight * |pha - phaTarget|) */
uint8_t ampTarget = tuningParams->ampTarget;
uint8_t phaTarget = tuningParams->phaTarget;
uint32_t ampWeight = tuningParams->ampWeight;
uint32_t phaWeight = tuningParams->phaWeight;
/* Temp variables to avoid MISRA R10.8 (cast on composite expression) */
uint8_t ad = ((amplitude > ampTarget) ? (amplitude - ampTarget) : (ampTarget - amplitude));
uint8_t pd = ((phase > phaTarget) ? (phase - phaTarget) : (phaTarget - phase));
uint32_t ampDelta = (uint32_t)ad;
uint32_t phaDelta = (uint32_t)pd;
return ((ampWeight * ampDelta) + (phaWeight * phaDelta));
}
/*******************************************************************************/
static ReturnCode aatStepDacVals(const struct st25r3916AatTuneParams *tuningParams,uint8_t *a, uint8_t *b, int32_t dir)
{
int16_t aat_a = (int16_t)*a, aat_b = (int16_t)*b;
switch (abs(dir))
{ /* Advance by steps size in requested direction */
case 1:
aat_a = (dir<0)?(aat_a - (int16_t)tuningParams->aat_a_stepWidth):(aat_a + (int16_t)tuningParams->aat_a_stepWidth);
if(aat_a < (int16_t)tuningParams->aat_a_min){ aat_a = (int16_t)tuningParams->aat_a_min; }
if(aat_a > (int16_t)tuningParams->aat_a_max){ aat_a = (int16_t)tuningParams->aat_a_max; }
if ((int16_t)*a == aat_a) {return ERR_PARAM;}
break;
case 2:
aat_b = (dir<0)?(aat_b - (int16_t)tuningParams->aat_b_stepWidth):(aat_b + (int16_t)tuningParams->aat_b_stepWidth);
if(aat_b < (int16_t)tuningParams->aat_b_min){ aat_b = (int16_t)tuningParams->aat_b_min; }
if(aat_b > (int16_t)tuningParams->aat_b_max){ aat_b = (int16_t)tuningParams->aat_b_max; }
if ((int16_t)*b == aat_b) {return ERR_PARAM;}
break;
default:
return ERR_REQUEST;
}
/* We only get here if actual values have changed. In all other cases an error is returned */
*a = (uint8_t)aat_a;
*b = (uint8_t)aat_b;
return ERR_NONE;
}
/*******************************************************************************/
static ReturnCode aatMeasure(uint8_t serCap, uint8_t parCap, uint8_t *amplitude, uint8_t *phase, uint16_t *measureCnt)
{
ReturnCode err;
*amplitude = 0;
*phase = 0;
st25r3916WriteRegister(ST25R3916_REG_ANT_TUNE_A, serCap);
st25r3916WriteRegister(ST25R3916_REG_ANT_TUNE_B, parCap);
/* Wait till caps have settled.. */
platformDelay( ST25R3916_AAT_CAP_DELAY_MAX );
/* Get amplitude and phase .. */
err = rfalChipMeasureAmplitude(amplitude);
if (ERR_NONE == err)
{
err = rfalChipMeasurePhase(phase);
}
if( measureCnt != NULL )
{
(*measureCnt)++;
}
return err;
}

View file

@ -0,0 +1,113 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file st25r3916_aat.h
*
* \author
*
* \brief ST25R3916 Antenna Tuning
*
* The antenna tuning algorithm tries to find the optimal settings for
* the AAT_A and AAT_B registers, which are connected to variable capacitors
* to tune the antenna matching.
*
*/
#ifndef ST25R3916_AAT_H
#define ST25R3916_AAT_H
#include "platform.h"
#include "st_errno.h"
/*
******************************************************************************
* GLOBAL DATATYPES
******************************************************************************
*/
/*!
* struct representing input parameters for the antenna tuning
*/
struct st25r3916AatTuneParams{
uint8_t aat_a_min; /*!< min value of A cap */
uint8_t aat_a_max; /*!< max value of A cap */
uint8_t aat_a_start; /*!< start value of A cap */
uint8_t aat_a_stepWidth; /*!< increment stepWidth for A cap */
uint8_t aat_b_min; /*!< min value of B cap */
uint8_t aat_b_max; /*!< max value of B cap */
uint8_t aat_b_start; /*!< start value of B cap */
uint8_t aat_b_stepWidth; /*!< increment stepWidth for B cap */
uint8_t phaTarget; /*!< target phase */
uint8_t phaWeight; /*!< weight of target phase */
uint8_t ampTarget; /*!< target amplitude */
uint8_t ampWeight; /*!< weight of target amplitude */
bool doDynamicSteps; /*!< dynamically reduce step size in algo */
uint8_t measureLimit; /*!< max number of allowed steps/measurements */
};
/*!
* struct representing out parameters for the antenna tuning
*/
struct st25r3916AatTuneResult{
uint8_t aat_a; /*!< serial cap after tuning */
uint8_t aat_b; /*!< parallel cap after tuning */
uint8_t pha; /*!< phase after tuning */
uint8_t amp; /*!< amplitude after tuning */
uint16_t measureCnt; /*!< number of measures performed */
};
/*!
*****************************************************************************
* \brief Perform antenna tuning
*
* This function starts an antenna tuning procedure by modifying the serial
* and parallel capacitors of the antenna matching circuit via the AAT_A
* and AAT_B registers.
*
* \param[in] tuningParams : Input parameters for the tuning algorithm. If NULL
* default values will be used.
* \param[out] tuningStatus : Result information of performed tuning. If NULL
* no further information is returned, only registers
* ST25R3916 (AAT_A,B) will be adapted.
*
* \return ERR_IO : Error during communication.
* \return ERR_PARAM : Invalid input parameters
* \return ERR_NONE : No error.
*
*****************************************************************************
*/
extern ReturnCode st25r3916AatTune(const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus);
#endif /* ST25R3916_AAT_H */

View file

@ -0,0 +1,649 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Gustavo Patricio
*
* \brief Implementation of ST25R3916 communication
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "st25r3916.h"
#include "st25r3916_com.h"
#include "st25r3916_led.h"
#include "st_errno.h"
#include "platform.h"
#include "utils.h"
/*
******************************************************************************
* LOCAL DEFINES
******************************************************************************
*/
#define ST25R3916_OPTIMIZE true /*!< Optimization switch: false always write value to register */
#define ST25R3916_I2C_ADDR (0xA0U >> 1) /*!< ST25R3916's default I2C address */
#define ST25R3916_REG_LEN 1U /*!< Byte length of a ST25R3916 register */
#define ST25R3916_WRITE_MODE (0U << 6) /*!< ST25R3916 Operation Mode: Write */
#define ST25R3916_READ_MODE (1U << 6) /*!< ST25R3916 Operation Mode: Read */
#define ST25R3916_CMD_MODE (3U << 6) /*!< ST25R3916 Operation Mode: Direct Command */
#define ST25R3916_FIFO_LOAD (0x80U) /*!< ST25R3916 Operation Mode: FIFO Load */
#define ST25R3916_FIFO_READ (0x9FU) /*!< ST25R3916 Operation Mode: FIFO Read */
#define ST25R3916_PT_A_CONFIG_LOAD (0xA0U) /*!< ST25R3916 Operation Mode: Passive Target Memory A-Config Load */
#define ST25R3916_PT_F_CONFIG_LOAD (0xA8U) /*!< ST25R3916 Operation Mode: Passive Target Memory F-Config Load */
#define ST25R3916_PT_TSN_DATA_LOAD (0xACU) /*!< ST25R3916 Operation Mode: Passive Target Memory TSN Load */
#define ST25R3916_PT_MEM_READ (0xBFU) /*!< ST25R3916 Operation Mode: Passive Target Memory Read */
#define ST25R3916_CMD_LEN (1U) /*!< ST25R3916 CMD length */
#define ST25R3916_BUF_LEN (ST25R3916_CMD_LEN+ST25R3916_FIFO_DEPTH) /*!< ST25R3916 communication buffer: CMD + FIFO length */
/*
******************************************************************************
* MACROS
******************************************************************************
*/
#ifdef RFAL_USE_I2C
#define st25r3916I2CStart() platformI2CStart() /*!< ST25R3916 HAL I2C driver macro to start a I2C transfer */
#define st25r3916I2CStop() platformI2CStop() /*!< ST25R3916 HAL I2C driver macro to stop a I2C transfer */
#define st25r3916I2CRepeatStart() platformI2CRepeatStart() /*!< ST25R3916 HAL I2C driver macro to repeat Start */
#define st25r3916I2CSlaveAddrWR( sA ) platformI2CSlaveAddrWR( sA ) /*!< ST25R3916 HAL I2C driver macro to repeat Start */
#define st25r3916I2CSlaveAddrRD( sA ) platformI2CSlaveAddrRD( sA ) /*!< ST25R3916 HAL I2C driver macro to repeat Start */
#endif /* RFAL_USE_I2C */
#if defined(ST25R_COM_SINGLETXRX) && !defined(RFAL_USE_I2C)
static uint8_t comBuf[ST25R3916_BUF_LEN]; /*!< ST25R3916 communication buffer */
static uint16_t comBufIt; /*!< ST25R3916 communication buffer iterator */
#endif /* ST25R_COM_SINGLETXRX */
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
******************************************************************************
* \brief ST25R3916 communication Start
*
* This method performs the required actions to start communications with
* ST25R3916, either by SPI or I2C
******************************************************************************
*/
static void st25r3916comStart( void );
/*!
******************************************************************************
* \brief ST25R3916 communication Stop
*
* This method performs the required actions to terminate communications with
* ST25R3916, either by SPI or I2C
******************************************************************************
*/
static void st25r3916comStop( void );
/*!
******************************************************************************
* \brief ST25R3916 communication Repeat Start
*
* This method performs the required actions to repeat start a transmission
* with ST25R3916, either by SPI or I2C
******************************************************************************
*/
#ifdef RFAL_USE_I2C
static void st25r3916comRepeatStart( void );
#else
#define st25r3916comRepeatStart()
#endif /* RFAL_USE_I2C */
/*!
******************************************************************************
* \brief ST25R3916 communication Tx
*
* This method performs the required actions to transmit the given buffer
* to ST25R3916, either by SPI or I2C
*
* \param[in] txBuf : the buffer to transmit
* \param[in] txLen : the length of the buffer to transmit
* \param[in] last : true if last data to be transmitted
* \param[in] txOnly : true no reception is to be performed
*
******************************************************************************
*/
static void st25r3916comTx( const uint8_t* txBuf, uint16_t txLen, bool last, bool txOnly );
/*!
******************************************************************************
* \brief ST25R3916 communication Rx
*
* This method performs the required actions to receive from ST25R3916 the given
* amount of bytes, either by SPI or I2C
*
* \param[out] rxBuf : the buffer place the received bytes
* \param[in] rxLen : the length to receive
*
******************************************************************************
*/
static void st25r3916comRx( uint8_t* rxBuf, uint16_t rxLen );
/*!
******************************************************************************
* \brief ST25R3916 communication Tx Byte
*
* This helper method transmits a byte passed by value and not by reference
*
* \param[in] txByte : the value of the byte to be transmitted
* \param[in] last : true if last byte to be transmitted
* \param[in] txOnly : true no reception is to be performed
*
******************************************************************************
*/
static void st25r3916comTxByte( uint8_t txByte, bool last, bool txOnly );
/*
******************************************************************************
* LOCAL FUNCTION
******************************************************************************
*/
static void st25r3916comStart( void )
{
/* Make this operation atomic, disabling ST25R3916 interrupt during communications*/
platformProtectST25RComm();
#ifdef RFAL_USE_I2C
/* I2C Start and send Slave Address */
st25r3916I2CStart();
st25r3916I2CSlaveAddrWR( ST25R3916_I2C_ADDR );
#else
/* Perform the chip select */
platformSpiSelect();
#if defined(ST25R_COM_SINGLETXRX)
comBufIt = 0; /* reset local buffer position */
#endif /* ST25R_COM_SINGLETXRX */
#endif /* RFAL_USE_I2C */
}
/*******************************************************************************/
static void st25r3916comStop( void )
{
#ifdef RFAL_USE_I2C
/* Generate Stop signal */
st25r3916I2CStop();
#else
/* Release the chip select */
platformSpiDeselect();
#endif /* RFAL_USE_I2C */
/* reEnable the ST25R3916 interrupt */
platformUnprotectST25RComm();
}
/*******************************************************************************/
#ifdef RFAL_USE_I2C
static void st25r3916comRepeatStart( void )
{
st25r3916I2CRepeatStart();
st25r3916I2CSlaveAddrRD( ST25R3916_I2C_ADDR );
}
#endif /* RFAL_USE_I2C */
/*******************************************************************************/
static void st25r3916comTx( const uint8_t* txBuf, uint16_t txLen, bool last, bool txOnly )
{
NO_WARNING(last);
NO_WARNING(txOnly);
if( txLen > 0U )
{
#ifdef RFAL_USE_I2C
platformI2CTx( txBuf, txLen, last, txOnly );
#else /* RFAL_USE_I2C */
#ifdef ST25R_COM_SINGLETXRX
ST_MEMCPY( &comBuf[comBufIt], txBuf, MIN( txLen, (ST25R3916_BUF_LEN - comBufIt) ) ); /* copy tx data to local buffer */
comBufIt += MIN( txLen, (ST25R3916_BUF_LEN - comBufIt) ); /* store position on local buffer */
if( last && txOnly ) /* only perform SPI transaction if no Rx will follow */
{
platformSpiTxRx( comBuf, NULL, comBufIt );
}
#else
platformSpiTxRx( txBuf, NULL, txLen );
#endif /* ST25R_COM_SINGLETXRX */
#endif /* RFAL_USE_I2C */
}
}
/*******************************************************************************/
static void st25r3916comRx( uint8_t* rxBuf, uint16_t rxLen )
{
if( rxLen > 0U )
{
#ifdef RFAL_USE_I2C
platformI2CRx( rxBuf, rxLen );
#else /* RFAL_USE_I2C */
#ifdef ST25R_COM_SINGLETXRX
ST_MEMSET( &comBuf[comBufIt], 0x00, MIN( rxLen, (ST25R3916_BUF_LEN - comBufIt) ) ); /* clear outgoing buffer */
platformSpiTxRx( comBuf, comBuf, MIN( (comBufIt + rxLen), ST25R3916_BUF_LEN ) ); /* transceive as a single SPI call */
ST_MEMCPY( rxBuf, &comBuf[comBufIt], MIN( rxLen, (ST25R3916_BUF_LEN - comBufIt) ) ); /* copy from local buf to output buffer and skip cmd byte */
#else
if( rxBuf != NULL)
{
ST_MEMSET( rxBuf, 0x00, rxLen ); /* clear outgoing buffer */
}
platformSpiTxRx( NULL, rxBuf, rxLen );
#endif /* ST25R_COM_SINGLETXRX */
#endif /* RFAL_USE_I2C */
}
}
/*******************************************************************************/
static void st25r3916comTxByte( uint8_t txByte, bool last, bool txOnly )
{
uint8_t val = txByte; /* MISRA 17.8: use intermediate variable */
st25r3916comTx( &val, ST25R3916_REG_LEN, last, txOnly );
}
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
ReturnCode st25r3916ReadRegister( uint8_t reg, uint8_t* val )
{
return st25r3916ReadMultipleRegisters( reg, val, ST25R3916_REG_LEN );
}
/*******************************************************************************/
ReturnCode st25r3916ReadMultipleRegisters( uint8_t reg, uint8_t* values, uint8_t length )
{
if( length > 0U )
{
st25r3916comStart();
/* If is a space-B register send a direct command first */
if( (reg & ST25R3916_SPACE_B) != 0U )
{
st25r3916comTxByte( ST25R3916_CMD_SPACE_B_ACCESS, false, false );
}
st25r3916comTxByte( ((reg & ~ST25R3916_SPACE_B) | ST25R3916_READ_MODE), true, false );
st25r3916comRepeatStart();
st25r3916comRx( values, length );
st25r3916comStop();
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916WriteRegister( uint8_t reg, uint8_t val )
{
uint8_t value = val; /* MISRA 17.8: use intermediate variable */
return st25r3916WriteMultipleRegisters( reg, &value, ST25R3916_REG_LEN );
}
/*******************************************************************************/
ReturnCode st25r3916WriteMultipleRegisters( uint8_t reg, const uint8_t* values, uint8_t length )
{
if( length > 0U )
{
st25r3916comStart();
if( (reg & ST25R3916_SPACE_B) != 0U )
{
st25r3916comTxByte( ST25R3916_CMD_SPACE_B_ACCESS, false, true );
}
st25r3916comTxByte( ((reg & ~ST25R3916_SPACE_B) | ST25R3916_WRITE_MODE), false, true );
st25r3916comTx( values, length, true, true );
st25r3916comStop();
/* Send a WriteMultiReg event to LED handling */
st25r3916ledEvtWrMultiReg( reg, values, length);
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916WriteFifo( const uint8_t* values, uint16_t length )
{
if( length > ST25R3916_FIFO_DEPTH )
{
return ERR_PARAM;
}
if( length > 0U )
{
st25r3916comStart();
st25r3916comTxByte( ST25R3916_FIFO_LOAD, false, true );
st25r3916comTx( values, length, true, true );
st25r3916comStop();
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916ReadFifo( uint8_t* buf, uint16_t length )
{
if( length > 0U )
{
st25r3916comStart();
st25r3916comTxByte( ST25R3916_FIFO_READ, true, false );
st25r3916comRepeatStart();
st25r3916comRx( buf, length );
st25r3916comStop();
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916WritePTMem( const uint8_t* values, uint16_t length )
{
if( length > ST25R3916_PTM_LEN )
{
return ERR_PARAM;
}
if( length > 0U )
{
st25r3916comStart();
st25r3916comTxByte( ST25R3916_PT_A_CONFIG_LOAD, false, true );
st25r3916comTx( values, length, true, true );
st25r3916comStop();
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916ReadPTMem( uint8_t* values, uint16_t length )
{
uint8_t tmp[ST25R3916_REG_LEN + ST25R3916_PTM_LEN]; /* local buffer to handle prepended byte on I2C and SPI */
if( length > 0U )
{
if( length > ST25R3916_PTM_LEN )
{
return ERR_PARAM;
}
st25r3916comStart();
st25r3916comTxByte( ST25R3916_PT_MEM_READ, true, false );
st25r3916comRepeatStart();
st25r3916comRx( tmp, (ST25R3916_REG_LEN + length) ); /* skip prepended byte */
st25r3916comStop();
/* Copy PTMem content without prepended byte */
ST_MEMCPY( values, (tmp+ST25R3916_REG_LEN), length );
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916WritePTMemF( const uint8_t* values, uint16_t length )
{
if( length > (ST25R3916_PTM_F_LEN + ST25R3916_PTM_TSN_LEN) )
{
return ERR_PARAM;
}
if( length > 0U )
{
st25r3916comStart();
st25r3916comTxByte( ST25R3916_PT_F_CONFIG_LOAD, false, true );
st25r3916comTx( values, length, true, true );
st25r3916comStop();
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916WritePTMemTSN( const uint8_t* values, uint16_t length )
{
if( length > ST25R3916_PTM_TSN_LEN )
{
return ERR_PARAM;
}
if(length > 0U)
{
st25r3916comStart();
st25r3916comTxByte( ST25R3916_PT_TSN_DATA_LOAD, false, true );
st25r3916comTx( values, length, true, true );
st25r3916comStop();
}
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916ExecuteCommand( uint8_t cmd )
{
st25r3916comStart();
st25r3916comTxByte( (cmd | ST25R3916_CMD_MODE ), true, true );
st25r3916comStop();
/* Send a cmd event to LED handling */
st25r3916ledEvtCmd(cmd);
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916ReadTestRegister( uint8_t reg, uint8_t* val )
{
st25r3916comStart();
st25r3916comTxByte( ST25R3916_CMD_TEST_ACCESS, false, false );
st25r3916comTxByte( (reg | ST25R3916_READ_MODE), true, false );
st25r3916comRepeatStart();
st25r3916comRx( val, ST25R3916_REG_LEN );
st25r3916comStop();
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916WriteTestRegister( uint8_t reg, uint8_t val )
{
uint8_t value = val; /* MISRA 17.8: use intermediate variable */
st25r3916comStart();
st25r3916comTxByte( ST25R3916_CMD_TEST_ACCESS, false, true );
st25r3916comTxByte( (reg | ST25R3916_WRITE_MODE), false, true );
st25r3916comTx( &value, ST25R3916_REG_LEN, true, true );
st25r3916comStop();
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3916ClrRegisterBits( uint8_t reg, uint8_t clr_mask )
{
ReturnCode ret;
uint8_t rdVal;
/* Read current reg value */
EXIT_ON_ERR( ret, st25r3916ReadRegister(reg, &rdVal) );
/* Only perform a Write if value to be written is different */
if( ST25R3916_OPTIMIZE && (rdVal == (uint8_t)(rdVal & ~clr_mask)) )
{
return ERR_NONE;
}
/* Write new reg value */
return st25r3916WriteRegister(reg, (uint8_t)(rdVal & ~clr_mask) );
}
/*******************************************************************************/
ReturnCode st25r3916SetRegisterBits( uint8_t reg, uint8_t set_mask )
{
ReturnCode ret;
uint8_t rdVal;
/* Read current reg value */
EXIT_ON_ERR( ret, st25r3916ReadRegister(reg, &rdVal) );
/* Only perform a Write if the value to be written is different */
if( ST25R3916_OPTIMIZE && (rdVal == (rdVal | set_mask)) )
{
return ERR_NONE;
}
/* Write new reg value */
return st25r3916WriteRegister(reg, (rdVal | set_mask) );
}
/*******************************************************************************/
ReturnCode st25r3916ChangeRegisterBits( uint8_t reg, uint8_t valueMask, uint8_t value )
{
return st25r3916ModifyRegister(reg, valueMask, (valueMask & value) );
}
/*******************************************************************************/
ReturnCode st25r3916ModifyRegister( uint8_t reg, uint8_t clr_mask, uint8_t set_mask )
{
ReturnCode ret;
uint8_t rdVal;
uint8_t wrVal;
/* Read current reg value */
EXIT_ON_ERR( ret, st25r3916ReadRegister(reg, &rdVal) );
/* Compute new value */
wrVal = (uint8_t)(rdVal & ~clr_mask);
wrVal |= set_mask;
/* Only perform a Write if the value to be written is different */
if( ST25R3916_OPTIMIZE && (rdVal == wrVal) )
{
return ERR_NONE;
}
/* Write new reg value */
return st25r3916WriteRegister(reg, wrVal );
}
/*******************************************************************************/
ReturnCode st25r3916ChangeTestRegisterBits( uint8_t reg, uint8_t valueMask, uint8_t value )
{
ReturnCode ret;
uint8_t rdVal;
uint8_t wrVal;
/* Read current reg value */
EXIT_ON_ERR( ret, st25r3916ReadTestRegister(reg, &rdVal) );
/* Compute new value */
wrVal = (uint8_t)(rdVal & ~valueMask);
wrVal |= (uint8_t)(value & valueMask);
/* Only perform a Write if the value to be written is different */
if( ST25R3916_OPTIMIZE && (rdVal == wrVal) )
{
return ERR_NONE;
}
/* Write new reg value */
return st25r3916WriteTestRegister(reg, wrVal );
}
/*******************************************************************************/
bool st25r3916CheckReg( uint8_t reg, uint8_t mask, uint8_t val )
{
uint8_t regVal;
regVal = 0;
st25r3916ReadRegister( reg, &regVal );
return ( (regVal & mask) == val );
}
/*******************************************************************************/
bool st25r3916IsRegValid( uint8_t reg )
{
if( !(( (int16_t)reg >= (int16_t)ST25R3916_REG_IO_CONF1) && (reg <= (ST25R3916_SPACE_B | ST25R3916_REG_IC_IDENTITY)) ))
{
return false;
}
return true;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,262 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Gustavo Patricio
*
* \brief ST25R3916 Interrupt handling
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "st25r3916_irq.h"
#include "st25r3916_com.h"
#include "st25r3916_led.h"
#include "st25r3916.h"
#include "utils.h"
/*
******************************************************************************
* LOCAL DATA TYPES
******************************************************************************
*/
/*! Holds current and previous interrupt callback pointer as well as current Interrupt status and mask */
typedef struct
{
void (*prevCallback)(void); /*!< call back function for ST25R3916 interrupt */
void (*callback)(void); /*!< call back function for ST25R3916 interrupt */
uint32_t status; /*!< latest interrupt status */
uint32_t mask; /*!< Interrupt mask. Negative mask = ST25R3916 mask regs */
} st25r3916Interrupt;
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
/*! Length of the interrupt registers */
#define ST25R3916_INT_REGS_LEN ( (ST25R3916_REG_IRQ_TARGET - ST25R3916_REG_IRQ_MAIN) + 1U )
/*
******************************************************************************
* GLOBAL VARIABLES
******************************************************************************
*/
static volatile st25r3916Interrupt st25r3916interrupt; /*!< Instance of ST25R3916 interrupt */
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
void st25r3916InitInterrupts( void )
{
platformIrqST25RPinInitialize();
platformIrqST25RSetCallback( st25r3916Isr );
st25r3916interrupt.callback = NULL;
st25r3916interrupt.prevCallback = NULL;
st25r3916interrupt.status = ST25R3916_IRQ_MASK_NONE;
st25r3916interrupt.mask = ST25R3916_IRQ_MASK_NONE;
}
/*******************************************************************************/
void st25r3916Isr( void )
{
st25r3916CheckForReceivedInterrupts();
// Check if callback is set and run it
if( NULL != st25r3916interrupt.callback )
{
st25r3916interrupt.callback();
}
}
/*******************************************************************************/
void st25r3916CheckForReceivedInterrupts( void )
{
uint8_t iregs[ST25R3916_INT_REGS_LEN];
uint32_t irqStatus;
/* Initialize iregs */
irqStatus = ST25R3916_IRQ_MASK_NONE;
ST_MEMSET( iregs, (int32_t)(ST25R3916_IRQ_MASK_ALL & 0xFFU), ST25R3916_INT_REGS_LEN );
/* In case the IRQ is Edge (not Level) triggered read IRQs until done */
while( platformGpioIsHigh( ST25R_INT_PORT, ST25R_INT_PIN ) )
{
st25r3916ReadMultipleRegisters( ST25R3916_REG_IRQ_MAIN, iregs, ST25R3916_INT_REGS_LEN );
irqStatus |= (uint32_t)iregs[0];
irqStatus |= (uint32_t)iregs[1]<<8;
irqStatus |= (uint32_t)iregs[2]<<16;
irqStatus |= (uint32_t)iregs[3]<<24;
}
/* Forward all interrupts, even masked ones to application */
platformProtectST25RIrqStatus();
st25r3916interrupt.status |= irqStatus;
platformUnprotectST25RIrqStatus();
/* Send an IRQ event to LED handling */
st25r3916ledEvtIrq( st25r3916interrupt.status );
}
/*******************************************************************************/
void st25r3916ModifyInterrupts(uint32_t clr_mask, uint32_t set_mask)
{
uint8_t i;
uint32_t old_mask;
uint32_t new_mask;
old_mask = st25r3916interrupt.mask;
new_mask = ((~old_mask & set_mask) | (old_mask & clr_mask));
st25r3916interrupt.mask &= ~clr_mask;
st25r3916interrupt.mask |= set_mask;
for(i=0; i<ST25R3916_INT_REGS_LEN; i++)
{
if( ((new_mask >> (8U*i)) & 0xFFU) == 0U )
{
continue;
}
st25r3916WriteRegister(ST25R3916_REG_IRQ_MASK_MAIN + i, (uint8_t)((st25r3916interrupt.mask>>(8U*i)) & 0xFFU) );
}
return;
}
/*******************************************************************************/
uint32_t st25r3916WaitForInterruptsTimed( uint32_t mask, uint16_t tmo )
{
uint32_t tmrDelay;
uint32_t status;
tmrDelay = platformTimerCreate( tmo );
/* Run until specific interrupt has happen or the timer has expired */
do
{
status = (st25r3916interrupt.status & mask);
} while( ( !platformTimerIsExpired( tmrDelay ) || (tmo == 0U)) && (status == 0U) );
platformTimerDestroy( tmrDelay );
status = st25r3916interrupt.status & mask;
platformProtectST25RIrqStatus();
st25r3916interrupt.status &= ~status;
platformUnprotectST25RIrqStatus();
return status;
}
/*******************************************************************************/
uint32_t st25r3916GetInterrupt( uint32_t mask )
{
uint32_t irqs;
irqs = (st25r3916interrupt.status & mask);
if(irqs != ST25R3916_IRQ_MASK_NONE)
{
platformProtectST25RIrqStatus();
st25r3916interrupt.status &= ~irqs;
platformUnprotectST25RIrqStatus();
}
return irqs;
}
/*******************************************************************************/
void st25r3916ClearAndEnableInterrupts( uint32_t mask )
{
st25r3916GetInterrupt( mask );
st25r3916EnableInterrupts( mask );
}
/*******************************************************************************/
void st25r3916EnableInterrupts(uint32_t mask)
{
st25r3916ModifyInterrupts(mask, 0);
}
/*******************************************************************************/
void st25r3916DisableInterrupts(uint32_t mask)
{
st25r3916ModifyInterrupts(0, mask);
}
/*******************************************************************************/
void st25r3916ClearInterrupts( void )
{
uint8_t iregs[ST25R3916_INT_REGS_LEN];
st25r3916ReadMultipleRegisters(ST25R3916_REG_IRQ_MAIN, iregs, ST25R3916_INT_REGS_LEN);
platformProtectST25RIrqStatus();
st25r3916interrupt.status = ST25R3916_IRQ_MASK_NONE;
platformUnprotectST25RIrqStatus();
return;
}
/*******************************************************************************/
void st25r3916IRQCallbackSet( void (*cb)(void) )
{
st25r3916interrupt.prevCallback = st25r3916interrupt.callback;
st25r3916interrupt.callback = cb;
}
/*******************************************************************************/
void st25r3916IRQCallbackRestore( void )
{
st25r3916interrupt.callback = st25r3916interrupt.prevCallback;
st25r3916interrupt.prevCallback = NULL;
}

View file

@ -0,0 +1,264 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Gustavo Patricio
*
* \brief ST25R3916 Interrupt handling
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-HAL
* \brief RFAL Hardware Abstraction Layer
* @{
*
* \addtogroup ST25R3916
* \brief RFAL ST25R3916 Driver
* @{
*
* \addtogroup ST25R3916_IRQ
* \brief RFAL ST25R3916 IRQ
* @{
*
*/
#ifndef ST25R3916_IRQ_H
#define ST25R3916_IRQ_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define ST25R3916_IRQ_MASK_ALL (uint32_t)(0xFFFFFFFFUL) /*!< All ST25R3916 interrupt sources */
#define ST25R3916_IRQ_MASK_NONE (uint32_t)(0x00000000UL) /*!< No ST25R3916 interrupt source */
/* Main interrupt register */
#define ST25R3916_IRQ_MASK_OSC (uint32_t)(0x00000080U) /*!< ST25R3916 oscillator stable interrupt */
#define ST25R3916_IRQ_MASK_FWL (uint32_t)(0x00000040U) /*!< ST25R3916 FIFO water level interrupt */
#define ST25R3916_IRQ_MASK_RXS (uint32_t)(0x00000020U) /*!< ST25R3916 start of receive interrupt */
#define ST25R3916_IRQ_MASK_RXE (uint32_t)(0x00000010U) /*!< ST25R3916 end of receive interrupt */
#define ST25R3916_IRQ_MASK_TXE (uint32_t)(0x00000008U) /*!< ST25R3916 end of transmission interrupt */
#define ST25R3916_IRQ_MASK_COL (uint32_t)(0x00000004U) /*!< ST25R3916 bit collision interrupt */
#define ST25R3916_IRQ_MASK_RX_REST (uint32_t)(0x00000002U) /*!< ST25R3916 automatic reception restart interrupt */
#define ST25R3916_IRQ_MASK_RFU (uint32_t)(0x00000001U) /*!< ST25R3916 RFU interrupt */
/* Timer and NFC interrupt register */
#define ST25R3916_IRQ_MASK_DCT (uint32_t)(0x00008000U) /*!< ST25R3916 termination of direct command interrupt. */
#define ST25R3916_IRQ_MASK_NRE (uint32_t)(0x00004000U) /*!< ST25R3916 no-response timer expired interrupt */
#define ST25R3916_IRQ_MASK_GPE (uint32_t)(0x00002000U) /*!< ST25R3916 general purpose timer expired interrupt */
#define ST25R3916_IRQ_MASK_EON (uint32_t)(0x00001000U) /*!< ST25R3916 external field on interrupt */
#define ST25R3916_IRQ_MASK_EOF (uint32_t)(0x00000800U) /*!< ST25R3916 external field off interrupt */
#define ST25R3916_IRQ_MASK_CAC (uint32_t)(0x00000400U) /*!< ST25R3916 collision during RF collision avoidance interrupt */
#define ST25R3916_IRQ_MASK_CAT (uint32_t)(0x00000200U) /*!< ST25R3916 minimum guard time expired interrupt */
#define ST25R3916_IRQ_MASK_NFCT (uint32_t)(0x00000100U) /*!< ST25R3916 initiator bit rate recognised interrupt */
/* Error and wake-up interrupt register */
#define ST25R3916_IRQ_MASK_CRC (uint32_t)(0x00800000U) /*!< ST25R3916 CRC error interrupt */
#define ST25R3916_IRQ_MASK_PAR (uint32_t)(0x00400000U) /*!< ST25R3916 parity error interrupt */
#define ST25R3916_IRQ_MASK_ERR2 (uint32_t)(0x00200000U) /*!< ST25R3916 soft framing error interrupt */
#define ST25R3916_IRQ_MASK_ERR1 (uint32_t)(0x00100000U) /*!< ST25R3916 hard framing error interrupt */
#define ST25R3916_IRQ_MASK_WT (uint32_t)(0x00080000U) /*!< ST25R3916 wake-up interrupt */
#define ST25R3916_IRQ_MASK_WAM (uint32_t)(0x00040000U) /*!< ST25R3916 wake-up due to amplitude interrupt */
#define ST25R3916_IRQ_MASK_WPH (uint32_t)(0x00020000U) /*!< ST25R3916 wake-up due to phase interrupt */
#define ST25R3916_IRQ_MASK_WCAP (uint32_t)(0x00010000U) /*!< ST25R3916 wake-up due to capacitance measurement */
/* Passive Target Interrupt Register */
#define ST25R3916_IRQ_MASK_PPON2 (uint32_t)(0x80000000U) /*!< ST25R3916 PPON2 Field on waiting Timer interrupt */
#define ST25R3916_IRQ_MASK_SL_WL (uint32_t)(0x40000000U) /*!< ST25R3916 Passive target slot number water level interrupt */
#define ST25R3916_IRQ_MASK_APON (uint32_t)(0x20000000U) /*!< ST25R3916 Anticollision done and Field On interrupt */
#define ST25R3916_IRQ_MASK_RXE_PTA (uint32_t)(0x10000000U) /*!< ST25R3916 RXE with an automatic response interrupt */
#define ST25R3916_IRQ_MASK_WU_F (uint32_t)(0x08000000U) /*!< ST25R3916 212/424b/s Passive target interrupt: Active */
#define ST25R3916_IRQ_MASK_RFU2 (uint32_t)(0x04000000U) /*!< ST25R3916 RFU2 interrupt */
#define ST25R3916_IRQ_MASK_WU_A_X (uint32_t)(0x02000000U) /*!< ST25R3916 106kb/s Passive target state interrupt: Active* */
#define ST25R3916_IRQ_MASK_WU_A (uint32_t)(0x01000000U) /*!< ST25R3916 106kb/s Passive target state interrupt: Active */
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Wait until an ST25R3916 interrupt occurs
*
* This function is used to access the ST25R3916 interrupt flags. Use this
* to wait for max. \a tmo milliseconds for the \b first interrupt indicated
* with mask \a mask to occur.
*
* \param[in] mask : mask indicating the interrupts to wait for.
* \param[in] tmo : time in milliseconds until timeout occurs. If set to 0
* the functions waits forever.
*
* \return : 0 if timeout occured otherwise a mask indicating the cleared
* interrupts.
*
*****************************************************************************
*/
uint32_t st25r3916WaitForInterruptsTimed( uint32_t mask, uint16_t tmo );
/*!
*****************************************************************************
* \brief Get status for the given interrupt
*
* This function is used to check whether the interrupt given by \a mask
* has occured. If yes the interrupt gets cleared. This function returns
* only status bits which are inside \a mask.
*
* \param[in] mask : mask indicating the interrupt to check for.
*
* \return the mask of the interrupts occurred
*
*****************************************************************************
*/
uint32_t st25r3916GetInterrupt( uint32_t mask );
/*!
*****************************************************************************
* \brief Init the 3916 interrupt
*
* This function is used to check whether the interrupt given by \a mask
* has occured.
*
*****************************************************************************
*/
void st25r3916InitInterrupts( void );
/*!
*****************************************************************************
* \brief Modifies the Interrupt
*
* This function modifies the interrupt
*
* \param[in] clr_mask : bit mask to be cleared on the interrupt mask
* \param[in] set_mask : bit mask to be set on the interrupt mask
*****************************************************************************
*/
void st25r3916ModifyInterrupts( uint32_t clr_mask, uint32_t set_mask );
/*!
*****************************************************************************
* \brief Checks received interrupts
*
* Checks received interrupts and saves the result into global params
*****************************************************************************
*/
void st25r3916CheckForReceivedInterrupts( void );
/*!
*****************************************************************************
* \brief ISR Service routine
*
* This function modiefies the interupt
*****************************************************************************
*/
void st25r3916Isr( void );
/*!
*****************************************************************************
* \brief Enable a given ST25R3916 Interrupt source
*
* This function enables all interrupts given by \a mask,
* ST25R3916_IRQ_MASK_ALL enables all interrupts.
*
* \param[in] mask: mask indicating the interrupts to be enabled
*
*****************************************************************************
*/
void st25r3916EnableInterrupts( uint32_t mask );
/*!
*****************************************************************************
* \brief Disable one or more a given ST25R3916 Interrupt sources
*
* This function disables all interrupts given by \a mask. 0xff disables all.
*
* \param[in] mask: mask indicating the interrupts to be disabled.
*
*****************************************************************************
*/
void st25r3916DisableInterrupts( uint32_t mask );
/*!
*****************************************************************************
* \brief Clear all ST25R3916 irq flags
*
*****************************************************************************
*/
void st25r3916ClearInterrupts( void );
/*!
*****************************************************************************
* \brief Clears and then enables the given ST25R3916 Interrupt sources
*
* \param[in] mask: mask indicating the interrupts to be cleared and enabled
*****************************************************************************
*/
void st25r3916ClearAndEnableInterrupts( uint32_t mask );
/*!
*****************************************************************************
* \brief Sets IRQ callback for the ST25R3916 interrupt
*
*****************************************************************************
*/
void st25r3916IRQCallbackSet( void (*cb)( void ) );
/*!
*****************************************************************************
* \brief Sets IRQ callback for the ST25R3916 interrupt
*
*****************************************************************************
*/
void st25r3916IRQCallbackRestore( void );
#endif /* ST25R3916_IRQ_H */
/**
* @}
*
* @}
*
* @}
*
* @}
*/

View file

@ -0,0 +1,157 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Gustavo Patricio
*
* \brief ST25R3916 LEDs handling
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "st25r3916_led.h"
#include "st25r3916_irq.h"
#include "st25r3916_com.h"
#include "st25r3916.h"
/*
******************************************************************************
* MACROS
******************************************************************************
*/
#ifdef PLATFORM_LED_RX_PIN
#define st25r3916ledRxOn() platformLedOn( PLATFORM_LED_RX_PORT, PLATFORM_LED_RX_PIN ); /*!< LED Rx Pin On from system HAL */
#define st25r3916ledRxOff() platformLedOff( PLATFORM_LED_RX_PORT, PLATFORM_LED_RX_PIN ); /*!< LED Rx Pin Off from system HAL */
#else /* PLATFORM_LED_RX_PIN */
#define st25r3916ledRxOn()
#define st25r3916ledRxOff()
#endif /* PLATFORM_LED_RX_PIN */
#ifdef PLATFORM_LED_FIELD_PIN
#define st25r3916ledFieldOn() platformLedOn( PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN ); /*!< LED Field Pin On from system HAL */
#define st25r3916ledFieldOff() platformLedOff( PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN ); /*!< LED Field Pin Off from system HAL */
#else /* PLATFORM_LED_FIELD_PIN */
#define st25r3916ledFieldOn()
#define st25r3916ledFieldOff()
#endif /* PLATFORM_LED_FIELD_PIN */
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
void st25r3916ledInit( void )
{
/* Initialize LEDs if existing and defined */
platformLedsInitialize();
st25r3916ledRxOff();
st25r3916ledFieldOff();
}
/*******************************************************************************/
void st25r3916ledEvtIrq( uint32_t irqs )
{
if( (irqs & (ST25R3916_IRQ_MASK_TXE | ST25R3916_IRQ_MASK_CAT) ) != 0U )
{
st25r3916ledFieldOn();
}
if( (irqs & (ST25R3916_IRQ_MASK_RXS | ST25R3916_IRQ_MASK_NFCT) ) != 0U )
{
st25r3916ledRxOn();
}
if( (irqs & (ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_NRE | ST25R3916_IRQ_MASK_RX_REST | ST25R3916_IRQ_MASK_RXE_PTA |
ST25R3916_IRQ_MASK_WU_A | ST25R3916_IRQ_MASK_WU_A_X | ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_RFU2) ) != 0U )
{
st25r3916ledRxOff();
}
}
/*******************************************************************************/
void st25r3916ledEvtWrReg( uint8_t reg, uint8_t val )
{
if( reg == ST25R3916_REG_OP_CONTROL )
{
if( (ST25R3916_REG_OP_CONTROL_tx_en & val) != 0U )
{
st25r3916ledFieldOn();
}
else
{
st25r3916ledFieldOff();
}
}
}
/*******************************************************************************/
void st25r3916ledEvtWrMultiReg( uint8_t reg, const uint8_t* vals, uint8_t len )
{
uint8_t i;
for(i=0; i<(len); i++)
{
st25r3916ledEvtWrReg( (reg+i), vals[i] );
}
}
/*******************************************************************************/
void st25r3916ledEvtCmd( uint8_t cmd )
{
if( (cmd >= ST25R3916_CMD_TRANSMIT_WITH_CRC) && (cmd <= ST25R3916_CMD_RESPONSE_RF_COLLISION_N) )
{
st25r3916ledFieldOff();
}
if( cmd == ST25R3916_CMD_UNMASK_RECEIVE_DATA )
{
st25r3916ledRxOff();
}
if( cmd == ST25R3916_CMD_SET_DEFAULT )
{
st25r3916ledFieldOff();
st25r3916ledRxOff();
}
}

View file

@ -0,0 +1,153 @@
/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2020 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3916 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Gustavo Patricio
*
* \brief ST25R3916 LEDs handling
*
*
* \addtogroup RFAL
* @{
*
* \addtogroup RFAL-HAL
* \brief RFAL Hardware Abstraction Layer
* @{
*
* \addtogroup ST25R3916
* \brief RFAL ST25R3916 Driver
* @{
*
* \addtogroup ST25R3916_LED
* \brief RFAL ST25R3916 LED
* @{
*
*/
#ifndef ST25R3916_LED_H
#define ST25R3916_LED_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief ST25R3916 LED Initialize
*
* This function initializes the LEDs that represent ST25R3916 activity
*
*****************************************************************************
*/
void st25r3916ledInit( void );
/*!
*****************************************************************************
* \brief ST25R3916 LED Event Interrupt
*
* This function should be called upon a ST25R3916 Interrupt, providing
* the interrupt event with ST25R3916 irq flags to update LEDs
*
* \param[in] irqs: ST25R3916 irqs mask
*
*****************************************************************************
*/
void st25r3916ledEvtIrq( uint32_t irqs );
/*!
*****************************************************************************
* \brief ST25R3916 LED Event Write Register
*
* This function should be called on a ST25R3916 Write Register operation
* providing the event with the register and value to update LEDs
*
* \param[in] reg: ST25R3916 register to be written
* \param[in] val: value to be written on the register
*
*****************************************************************************
*/
void st25r3916ledEvtWrReg( uint8_t reg, uint8_t val );
/*!
*****************************************************************************
* \brief ST25R3916 LED Event Write Multiple Register
*
* This function should be called upon a ST25R3916 Write Multiple Registers,
* providing the event with the registers and values to update LEDs
*
* \param[in] reg : ST25R3916 first register written
* \param[in] vals: pointer to the values written
* \param[in] len : number of registers written
*
*****************************************************************************
*/
void st25r3916ledEvtWrMultiReg( uint8_t reg, const uint8_t* vals, uint8_t len );
/*!
*****************************************************************************
* \brief ST25R3916 LED Event Direct Command
*
* This function should be called upon a ST25R3916 direct command, providing
* the event with the command executed
*
* \param[in] cmd: ST25R3916 cmd executed
*
*****************************************************************************
*/
void st25r3916ledEvtCmd( uint8_t cmd );
#endif /* ST25R3916_LED_H */
/**
* @}
*
* @}
*
* @}
*
* @}
*/

165
lib/ST25RFAL002/st_errno.h Normal file
View file

@ -0,0 +1,165 @@
/******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2018 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: STxxxx firmware
* LANGUAGE: ISO C99
*/
/*! \file st_errno.h
*
* \author
*
* \brief Main error codes
*
*/
#ifndef ST_ERRNO_H
#define ST_ERRNO_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include <stdint.h>
/*
******************************************************************************
* GLOBAL DATA TYPES
******************************************************************************
*/
typedef uint16_t ReturnCode; /*!< Standard Return Code type from function. */
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
/*
* Error codes to be used within the application.
* They are represented by an uint8_t
*/
enum {
ERR_NONE = 0, /*!< no error occurred */
ERR_NOMEM = 1, /*!< not enough memory to perform the requested operation */
ERR_BUSY = 2, /*!< device or resource busy */
ERR_IO = 3, /*!< generic IO error */
ERR_TIMEOUT = 4, /*!< error due to timeout */
ERR_REQUEST = 5, /*!< invalid request or requested function can't be executed at the moment */
ERR_NOMSG = 6, /*!< No message of desired type */
ERR_PARAM = 7, /*!< Parameter error */
ERR_SYSTEM = 8, /*!< System error */
ERR_FRAMING = 9, /*!< Framing error */
ERR_OVERRUN = 10, /*!< lost one or more received bytes */
ERR_PROTO = 11, /*!< protocol error */
ERR_INTERNAL = 12, /*!< Internal Error */
ERR_AGAIN = 13, /*!< Call again */
ERR_MEM_CORRUPT = 14, /*!< memory corruption */
ERR_NOT_IMPLEMENTED = 15, /*!< not implemented */
ERR_PC_CORRUPT = 16, /*!< Program Counter has been manipulated or spike/noise trigger illegal operation */
ERR_SEND = 17, /*!< error sending*/
ERR_IGNORE = 18, /*!< indicates error detected but to be ignored */
ERR_SEMANTIC = 19, /*!< indicates error in state machine (unexpected cmd) */
ERR_SYNTAX = 20, /*!< indicates error in state machine (unknown cmd) */
ERR_CRC = 21, /*!< crc error */
ERR_NOTFOUND = 22, /*!< transponder not found */
ERR_NOTUNIQUE = 23, /*!< transponder not unique - more than one transponder in field */
ERR_NOTSUPP = 24, /*!< requested operation not supported */
ERR_WRITE = 25, /*!< write error */
ERR_FIFO = 26, /*!< fifo over or underflow error */
ERR_PAR = 27, /*!< parity error */
ERR_DONE = 28, /*!< transfer has already finished */
ERR_RF_COLLISION = 29, /*!< collision error (Bit Collision or during RF Collision avoidance ) */
ERR_HW_OVERRUN = 30, /*!< lost one or more received bytes */
ERR_RELEASE_REQ = 31, /*!< device requested release */
ERR_SLEEP_REQ = 32, /*!< device requested sleep */
ERR_WRONG_STATE = 33, /*!< incorrent state for requested operation */
ERR_MAX_RERUNS = 34, /*!< blocking procedure reached maximum runs */
ERR_DISABLED = 35, /*!< operation aborted due to disabled configuration */
ERR_HW_MISMATCH = 36, /*!< expected hw do not match */
ERR_LINK_LOSS = 37, /*!< Other device's field didn't behave as expected: turned off by Initiator in Passive mode, or AP2P did not turn on field */
ERR_INVALID_HANDLE = 38, /*!< invalid or not initalized device handle */
ERR_INCOMPLETE_BYTE = 40, /*!< Incomplete byte rcvd */
ERR_INCOMPLETE_BYTE_01 = 41, /*!< Incomplete byte rcvd - 1 bit */
ERR_INCOMPLETE_BYTE_02 = 42, /*!< Incomplete byte rcvd - 2 bit */
ERR_INCOMPLETE_BYTE_03 = 43, /*!< Incomplete byte rcvd - 3 bit */
ERR_INCOMPLETE_BYTE_04 = 44, /*!< Incomplete byte rcvd - 4 bit */
ERR_INCOMPLETE_BYTE_05 = 45, /*!< Incomplete byte rcvd - 5 bit */
ERR_INCOMPLETE_BYTE_06 = 46, /*!< Incomplete byte rcvd - 6 bit */
ERR_INCOMPLETE_BYTE_07 = 47, /*!< Incomplete byte rcvd - 7 bit */
};
/* General Sub-category number */
#define ERR_GENERIC_GRP (0x0000) /*!< Reserved value for generic error no */
#define ERR_WARN_GRP (0x0100) /*!< Errors which are not expected in normal operation */
#define ERR_PROCESS_GRP (0x0200) /*!< Processes management errors */
#define ERR_SIO_GRP (0x0800) /*!< SIO errors due to logging */
#define ERR_RINGBUF_GRP (0x0900) /*!< Ring Buffer errors */
#define ERR_MQ_GRP (0x0A00) /*!< MQ errors */
#define ERR_TIMER_GRP (0x0B00) /*!< Timer errors */
#define ERR_RFAL_GRP (0x0C00) /*!< RFAL errors */
#define ERR_UART_GRP (0x0D00) /*!< UART errors */
#define ERR_SPI_GRP (0x0E00) /*!< SPI errors */
#define ERR_I2C_GRP (0x0F00) /*!< I2c errors */
#define ERR_INSERT_SIO_GRP(x) (ERR_SIO_GRP | x) /*!< Insert the SIO grp */
#define ERR_INSERT_RINGBUF_GRP(x) (ERR_RINGBUF_GRP | x) /*!< Insert the Ring Buffer grp */
#define ERR_INSERT_RFAL_GRP(x) (ERR_RFAL_GRP | x) /*!< Insert the RFAL grp */
#define ERR_INSERT_SPI_GRP(x) (ERR_SPI_GRP | x) /*!< Insert the spi grp */
#define ERR_INSERT_I2C_GRP(x) (ERR_I2C_GRP | x) /*!< Insert the i2c grp */
#define ERR_INSERT_UART_GRP(x) (ERR_UART_GRP | x) /*!< Insert the uart grp */
#define ERR_INSERT_TIMER_GRP(x) (ERR_TIMER_GRP | x) /*!< Insert the timer grp */
#define ERR_INSERT_MQ_GRP(x) (ERR_MQ_GRP | x) /*!< Insert the mq grp */
#define ERR_INSERT_PROCESS_GRP(x) (ERR_PROCESS_GRP | x) /*!< Insert the process grp */
#define ERR_INSERT_WARN_GRP(x) (ERR_WARN_GRP | x) /*!< Insert the i2c grp */
#define ERR_INSERT_GENERIC_GRP(x) (ERR_GENERIC_GRP | x) /*!< Insert the generic grp */
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define ERR_NO_MASK(x) (x & 0x00FF) /*!< Mask the error number */
/*! Common code to exit a function with the error if function f return error */
#define EXIT_ON_ERR(r, f) \
if (ERR_NONE != (r = f)) \
{ \
return r; \
}
#endif /* ST_ERRNO_H */

116
lib/ST25RFAL002/timer.c Normal file
View file

@ -0,0 +1,116 @@
/******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* $Revision: $
* LANGUAGE: ANSI C
*/
/*! \file timer.c
*
* \brief SW Timer implementation
*
* \author Gustavo Patricio
*
* This module makes use of a System Tick in millisconds and provides
* an abstraction for SW timers
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "timer.h"
/*
******************************************************************************
* LOCAL DEFINES
******************************************************************************
*/
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
static uint32_t timerStopwatchTick;
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
/*******************************************************************************/
uint32_t timerCalculateTimer( uint16_t time )
{
return (osKernelGetTickCount() + time);
}
/*******************************************************************************/
bool timerIsExpired( uint32_t timer )
{
uint32_t uDiff;
int32_t sDiff;
uDiff = (timer - osKernelGetTickCount()); /* Calculate the diff between the timers */
sDiff = uDiff; /* Convert the diff to a signed var */
/* Check if the given timer has expired already */
if( sDiff < 0 )
{
return true;
}
return false;
}
/*******************************************************************************/
void timerDelay( uint16_t tOut )
{
uint32_t t;
/* Calculate the timer and wait blocking until is running */
t = timerCalculateTimer( tOut );
while( timerIsRunning(t) );
}
/*******************************************************************************/
void timerStopwatchStart( void )
{
timerStopwatchTick = osKernelGetTickCount();
}
/*******************************************************************************/
uint32_t timerStopwatchMeasure( void )
{
return (uint32_t)(osKernelGetTickCount() - timerStopwatchTick);
}

128
lib/ST25RFAL002/timer.h Normal file
View file

@ -0,0 +1,128 @@
/******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R391x firmware
* $Revision: $
* LANGUAGE: ANSI C
*/
/*! \file timer.h
*
* \brief SW Timer implementation header file
*
* This module makes use of a System Tick in millisconds and provides
* an abstraction for SW timers
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "platform.h"
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define timerIsRunning(t) (!timerIsExpired(t))
/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Calculate Timer
*
* This method calculates when the timer will be expired given the amount
* time in milliseconds /a tOut.
* Once the timer has been calculated it will then be used to check when
* it expires.
*
* \see timersIsExpired
*
* \param[in] time : time/duration in Milliseconds for the timer
*
* \return u32 : The new timer calculated based on the given time
*****************************************************************************
*/
uint32_t timerCalculateTimer( uint16_t time );
/*!
*****************************************************************************
* \brief Checks if a Timer is Expired
*
* This method checks if a timer has already expired.
* Based on the given timer previously calculated it checks if this timer
* has already elapsed
*
* \see timersCalculateTimer
*
* \param[in] timer : the timer to check
*
* \return true : timer has already expired
* \return false : timer is still running
*****************************************************************************
*/
bool timerIsExpired( uint32_t timer );
/*!
*****************************************************************************
* \brief Performs a Delay
*
* This method performs a delay for the given amount of time in Milliseconds
*
* \param[in] time : time/duration in Milliseconds of the delay
*
*****************************************************************************
*/
void timerDelay( uint16_t time );
/*!
*****************************************************************************
* \brief Stopwatch start
*
* This method initiates the stopwatch to later measure the time in ms
*
*****************************************************************************
*/
void timerStopwatchStart( void );
/*!
*****************************************************************************
* \brief Stopwatch Measure
*
* This method returns the elapsed time in ms since the stopwatch was initiated
*
* \return The time in ms since the stopwatch was started
*****************************************************************************
*/
uint32_t timerStopwatchMeasure( void );

102
lib/ST25RFAL002/utils.h Normal file
View file

@ -0,0 +1,102 @@
/******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2018 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: NFCC firmware
* $Revision: $
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Ulrich Herrmann
*
* \brief Common and helpful macros
*
*/
#ifndef UTILS_H
#define UTILS_H
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include <string.h>
#include <stdint.h>
/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
/*!
* this macro evaluates an error variable \a ERR against an error code \a EC.
* in case it is not equal it jumps to the given label \a LABEL.
*/
#define EVAL_ERR_NE_GOTO(EC, ERR, LABEL) \
if (EC != ERR) goto LABEL;
/*!
* this macro evaluates an error variable \a ERR against an error code \a EC.
* in case it is equal it jumps to the given label \a LABEL.
*/
#define EVAL_ERR_EQ_GOTO(EC, ERR, LABEL) \
if (EC == ERR) goto LABEL;
#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(a[0])) /*!< Compute the size of an array */
#define MAX(a, b) (((a) > (b)) ? (a) : (b)) /*!< Return the maximum of the 2 values */
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) /*!< Return the minimum of the 2 values */
#define BITMASK_1 (0x01) /*!< Bit mask for lsb bit */
#define BITMASK_2 (0x03) /*!< Bit mask for two lsb bits */
#define BITMASK_3 (0x07) /*!< Bit mask for three lsb bits */
#define BITMASK_4 (0x0F) /*!< Bit mask for four lsb bits */
#define U16TOU8(a) ((a) & 0x00FF) /*!< Cast 16-bit unsigned to 8-bit unsigned */
#define GETU16(a) (uint16_t)((a[0] << 8) | a[1])/*!< Cast two Big Endian 8-bits byte array to 16-bits unsigned */
#define REVERSE_BYTES(pData, nDataSize) \
unsigned char swap, *lo = pData, *hi = pData + nDataSize - 1; \
while (lo < hi) { swap = *lo; *lo++ = *hi; *hi-- = swap; }
#define ST_MEMMOVE memmove /*!< map memmove to string library code */
#define ST_MEMCPY memcpy /*!< map memcpy to string library code */
#define ST_MEMSET memset /*!< map memset to string library code */
#define ST_BYTECMP memcmp /*!< map bytecmp to string library code */
#define NO_WARNING(v) ((void) (v)) /*!< Macro to suppress compiler warning */
#ifndef NULL
#define NULL (void*)0 /*!< represents a NULL pointer */
#endif /* !NULL */
/*
******************************************************************************
* GLOBAL FUNCTION PROTOTYPES
******************************************************************************
*/
#endif /* UTILS_H */

View file

@ -33,4 +33,14 @@ FATFS_DIR = $(LIB_DIR)/fatfs
C_SOURCES += $(FATFS_DIR)/ff.c
C_SOURCES += $(FATFS_DIR)/ff_gen_drv.c
C_SOURCES += $(FATFS_DIR)/diskio.c
C_SOURCES += $(FATFS_DIR)/option/unicode.c
C_SOURCES += $(FATFS_DIR)/option/unicode.c
ifeq ($(APP_NFC), 1)
ST25RFAL002_DIR = $(LIB_DIR)/ST25RFAL002
CFLAGS += -I$(ST25RFAL002_DIR)
CFLAGS += -I$(ST25RFAL002_DIR)/include
CFLAGS += -I$(ST25RFAL002_DIR)/source/st25r3916
C_SOURCES += $(wildcard $(ST25RFAL002_DIR)/*.c)
C_SOURCES += $(wildcard $(ST25RFAL002_DIR)/source/*.c)
C_SOURCES += $(wildcard $(ST25RFAL002_DIR)/source/st25r3916/*.c)
endif