mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-02 22:18:56 -07:00
Merge branch 'ofw_dev' into nfcrefactoring
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
|
||||
- `FreeRTOS-Kernel` - FreeRTOS kernel source code
|
||||
- `FreeRTOS-glue` - Extra glue to hold together FreeRTOS kernel and flipper firmware
|
||||
- `ST25RFAL002` - ST25R3916 Driver and protocol stack
|
||||
- `app-scened-template` - C++ app library
|
||||
- `callback-connector` - Callback connector library
|
||||
- `cmsis_core` - CMSIS Core package, contain cortex-m core headers
|
||||
|
||||
+2
-2
@@ -5,11 +5,11 @@ env.Append(
|
||||
Dir("app-scened-template"),
|
||||
Dir("digital_signal"),
|
||||
Dir("pulse_reader"),
|
||||
Dir("signal_reader"),
|
||||
Dir("drivers"),
|
||||
Dir("flipper_format"),
|
||||
Dir("infrared"),
|
||||
Dir("nfc"),
|
||||
Dir("ST25RFAL002"),
|
||||
Dir("subghz"),
|
||||
Dir("toolbox"),
|
||||
Dir("u8g2"),
|
||||
@@ -83,7 +83,6 @@ libs = env.BuildModules(
|
||||
"print",
|
||||
"microtar",
|
||||
"toolbox",
|
||||
"ST25RFAL002",
|
||||
"libusb_stm32",
|
||||
"drivers",
|
||||
"fatfs",
|
||||
@@ -97,6 +96,7 @@ libs = env.BuildModules(
|
||||
"nfc",
|
||||
"digital_signal",
|
||||
"pulse_reader",
|
||||
"signal_reader",
|
||||
"appframe",
|
||||
"misc",
|
||||
"lfrfid",
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
Import("env")
|
||||
|
||||
env.Append(
|
||||
CPPPATH=[
|
||||
"#/lib/ST25RFAL002",
|
||||
"#/lib/ST25RFAL002/include",
|
||||
"#/lib/ST25RFAL002/source/st25r3916",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
libenv = env.Clone(FW_LIB_NAME="st25rfal002")
|
||||
libenv.ApplyLibFlags()
|
||||
|
||||
sources = libenv.GlobRecursive("*.c")
|
||||
|
||||
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
|
||||
libenv.Install("${LIB_DIST_DIR}", lib)
|
||||
Return("lib")
|
||||
@@ -1,354 +0,0 @@
|
||||
<!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> </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: "Times New Roman";"> </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 Tuning) 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;">Additional 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 inconsistency 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 suppression 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> </o:p></p>
|
||||
</div>
|
||||
</body></html>
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
Binary file not shown.
@@ -1,435 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 Configuration 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,287 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,74 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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_ */
|
||||
@@ -1,207 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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 method 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 method
|
||||
*
|
||||
* 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,206 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 occurred, data incorrect
|
||||
* \return ERR_CRC : CRC error, data incorrect
|
||||
* \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
@@ -1,425 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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; /*!< Compliance 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 */
|
||||
|
||||
bool activate_after_sak; // Set device to Active mode after SAK response
|
||||
} 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 active
|
||||
*
|
||||
* \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,
|
||||
uint32_t tx_flag);
|
||||
|
||||
ReturnCode rfalNfcDataExchangeCustomStart(
|
||||
uint8_t* txData,
|
||||
uint16_t txDataLen,
|
||||
uint8_t** rxData,
|
||||
uint16_t** rvdLen,
|
||||
uint32_t fwt,
|
||||
uint32_t flags);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,830 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 Divider 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 outputted,
|
||||
* 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_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,497 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 immediately. 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 immediately. 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 immediately. 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,425 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,403 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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/Response code length */
|
||||
#define RFAL_NFCF_CMD_LEN 1U /*!< Command/Response 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 according to T3T 1.0 and JIS X6319-4 and
|
||||
* sends it to PICC. If successfully, 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 according 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 outputted,
|
||||
* 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,923 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,340 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,844 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,178 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,150 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,395 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 occurrence */
|
||||
#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 response 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 Status 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,103 +0,0 @@
|
||||
#include "platform.h"
|
||||
#include <assert.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal_spi.h>
|
||||
|
||||
typedef struct {
|
||||
FuriThread* thread;
|
||||
volatile PlatformIrqCallback callback;
|
||||
bool need_spi_lock;
|
||||
} RfalPlatform;
|
||||
|
||||
static volatile RfalPlatform rfal_platform = {
|
||||
.thread = NULL,
|
||||
.callback = NULL,
|
||||
.need_spi_lock = true,
|
||||
};
|
||||
|
||||
void nfc_isr(void* _ctx) {
|
||||
UNUSED(_ctx);
|
||||
if(rfal_platform.callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) {
|
||||
furi_thread_flags_set(furi_thread_get_id(rfal_platform.thread), 0x1);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t rfal_platform_irq_thread(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
while(1) {
|
||||
uint32_t flags = furi_thread_flags_wait(0x1, FuriFlagWaitAny, FuriWaitForever);
|
||||
if(flags & 0x1) {
|
||||
rfal_platform.callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void platformEnableIrqCallback() {
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullDown, GpioSpeedLow);
|
||||
furi_hal_gpio_enable_int_callback(&gpio_nfc_irq_rfid_pull);
|
||||
}
|
||||
|
||||
void platformDisableIrqCallback() {
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull);
|
||||
}
|
||||
|
||||
void platformSetIrqCallback(PlatformIrqCallback callback) {
|
||||
rfal_platform.callback = callback;
|
||||
|
||||
if(!rfal_platform.thread) {
|
||||
rfal_platform.thread =
|
||||
furi_thread_alloc_ex("RfalIrqDriver", 1024, rfal_platform_irq_thread, NULL);
|
||||
furi_thread_mark_as_service(rfal_platform.thread);
|
||||
furi_thread_set_priority(rfal_platform.thread, FuriThreadPriorityIsr);
|
||||
furi_thread_start(rfal_platform.thread);
|
||||
}
|
||||
|
||||
furi_hal_gpio_add_int_callback(&gpio_nfc_irq_rfid_pull, nfc_isr, NULL);
|
||||
// Disable interrupt callback as the pin is shared between 2 apps
|
||||
// It is enabled in rfalLowPowerModeStop()
|
||||
furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull);
|
||||
}
|
||||
|
||||
bool platformSpiTxRx(const uint8_t* txBuf, uint8_t* rxBuf, uint16_t len) {
|
||||
bool ret = false;
|
||||
if(txBuf && rxBuf) {
|
||||
ret =
|
||||
furi_hal_spi_bus_trx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)txBuf, rxBuf, len, 1000);
|
||||
} else if(txBuf) {
|
||||
ret = furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)txBuf, len, 1000);
|
||||
} else if(rxBuf) {
|
||||
ret = furi_hal_spi_bus_rx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)rxBuf, len, 1000);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Until we completely remove RFAL, NFC works with SPI from rfal_platform_irq_thread and nfc_worker
|
||||
// threads. Some nfc features already stop using RFAL and work with SPI from nfc_worker only.
|
||||
// rfal_platform_spi_acquire() and rfal_platform_spi_release() functions are used to lock SPI for a
|
||||
// long term without locking it for each SPI transaction. This is needed for time critical communications.
|
||||
void rfal_platform_spi_acquire() {
|
||||
platformDisableIrqCallback();
|
||||
rfal_platform.need_spi_lock = false;
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_nfc);
|
||||
}
|
||||
|
||||
void rfal_platform_spi_release() {
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_nfc);
|
||||
rfal_platform.need_spi_lock = true;
|
||||
platformEnableIrqCallback();
|
||||
}
|
||||
|
||||
void platformProtectST25RComm() {
|
||||
if(rfal_platform.need_spi_lock) {
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_nfc);
|
||||
}
|
||||
}
|
||||
|
||||
void platformUnprotectST25RComm() {
|
||||
if(rfal_platform.need_spi_lock) {
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_nfc);
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include "timer.h"
|
||||
#include "math.h"
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_light.h>
|
||||
#include <furi_hal_spi.h>
|
||||
|
||||
typedef void (*PlatformIrqCallback)();
|
||||
void platformSetIrqCallback(PlatformIrqCallback cb);
|
||||
void platformEnableIrqCallback();
|
||||
void platformDisableIrqCallback();
|
||||
|
||||
bool platformSpiTxRx(const uint8_t* txBuf, uint8_t* rxBuf, uint16_t len);
|
||||
void platformProtectST25RComm();
|
||||
void platformUnprotectST25RComm();
|
||||
void rfal_platform_spi_acquire();
|
||||
void rfal_platform_spi_release();
|
||||
|
||||
#define ST25R_SS_PIN NFC_CS_Pin
|
||||
#define ST25R_SS_PORT NFC_CS_GPIO_Port
|
||||
|
||||
#define ST25R_INT_PIN NFC_IRQ_Pin
|
||||
#define ST25R_INT_PORT NFC_IRQ_GPIO_Port
|
||||
|
||||
#define RFAL_ANALOG_CONFIG_CUSTOM \
|
||||
true /*!< Enable/Disable RFAL custom analog configuration */
|
||||
|
||||
#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 platformIrqST25RSetCallback(cb) platformSetIrqCallback(cb)
|
||||
|
||||
#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) \
|
||||
furi_hal_gpio_write_port_pin( \
|
||||
port, pin, true) /*!< Turns the given GPIO High */
|
||||
#define platformGpioClear(port, pin) \
|
||||
furi_hal_gpio_write_port_pin( \
|
||||
port, pin, false) /*!< Turns the given GPIO Low */
|
||||
|
||||
#define platformGpioIsHigh(port, pin) \
|
||||
(furi_hal_gpio_read_port_pin(port, pin) == \
|
||||
true) /*!< 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) furi_delay_ms(t) /*!< Performs a delay for the given time (ms) */
|
||||
|
||||
#define platformGetSysTick() furi_get_tick() /*!< Get System Tick (1 tick = 1 ms) */
|
||||
|
||||
#define platformAssert(exp) assert_param(exp) /*!< Asserts whether the given expression is true*/
|
||||
|
||||
#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 */
|
||||
@@ -1,777 +0,0 @@
|
||||
#include "rfal_analogConfigTbl.h"
|
||||
|
||||
const uint8_t rfalAnalogConfigCustomSettings[] = {
|
||||
/****** Default Analog Configuration for Chip-Specific Reset ******/
|
||||
MODE_ENTRY_16_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,
|
||||
ST25R3916_REG_AUX_MOD_lm_ext /* 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),
|
||||
0x0f /* 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 */
|
||||
)
|
||||
|
||||
};
|
||||
|
||||
const uint16_t rfalAnalogConfigCustomSettingsLength = sizeof(rfalAnalogConfigCustomSettings);
|
||||
@@ -1,476 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 Functions 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 = ¤tConfigTbl[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() */
|
||||
@@ -1,82 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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;
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,514 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,886 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,519 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,585 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,563 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 committing 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 */
|
||||
@@ -1,818 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,233 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,253 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,397 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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) {
|
||||
/* Extended field coding not supported */
|
||||
return ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Check whether requested Lc fits */
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
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 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,109 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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
@@ -1,792 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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);
|
||||
|
||||
/* Disable 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 whether 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, ®);
|
||||
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 & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >>
|
||||
ST25R3916_REG_FIFO_STATUS2_fifo_b_shift);
|
||||
result = ((uint16_t)reg << 8);
|
||||
|
||||
st25r3916ReadRegister(ST25R3916_REG_FIFO_STATUS1, ®);
|
||||
result |= (((uint16_t)reg) & 0x00FFU);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
uint8_t st25r3916GetNumFIFOLastBits(void) {
|
||||
uint8_t reg;
|
||||
|
||||
st25r3916ReadRegister(ST25R3916_REG_FIFO_STATUS2, ®);
|
||||
|
||||
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, ®Dump->RsA[regIt]);
|
||||
}
|
||||
|
||||
regIt = 0;
|
||||
|
||||
/* Read non-consecutive Registers on space B */
|
||||
st25r3916ReadRegister(ST25R3916_REG_EMD_SUP_CONF, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_SUBC_START_TIME, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_P2P_RX_CONF, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_CORR_CONF1, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_CORR_CONF2, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_SQUELCH_TIMER, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_FIELD_ON_GT, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_AUX_MOD, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_TX_DRIVER_TIMING, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_RES_AM_MOD, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_TX_DRIVER_STATUS, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_REGULATOR_RESULT, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_OVERSHOOT_CONF1, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_OVERSHOOT_CONF2, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_UNDERSHOOT_CONF1, ®Dump->RsB[regIt++]);
|
||||
st25r3916ReadRegister(ST25R3916_REG_UNDERSHOOT_CONF2, ®Dump->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;
|
||||
}
|
||||
@@ -1,669 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 signal 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 around 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,366 +0,0 @@
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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, &, &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, &, &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, &, &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;
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,618 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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, ®Val);
|
||||
|
||||
return ((regVal & mask) == val);
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
bool st25r3916IsRegValid(uint8_t reg) {
|
||||
#pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
if(!(((int16_t)reg >= (int32_t)ST25R3916_REG_IO_CONF1) &&
|
||||
(reg <= (ST25R3916_SPACE_B | ST25R3916_REG_IC_IDENTITY)))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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;
|
||||
}
|
||||
@@ -1,296 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 occurred 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 occurred. 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 occurred.
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
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 interrupt
|
||||
*****************************************************************************
|
||||
*/
|
||||
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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,148 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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();
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@@ -1,158 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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 */
|
||||
@@ -1,105 +0,0 @@
|
||||
/******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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"
|
||||
#include <furi.h>
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* LOCAL DEFINES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* LOCAL VARIABLES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static uint32_t timerStopwatchTick;
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* GLOBAL FUNCTIONS
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*******************************************************************************/
|
||||
uint32_t timerCalculateTimer(uint16_t time) {
|
||||
return (furi_get_tick() + time);
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
bool timerIsExpired(uint32_t timer) {
|
||||
uint32_t uDiff;
|
||||
int32_t sDiff;
|
||||
|
||||
uDiff = (timer - furi_get_tick()); /* 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 = furi_get_tick();
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
uint32_t timerStopwatchMeasure(void) {
|
||||
return (uint32_t)(furi_get_tick() - timerStopwatchTick);
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
#pragma once
|
||||
/******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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 <stdint.h>
|
||||
#include <stdbool.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);
|
||||
@@ -1,100 +0,0 @@
|
||||
|
||||
/******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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 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 */
|
||||
@@ -6,6 +6,7 @@ env.Append(
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("digital_signal.h"),
|
||||
File("digital_sequence.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
#include "digital_sequence.h"
|
||||
#include "digital_signal_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
|
||||
/**
|
||||
* To enable debug output on an additional pin, set DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN to the required
|
||||
* GpioPin variable. It can be passed at compile time via the --extra-define fbt switch.
|
||||
* NOTE: This pin must be on the same GPIO port as the main pin.
|
||||
*
|
||||
* Example:
|
||||
* ./fbt --extra-define=DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN=gpio_ext_pb3
|
||||
*/
|
||||
|
||||
#define TAG "DigitalSequence"
|
||||
|
||||
/* Special value used to indicate the end of DMA ring buffer. */
|
||||
#define DIGITAL_SEQUENCE_TIMER_MAX 0xFFFFFFFFUL
|
||||
|
||||
/* Time to wait in loops before returning */
|
||||
#define DIGITAL_SEQUENCE_LOCK_WAIT_MS 10UL
|
||||
#define DIGITAL_SEQUENCE_LOCK_WAIT_TICKS (DIGITAL_SEQUENCE_LOCK_WAIT_MS * 1000 * 64)
|
||||
|
||||
#define DIGITAL_SEQUENCE_GPIO_BUFFER_SIZE 2
|
||||
|
||||
/* Maximum capacity of the DMA ring buffer. */
|
||||
#define DIGITAL_SEQUENCE_RING_BUFFER_SIZE 128
|
||||
|
||||
#define DIGITAL_SEQUENCE_RING_BUFFER_MIN_FREE_SIZE 2
|
||||
|
||||
/* Maximum amount of registered signals. */
|
||||
#define DIGITAL_SEQUENCE_BANK_SIZE 32
|
||||
|
||||
typedef enum {
|
||||
DigitalSequenceStateIdle,
|
||||
DigitalSequenceStateActive,
|
||||
} DigitalSequenceState;
|
||||
|
||||
typedef struct {
|
||||
uint32_t data[DIGITAL_SEQUENCE_RING_BUFFER_SIZE];
|
||||
uint32_t write_pos;
|
||||
uint32_t read_pos;
|
||||
} DigitalSequenceRingBuffer;
|
||||
|
||||
typedef uint32_t DigitalSequenceGpioBuffer[DIGITAL_SEQUENCE_GPIO_BUFFER_SIZE];
|
||||
|
||||
typedef const DigitalSignal* DigitalSequenceSignalBank[DIGITAL_SEQUENCE_BANK_SIZE];
|
||||
|
||||
struct DigitalSequence {
|
||||
const GpioPin* gpio;
|
||||
|
||||
uint32_t size;
|
||||
uint32_t max_size;
|
||||
uint8_t* data;
|
||||
|
||||
LL_DMA_InitTypeDef dma_config_gpio;
|
||||
LL_DMA_InitTypeDef dma_config_timer;
|
||||
|
||||
DigitalSequenceGpioBuffer gpio_buf;
|
||||
DigitalSequenceRingBuffer timer_buf;
|
||||
DigitalSequenceSignalBank signals;
|
||||
DigitalSequenceState state;
|
||||
};
|
||||
|
||||
DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) {
|
||||
furi_assert(size);
|
||||
furi_assert(gpio);
|
||||
|
||||
DigitalSequence* sequence = malloc(sizeof(DigitalSequence));
|
||||
|
||||
sequence->gpio = gpio;
|
||||
sequence->max_size = size;
|
||||
|
||||
sequence->data = malloc(sequence->max_size);
|
||||
|
||||
sequence->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t)&gpio->port->BSRR;
|
||||
sequence->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)sequence->gpio_buf;
|
||||
sequence->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
sequence->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
sequence->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
sequence->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
sequence->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||
sequence->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
sequence->dma_config_gpio.NbData = DIGITAL_SEQUENCE_GPIO_BUFFER_SIZE;
|
||||
sequence->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
sequence->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||
|
||||
sequence->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t)&TIM2->ARR;
|
||||
sequence->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)sequence->timer_buf.data;
|
||||
sequence->dma_config_timer.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
sequence->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
sequence->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
sequence->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
sequence->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||
sequence->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
sequence->dma_config_timer.NbData = DIGITAL_SEQUENCE_RING_BUFFER_SIZE;
|
||||
sequence->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
sequence->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH;
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
void digital_sequence_free(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
|
||||
free(sequence->data);
|
||||
free(sequence);
|
||||
}
|
||||
|
||||
void digital_sequence_register_signal(
|
||||
DigitalSequence* sequence,
|
||||
uint8_t signal_index,
|
||||
const DigitalSignal* signal) {
|
||||
furi_assert(sequence);
|
||||
furi_assert(signal);
|
||||
furi_assert(signal_index < DIGITAL_SEQUENCE_BANK_SIZE);
|
||||
|
||||
sequence->signals[signal_index] = signal;
|
||||
}
|
||||
|
||||
void digital_sequence_add_signal(DigitalSequence* sequence, uint8_t signal_index) {
|
||||
furi_assert(sequence);
|
||||
furi_assert(signal_index < DIGITAL_SEQUENCE_BANK_SIZE);
|
||||
furi_assert(sequence->size < sequence->max_size);
|
||||
|
||||
sequence->data[sequence->size++] = signal_index;
|
||||
}
|
||||
|
||||
static inline void digital_sequence_start_dma(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &sequence->dma_config_gpio);
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &sequence->dma_config_timer);
|
||||
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
}
|
||||
|
||||
static inline void digital_sequence_stop_dma() {
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
LL_DMA_ClearFlag_TC2(DMA1);
|
||||
}
|
||||
|
||||
static inline void digital_sequence_start_timer() {
|
||||
furi_hal_bus_enable(FuriHalBusTIM2);
|
||||
|
||||
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);
|
||||
LL_TIM_SetPrescaler(TIM2, 0);
|
||||
LL_TIM_SetAutoReload(TIM2, DIGITAL_SEQUENCE_TIMER_MAX);
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
|
||||
LL_TIM_EnableCounter(TIM2);
|
||||
LL_TIM_EnableUpdateEvent(TIM2);
|
||||
LL_TIM_EnableDMAReq_UPDATE(TIM2);
|
||||
LL_TIM_GenerateEvent_UPDATE(TIM2);
|
||||
}
|
||||
|
||||
static void digital_sequence_stop_timer() {
|
||||
LL_TIM_DisableCounter(TIM2);
|
||||
LL_TIM_DisableUpdateEvent(TIM2);
|
||||
LL_TIM_DisableDMAReq_UPDATE(TIM2);
|
||||
|
||||
furi_hal_bus_disable(FuriHalBusTIM2);
|
||||
}
|
||||
|
||||
static inline void digital_sequence_init_gpio_buffer(
|
||||
DigitalSequence* sequence,
|
||||
const DigitalSignal* first_signal) {
|
||||
const uint32_t bit_set = sequence->gpio->pin << GPIO_BSRR_BS0_Pos
|
||||
#ifdef DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN
|
||||
| DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN.pin << GPIO_BSRR_BS0_Pos
|
||||
#endif
|
||||
;
|
||||
|
||||
const uint32_t bit_reset = sequence->gpio->pin << GPIO_BSRR_BR0_Pos
|
||||
#ifdef DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN
|
||||
| DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN.pin << GPIO_BSRR_BR0_Pos
|
||||
#endif
|
||||
;
|
||||
|
||||
if(first_signal->start_level) {
|
||||
sequence->gpio_buf[0] = bit_set;
|
||||
sequence->gpio_buf[1] = bit_reset;
|
||||
} else {
|
||||
sequence->gpio_buf[0] = bit_reset;
|
||||
sequence->gpio_buf[1] = bit_set;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void digital_sequence_finish(DigitalSequence* sequence) {
|
||||
if(sequence->state == DigitalSequenceStateActive) {
|
||||
const uint32_t prev_timer = DWT->CYCCNT;
|
||||
|
||||
do {
|
||||
/* Special value has been loaded into the timer, signaling the end of transmission. */
|
||||
if(TIM2->ARR == DIGITAL_SEQUENCE_TIMER_MAX) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(DWT->CYCCNT - prev_timer > DIGITAL_SEQUENCE_LOCK_WAIT_TICKS) {
|
||||
DigitalSequenceRingBuffer* dma_buffer = &sequence->timer_buf;
|
||||
dma_buffer->read_pos = DIGITAL_SEQUENCE_RING_BUFFER_SIZE -
|
||||
LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"[SEQ] hung %lu ms in finish (ARR 0x%08lx, read %lu, write %lu)",
|
||||
DIGITAL_SEQUENCE_LOCK_WAIT_MS,
|
||||
TIM2->ARR,
|
||||
dma_buffer->read_pos,
|
||||
dma_buffer->write_pos);
|
||||
break;
|
||||
}
|
||||
} while(true);
|
||||
}
|
||||
|
||||
digital_sequence_stop_timer();
|
||||
digital_sequence_stop_dma();
|
||||
}
|
||||
|
||||
static inline void digital_sequence_enqueue_period(DigitalSequence* sequence, uint32_t length) {
|
||||
DigitalSequenceRingBuffer* dma_buffer = &sequence->timer_buf;
|
||||
|
||||
if(sequence->state == DigitalSequenceStateActive) {
|
||||
const uint32_t prev_timer = DWT->CYCCNT;
|
||||
|
||||
do {
|
||||
dma_buffer->read_pos =
|
||||
DIGITAL_SEQUENCE_RING_BUFFER_SIZE - LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2);
|
||||
|
||||
const uint32_t size_free = (DIGITAL_SEQUENCE_RING_BUFFER_SIZE + dma_buffer->read_pos -
|
||||
dma_buffer->write_pos) %
|
||||
DIGITAL_SEQUENCE_RING_BUFFER_SIZE;
|
||||
|
||||
if(size_free > DIGITAL_SEQUENCE_RING_BUFFER_MIN_FREE_SIZE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(DWT->CYCCNT - prev_timer > DIGITAL_SEQUENCE_LOCK_WAIT_TICKS) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"[SEQ] hung %lu ms in queue (ARR 0x%08lx, read %lu, write %lu)",
|
||||
DIGITAL_SEQUENCE_LOCK_WAIT_MS,
|
||||
TIM2->ARR,
|
||||
dma_buffer->read_pos,
|
||||
dma_buffer->write_pos);
|
||||
break;
|
||||
}
|
||||
|
||||
if(TIM2->ARR == DIGITAL_SEQUENCE_TIMER_MAX) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"[SEQ] buffer underrun in queue (ARR 0x%08lx, read %lu, write %lu)",
|
||||
TIM2->ARR,
|
||||
dma_buffer->read_pos,
|
||||
dma_buffer->write_pos);
|
||||
break;
|
||||
}
|
||||
} while(true);
|
||||
}
|
||||
|
||||
dma_buffer->data[dma_buffer->write_pos] = length;
|
||||
|
||||
dma_buffer->write_pos += 1;
|
||||
dma_buffer->write_pos %= DIGITAL_SEQUENCE_RING_BUFFER_SIZE;
|
||||
|
||||
dma_buffer->data[dma_buffer->write_pos] = DIGITAL_SEQUENCE_TIMER_MAX;
|
||||
}
|
||||
|
||||
static inline void digital_sequence_timer_buffer_reset(DigitalSequence* sequence) {
|
||||
sequence->timer_buf.data[0] = DIGITAL_SEQUENCE_TIMER_MAX;
|
||||
sequence->timer_buf.read_pos = 0;
|
||||
sequence->timer_buf.write_pos = 0;
|
||||
}
|
||||
|
||||
void digital_sequence_transmit(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
furi_assert(sequence->size);
|
||||
furi_assert(sequence->state == DigitalSequenceStateIdle);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
|
||||
furi_hal_gpio_init(sequence->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#ifdef DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN
|
||||
furi_hal_gpio_init(
|
||||
&DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#endif
|
||||
|
||||
const DigitalSignal* signal_current = sequence->signals[sequence->data[0]];
|
||||
|
||||
digital_sequence_init_gpio_buffer(sequence, signal_current);
|
||||
|
||||
int32_t remainder_ticks = 0;
|
||||
uint32_t reload_value_carry = 0;
|
||||
uint32_t next_signal_index = 1;
|
||||
|
||||
for(;;) {
|
||||
const DigitalSignal* signal_next =
|
||||
(next_signal_index < sequence->size) ?
|
||||
sequence->signals[sequence->data[next_signal_index++]] :
|
||||
NULL;
|
||||
|
||||
for(uint32_t i = 0; i < signal_current->size; i++) {
|
||||
const bool is_last_value = (i == signal_current->size - 1);
|
||||
const uint32_t reload_value = signal_current->data[i] + reload_value_carry;
|
||||
|
||||
reload_value_carry = 0;
|
||||
|
||||
if(is_last_value) {
|
||||
if(signal_next != NULL) {
|
||||
/* Special case: signal boundary. Depending on whether the adjacent levels are equal or not,
|
||||
* they will be combined to a single one or handled separately. */
|
||||
const bool end_level = signal_current->start_level ^
|
||||
((signal_current->size % 2) == 0);
|
||||
|
||||
/* If the adjacent levels are equal, carry the current period duration over to the next signal. */
|
||||
if(end_level == signal_next->start_level) {
|
||||
reload_value_carry = reload_value;
|
||||
}
|
||||
} else {
|
||||
/** Special case: during the last period of the last signal, hold the output level indefinitely.
|
||||
* @see digital_signal.h
|
||||
*
|
||||
* Setting reload_value_carry to a non-zero value will prevent the respective period from being
|
||||
* added to the DMA ring buffer. */
|
||||
reload_value_carry = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* A non-zero reload_value_carry means that the level was the same on the both sides of the signal boundary
|
||||
* and the two respective periods were combined to one. */
|
||||
if(reload_value_carry == 0) {
|
||||
digital_sequence_enqueue_period(sequence, reload_value);
|
||||
}
|
||||
|
||||
if(sequence->state == DigitalSequenceStateIdle) {
|
||||
const bool is_buffer_filled = sequence->timer_buf.write_pos >=
|
||||
(DIGITAL_SEQUENCE_RING_BUFFER_SIZE -
|
||||
DIGITAL_SEQUENCE_RING_BUFFER_MIN_FREE_SIZE);
|
||||
const bool is_end_of_data = (signal_next == NULL) && is_last_value;
|
||||
|
||||
if(is_buffer_filled || is_end_of_data) {
|
||||
digital_sequence_start_dma(sequence);
|
||||
digital_sequence_start_timer();
|
||||
sequence->state = DigitalSequenceStateActive;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Exit the loop here when no further signals are available */
|
||||
if(signal_next == NULL) break;
|
||||
|
||||
/* Prevent the rounding error from accumulating by distributing it across multiple periods. */
|
||||
remainder_ticks += signal_current->remainder;
|
||||
if(remainder_ticks >= DIGITAL_SIGNAL_T_TIM_DIV2) {
|
||||
remainder_ticks -= DIGITAL_SIGNAL_T_TIM;
|
||||
reload_value_carry += 1;
|
||||
}
|
||||
|
||||
signal_current = signal_next;
|
||||
};
|
||||
|
||||
digital_sequence_finish(sequence);
|
||||
digital_sequence_timer_buffer_reset(sequence);
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
sequence->state = DigitalSequenceStateIdle;
|
||||
}
|
||||
|
||||
void digital_sequence_clear(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
|
||||
sequence->size = 0;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @file digital_sequence.h
|
||||
* @brief Fast and precise digital signal generation library.
|
||||
*
|
||||
* Each sequence is represented by one or more (up to 32) registered signals, which are addressed
|
||||
* by their indices, and a list of signal indices to be transmitted.
|
||||
*
|
||||
* The registered signals must be set up prior to actually defining the sequence.
|
||||
*
|
||||
* Example: A sequence containing 4 registered signals and n indices to transmit.
|
||||
*
|
||||
* |Signal | Index |
|
||||
* |:-----:|:-----:|
|
||||
* | SOF | 0 |
|
||||
* | EOF | 1 |
|
||||
* | Zero | 2 |
|
||||
* | One | 3 |
|
||||
*
|
||||
* ```
|
||||
* Signal index | 0 | 3 | 2 | 2 | ... | 3 | 1 |
|
||||
* 0 1 2 3 ... n - 2 n - 1
|
||||
* ```
|
||||
*
|
||||
* The above sequence starts by transmitting the signal with index 0, which is SOF in this case,
|
||||
* then it proceeds with indices 3, 2, 2, which are One, Zero, Zero and after n - 2 signals,
|
||||
* it will conclude with indices 3 and 1 which are One and EOF respectively.
|
||||
*
|
||||
* This way, only the order in which the signals are sent is stored, while the signals themselves
|
||||
* are not duplicated.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_gpio.h>
|
||||
|
||||
#include <digital_signal/digital_signal.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct DigitalSequence DigitalSequence;
|
||||
|
||||
/**
|
||||
* @brief Allocate a DigitalSequence instance of a given size which will operate on a set GPIO pin.
|
||||
*
|
||||
* @param[in] size maximum number of signal indices contained in the instance.
|
||||
* @param[in] gpio the GPIO pin used to generate the signal.
|
||||
* @returns pointer to the allocated DigitalSequence instance.
|
||||
*/
|
||||
DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio);
|
||||
|
||||
/**
|
||||
* @brief Delete a previously allocated DigitalSequence instance.
|
||||
*
|
||||
* @param[in,out] sequence pointer to the instance to be deleted.
|
||||
*/
|
||||
void digital_sequence_free(DigitalSequence* sequence);
|
||||
|
||||
/**
|
||||
* @brief Register a signal within a DigitalSequence instance by its index.
|
||||
*
|
||||
* This function must be called for each signal to be used in the sequence. The DigitalSequence
|
||||
* instance does not own the signals, therefore, their lifetime must be no less than the instance's.
|
||||
*
|
||||
* The user is responsible for creation and deletion of DigitalSignal instances and
|
||||
* also for keeping track of their respective indices.
|
||||
*
|
||||
* @param[in,out] sequence pointer to the instance to be modified.
|
||||
* @param[in] signal_index index to register the signal under (must be less than 32).
|
||||
* @param[in] signal pointer to the DigitalSignal instance to be registered.
|
||||
*/
|
||||
void digital_sequence_register_signal(
|
||||
DigitalSequence* sequence,
|
||||
uint8_t signal_index,
|
||||
const DigitalSignal* signal);
|
||||
|
||||
/**
|
||||
* @brief Append a signal index to a DigitalSequence instance.
|
||||
*
|
||||
* The signal under the index must be registered beforehand by calling digital_sequence_set_signal().
|
||||
*
|
||||
* @param[in,out] sequence pointer to the instance to be modified.
|
||||
* @param[in] signal_index signal index to be appended to the sequence (must be less than 32).
|
||||
*/
|
||||
void digital_sequence_add_signal(DigitalSequence* sequence, uint8_t signal_index);
|
||||
|
||||
/**
|
||||
* @brief Transmit the sequence contained in the DigitalSequence instance.
|
||||
*
|
||||
* Must contain at least one registered signal and one signal index.
|
||||
*
|
||||
* NOTE: The current implementation will properly initialise the GPIO provided during construction,
|
||||
* but it is the caller's responsibility to reconfigure it back before reusing for other purposes.
|
||||
* This is due to performance reasons.
|
||||
*
|
||||
* @param[in] sequence pointer to the sequence to be transmitted.
|
||||
*/
|
||||
void digital_sequence_transmit(DigitalSequence* sequence);
|
||||
|
||||
/**
|
||||
* @brief Clear the signal sequence in a DigitalSequence instance.
|
||||
*
|
||||
* Calling this function does not un-register the registered signals, so it is
|
||||
* safe to call digital_sequence_add_signal() right afterwards.
|
||||
*
|
||||
* @param[in,out] sequence pointer to the instance to be cleared.
|
||||
*/
|
||||
void digital_sequence_clear(DigitalSequence* sequence);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,106 +1,15 @@
|
||||
#include "digital_signal.h"
|
||||
#include "digital_signal_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
|
||||
/* must be on bank B */
|
||||
// For debugging purposes use `--extra-define=DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN=gpio_ext_pb3` fbt option
|
||||
|
||||
struct ReloadBuffer {
|
||||
uint32_t* buffer; /* DMA ringbuffer */
|
||||
uint32_t size; /* maximum entry count of the ring buffer */
|
||||
uint32_t write_pos; /* current buffer write index */
|
||||
uint32_t read_pos; /* current buffer read index */
|
||||
bool dma_active;
|
||||
};
|
||||
|
||||
struct DigitalSequence {
|
||||
uint8_t signals_size;
|
||||
bool bake;
|
||||
uint32_t sequence_used;
|
||||
uint32_t sequence_size;
|
||||
DigitalSignal** signals;
|
||||
uint8_t* sequence;
|
||||
const GpioPin* gpio;
|
||||
uint32_t send_time;
|
||||
bool send_time_active;
|
||||
LL_DMA_InitTypeDef dma_config_gpio;
|
||||
LL_DMA_InitTypeDef dma_config_timer;
|
||||
uint32_t* gpio_buff;
|
||||
struct ReloadBuffer* dma_buffer;
|
||||
};
|
||||
|
||||
struct DigitalSignalInternals {
|
||||
uint64_t factor;
|
||||
uint32_t reload_reg_entries;
|
||||
uint32_t reload_reg_remainder;
|
||||
uint32_t gpio_buff[2];
|
||||
const GpioPin* gpio;
|
||||
LL_DMA_InitTypeDef dma_config_gpio;
|
||||
LL_DMA_InitTypeDef dma_config_timer;
|
||||
};
|
||||
|
||||
#define TAG "DigitalSignal"
|
||||
|
||||
#define F_TIM (64000000.0)
|
||||
#define T_TIM 1562 /* 15.625 ns *100 */
|
||||
#define T_TIM_DIV2 781 /* 15.625 ns / 2 *100 */
|
||||
|
||||
/* end marker in DMA ringbuffer, will get written into timer register at the end */
|
||||
#define SEQ_TIMER_MAX 0xFFFFFFFF
|
||||
|
||||
/* time to wait in loops before returning */
|
||||
#define SEQ_LOCK_WAIT_MS 10UL
|
||||
#define SEQ_LOCK_WAIT_TICKS (SEQ_LOCK_WAIT_MS * 1000 * 64)
|
||||
|
||||
/* maximum entry count of the sequence dma ring buffer */
|
||||
#define RINGBUFFER_SIZE 128
|
||||
|
||||
/* maximum number of DigitalSignals in a sequence */
|
||||
#define SEQUENCE_SIGNALS_SIZE 32
|
||||
/*
|
||||
* if sequence size runs out from the initial value passed to digital_sequence_alloc
|
||||
* the size will be increased by this amount and reallocated
|
||||
*/
|
||||
#define SEQUENCE_SIZE_REALLOCATE_INCREMENT 256
|
||||
|
||||
DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) {
|
||||
DigitalSignal* digital_signal_alloc(uint32_t max_size) {
|
||||
DigitalSignal* signal = malloc(sizeof(DigitalSignal));
|
||||
signal->start_level = true;
|
||||
signal->edges_max_cnt = max_edges_cnt;
|
||||
signal->edge_timings = malloc(signal->edges_max_cnt * sizeof(uint32_t));
|
||||
signal->edge_cnt = 0;
|
||||
signal->reload_reg_buff = malloc(signal->edges_max_cnt * sizeof(uint32_t));
|
||||
|
||||
signal->internals = malloc(sizeof(DigitalSignalInternals));
|
||||
DigitalSignalInternals* internals = signal->internals;
|
||||
|
||||
internals->factor = 1024 * 1024;
|
||||
|
||||
internals->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
internals->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
internals->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
internals->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
internals->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||
internals->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
internals->dma_config_gpio.NbData = 2;
|
||||
internals->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
internals->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||
|
||||
internals->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR);
|
||||
internals->dma_config_timer.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
internals->dma_config_timer.Mode = LL_DMA_MODE_NORMAL;
|
||||
internals->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
internals->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
internals->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||
internals->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
internals->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
internals->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH;
|
||||
signal->max_size = max_size;
|
||||
signal->data = malloc(max_size * sizeof(uint32_t));
|
||||
|
||||
return signal;
|
||||
}
|
||||
@@ -108,559 +17,81 @@ DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) {
|
||||
void digital_signal_free(DigitalSignal* signal) {
|
||||
furi_assert(signal);
|
||||
|
||||
free(signal->edge_timings);
|
||||
free(signal->reload_reg_buff);
|
||||
free(signal->internals);
|
||||
free(signal->data);
|
||||
free(signal);
|
||||
}
|
||||
|
||||
bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b) {
|
||||
furi_assert(signal_a);
|
||||
furi_assert(signal_b);
|
||||
|
||||
if(signal_a->edges_max_cnt < signal_a->edge_cnt + signal_b->edge_cnt) {
|
||||
return false;
|
||||
}
|
||||
/* in case there are no edges in our target signal, the signal to append makes the rules */
|
||||
if(!signal_a->edge_cnt) {
|
||||
signal_a->start_level = signal_b->start_level;
|
||||
}
|
||||
bool end_level = signal_a->start_level;
|
||||
if(signal_a->edge_cnt) {
|
||||
end_level = signal_a->start_level ^ !(signal_a->edge_cnt % 2);
|
||||
}
|
||||
uint8_t start_copy = 0;
|
||||
if(end_level == signal_b->start_level) {
|
||||
if(signal_a->edge_cnt) {
|
||||
signal_a->edge_timings[signal_a->edge_cnt - 1] += signal_b->edge_timings[0];
|
||||
start_copy += 1;
|
||||
} else {
|
||||
signal_a->edge_timings[signal_a->edge_cnt] += signal_b->edge_timings[0];
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < signal_b->edge_cnt - start_copy; i++) {
|
||||
signal_a->edge_timings[signal_a->edge_cnt + i] = signal_b->edge_timings[start_copy + i];
|
||||
}
|
||||
signal_a->edge_cnt += signal_b->edge_cnt - start_copy;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool digital_signal_get_start_level(DigitalSignal* signal) {
|
||||
bool digital_signal_get_start_level(const DigitalSignal* signal) {
|
||||
furi_assert(signal);
|
||||
|
||||
return signal->start_level;
|
||||
}
|
||||
|
||||
uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal) {
|
||||
void digital_signal_set_start_level(DigitalSignal* signal, bool level) {
|
||||
furi_assert(signal);
|
||||
|
||||
return signal->edge_cnt;
|
||||
signal->start_level = level;
|
||||
}
|
||||
|
||||
void digital_signal_add(DigitalSignal* signal, uint32_t ticks) {
|
||||
uint32_t digital_signal_get_size(const DigitalSignal* signal) {
|
||||
furi_assert(signal);
|
||||
furi_assert(signal->edge_cnt < signal->edges_max_cnt);
|
||||
|
||||
signal->edge_timings[signal->edge_cnt++] = ticks;
|
||||
return signal->size;
|
||||
}
|
||||
|
||||
void digital_signal_add_pulse(DigitalSignal* signal, uint32_t ticks, bool level) {
|
||||
void digital_signal_add_period(DigitalSignal* signal, uint32_t ticks) {
|
||||
furi_assert(signal);
|
||||
furi_assert(signal->edge_cnt < signal->edges_max_cnt);
|
||||
furi_assert(signal->size < signal->max_size);
|
||||
|
||||
/* virgin signal? add it as the only level */
|
||||
if(signal->edge_cnt == 0) {
|
||||
const uint32_t duration = ticks + signal->remainder;
|
||||
|
||||
uint32_t reload_value = duration / DIGITAL_SIGNAL_T_TIM;
|
||||
int32_t remainder = duration - reload_value * DIGITAL_SIGNAL_T_TIM;
|
||||
|
||||
if(remainder >= DIGITAL_SIGNAL_T_TIM_DIV2) {
|
||||
reload_value += 1;
|
||||
remainder -= DIGITAL_SIGNAL_T_TIM;
|
||||
}
|
||||
|
||||
furi_check(reload_value > 1);
|
||||
|
||||
signal->data[signal->size++] = reload_value - 1;
|
||||
signal->remainder = remainder;
|
||||
}
|
||||
|
||||
static void digital_signal_extend_last_period(DigitalSignal* signal, uint32_t ticks) {
|
||||
furi_assert(signal->size <= signal->max_size);
|
||||
|
||||
const uint32_t reload_value_old = signal->data[signal->size - 1] + 1;
|
||||
const uint32_t duration = ticks + signal->remainder + reload_value_old * DIGITAL_SIGNAL_T_TIM;
|
||||
|
||||
uint32_t reload_value = duration / DIGITAL_SIGNAL_T_TIM;
|
||||
int32_t remainder = duration - reload_value * DIGITAL_SIGNAL_T_TIM;
|
||||
|
||||
if(remainder >= DIGITAL_SIGNAL_T_TIM_DIV2) {
|
||||
reload_value += 1;
|
||||
remainder -= DIGITAL_SIGNAL_T_TIM;
|
||||
}
|
||||
|
||||
furi_check(reload_value > 1);
|
||||
|
||||
signal->data[signal->size - 1] = reload_value - 1;
|
||||
signal->remainder = remainder;
|
||||
}
|
||||
|
||||
void digital_signal_add_period_with_level(DigitalSignal* signal, uint32_t ticks, bool level) {
|
||||
furi_assert(signal);
|
||||
|
||||
if(signal->size == 0) {
|
||||
signal->start_level = level;
|
||||
signal->edge_timings[signal->edge_cnt++] = ticks;
|
||||
digital_signal_add_period(signal, ticks);
|
||||
} else {
|
||||
bool end_level = signal->start_level ^ !(signal->edge_cnt % 2);
|
||||
const bool end_level = signal->start_level ^ !(signal->size % 2);
|
||||
|
||||
if(level != end_level) {
|
||||
signal->edge_timings[signal->edge_cnt++] = ticks;
|
||||
digital_signal_add_period(signal, ticks);
|
||||
} else {
|
||||
signal->edge_timings[signal->edge_cnt - 1] += ticks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num) {
|
||||
furi_assert(signal);
|
||||
furi_assert(edge_num < signal->edge_cnt);
|
||||
|
||||
return signal->edge_timings[edge_num];
|
||||
}
|
||||
|
||||
void digital_signal_prepare_arr(DigitalSignal* signal) {
|
||||
furi_assert(signal);
|
||||
|
||||
DigitalSignalInternals* internals = signal->internals;
|
||||
|
||||
/* set up signal polarities */
|
||||
if(internals->gpio) {
|
||||
uint32_t bit_set = internals->gpio->pin;
|
||||
uint32_t bit_reset = internals->gpio->pin << 16;
|
||||
|
||||
#ifdef DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN
|
||||
bit_set |= DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN.pin;
|
||||
bit_reset |= DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN.pin << 16;
|
||||
#endif
|
||||
|
||||
if(signal->start_level) {
|
||||
internals->gpio_buff[0] = bit_set;
|
||||
internals->gpio_buff[1] = bit_reset;
|
||||
} else {
|
||||
internals->gpio_buff[0] = bit_reset;
|
||||
internals->gpio_buff[1] = bit_set;
|
||||
}
|
||||
}
|
||||
|
||||
/* set up edge timings */
|
||||
internals->reload_reg_entries = 0;
|
||||
|
||||
for(size_t pos = 0; pos < signal->edge_cnt; pos++) {
|
||||
uint32_t pulse_duration = signal->edge_timings[pos] + internals->reload_reg_remainder;
|
||||
if(pulse_duration < 10 || pulse_duration > 10000000) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"[prepare] pulse_duration out of range: %lu = %lu * %llu",
|
||||
pulse_duration,
|
||||
signal->edge_timings[pos],
|
||||
internals->factor);
|
||||
pulse_duration = 100;
|
||||
}
|
||||
uint32_t pulse_ticks = (pulse_duration + T_TIM_DIV2) / T_TIM;
|
||||
internals->reload_reg_remainder = pulse_duration - (pulse_ticks * T_TIM);
|
||||
|
||||
if(pulse_ticks > 1) {
|
||||
signal->reload_reg_buff[internals->reload_reg_entries++] = pulse_ticks - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void digital_signal_stop_dma() {
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
LL_DMA_ClearFlag_TC2(DMA1);
|
||||
}
|
||||
|
||||
static void digital_signal_stop_timer() {
|
||||
LL_TIM_DisableCounter(TIM2);
|
||||
LL_TIM_DisableUpdateEvent(TIM2);
|
||||
LL_TIM_DisableDMAReq_UPDATE(TIM2);
|
||||
|
||||
furi_hal_bus_disable(FuriHalBusTIM2);
|
||||
}
|
||||
|
||||
static void digital_signal_setup_timer() {
|
||||
furi_hal_bus_enable(FuriHalBusTIM2);
|
||||
|
||||
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);
|
||||
LL_TIM_SetPrescaler(TIM2, 0);
|
||||
LL_TIM_SetAutoReload(TIM2, SEQ_TIMER_MAX);
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
}
|
||||
|
||||
static void digital_signal_start_timer() {
|
||||
LL_TIM_EnableCounter(TIM2);
|
||||
LL_TIM_EnableUpdateEvent(TIM2);
|
||||
LL_TIM_EnableDMAReq_UPDATE(TIM2);
|
||||
LL_TIM_GenerateEvent_UPDATE(TIM2);
|
||||
}
|
||||
|
||||
static bool digital_signal_setup_dma(DigitalSignal* signal) {
|
||||
furi_assert(signal);
|
||||
DigitalSignalInternals* internals = signal->internals;
|
||||
|
||||
if(!signal->internals->reload_reg_entries) {
|
||||
return false;
|
||||
}
|
||||
digital_signal_stop_dma();
|
||||
|
||||
internals->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)internals->gpio_buff;
|
||||
internals->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) & (internals->gpio->port->BSRR);
|
||||
internals->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)signal->reload_reg_buff;
|
||||
internals->dma_config_timer.NbData = signal->internals->reload_reg_entries;
|
||||
|
||||
/* set up DMA channel 1 and 2 for GPIO and timer copy operations */
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &internals->dma_config_gpio);
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &internals->dma_config_timer);
|
||||
|
||||
/* enable both DMA channels */
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio) {
|
||||
furi_assert(signal);
|
||||
|
||||
if(!signal->edge_cnt) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configure gpio as output */
|
||||
signal->internals->gpio = gpio;
|
||||
furi_hal_gpio_init(
|
||||
signal->internals->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
|
||||
digital_signal_prepare_arr(signal);
|
||||
|
||||
digital_signal_setup_dma(signal);
|
||||
digital_signal_setup_timer();
|
||||
digital_signal_start_timer();
|
||||
|
||||
while(!LL_DMA_IsActiveFlag_TC2(DMA1)) {
|
||||
}
|
||||
|
||||
digital_signal_stop_timer();
|
||||
digital_signal_stop_dma();
|
||||
}
|
||||
|
||||
static void digital_sequence_alloc_signals(DigitalSequence* sequence, uint32_t size) {
|
||||
sequence->signals_size = size;
|
||||
sequence->signals = malloc(sequence->signals_size * sizeof(DigitalSignal*));
|
||||
}
|
||||
|
||||
static void digital_sequence_alloc_sequence(DigitalSequence* sequence, uint32_t size) {
|
||||
sequence->sequence_used = 0;
|
||||
sequence->sequence_size = size;
|
||||
sequence->sequence = malloc(sequence->sequence_size);
|
||||
sequence->send_time = 0;
|
||||
sequence->send_time_active = false;
|
||||
}
|
||||
|
||||
DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) {
|
||||
furi_assert(gpio);
|
||||
|
||||
DigitalSequence* sequence = malloc(sizeof(DigitalSequence));
|
||||
|
||||
sequence->gpio = gpio;
|
||||
sequence->bake = false;
|
||||
|
||||
sequence->dma_buffer = malloc(sizeof(struct ReloadBuffer));
|
||||
sequence->dma_buffer->size = RINGBUFFER_SIZE;
|
||||
sequence->dma_buffer->buffer = malloc(sequence->dma_buffer->size * sizeof(uint32_t));
|
||||
|
||||
sequence->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
sequence->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
sequence->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
sequence->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
sequence->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||
sequence->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
sequence->dma_config_gpio.NbData = 2;
|
||||
sequence->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
sequence->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||
|
||||
sequence->dma_config_timer.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
sequence->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
sequence->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
sequence->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
sequence->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD;
|
||||
sequence->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
sequence->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR);
|
||||
sequence->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)sequence->dma_buffer->buffer;
|
||||
sequence->dma_config_timer.NbData = sequence->dma_buffer->size;
|
||||
sequence->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
sequence->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH;
|
||||
|
||||
digital_sequence_alloc_signals(sequence, SEQUENCE_SIGNALS_SIZE);
|
||||
digital_sequence_alloc_sequence(sequence, size);
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
void digital_sequence_free(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
|
||||
free(sequence->signals);
|
||||
free(sequence->sequence);
|
||||
free(sequence->dma_buffer->buffer);
|
||||
free(sequence->dma_buffer);
|
||||
free(sequence);
|
||||
}
|
||||
|
||||
void digital_sequence_set_signal(
|
||||
DigitalSequence* sequence,
|
||||
uint8_t signal_index,
|
||||
DigitalSignal* signal) {
|
||||
furi_assert(sequence);
|
||||
furi_assert(signal);
|
||||
furi_assert(signal_index < sequence->signals_size);
|
||||
|
||||
sequence->signals[signal_index] = signal;
|
||||
signal->internals->gpio = sequence->gpio;
|
||||
signal->internals->reload_reg_remainder = 0;
|
||||
|
||||
digital_signal_prepare_arr(signal);
|
||||
}
|
||||
|
||||
void digital_sequence_set_sendtime(DigitalSequence* sequence, uint32_t send_time) {
|
||||
furi_assert(sequence);
|
||||
|
||||
sequence->send_time = send_time;
|
||||
sequence->send_time_active = true;
|
||||
}
|
||||
|
||||
void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index) {
|
||||
furi_assert(sequence);
|
||||
furi_assert(signal_index < sequence->signals_size);
|
||||
|
||||
if(sequence->sequence_used >= sequence->sequence_size) {
|
||||
sequence->sequence_size += SEQUENCE_SIZE_REALLOCATE_INCREMENT;
|
||||
sequence->sequence = realloc(sequence->sequence, sequence->sequence_size); //-V701
|
||||
furi_assert(sequence->sequence);
|
||||
}
|
||||
|
||||
sequence->sequence[sequence->sequence_used++] = signal_index;
|
||||
}
|
||||
|
||||
static bool digital_sequence_setup_dma(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
|
||||
digital_signal_stop_dma();
|
||||
|
||||
sequence->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)sequence->gpio_buff;
|
||||
sequence->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) & (sequence->gpio->port->BSRR);
|
||||
|
||||
/* set up DMA channel 1 and 2 for GPIO and timer copy operations */
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &sequence->dma_config_gpio);
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &sequence->dma_config_timer);
|
||||
|
||||
/* enable both DMA channels */
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static DigitalSignal* digital_sequence_bake(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
|
||||
uint32_t edges = 0;
|
||||
|
||||
for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) {
|
||||
uint8_t signal_index = sequence->sequence[pos];
|
||||
DigitalSignal* sig = sequence->signals[signal_index];
|
||||
|
||||
edges += sig->edge_cnt;
|
||||
}
|
||||
|
||||
DigitalSignal* ret = digital_signal_alloc(edges);
|
||||
|
||||
for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) {
|
||||
uint8_t signal_index = sequence->sequence[pos];
|
||||
DigitalSignal* sig = sequence->signals[signal_index];
|
||||
|
||||
digital_signal_append(ret, sig);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void digital_sequence_finish(DigitalSequence* sequence) {
|
||||
struct ReloadBuffer* dma_buffer = sequence->dma_buffer;
|
||||
|
||||
if(dma_buffer->dma_active) {
|
||||
uint32_t prev_timer = DWT->CYCCNT;
|
||||
do {
|
||||
/* we are finished, when the DMA transferred the SEQ_TIMER_MAX marker */
|
||||
if(TIM2->ARR == SEQ_TIMER_MAX) {
|
||||
break;
|
||||
}
|
||||
if(DWT->CYCCNT - prev_timer > SEQ_LOCK_WAIT_TICKS) {
|
||||
dma_buffer->read_pos =
|
||||
RINGBUFFER_SIZE - LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"[SEQ] hung %lu ms in finish (ARR 0x%08lx, read %lu, write %lu)",
|
||||
SEQ_LOCK_WAIT_MS,
|
||||
TIM2->ARR,
|
||||
dma_buffer->read_pos,
|
||||
dma_buffer->write_pos);
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
}
|
||||
|
||||
digital_signal_stop_timer();
|
||||
digital_signal_stop_dma();
|
||||
}
|
||||
|
||||
static void digital_sequence_queue_pulse(DigitalSequence* sequence, uint32_t length) {
|
||||
struct ReloadBuffer* dma_buffer = sequence->dma_buffer;
|
||||
|
||||
if(dma_buffer->dma_active) {
|
||||
uint32_t prev_timer = DWT->CYCCNT;
|
||||
do {
|
||||
dma_buffer->read_pos = RINGBUFFER_SIZE - LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2);
|
||||
|
||||
uint32_t free =
|
||||
(RINGBUFFER_SIZE + dma_buffer->read_pos - dma_buffer->write_pos) % RINGBUFFER_SIZE;
|
||||
|
||||
if(free > 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(DWT->CYCCNT - prev_timer > SEQ_LOCK_WAIT_TICKS) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"[SEQ] hung %lu ms in queue (ARR 0x%08lx, read %lu, write %lu)",
|
||||
SEQ_LOCK_WAIT_MS,
|
||||
TIM2->ARR,
|
||||
dma_buffer->read_pos,
|
||||
dma_buffer->write_pos);
|
||||
break;
|
||||
}
|
||||
if(TIM2->ARR == SEQ_TIMER_MAX) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"[SEQ] buffer underrun in queue (ARR 0x%08lx, read %lu, write %lu)",
|
||||
TIM2->ARR,
|
||||
dma_buffer->read_pos,
|
||||
dma_buffer->write_pos);
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
}
|
||||
|
||||
dma_buffer->buffer[dma_buffer->write_pos] = length;
|
||||
dma_buffer->write_pos++;
|
||||
dma_buffer->write_pos %= RINGBUFFER_SIZE;
|
||||
dma_buffer->buffer[dma_buffer->write_pos] = SEQ_TIMER_MAX;
|
||||
}
|
||||
|
||||
bool digital_sequence_send(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
|
||||
struct ReloadBuffer* dma_buffer = sequence->dma_buffer;
|
||||
|
||||
furi_hal_gpio_init(sequence->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#ifdef DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN
|
||||
furi_hal_gpio_init(
|
||||
&DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
#endif
|
||||
|
||||
if(sequence->bake) {
|
||||
DigitalSignal* sig = digital_sequence_bake(sequence);
|
||||
|
||||
digital_signal_send(sig, sequence->gpio);
|
||||
digital_signal_free(sig);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!sequence->sequence_used) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t remainder = 0;
|
||||
uint32_t trade_for_next = 0;
|
||||
uint32_t seq_pos_next = 1;
|
||||
|
||||
dma_buffer->dma_active = false;
|
||||
dma_buffer->buffer[0] = SEQ_TIMER_MAX;
|
||||
dma_buffer->read_pos = 0;
|
||||
dma_buffer->write_pos = 0;
|
||||
|
||||
/* already prepare the current signal pointer */
|
||||
DigitalSignal* sig = sequence->signals[sequence->sequence[0]];
|
||||
DigitalSignal* sig_next = NULL;
|
||||
/* re-use the GPIO buffer from the first signal */
|
||||
sequence->gpio_buff = sig->internals->gpio_buff;
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
|
||||
while(sig) {
|
||||
bool last_signal = (seq_pos_next >= sequence->sequence_used);
|
||||
|
||||
if(!last_signal) {
|
||||
sig_next = sequence->signals[sequence->sequence[seq_pos_next++]];
|
||||
}
|
||||
|
||||
for(uint32_t pulse_pos = 0; pulse_pos < sig->internals->reload_reg_entries; pulse_pos++) {
|
||||
bool last_pulse = ((pulse_pos + 1) >= sig->internals->reload_reg_entries);
|
||||
uint32_t pulse_length = sig->reload_reg_buff[pulse_pos] + trade_for_next;
|
||||
|
||||
trade_for_next = 0;
|
||||
|
||||
/* when we are too late more than half a tick, make the first edge temporarily longer */
|
||||
if(remainder >= T_TIM_DIV2) {
|
||||
remainder -= T_TIM;
|
||||
pulse_length += 1;
|
||||
}
|
||||
|
||||
/* last pulse in current signal and have a next signal? */
|
||||
if(last_pulse && sig_next) {
|
||||
/* when a signal ends with the same level as the next signal begins, let the next signal generate the whole pulse.
|
||||
beware, we do not want the level after the last edge, but the last level before that edge */
|
||||
bool end_level = sig->start_level ^ ((sig->edge_cnt % 2) == 0);
|
||||
|
||||
/* if they have the same level, pass the duration to the next pulse(s) */
|
||||
if(end_level == sig_next->start_level) {
|
||||
trade_for_next = pulse_length;
|
||||
}
|
||||
}
|
||||
|
||||
/* if it was decided, that the next signal's first pulse shall also handle our "length", then do not queue here */
|
||||
if(!trade_for_next) {
|
||||
digital_sequence_queue_pulse(sequence, pulse_length);
|
||||
|
||||
if(!dma_buffer->dma_active) {
|
||||
/* start transmission when buffer was filled enough */
|
||||
bool start_send = sequence->dma_buffer->write_pos >= (RINGBUFFER_SIZE - 2);
|
||||
|
||||
/* or it was the last pulse */
|
||||
if(last_pulse && last_signal) {
|
||||
start_send = true;
|
||||
}
|
||||
|
||||
/* start transmission */
|
||||
if(start_send) {
|
||||
digital_sequence_setup_dma(sequence);
|
||||
digital_signal_setup_timer();
|
||||
|
||||
/* if the send time is specified, wait till the core timer passed beyond that time */
|
||||
if(sequence->send_time_active) {
|
||||
sequence->send_time_active = false;
|
||||
while(sequence->send_time - DWT->CYCCNT < 0x80000000) {
|
||||
}
|
||||
}
|
||||
digital_signal_start_timer();
|
||||
dma_buffer->dma_active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remainder += sig->internals->reload_reg_remainder;
|
||||
sig = sig_next;
|
||||
sig_next = NULL;
|
||||
}
|
||||
|
||||
/* wait until last dma transaction was finished */
|
||||
FURI_CRITICAL_EXIT();
|
||||
digital_sequence_finish(sequence);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void digital_sequence_clear(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
|
||||
sequence->sequence_used = 0;
|
||||
}
|
||||
|
||||
void digital_sequence_timebase_correction(DigitalSequence* sequence, float factor) {
|
||||
for(uint32_t sig_pos = 0; sig_pos < sequence->signals_size; sig_pos++) {
|
||||
DigitalSignal* signal = sequence->signals[sig_pos];
|
||||
|
||||
if(signal) {
|
||||
signal->internals->factor = (uint32_t)(1024 * 1024 * factor);
|
||||
digital_signal_prepare_arr(signal);
|
||||
digital_signal_extend_last_period(signal, ticks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,74 +1,121 @@
|
||||
/**
|
||||
* @file digital_signal.h
|
||||
* @brief Simple digital signal container for the DigitalSequence library.
|
||||
*
|
||||
* Each signal is represented by its start level (high or low) and one or more periods.
|
||||
* The output will transition to its inverse value on each period boundary.
|
||||
*
|
||||
* Example: A signal with n periods and HIGH start level.
|
||||
*
|
||||
* ```
|
||||
* ----+ +------+ +- ... -+
|
||||
* t0 | t1 | t2 | t3 | | tn - 1
|
||||
* +--------+ +----+ +--------
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <furi_hal_gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* helper for easier signal generation */
|
||||
// DigitalSignal uses 10 picosecond time units (1 tick = 10 ps).
|
||||
// Use the macros below to convert the time from other units.
|
||||
|
||||
#define DIGITAL_SIGNAL_MS(x) ((x)*100000000UL)
|
||||
#define DIGITAL_SIGNAL_US(x) ((x)*100000UL)
|
||||
#define DIGITAL_SIGNAL_NS(x) ((x)*100UL)
|
||||
#define DIGITAL_SIGNAL_PS(x) ((x) / 10UL)
|
||||
|
||||
/* using an anonymous type for the internals */
|
||||
typedef struct DigitalSignalInternals DigitalSignalInternals;
|
||||
typedef struct DigitalSignal DigitalSignal;
|
||||
|
||||
/* and a public one for accessing user-side fields */
|
||||
typedef struct DigitalSignal {
|
||||
bool start_level;
|
||||
uint32_t edge_cnt;
|
||||
uint32_t edges_max_cnt;
|
||||
uint32_t* edge_timings;
|
||||
uint32_t* reload_reg_buff; /* internal, but used by unit tests */
|
||||
DigitalSignalInternals* internals;
|
||||
} DigitalSignal;
|
||||
|
||||
typedef struct DigitalSequence DigitalSequence;
|
||||
|
||||
DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt);
|
||||
/**
|
||||
* @brief Allocate a DigitalSignal instance with a defined maximum size.
|
||||
*
|
||||
* @param[in] max_size the maximum number of periods the instance will be able to contain.
|
||||
* @returns pointer to the allocated instance.
|
||||
*/
|
||||
DigitalSignal* digital_signal_alloc(uint32_t max_size);
|
||||
|
||||
/**
|
||||
* @brief Delete a previously allocated DigitalSignal instance.
|
||||
*
|
||||
* @param[in,out] signal pointer to the instance to be deleted.
|
||||
*/
|
||||
void digital_signal_free(DigitalSignal* signal);
|
||||
|
||||
void digital_signal_add(DigitalSignal* signal, uint32_t ticks);
|
||||
/**
|
||||
* @brief Append one period to the end of the DigitalSignal instance.
|
||||
*
|
||||
* @param[in,out] signal pointer to a the instance to append to.
|
||||
* @param[in] ticks the period length, in 10 picosecond units.
|
||||
*/
|
||||
void digital_signal_add_period(DigitalSignal* signal, uint32_t ticks);
|
||||
|
||||
void digital_signal_add_pulse(DigitalSignal* signal, uint32_t ticks, bool level);
|
||||
/**
|
||||
* @brief Append one period to the end of the DigitalSignal instance, with the level specified.
|
||||
*
|
||||
* If the level is the same as the last level contained in the instance, then it is extened
|
||||
* by the given ticks value. Otherwise, the behaviour is identical to digital_signal_add_period().
|
||||
*
|
||||
* Example 1: add tc with HIGH level
|
||||
* ```
|
||||
* before:
|
||||
* ... ------+
|
||||
* ta | tb
|
||||
* +-------
|
||||
* after:
|
||||
* ... ------+ +-------
|
||||
* ta | tb | tc
|
||||
* +------+
|
||||
* ```
|
||||
* Example 2: add tc with LOW level
|
||||
* ```
|
||||
* before:
|
||||
* ... ------+
|
||||
* ta | tb
|
||||
* +-------
|
||||
* after:
|
||||
* ... ------+
|
||||
* ta | tb + tc
|
||||
* +--------------
|
||||
* ```
|
||||
*
|
||||
* @param[in,out] signal pointer to the instance to append to.
|
||||
* @param[in] ticks the period length, in 10 picosecond units.
|
||||
* @param[in] level the level to be set during the period.
|
||||
*/
|
||||
void digital_signal_add_period_with_level(DigitalSignal* signal, uint32_t ticks, bool level);
|
||||
|
||||
bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b);
|
||||
/**
|
||||
* @brief Get the current start level contained in the DigitalSignal instance.
|
||||
*
|
||||
* If not explicitly set with digital_signal_set_start_level(), it defaults to false.
|
||||
*
|
||||
* @param[in] signal pointer to the instance to be queried.
|
||||
* @returns the start level value.
|
||||
*/
|
||||
bool digital_signal_get_start_level(const DigitalSignal* signal);
|
||||
|
||||
void digital_signal_prepare_arr(DigitalSignal* signal);
|
||||
/**
|
||||
* @brief Set the start level contained in the DigitalSignal instance.
|
||||
*
|
||||
* @param[in,out] signal pointer to the instance to be modified.
|
||||
* @param[in] level signal level to be set as the start level.
|
||||
*/
|
||||
void digital_signal_set_start_level(DigitalSignal* signal, bool level);
|
||||
|
||||
bool digital_signal_get_start_level(DigitalSignal* signal);
|
||||
|
||||
uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal);
|
||||
|
||||
uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num);
|
||||
|
||||
void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio);
|
||||
|
||||
DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio);
|
||||
|
||||
void digital_sequence_free(DigitalSequence* sequence);
|
||||
|
||||
void digital_sequence_set_signal(
|
||||
DigitalSequence* sequence,
|
||||
uint8_t signal_index,
|
||||
DigitalSignal* signal);
|
||||
|
||||
void digital_sequence_set_sendtime(DigitalSequence* sequence, uint32_t send_time);
|
||||
|
||||
void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index);
|
||||
|
||||
bool digital_sequence_send(DigitalSequence* sequence);
|
||||
|
||||
void digital_sequence_clear(DigitalSequence* sequence);
|
||||
|
||||
void digital_sequence_timebase_correction(DigitalSequence* sequence, float factor);
|
||||
/**
|
||||
* @brief Get the number of periods currently stored in a DigitalSignal instance.
|
||||
*
|
||||
* @param[in] signal pointer to the instance to be queried.
|
||||
* @return the number of periods stored in the instance.
|
||||
*/
|
||||
uint32_t digital_signal_get_size(const DigitalSignal* signal);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @file digital_signal_i.h
|
||||
* @brief DigitalSignal private definitions.
|
||||
*
|
||||
* This file is an implementation detail. It must not be included in
|
||||
* any public API-related headers.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define DIGITAL_SIGNAL_T_TIM 1562 /**< 15.625 ns *100 */
|
||||
#define DIGITAL_SIGNAL_T_TIM_DIV2 (DIGITAL_SIGNAL_T_TIM / 2) /**< 15.625 ns / 2 *100 */
|
||||
|
||||
/**
|
||||
* @brief DigitalSignal structure type.
|
||||
*/
|
||||
struct DigitalSignal {
|
||||
bool start_level; /**< The level to begin the signal with. */
|
||||
uint32_t size; /**< Current period count contained in the instance. */
|
||||
uint32_t max_size; /**< Maximum period count this instance can hold. */
|
||||
uint32_t* data; /**< Pointer to the array of time periods. */
|
||||
int32_t remainder; /**< Remainder left after converting all periods into timer ticks. */
|
||||
};
|
||||
@@ -0,0 +1,139 @@
|
||||
#include "iso14443_3a_signal.h"
|
||||
|
||||
#include <digital_signal/digital_sequence.h>
|
||||
|
||||
#define BITS_IN_BYTE (8)
|
||||
|
||||
#define ISO14443_3A_SIGNAL_BIT_MAX_EDGES (10)
|
||||
#define ISO14443_3A_SIGNAL_MAX_EDGES (1350)
|
||||
|
||||
#define ISO14443_3A_SIGNAL_SEQUENCE_SIZE \
|
||||
(ISO14443_3A_SIGNAL_MAX_EDGES / (ISO14443_3A_SIGNAL_BIT_MAX_EDGES - 2))
|
||||
|
||||
#define ISO14443_3A_SIGNAL_F_SIG (13560000.0)
|
||||
#define ISO14443_3A_SIGNAL_T_SIG 7374 //73.746ns*100
|
||||
#define ISO14443_3A_SIGNAL_T_SIG_X8 58992 //T_SIG*8
|
||||
#define ISO14443_3A_SIGNAL_T_SIG_X8_X8 471936 //T_SIG*8*8
|
||||
#define ISO14443_3A_SIGNAL_T_SIG_X8_X9 530928 //T_SIG*8*9
|
||||
|
||||
typedef enum {
|
||||
Iso14443_3aSignalIndexZero,
|
||||
Iso14443_3aSignalIndexOne,
|
||||
Iso14443_3aSignalIndexCount,
|
||||
} Iso14443_3aSignalIndex;
|
||||
|
||||
typedef DigitalSignal* Iso14443_3aSignalBank[Iso14443_3aSignalIndexCount];
|
||||
|
||||
struct Iso14443_3aSignal {
|
||||
DigitalSequence* tx_sequence;
|
||||
Iso14443_3aSignalBank signals;
|
||||
};
|
||||
|
||||
static void iso14443_3a_signal_add_byte(Iso14443_3aSignal* instance, uint8_t byte, bool parity) {
|
||||
for(size_t i = 0; i < BITS_IN_BYTE; i++) {
|
||||
digital_sequence_add_signal(
|
||||
instance->tx_sequence,
|
||||
FURI_BIT(byte, i) ? Iso14443_3aSignalIndexOne : Iso14443_3aSignalIndexZero);
|
||||
}
|
||||
digital_sequence_add_signal(
|
||||
instance->tx_sequence, parity ? Iso14443_3aSignalIndexOne : Iso14443_3aSignalIndexZero);
|
||||
}
|
||||
|
||||
static void iso14443_3a_signal_encode(
|
||||
Iso14443_3aSignal* instance,
|
||||
const uint8_t* tx_data,
|
||||
const uint8_t* tx_parity,
|
||||
size_t tx_bits) {
|
||||
furi_assert(instance);
|
||||
furi_assert(tx_data);
|
||||
furi_assert(tx_parity);
|
||||
|
||||
// Start of frame
|
||||
digital_sequence_add_signal(instance->tx_sequence, Iso14443_3aSignalIndexOne);
|
||||
|
||||
if(tx_bits < BITS_IN_BYTE) {
|
||||
for(size_t i = 0; i < tx_bits; i++) {
|
||||
digital_sequence_add_signal(
|
||||
instance->tx_sequence,
|
||||
FURI_BIT(tx_data[0], i) ? Iso14443_3aSignalIndexOne : Iso14443_3aSignalIndexZero);
|
||||
}
|
||||
} else {
|
||||
for(size_t i = 0; i < tx_bits / BITS_IN_BYTE; i++) {
|
||||
bool parity = FURI_BIT(tx_parity[i / BITS_IN_BYTE], i % BITS_IN_BYTE);
|
||||
iso14443_3a_signal_add_byte(instance, tx_data[i], parity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iso14443_3a_signal_set_bit(DigitalSignal* signal, bool bit) {
|
||||
digital_signal_set_start_level(signal, bit);
|
||||
|
||||
if(bit) {
|
||||
for(uint32_t i = 0; i < 7; ++i) {
|
||||
digital_signal_add_period(signal, ISO14443_3A_SIGNAL_T_SIG_X8);
|
||||
}
|
||||
digital_signal_add_period(signal, ISO14443_3A_SIGNAL_T_SIG_X8_X9);
|
||||
} else {
|
||||
digital_signal_add_period(signal, ISO14443_3A_SIGNAL_T_SIG_X8_X8);
|
||||
for(uint32_t i = 0; i < 8; ++i) {
|
||||
digital_signal_add_period(signal, ISO14443_3A_SIGNAL_T_SIG_X8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iso14443_3a_signal_bank_fill(Iso14443_3aSignalBank bank) {
|
||||
for(uint32_t i = 0; i < Iso14443_3aSignalIndexCount; ++i) {
|
||||
bank[i] = digital_signal_alloc(ISO14443_3A_SIGNAL_BIT_MAX_EDGES);
|
||||
iso14443_3a_signal_set_bit(bank[i], i % Iso14443_3aSignalIndexCount != 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iso14443_3a_signal_bank_clear(Iso14443_3aSignalBank bank) {
|
||||
for(uint32_t i = 0; i < Iso14443_3aSignalIndexCount; ++i) {
|
||||
digital_signal_free(bank[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
iso14443_3a_signal_bank_register(Iso14443_3aSignalBank bank, DigitalSequence* sequence) {
|
||||
for(uint32_t i = 0; i < Iso14443_3aSignalIndexCount; ++i) {
|
||||
digital_sequence_register_signal(sequence, i, bank[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Iso14443_3aSignal* iso14443_3a_signal_alloc(const GpioPin* pin) {
|
||||
furi_assert(pin);
|
||||
|
||||
Iso14443_3aSignal* instance = malloc(sizeof(Iso14443_3aSignal));
|
||||
instance->tx_sequence = digital_sequence_alloc(ISO14443_3A_SIGNAL_SEQUENCE_SIZE, pin);
|
||||
|
||||
iso14443_3a_signal_bank_fill(instance->signals);
|
||||
iso14443_3a_signal_bank_register(instance->signals, instance->tx_sequence);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void iso14443_3a_signal_free(Iso14443_3aSignal* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->tx_sequence);
|
||||
|
||||
iso14443_3a_signal_bank_clear(instance->signals);
|
||||
digital_sequence_free(instance->tx_sequence);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void iso14443_3a_signal_tx(
|
||||
Iso14443_3aSignal* instance,
|
||||
const uint8_t* tx_data,
|
||||
const uint8_t* tx_parity,
|
||||
size_t tx_bits) {
|
||||
furi_assert(instance);
|
||||
furi_assert(tx_data);
|
||||
furi_assert(tx_parity);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
digital_sequence_clear(instance->tx_sequence);
|
||||
iso14443_3a_signal_encode(instance, tx_data, tx_parity, tx_bits);
|
||||
digital_sequence_transmit(instance->tx_sequence);
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file iso14443_3a_signal.h
|
||||
* @brief DigitalSequence preset for generating ISO14443-3A compliant signals.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_resources.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Iso14443_3aSignal Iso14443_3aSignal;
|
||||
|
||||
/**
|
||||
* @brief Allocate an Iso14443_3aSignal instance with a set GPIO pin.
|
||||
*
|
||||
* @param[in] pin GPIO pin to use during transmission.
|
||||
* @returns pointer to the allocated instance.
|
||||
*/
|
||||
Iso14443_3aSignal* iso14443_3a_signal_alloc(const GpioPin* pin);
|
||||
|
||||
/**
|
||||
* @brief Delete an Iso14443_3aSignal instance.
|
||||
*
|
||||
* @param[in,out] instance pointer to the instance to be deleted.
|
||||
*/
|
||||
void iso14443_3a_signal_free(Iso14443_3aSignal* instance);
|
||||
|
||||
/**
|
||||
* @brief Transmit arbitrary bytes using an Iso14443_3aSignal instance.
|
||||
*
|
||||
* This function will block until the transmisson has been completed.
|
||||
*
|
||||
* @param[in] instance pointer to the instance used in transmission.
|
||||
* @param[in] tx_data pointer to the data to be transmitted.
|
||||
* @param[in] tx_parity pointer to the bit-packed parity array.
|
||||
* @param[in] tx_bits size of the data to be transmitted in bits.
|
||||
*/
|
||||
void iso14443_3a_signal_tx(
|
||||
Iso14443_3aSignal* instance,
|
||||
const uint8_t* tx_data,
|
||||
const uint8_t* tx_parity,
|
||||
size_t tx_bits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,204 @@
|
||||
#include "iso15693_signal.h"
|
||||
|
||||
#include <digital_signal/digital_sequence.h>
|
||||
|
||||
#define BITS_IN_BYTE (8U)
|
||||
|
||||
#define ISO15693_SIGNAL_COEFF_HI (1U)
|
||||
#define ISO15693_SIGNAL_COEFF_LO (4U)
|
||||
|
||||
#define ISO15693_SIGNAL_ZERO_EDGES (16U)
|
||||
#define ISO15693_SIGNAL_ONE_EDGES (ISO15693_SIGNAL_ZERO_EDGES + 1U)
|
||||
#define ISO15693_SIGNAL_EOF_EDGES (64U)
|
||||
#define ISO15693_SIGNAL_SOF_EDGES (ISO15693_SIGNAL_EOF_EDGES + 1U)
|
||||
#define ISO15693_SIGNAL_EDGES (1350U)
|
||||
|
||||
#define ISO15693_SIGNAL_FC (13.56e6)
|
||||
#define ISO15693_SIGNAL_FC_16 (16.0e11 / ISO15693_SIGNAL_FC)
|
||||
#define ISO15693_SIGNAL_FC_256 (256.0e11 / ISO15693_SIGNAL_FC)
|
||||
#define ISO15693_SIGNAL_FC_768 (768.0e11 / ISO15693_SIGNAL_FC)
|
||||
|
||||
typedef enum {
|
||||
Iso15693SignalIndexSof,
|
||||
Iso15693SignalIndexEof,
|
||||
Iso15693SignalIndexOne,
|
||||
Iso15693SignalIndexZero,
|
||||
Iso15693SignalIndexNum,
|
||||
} Iso15693SignalIndex;
|
||||
|
||||
typedef DigitalSignal* Iso15693SignalBank[Iso15693SignalIndexNum];
|
||||
|
||||
struct Iso15693Signal {
|
||||
DigitalSequence* tx_sequence;
|
||||
Iso15693SignalBank banks[Iso15693SignalDataRateNum];
|
||||
};
|
||||
|
||||
// Add an unmodulated signal for the length of Fc / 256 * k (where k = 1 or 4)
|
||||
static void iso15693_add_silence(DigitalSignal* signal, Iso15693SignalDataRate data_rate) {
|
||||
const uint32_t k = data_rate == Iso15693SignalDataRateHi ? ISO15693_SIGNAL_COEFF_HI :
|
||||
ISO15693_SIGNAL_COEFF_LO;
|
||||
digital_signal_add_period_with_level(signal, ISO15693_SIGNAL_FC_256 * k, false);
|
||||
}
|
||||
|
||||
// Add 8 * k subcarrier pulses of Fc / 16 (where k = 1 or 4)
|
||||
static void iso15693_add_subcarrier(DigitalSignal* signal, Iso15693SignalDataRate data_rate) {
|
||||
const uint32_t k = data_rate == Iso15693SignalDataRateHi ? ISO15693_SIGNAL_COEFF_HI :
|
||||
ISO15693_SIGNAL_COEFF_LO;
|
||||
for(uint32_t i = 0; i < ISO15693_SIGNAL_ZERO_EDGES * k; ++i) {
|
||||
digital_signal_add_period_with_level(signal, ISO15693_SIGNAL_FC_16, !(i % 2));
|
||||
}
|
||||
}
|
||||
|
||||
static void iso15693_add_bit(DigitalSignal* signal, Iso15693SignalDataRate data_rate, bool bit) {
|
||||
if(bit) {
|
||||
iso15693_add_silence(signal, data_rate);
|
||||
iso15693_add_subcarrier(signal, data_rate);
|
||||
} else {
|
||||
iso15693_add_subcarrier(signal, data_rate);
|
||||
iso15693_add_silence(signal, data_rate);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iso15693_add_sof(DigitalSignal* signal, Iso15693SignalDataRate data_rate) {
|
||||
// Not adding silence since it only increases response time
|
||||
|
||||
for(uint32_t i = 0; i < ISO15693_SIGNAL_FC_768 / ISO15693_SIGNAL_FC_256; ++i) {
|
||||
iso15693_add_subcarrier(signal, data_rate);
|
||||
}
|
||||
|
||||
iso15693_add_bit(signal, data_rate, true);
|
||||
}
|
||||
|
||||
static inline void iso15693_add_eof(DigitalSignal* signal, Iso15693SignalDataRate data_rate) {
|
||||
iso15693_add_bit(signal, data_rate, false);
|
||||
|
||||
for(uint32_t i = 0; i < ISO15693_SIGNAL_FC_768 / ISO15693_SIGNAL_FC_256; ++i) {
|
||||
iso15693_add_subcarrier(signal, data_rate);
|
||||
}
|
||||
|
||||
// Not adding silence since it does nothing here
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
iso15693_get_sequence_index(Iso15693SignalIndex index, Iso15693SignalDataRate data_rate) {
|
||||
return index + data_rate * Iso15693SignalIndexNum;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iso15693_add_byte(Iso15693Signal* instance, Iso15693SignalDataRate data_rate, uint8_t byte) {
|
||||
for(size_t i = 0; i < BITS_IN_BYTE; i++) {
|
||||
const uint8_t bit = byte & (1U << i);
|
||||
digital_sequence_add_signal(
|
||||
instance->tx_sequence,
|
||||
iso15693_get_sequence_index(
|
||||
bit ? Iso15693SignalIndexOne : Iso15693SignalIndexZero, data_rate));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iso15693_signal_encode(
|
||||
Iso15693Signal* instance,
|
||||
Iso15693SignalDataRate data_rate,
|
||||
const uint8_t* tx_data,
|
||||
size_t tx_data_size) {
|
||||
digital_sequence_add_signal(
|
||||
instance->tx_sequence, iso15693_get_sequence_index(Iso15693SignalIndexSof, data_rate));
|
||||
|
||||
for(size_t i = 0; i < tx_data_size; i++) {
|
||||
iso15693_add_byte(instance, data_rate, tx_data[i]);
|
||||
}
|
||||
|
||||
digital_sequence_add_signal(
|
||||
instance->tx_sequence, iso15693_get_sequence_index(Iso15693SignalIndexEof, data_rate));
|
||||
}
|
||||
|
||||
static void iso15693_signal_bank_fill(Iso15693Signal* instance, Iso15693SignalDataRate data_rate) {
|
||||
const uint32_t k = data_rate == Iso15693SignalDataRateHi ? ISO15693_SIGNAL_COEFF_HI :
|
||||
ISO15693_SIGNAL_COEFF_LO;
|
||||
DigitalSignal** bank = instance->banks[data_rate];
|
||||
|
||||
bank[Iso15693SignalIndexSof] = digital_signal_alloc(ISO15693_SIGNAL_SOF_EDGES * k);
|
||||
bank[Iso15693SignalIndexEof] = digital_signal_alloc(ISO15693_SIGNAL_EOF_EDGES * k);
|
||||
bank[Iso15693SignalIndexOne] = digital_signal_alloc(ISO15693_SIGNAL_ONE_EDGES * k);
|
||||
bank[Iso15693SignalIndexZero] = digital_signal_alloc(ISO15693_SIGNAL_ZERO_EDGES * k);
|
||||
|
||||
iso15693_add_sof(bank[Iso15693SignalIndexSof], data_rate);
|
||||
iso15693_add_eof(bank[Iso15693SignalIndexEof], data_rate);
|
||||
iso15693_add_bit(bank[Iso15693SignalIndexOne], data_rate, true);
|
||||
iso15693_add_bit(bank[Iso15693SignalIndexZero], data_rate, false);
|
||||
}
|
||||
|
||||
static void
|
||||
iso15693_signal_bank_clear(Iso15693Signal* instance, Iso15693SignalDataRate data_rate) {
|
||||
DigitalSignal** bank = instance->banks[data_rate];
|
||||
|
||||
for(uint32_t i = 0; i < Iso15693SignalIndexNum; ++i) {
|
||||
digital_signal_free(bank[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iso15693_signal_bank_register(Iso15693Signal* instance, Iso15693SignalDataRate data_rate) {
|
||||
for(uint32_t i = 0; i < Iso15693SignalIndexNum; ++i) {
|
||||
digital_sequence_register_signal(
|
||||
instance->tx_sequence,
|
||||
iso15693_get_sequence_index(i, data_rate),
|
||||
instance->banks[data_rate][i]);
|
||||
}
|
||||
}
|
||||
|
||||
Iso15693Signal* iso15693_signal_alloc(const GpioPin* pin) {
|
||||
furi_assert(pin);
|
||||
|
||||
Iso15693Signal* instance = malloc(sizeof(Iso15693Signal));
|
||||
|
||||
instance->tx_sequence = digital_sequence_alloc(BITS_IN_BYTE * 255 + 2, pin);
|
||||
|
||||
for(uint32_t i = 0; i < Iso15693SignalDataRateNum; ++i) {
|
||||
iso15693_signal_bank_fill(instance, i);
|
||||
iso15693_signal_bank_register(instance, i);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void iso15693_signal_free(Iso15693Signal* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
digital_sequence_free(instance->tx_sequence);
|
||||
|
||||
for(uint32_t i = 0; i < Iso15693SignalDataRateNum; ++i) {
|
||||
iso15693_signal_bank_clear(instance, i);
|
||||
}
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void iso15693_signal_tx(
|
||||
Iso15693Signal* instance,
|
||||
Iso15693SignalDataRate data_rate,
|
||||
const uint8_t* tx_data,
|
||||
size_t tx_data_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data_rate < Iso15693SignalDataRateNum);
|
||||
furi_assert(tx_data);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
digital_sequence_clear(instance->tx_sequence);
|
||||
iso15693_signal_encode(instance, data_rate, tx_data, tx_data_size);
|
||||
digital_sequence_transmit(instance->tx_sequence);
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void iso15693_signal_tx_sof(Iso15693Signal* instance, Iso15693SignalDataRate data_rate) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data_rate < Iso15693SignalDataRateNum);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
digital_sequence_clear(instance->tx_sequence);
|
||||
digital_sequence_add_signal(
|
||||
instance->tx_sequence, iso15693_get_sequence_index(Iso15693SignalIndexSof, data_rate));
|
||||
digital_sequence_transmit(instance->tx_sequence);
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file iso15693_signal.h
|
||||
* @brief DigitalSequence preset for generating ISO15693-compliant signals.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_resources.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Iso15693Signal Iso15693Signal;
|
||||
|
||||
/**
|
||||
* @brief Supported data rates.
|
||||
*/
|
||||
typedef enum {
|
||||
Iso15693SignalDataRateHi, /**< High data rate. */
|
||||
Iso15693SignalDataRateLo, /**< Low data rate. */
|
||||
Iso15693SignalDataRateNum, /**< Data rate mode count. Internal use. */
|
||||
} Iso15693SignalDataRate;
|
||||
|
||||
/**
|
||||
* @brief Allocate an Iso15693Signal instance with a set GPIO pin.
|
||||
*
|
||||
* @param[in] pin GPIO pin to use during transmission.
|
||||
* @returns pointer to the allocated instance.
|
||||
*/
|
||||
Iso15693Signal* iso15693_signal_alloc(const GpioPin* pin);
|
||||
|
||||
/**
|
||||
* @brief Delete an Iso15693Signal instance.
|
||||
*
|
||||
* @param[in,out] instance pointer to the instance to be deleted.
|
||||
*/
|
||||
void iso15693_signal_free(Iso15693Signal* instance);
|
||||
|
||||
/**
|
||||
* @brief Transmit arbitrary bytes using an Iso15693Signal instance.
|
||||
* @see Iso15693SignalDataRate
|
||||
*
|
||||
* This function will block until the transmisson has been completed.
|
||||
*
|
||||
* @param[in] instance pointer to the instance used in transmission.
|
||||
* @param[in] data_rate data rate to transmit at.
|
||||
* @param[in] tx_data pointer to the data to be transmitted.
|
||||
* @param[in] tx_data_size size of the data to be transmitted in bytes.
|
||||
*/
|
||||
void iso15693_signal_tx(
|
||||
Iso15693Signal* instance,
|
||||
Iso15693SignalDataRate data_rate,
|
||||
const uint8_t* tx_data,
|
||||
size_t tx_data_size);
|
||||
|
||||
/**
|
||||
* @brief Transmit Start of Frame using an Iso15693Signal instance.
|
||||
* @see Iso15693SignalDataRate
|
||||
*
|
||||
* This function will block until the transmisson has been completed.
|
||||
*
|
||||
* @param[in] instance pointer to the instance used in transmission.
|
||||
* @param[in] data_rate data rate to transmit at.
|
||||
*/
|
||||
void iso15693_signal_tx_sof(Iso15693Signal* instance, Iso15693SignalDataRate data_rate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "st25r3916.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
void st25r3916_mask_irq(FuriHalSpiBusHandle* handle, uint32_t mask) {
|
||||
furi_assert(handle);
|
||||
|
||||
uint8_t irq_mask_regs[4] = {
|
||||
mask & 0xff,
|
||||
(mask >> 8) & 0xff,
|
||||
(mask >> 16) & 0xff,
|
||||
(mask >> 24) & 0xff,
|
||||
};
|
||||
st25r3916_write_burst_regs(handle, ST25R3916_REG_IRQ_MASK_MAIN, irq_mask_regs, 4);
|
||||
}
|
||||
|
||||
uint32_t st25r3916_get_irq(FuriHalSpiBusHandle* handle) {
|
||||
furi_assert(handle);
|
||||
|
||||
uint8_t irq_regs[4] = {};
|
||||
uint32_t irq = 0;
|
||||
st25r3916_read_burst_regs(handle, ST25R3916_REG_IRQ_MASK_MAIN, irq_regs, 4);
|
||||
// FURI_LOG_I(
|
||||
// "Mask Irq", "%02X %02X %02X %02X", irq_regs[0], irq_regs[1], irq_regs[2], irq_regs[3]);
|
||||
st25r3916_read_burst_regs(handle, ST25R3916_REG_IRQ_MAIN, irq_regs, 4);
|
||||
irq = (uint32_t)irq_regs[0];
|
||||
irq |= (uint32_t)irq_regs[1] << 8;
|
||||
irq |= (uint32_t)irq_regs[2] << 16;
|
||||
irq |= (uint32_t)irq_regs[3] << 24;
|
||||
// FURI_LOG_I("iRQ", "%02X %02X %02X %02X", irq_regs[0], irq_regs[1], irq_regs[2], irq_regs[3]);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
void st25r3916_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* buff, size_t bits) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
|
||||
size_t bytes = (bits + 7) / 8;
|
||||
|
||||
st25r3916_write_reg(handle, ST25R3916_REG_NUM_TX_BYTES2, (uint8_t)(bits & 0xFFU));
|
||||
st25r3916_write_reg(handle, ST25R3916_REG_NUM_TX_BYTES1, (uint8_t)((bits >> 8) & 0xFFU));
|
||||
|
||||
st25r3916_reg_write_fifo(handle, buff, bytes);
|
||||
}
|
||||
|
||||
bool st25r3916_read_fifo(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* buff,
|
||||
size_t buff_size,
|
||||
size_t* buff_bits) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
|
||||
bool read_success = false;
|
||||
|
||||
do {
|
||||
uint8_t fifo_status[2] = {};
|
||||
st25r3916_read_burst_regs(handle, ST25R3916_REG_FIFO_STATUS1, fifo_status, 2);
|
||||
size_t bytes = ((fifo_status[1] & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >>
|
||||
ST25R3916_REG_FIFO_STATUS2_fifo_b_shift) |
|
||||
fifo_status[0];
|
||||
uint8_t bits =
|
||||
((fifo_status[1] & ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask) >>
|
||||
ST25R3916_REG_FIFO_STATUS2_fifo_lb_shift);
|
||||
|
||||
if(bytes == 0) break;
|
||||
if(bytes > buff_size) break;
|
||||
|
||||
st25r3916_reg_read_fifo(handle, buff, bytes);
|
||||
|
||||
if(bits) {
|
||||
*buff_bits = (bytes - 1) * 8 + bits;
|
||||
} else {
|
||||
*buff_bits = bytes * 8;
|
||||
}
|
||||
read_success = true;
|
||||
} while(false);
|
||||
|
||||
return read_success;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include "st25r3916_reg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
#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 */
|
||||
|
||||
/** Mask st25r3916 interrupts
|
||||
*
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param mask - mask of interrupts to be disabled
|
||||
*/
|
||||
void st25r3916_mask_irq(FuriHalSpiBusHandle* handle, uint32_t mask);
|
||||
|
||||
/** Get st25r3916 interrupts
|
||||
*
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
*
|
||||
* @return received interrupts
|
||||
*/
|
||||
uint32_t st25r3916_get_irq(FuriHalSpiBusHandle* handle);
|
||||
|
||||
/** Write FIFO
|
||||
*
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param buff - buffer to write to FIFO
|
||||
* @param bits - number of bits to write
|
||||
*/
|
||||
void st25r3916_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* buff, size_t bits);
|
||||
|
||||
/** Read FIFO
|
||||
*
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param buff - buffer to read from FIFO
|
||||
* @param buff_size - buffer size n bytes
|
||||
* @param buff_bits - pointer to number of bits read
|
||||
*
|
||||
* @return true if read success, false otherwise
|
||||
*/
|
||||
bool st25r3916_read_fifo(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* buff,
|
||||
size_t buff_size,
|
||||
size_t* buff_bits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,257 @@
|
||||
#include "st25r3916_reg.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#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_FIFO_DEPTH (512U)
|
||||
#define ST25R3916_BUF_LEN \
|
||||
(ST25R3916_CMD_LEN + \
|
||||
ST25R3916_FIFO_DEPTH) /*!< ST25R3916 communication buffer: CMD + FIFO length */
|
||||
|
||||
static void st25r3916_reg_tx_byte(FuriHalSpiBusHandle* handle, uint8_t byte) {
|
||||
uint8_t val = byte;
|
||||
furi_hal_spi_bus_tx(handle, &val, 1, 5);
|
||||
}
|
||||
|
||||
void st25r3916_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* val) {
|
||||
furi_assert(handle);
|
||||
st25r3916_read_burst_regs(handle, reg, val, 1);
|
||||
}
|
||||
|
||||
void st25r3916_read_burst_regs(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg_start,
|
||||
uint8_t* values,
|
||||
uint8_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(values);
|
||||
furi_assert(length);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
|
||||
if(reg_start & ST25R3916_SPACE_B) {
|
||||
// Send direct command first
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_CMD_SPACE_B_ACCESS);
|
||||
}
|
||||
st25r3916_reg_tx_byte(handle, (reg_start & ~ST25R3916_SPACE_B) | ST25R3916_READ_MODE);
|
||||
furi_hal_spi_bus_rx(handle, values, length, 5);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t val) {
|
||||
furi_assert(handle);
|
||||
uint8_t reg_val = val;
|
||||
st25r3916_write_burst_regs(handle, reg, ®_val, 1);
|
||||
}
|
||||
|
||||
void st25r3916_write_burst_regs(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg_start,
|
||||
const uint8_t* values,
|
||||
uint8_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(values);
|
||||
furi_assert(length);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
|
||||
if(reg_start & ST25R3916_SPACE_B) {
|
||||
// Send direct command first
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_CMD_SPACE_B_ACCESS);
|
||||
}
|
||||
st25r3916_reg_tx_byte(handle, (reg_start & ~ST25R3916_SPACE_B) | ST25R3916_WRITE_MODE);
|
||||
furi_hal_spi_bus_tx(handle, values, length, 5);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_reg_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* buff, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
furi_assert(length);
|
||||
furi_assert(length <= ST25R3916_FIFO_DEPTH);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_FIFO_LOAD);
|
||||
furi_hal_spi_bus_tx(handle, buff, length, 200);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_reg_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
furi_assert(length);
|
||||
furi_assert(length <= ST25R3916_FIFO_DEPTH);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_FIFO_READ);
|
||||
furi_hal_spi_bus_rx(handle, buff, length, 200);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_write_pta_mem(FuriHalSpiBusHandle* handle, const uint8_t* values, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(values);
|
||||
furi_assert(length);
|
||||
furi_assert(length <= ST25R3916_PTM_LEN);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_PT_A_CONFIG_LOAD);
|
||||
furi_hal_spi_bus_tx(handle, values, length, 200);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_read_pta_mem(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
furi_assert(length);
|
||||
furi_assert(length <= ST25R3916_PTM_LEN);
|
||||
|
||||
uint8_t tmp_buff[ST25R3916_PTM_LEN + 1];
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_PT_MEM_READ);
|
||||
furi_hal_spi_bus_rx(handle, tmp_buff, length + 1, 200);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
memcpy(buff, tmp_buff + 1, length);
|
||||
}
|
||||
|
||||
void st25r3916_write_ptf_mem(FuriHalSpiBusHandle* handle, const uint8_t* values, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(values);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_PT_F_CONFIG_LOAD);
|
||||
furi_hal_spi_bus_tx(handle, values, length, 200);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_write_pttsn_mem(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_PT_TSN_DATA_LOAD);
|
||||
furi_hal_spi_bus_tx(handle, buff, length, 200);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_direct_cmd(FuriHalSpiBusHandle* handle, uint8_t cmd) {
|
||||
furi_assert(handle);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, cmd | ST25R3916_CMD_MODE);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_read_test_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* val) {
|
||||
furi_assert(handle);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_CMD_TEST_ACCESS);
|
||||
st25r3916_reg_tx_byte(handle, reg | ST25R3916_READ_MODE);
|
||||
furi_hal_spi_bus_rx(handle, val, 1, 5);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_write_test_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t val) {
|
||||
furi_assert(handle);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_CMD_TEST_ACCESS);
|
||||
st25r3916_reg_tx_byte(handle, reg | ST25R3916_WRITE_MODE);
|
||||
furi_hal_spi_bus_tx(handle, &val, 1, 5);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
}
|
||||
|
||||
void st25r3916_clear_reg_bits(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t clr_mask) {
|
||||
furi_assert(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
st25r3916_read_reg(handle, reg, ®_val);
|
||||
if((reg_val & ~clr_mask) != reg_val) {
|
||||
reg_val &= ~clr_mask;
|
||||
st25r3916_write_reg(handle, reg, reg_val);
|
||||
}
|
||||
}
|
||||
|
||||
void st25r3916_set_reg_bits(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t set_mask) {
|
||||
furi_assert(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
st25r3916_read_reg(handle, reg, ®_val);
|
||||
if((reg_val | set_mask) != reg_val) {
|
||||
reg_val |= set_mask;
|
||||
st25r3916_write_reg(handle, reg, reg_val);
|
||||
}
|
||||
}
|
||||
|
||||
void st25r3916_change_reg_bits(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg,
|
||||
uint8_t mask,
|
||||
uint8_t value) {
|
||||
furi_assert(handle);
|
||||
|
||||
st25r3916_modify_reg(handle, reg, mask, (mask & value));
|
||||
}
|
||||
|
||||
void st25r3916_modify_reg(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg,
|
||||
uint8_t clr_mask,
|
||||
uint8_t set_mask) {
|
||||
furi_assert(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
uint8_t new_val = 0;
|
||||
st25r3916_read_reg(handle, reg, ®_val);
|
||||
new_val = (reg_val & ~clr_mask) | set_mask;
|
||||
if(new_val != reg_val) {
|
||||
st25r3916_write_reg(handle, reg, new_val);
|
||||
}
|
||||
}
|
||||
|
||||
void st25r3916_change_test_reg_bits(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg,
|
||||
uint8_t mask,
|
||||
uint8_t value) {
|
||||
furi_assert(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
uint8_t new_val = 0;
|
||||
st25r3916_read_test_reg(handle, reg, ®_val);
|
||||
new_val = (reg_val & ~mask) | (mask & value);
|
||||
if(new_val != reg_val) {
|
||||
st25r3916_write_test_reg(handle, reg, new_val);
|
||||
}
|
||||
}
|
||||
|
||||
bool st25r3916_check_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t mask, uint8_t val) {
|
||||
furi_assert(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
st25r3916_read_reg(handle, reg, ®_val);
|
||||
return ((reg_val & mask) == val);
|
||||
}
|
||||
@@ -1,262 +1,202 @@
|
||||
#pragma once
|
||||
|
||||
/******************************************************************************
|
||||
* \attention
|
||||
*
|
||||
* <h2><center>© 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include <furi_hal_spi.h>
|
||||
|
||||
/*
|
||||
* PROJECT: ST25R3916 firmware
|
||||
* Revision:
|
||||
* LANGUAGE: ISO C99
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \author Gustavo Patricio
|
||||
*
|
||||
* \brief ST25R3916 communication declaration file
|
||||
*
|
||||
* This driver provides basic abstraction for communication with the ST25R3916
|
||||
*
|
||||
*
|
||||
* \addtogroup RFAL
|
||||
* @{
|
||||
*
|
||||
* \addtogroup RFAL-HAL
|
||||
* \brief RFAL Hardware Abstraction Layer
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ST25R3916
|
||||
* \brief RFAL ST25R3916 Driver
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ST25R3916_COM
|
||||
* \brief RFAL ST25R3916 Communications
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
/** 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 */
|
||||
|
||||
#ifndef ST25R3916_COM_H
|
||||
#define ST25R3916_COM_H
|
||||
#define ST25R3916_SPACE_B 0x40U /** ST25R3916 Space-B indicator */
|
||||
#define ST25R3916_SPACE_B_REG_LEN 16U /** Number of register in the space B */
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* INCLUDES
|
||||
******************************************************************************
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "st_errno.h"
|
||||
#define ST25R3916_FIFO_STATUS_LEN 2 /** Number of FIFO Status Register */
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* GLOBAL DEFINES
|
||||
******************************************************************************
|
||||
*/
|
||||
#define ST25R3916_SPACE_B 0x40U /*!< ST25R3916 Space-B indicator */
|
||||
#define ST25R3916_SPACE_B_REG_LEN 16U /*!< Number of register in the space B */
|
||||
#define ST25R3916_PTM_A_LEN 15U /** Passive target memory A config length */
|
||||
#define ST25R3916_PTM_B_LEN 0U /** Passive target memory B config length */
|
||||
#define ST25R3916_PTM_F_LEN 21U /** Passive target memory F config length */
|
||||
#define ST25R3916_PTM_TSN_LEN 12U /** Passive target memory TSN data length */
|
||||
|
||||
#define ST25R3916_FIFO_STATUS_LEN 2 /*!< Number of FIFO Status Register */
|
||||
|
||||
#define ST25R3916_PTM_A_LEN 15U /*!< Passive target memory A config length */
|
||||
#define ST25R3916_PTM_B_LEN 0U /*!< Passive target memory B config length */
|
||||
#define ST25R3916_PTM_F_LEN 21U /*!< Passive target memory F config length */
|
||||
#define ST25R3916_PTM_TSN_LEN 12U /*!< Passive target memory TSN data length */
|
||||
|
||||
/*! Full Passive target memory length */
|
||||
/** Full Passive target memory length */
|
||||
#define ST25R3916_PTM_LEN \
|
||||
(ST25R3916_PTM_A_LEN + ST25R3916_PTM_B_LEN + ST25R3916_PTM_F_LEN + ST25R3916_PTM_TSN_LEN)
|
||||
|
||||
/* IO configuration registers */
|
||||
#define ST25R3916_REG_IO_CONF1 0x00U /*!< RW IO Configuration Register 1 */
|
||||
#define ST25R3916_REG_IO_CONF2 0x01U /*!< RW IO Configuration Register 2 */
|
||||
/** IO configuration registers */
|
||||
#define ST25R3916_REG_IO_CONF1 0x00U /** RW IO Configuration Register 1 */
|
||||
#define ST25R3916_REG_IO_CONF2 0x01U /** RW IO Configuration Register 2 */
|
||||
|
||||
/* Operation control and mode definition registers */
|
||||
#define ST25R3916_REG_OP_CONTROL 0x02U /*!< RW Operation Control Register */
|
||||
#define ST25R3916_REG_MODE 0x03U /*!< RW Mode Definition Register */
|
||||
#define ST25R3916_REG_BIT_RATE 0x04U /*!< RW Bit Rate Definition Register */
|
||||
/** Operation control and mode definition */
|
||||
#define ST25R3916_REG_OP_CONTROL 0x02U /** RW Operation Control Register */
|
||||
#define ST25R3916_REG_MODE 0x03U /** RW Mode Definition Register */
|
||||
#define ST25R3916_REG_BIT_RATE 0x04U /** RW Bit Rate Definition Register */
|
||||
|
||||
/* Protocol Configuration registers */
|
||||
#define ST25R3916_REG_ISO14443A_NFC \
|
||||
0x05U /*!< RW ISO14443A and NFC 106 kBit/s Settings Register */
|
||||
/** Protocol Configuration registers */
|
||||
#define ST25R3916_REG_ISO14443A_NFC 0x05U /** RW ISO14443A and NFC 106 kBit/s Settings Register */
|
||||
#define ST25R3916_REG_EMD_SUP_CONF \
|
||||
(ST25R3916_SPACE_B | 0x05U) /*!< RW EMD Suppression Configuration Register */
|
||||
#define ST25R3916_REG_ISO14443B_1 \
|
||||
0x06U /*!< RW ISO14443B Settings Register 1 */
|
||||
(ST25R3916_SPACE_B | 0x05U) /*!< RW EMD Suppression Configuration Register */
|
||||
#define ST25R3916_REG_ISO14443B_1 0x06U /** RW ISO14443B Settings Register 1 */
|
||||
#define ST25R3916_REG_SUBC_START_TIME \
|
||||
(ST25R3916_SPACE_B | 0x06U) /*!< RW Subcarrier Start Time Register */
|
||||
#define ST25R3916_REG_ISO14443B_2 \
|
||||
0x07U /*!< RW ISO14443B Settings Register 2 */
|
||||
#define ST25R3916_REG_PASSIVE_TARGET \
|
||||
0x08U /*!< RW Passive Target Definition Register */
|
||||
#define ST25R3916_REG_STREAM_MODE \
|
||||
0x09U /*!< RW Stream Mode Definition Register */
|
||||
#define ST25R3916_REG_AUX 0x0AU /*!< RW Auxiliary Definition Register */
|
||||
(ST25R3916_SPACE_B | 0x06U) /*!< RW Subcarrier Start Time Register */
|
||||
#define ST25R3916_REG_ISO14443B_2 0x07U /** RW ISO14443B Settings Register 2 */
|
||||
#define ST25R3916_REG_PASSIVE_TARGET 0x08U /** RW Passive Target Definition Register */
|
||||
#define ST25R3916_REG_STREAM_MODE 0x09U /** RW Stream Mode Definition Register */
|
||||
#define ST25R3916_REG_AUX 0x0AU /** RW Auxiliary Definition Register */
|
||||
|
||||
/* Receiver Configuration registers */
|
||||
#define ST25R3916_REG_RX_CONF1 0x0BU /*!< RW Receiver Configuration Register 1 */
|
||||
#define ST25R3916_REG_RX_CONF2 0x0CU /*!< RW Receiver Configuration Register 2 */
|
||||
#define ST25R3916_REG_RX_CONF3 0x0DU /*!< RW Receiver Configuration Register 3 */
|
||||
#define ST25R3916_REG_RX_CONF4 0x0EU /*!< RW Receiver Configuration Register 4 */
|
||||
/** Receiver Configuration registers */
|
||||
#define ST25R3916_REG_RX_CONF1 0x0BU /** RW Receiver Configuration Register 1 */
|
||||
#define ST25R3916_REG_RX_CONF2 0x0CU /** RW Receiver Configuration Register 2 */
|
||||
#define ST25R3916_REG_RX_CONF3 0x0DU /** RW Receiver Configuration Register 3 */
|
||||
#define ST25R3916_REG_RX_CONF4 0x0EU /** RW Receiver Configuration Register 4 */
|
||||
#define ST25R3916_REG_P2P_RX_CONF \
|
||||
(ST25R3916_SPACE_B | 0x0BU) /*!< RW P2P Receiver Configuration Register 1 */
|
||||
(ST25R3916_SPACE_B | 0x0BU) /** RW P2P Receiver Configuration Register 1 */
|
||||
#define ST25R3916_REG_CORR_CONF1 \
|
||||
(ST25R3916_SPACE_B | 0x0CU) /*!< RW Correlator configuration register 1 */
|
||||
(ST25R3916_SPACE_B | 0x0CU) /** RW Correlator configuration register 1 */
|
||||
#define ST25R3916_REG_CORR_CONF2 \
|
||||
(ST25R3916_SPACE_B | 0x0DU) /*!< RW Correlator configuration register 2 */
|
||||
(ST25R3916_SPACE_B | 0x0DU) /** RW Correlator configuration register 2 */
|
||||
|
||||
/* Timer definition registers */
|
||||
#define ST25R3916_REG_MASK_RX_TIMER \
|
||||
0x0FU /*!< RW Mask Receive Timer Register */
|
||||
#define ST25R3916_REG_NO_RESPONSE_TIMER1 \
|
||||
0x10U /*!< RW No-response Timer Register 1 */
|
||||
#define ST25R3916_REG_NO_RESPONSE_TIMER2 \
|
||||
0x11U /*!< RW No-response Timer Register 2 */
|
||||
#define ST25R3916_REG_TIMER_EMV_CONTROL \
|
||||
0x12U /*!< RW Timer and EMV Control */
|
||||
#define ST25R3916_REG_GPT1 0x13U /*!< RW General Purpose Timer Register 1 */
|
||||
#define ST25R3916_REG_GPT2 0x14U /*!< RW General Purpose Timer Register 2 */
|
||||
#define ST25R3916_REG_PPON2 0x15U /*!< RW PPON2 Field waiting Timer Register */
|
||||
#define ST25R3916_REG_SQUELCH_TIMER \
|
||||
(ST25R3916_SPACE_B | 0x0FU) /*!< RW Squelch timeout Register */
|
||||
#define ST25R3916_REG_FIELD_ON_GT \
|
||||
(ST25R3916_SPACE_B | 0x15U) /*!< RW NFC Field on guard time */
|
||||
/** Timer definition registers */
|
||||
#define ST25R3916_REG_MASK_RX_TIMER 0x0FU /** RW Mask Receive Timer Register */
|
||||
#define ST25R3916_REG_NO_RESPONSE_TIMER1 0x10U /** RW No-response Timer Register 1 */
|
||||
#define ST25R3916_REG_NO_RESPONSE_TIMER2 0x11U /** RW No-response Timer Register 2 */
|
||||
#define ST25R3916_REG_TIMER_EMV_CONTROL 0x12U /** RW Timer and EMV Control */
|
||||
#define ST25R3916_REG_GPT1 0x13U /** RW General Purpose Timer Register 1 */
|
||||
#define ST25R3916_REG_GPT2 0x14U /** RW General Purpose Timer Register 2 */
|
||||
#define ST25R3916_REG_PPON2 0x15U /** RW PPON2 Field waiting Timer Register */
|
||||
#define ST25R3916_REG_SQUELCH_TIMER (ST25R3916_SPACE_B | 0x0FU) /** RW Squelch timeout Register */
|
||||
#define ST25R3916_REG_FIELD_ON_GT (ST25R3916_SPACE_B | 0x15U) /** RW NFC Field on guard time */
|
||||
|
||||
/* Interrupt and associated reporting registers */
|
||||
#define ST25R3916_REG_IRQ_MASK_MAIN \
|
||||
0x16U /*!< RW Mask Main Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_MASK_TIMER_NFC \
|
||||
0x17U /*!< RW Mask Timer and NFC Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_MASK_ERROR_WUP \
|
||||
0x18U /*!< RW Mask Error and Wake-up Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_MASK_TARGET \
|
||||
0x19U /*!< RW Mask 3916 Target Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_MAIN 0x1AU /*!< R Main Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_TIMER_NFC \
|
||||
0x1BU /*!< R Timer and NFC Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_ERROR_WUP \
|
||||
0x1CU /*!< R Error and Wake-up Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_TARGET 0x1DU /*!< R ST25R3916 Target Interrupt Register */
|
||||
#define ST25R3916_REG_FIFO_STATUS1 \
|
||||
0x1EU /*!< R FIFO Status Register 1 */
|
||||
#define ST25R3916_REG_FIFO_STATUS2 \
|
||||
0x1FU /*!< R FIFO Status Register 2 */
|
||||
#define ST25R3916_REG_COLLISION_STATUS \
|
||||
0x20U /*!< R Collision Display Register */
|
||||
#define ST25R3916_REG_PASSIVE_TARGET_STATUS \
|
||||
0x21U /*!< R Passive target state status */
|
||||
/** Interrupt and associated reporting registers */
|
||||
#define ST25R3916_REG_IRQ_MASK_MAIN 0x16U /** RW Mask Main Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_MASK_TIMER_NFC 0x17U /** RW Mask Timer and NFC Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_MASK_ERROR_WUP 0x18U /** RW Mask Error and Wake-up Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_MASK_TARGET 0x19U /** RW Mask 3916 Target Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_MAIN 0x1AU /** R Main Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_TIMER_NFC 0x1BU /** R Timer and NFC Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_ERROR_WUP 0x1CU /** R Error and Wake-up Interrupt Register */
|
||||
#define ST25R3916_REG_IRQ_TARGET 0x1DU /*!< R ST25R3916 Target Interrupt Register */
|
||||
#define ST25R3916_REG_FIFO_STATUS1 0x1EU /** R FIFO Status Register 1 */
|
||||
#define ST25R3916_REG_FIFO_STATUS2 0x1FU /** R FIFO Status Register 2 */
|
||||
#define ST25R3916_REG_COLLISION_STATUS 0x20U /** R Collision Display Register */
|
||||
#define ST25R3916_REG_PASSIVE_TARGET_STATUS 0x21U /** R Passive target state status */
|
||||
|
||||
/* Definition of number of transmitted bytes */
|
||||
#define ST25R3916_REG_NUM_TX_BYTES1 \
|
||||
0x22U /*!< RW Number of Transmitted Bytes Register 1 */
|
||||
#define ST25R3916_REG_NUM_TX_BYTES2 \
|
||||
0x23U /*!< RW Number of Transmitted Bytes Register 2 */
|
||||
/** Definition of number of transmitted bytes */
|
||||
#define ST25R3916_REG_NUM_TX_BYTES1 0x22U /** RW Number of Transmitted Bytes Register 1 */
|
||||
#define ST25R3916_REG_NUM_TX_BYTES2 0x23U /** RW Number of Transmitted Bytes Register 2 */
|
||||
|
||||
/* NFCIP Bit Rate Display Register */
|
||||
#define ST25R3916_REG_NFCIP1_BIT_RATE \
|
||||
0x24U /*!< R NFCIP Bit Rate Detection Display Register */
|
||||
/** NFCIP Bit Rate Display Register */
|
||||
#define ST25R3916_REG_NFCIP1_BIT_RATE 0x24U /** R NFCIP Bit Rate Detection Display Register */
|
||||
|
||||
/* A/D Converter Output Register */
|
||||
#define ST25R3916_REG_AD_RESULT 0x25U /*!< R A/D Converter Output Register */
|
||||
/** A/D Converter Output Register */
|
||||
#define ST25R3916_REG_AD_RESULT 0x25U /** R A/D Converter Output Register */
|
||||
|
||||
/* Antenna tuning registers */
|
||||
#define ST25R3916_REG_ANT_TUNE_A 0x26U /*!< RW Antenna Tuning Control (AAT-A) Register 1 */
|
||||
#define ST25R3916_REG_ANT_TUNE_B 0x27U /*!< RW Antenna Tuning Control (AAT-B) Register 2 */
|
||||
/** Antenna tuning registers */
|
||||
#define ST25R3916_REG_ANT_TUNE_A 0x26U /** RW Antenna Tuning Control (AAT-A) Register 1 */
|
||||
#define ST25R3916_REG_ANT_TUNE_B 0x27U /** RW Antenna Tuning Control (AAT-B) Register 2 */
|
||||
|
||||
/* Antenna Driver and Modulation registers */
|
||||
#define ST25R3916_REG_TX_DRIVER 0x28U /*!< RW TX driver register */
|
||||
#define ST25R3916_REG_PT_MOD 0x29U /*!< RW PT modulation Register */
|
||||
#define ST25R3916_REG_AUX_MOD \
|
||||
(ST25R3916_SPACE_B | 0x28U) /*!< RW Aux Modulation setting Register */
|
||||
/** Antenna Driver and Modulation registers */
|
||||
#define ST25R3916_REG_TX_DRIVER 0x28U /** RW TX driver register */
|
||||
#define ST25R3916_REG_PT_MOD 0x29U /** RW PT modulation Register */
|
||||
#define ST25R3916_REG_AUX_MOD (ST25R3916_SPACE_B | 0x28U) /** RW Aux Modulation setting Register */
|
||||
#define ST25R3916_REG_TX_DRIVER_TIMING \
|
||||
(ST25R3916_SPACE_B | 0x29U) /*!< RW TX driver timing Register */
|
||||
(ST25R3916_SPACE_B | 0x29U) /** RW TX driver timing Register */
|
||||
#define ST25R3916_REG_RES_AM_MOD \
|
||||
(ST25R3916_SPACE_B | 0x2AU) /*!< RW Resistive AM modulation register */
|
||||
(ST25R3916_SPACE_B | 0x2AU) /** RW Resistive AM modulation register */
|
||||
#define ST25R3916_REG_TX_DRIVER_STATUS \
|
||||
(ST25R3916_SPACE_B | 0x2BU) /*!< R TX driver timing readout Register */
|
||||
(ST25R3916_SPACE_B | 0x2BU) /** R TX driver timing readout Register */
|
||||
|
||||
/* External Field Detector Threshold Registers */
|
||||
/** External Field Detector Threshold Registers */
|
||||
#define ST25R3916_REG_FIELD_THRESHOLD_ACTV \
|
||||
0x2AU /*!< RW External Field Detector Activation Threshold Reg */
|
||||
0x2AU /** RW External Field Detector Activation Threshold Reg */
|
||||
#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV \
|
||||
0x2BU /*!< RW External Field Detector Deactivation Threshold Reg*/
|
||||
0x2BU /** RW External Field Detector Deactivation Threshold Reg */
|
||||
|
||||
/* Regulator registers */
|
||||
#define ST25R3916_REG_REGULATOR_CONTROL \
|
||||
0x2CU /*!< RW Regulated Voltage Control Register */
|
||||
/** Regulator registers */
|
||||
#define ST25R3916_REG_REGULATOR_CONTROL 0x2CU /** RW Regulated Voltage Control Register */
|
||||
#define ST25R3916_REG_REGULATOR_RESULT \
|
||||
(ST25R3916_SPACE_B | 0x2CU) /*!< R Regulator Display Register */
|
||||
(ST25R3916_SPACE_B | 0x2CU) /** R Regulator Display Register */
|
||||
|
||||
/* Receiver State Display Register */
|
||||
#define ST25R3916_REG_RSSI_RESULT \
|
||||
0x2DU /*!< R RSSI Display Register */
|
||||
#define ST25R3916_REG_GAIN_RED_STATE \
|
||||
0x2EU /*!< R Gain Reduction State Register */
|
||||
#define ST25R3916_REG_CAP_SENSOR_CONTROL \
|
||||
0x2FU /*!< RW Capacitive Sensor Control Register */
|
||||
#define ST25R3916_REG_CAP_SENSOR_RESULT \
|
||||
0x30U /*!< R Capacitive Sensor Display Register */
|
||||
#define ST25R3916_REG_AUX_DISPLAY \
|
||||
0x31U /*!< R Auxiliary Display Register */
|
||||
/** Receiver State Display Register */
|
||||
#define ST25R3916_REG_RSSI_RESULT 0x2DU /** R RSSI Display Register */
|
||||
#define ST25R3916_REG_GAIN_RED_STATE 0x2EU /** R Gain Reduction State Register */
|
||||
#define ST25R3916_REG_CAP_SENSOR_CONTROL 0x2FU /** RW Capacitive Sensor Control Register */
|
||||
#define ST25R3916_REG_CAP_SENSOR_RESULT 0x30U /** R Capacitive Sensor Display Register */
|
||||
#define ST25R3916_REG_AUX_DISPLAY 0x31U /** R Auxiliary Display Register */
|
||||
|
||||
/* Over/Undershoot Protection Configuration Registers */
|
||||
/** Over/Undershoot Protection Configuration Registers */
|
||||
#define ST25R3916_REG_OVERSHOOT_CONF1 \
|
||||
(ST25R3916_SPACE_B | 0x30U) /*!< RW Overshoot Protection Configuration Register 1 */
|
||||
(ST25R3916_SPACE_B | 0x30U) /** RW Overshoot Protection Configuration Register 1 */
|
||||
#define ST25R3916_REG_OVERSHOOT_CONF2 \
|
||||
(ST25R3916_SPACE_B | 0x31U) /*!< RW Overshoot Protection Configuration Register 2 */
|
||||
(ST25R3916_SPACE_B | 0x31U) /** RW Overshoot Protection Configuration Register 2 */
|
||||
#define ST25R3916_REG_UNDERSHOOT_CONF1 \
|
||||
(ST25R3916_SPACE_B | 0x32U) /*!< RW Undershoot Protection Configuration Register 1 */
|
||||
(ST25R3916_SPACE_B | 0x32U) /** RW Undershoot Protection Configuration Register 1 */
|
||||
#define ST25R3916_REG_UNDERSHOOT_CONF2 \
|
||||
(ST25R3916_SPACE_B | 0x33U) /*!< RW Undershoot Protection Configuration Register 2 */
|
||||
(ST25R3916_SPACE_B | 0x33U) /** RW Undershoot Protection Configuration Register 2 */
|
||||
|
||||
/* Detection of card presence */
|
||||
#define ST25R3916_REG_WUP_TIMER_CONTROL \
|
||||
0x32U /*!< RW Wake-up Timer Control Register */
|
||||
/** Detection of card presence */
|
||||
#define ST25R3916_REG_WUP_TIMER_CONTROL 0x32U /** RW Wake-up Timer Control Register */
|
||||
#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF \
|
||||
0x33U /*!< RW Amplitude Measurement Configuration Register */
|
||||
0x33U /** RW Amplitude Measurement Configuration Register */
|
||||
#define ST25R3916_REG_AMPLITUDE_MEASURE_REF \
|
||||
0x34U /*!< RW Amplitude Measurement Reference Register */
|
||||
0x34U /** RW Amplitude Measurement Reference Register */
|
||||
#define ST25R3916_REG_AMPLITUDE_MEASURE_AA_RESULT \
|
||||
0x35U /*!< R Amplitude Measurement Auto Averaging Display Reg */
|
||||
0x35U /** R Amplitude Measurement Auto Averaging Display Reg */
|
||||
#define ST25R3916_REG_AMPLITUDE_MEASURE_RESULT \
|
||||
0x36U /*!< R Amplitude Measurement Display Register */
|
||||
#define ST25R3916_REG_PHASE_MEASURE_CONF \
|
||||
0x37U /*!< RW Phase Measurement Configuration Register */
|
||||
#define ST25R3916_REG_PHASE_MEASURE_REF \
|
||||
0x38U /*!< RW Phase Measurement Reference Register */
|
||||
0x36U /** R Amplitude Measurement Display Register */
|
||||
#define ST25R3916_REG_PHASE_MEASURE_CONF 0x37U /** RW Phase Measurement Configuration Register */
|
||||
#define ST25R3916_REG_PHASE_MEASURE_REF 0x38U /** RW Phase Measurement Reference Register */
|
||||
#define ST25R3916_REG_PHASE_MEASURE_AA_RESULT \
|
||||
0x39U /*!< R Phase Measurement Auto Averaging Display Register */
|
||||
#define ST25R3916_REG_PHASE_MEASURE_RESULT \
|
||||
0x3AU /*!< R Phase Measurement Display Register */
|
||||
0x39U /** R Phase Measurement Auto Averaging Display */
|
||||
#define ST25R3916_REG_PHASE_MEASURE_RESULT 0x3AU /** R Phase Measurement Display Register */
|
||||
#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF \
|
||||
0x3BU /*!< RW Capacitance Measurement Configuration Register */
|
||||
0x3BU /** RW Capacitance Measurement Configuration Register */
|
||||
#define ST25R3916_REG_CAPACITANCE_MEASURE_REF \
|
||||
0x3CU /*!< RW Capacitance Measurement Reference Register */
|
||||
0x3CU /** RW Capacitance Measurement Reference Register */
|
||||
#define ST25R3916_REG_CAPACITANCE_MEASURE_AA_RESULT \
|
||||
0x3DU /*!< R Capacitance Measurement Auto Averaging Display Reg*/
|
||||
0x3DU /** R Capacitance Measurement Auto Averaging Display Reg */
|
||||
#define ST25R3916_REG_CAPACITANCE_MEASURE_RESULT \
|
||||
0x3EU /*!< R Capacitance Measurement Display Register */
|
||||
0x3EU /** R Capacitance Measurement Display Register */
|
||||
|
||||
/* IC identity */
|
||||
#define ST25R3916_REG_IC_IDENTITY \
|
||||
0x3FU /*!< R Chip Id: 0 for old silicon, v2 silicon: 0x09 */
|
||||
/** IC identity */
|
||||
#define ST25R3916_REG_IC_IDENTITY 0x3FU /** R Chip Id: 0 for old silicon, v2 silicon: 0x09 */
|
||||
|
||||
/*! Register bit definitions \cond DOXYGEN_SUPRESS */
|
||||
/** Register bit definitions */
|
||||
|
||||
#define ST25R3916_REG_IO_CONF1_single (1U << 7)
|
||||
#define ST25R3916_REG_IO_CONF1_rfo2 (1U << 6)
|
||||
@@ -1021,364 +961,184 @@
|
||||
#define ST25R3916_REG_IC_IDENTITY_ic_rev_mask (7U << 0)
|
||||
#define ST25R3916_REG_IC_IDENTITY_ic_rev_shift (0U)
|
||||
|
||||
/*! \endcond DOXYGEN_SUPRESS */
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* GLOBAL FUNCTION PROTOTYPES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Returns the content of a register within the ST25R3916
|
||||
/** Read register
|
||||
*
|
||||
* This function is used to read out the content of ST25R3916 registers.
|
||||
*
|
||||
* \param[in] reg: Address of register to read.
|
||||
* \param[out] val: Returned value.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer t FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param val - pointer to the variable to store the read value
|
||||
*/
|
||||
ReturnCode st25r3916ReadRegister(uint8_t reg, uint8_t* val);
|
||||
void st25r3916_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* val);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Reads from multiple ST25R3916 registers
|
||||
/** Read multiple registers
|
||||
*
|
||||
* This function is used to read from multiple registers using the
|
||||
* auto-increment feature. That is, after each read the address pointer
|
||||
* inside the ST25R3916 gets incremented automatically.
|
||||
*
|
||||
* \param[in] reg: Address of the first register to read from.
|
||||
* \param[in] values: pointer to a buffer where the result shall be written to.
|
||||
* \param[in] length: Number of registers to be read out.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg_start - start register address
|
||||
* @param values - pointer to the buffer to store the read values
|
||||
* @param length - number of registers to read
|
||||
*/
|
||||
ReturnCode st25r3916ReadMultipleRegisters(uint8_t reg, uint8_t* values, uint8_t length);
|
||||
void st25r3916_read_burst_regs(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg_start,
|
||||
uint8_t* values,
|
||||
uint8_t length);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Writes a given value to a register within the ST25R3916
|
||||
/** Write register
|
||||
*
|
||||
* This function is used to write \a val to address \a reg within the ST25R3916.
|
||||
*
|
||||
* \param[in] reg: Address of the register to write.
|
||||
* \param[in] val: Value to be written.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param val - value to write
|
||||
*/
|
||||
ReturnCode st25r3916WriteRegister(uint8_t reg, uint8_t val);
|
||||
void st25r3916_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t val);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Writes multiple values to ST25R3916 registers
|
||||
/** Write multiple registers
|
||||
*
|
||||
* This function is used to write multiple values to the ST25R3916 using the
|
||||
* auto-increment feature. That is, after each write the address pointer
|
||||
* inside the ST25R3916 gets incremented automatically.
|
||||
*
|
||||
* \param[in] reg: Address of the first register to write.
|
||||
* \param[in] values: pointer to a buffer containing the values to be written.
|
||||
* \param[in] length: Number of values to be written.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg_start - start register address
|
||||
* @param values - pointer to buffer to write
|
||||
* @param length - number of registers to write
|
||||
*/
|
||||
ReturnCode st25r3916WriteMultipleRegisters(uint8_t reg, const uint8_t* values, uint8_t length);
|
||||
void st25r3916_write_burst_regs(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg_start,
|
||||
const uint8_t* values,
|
||||
uint8_t length);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Writes values to ST25R3916 FIFO
|
||||
/** Write fifo register
|
||||
*
|
||||
* This function needs to be called in order to write to the ST25R3916 FIFO.
|
||||
*
|
||||
* \param[in] values: pointer to a buffer containing the values to be written
|
||||
* to the FIFO.
|
||||
* \param[in] length: Number of values to be written.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param buff - buffer to write to FIFO
|
||||
* @param length - number of bytes to write
|
||||
*/
|
||||
ReturnCode st25r3916WriteFifo(const uint8_t* values, uint16_t length);
|
||||
void st25r3916_reg_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* buff, size_t length);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Read values from ST25R3916 FIFO
|
||||
/** Read fifo register
|
||||
*
|
||||
* This function needs to be called in order to read from ST25R3916 FIFO.
|
||||
*
|
||||
* \param[out] buf: pointer to a buffer where the FIFO content shall be
|
||||
* written to.
|
||||
* \param[in] length: Number of bytes to read.
|
||||
*
|
||||
* \note: This function doesn't check whether \a length is really the
|
||||
* number of available bytes in FIFO
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param buff - buffer to store the read values
|
||||
* @param length - number of bytes to read
|
||||
*/
|
||||
ReturnCode st25r3916ReadFifo(uint8_t* buf, uint16_t length);
|
||||
void st25r3916_reg_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t length);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Writes values to ST25R3916 PTM
|
||||
/** Write PTA memory register
|
||||
*
|
||||
* Accesses to the begging of ST25R3916 Passive Target Memory (PTM A Config)
|
||||
* and writes the given values
|
||||
*
|
||||
* \param[in] values: pointer to a buffer containing the values to be written
|
||||
* to the Passive Target Memory.
|
||||
* \param[in] length: Number of values to be written.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param values - pointer to buffer to write
|
||||
* @param length - number of bytes to write
|
||||
*/
|
||||
ReturnCode st25r3916WritePTMem(const uint8_t* values, uint16_t length);
|
||||
void st25r3916_write_pta_mem(FuriHalSpiBusHandle* handle, const uint8_t* values, size_t length);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Reads the ST25R3916 PTM
|
||||
/** Read PTA memory register
|
||||
*
|
||||
* Accesses to the begging of ST25R3916 Passive Target Memory (PTM A Config)
|
||||
* and reads the memory for the given length
|
||||
*
|
||||
* \param[out] values: pointer to a buffer where the PTM content shall be
|
||||
* written to.
|
||||
* \param[in] length: Number of bytes to read.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param values - buffer to store the read values
|
||||
* @param length - number of bytes to read
|
||||
*/
|
||||
ReturnCode st25r3916ReadPTMem(uint8_t* values, uint16_t length);
|
||||
void st25r3916_read_pta_mem(FuriHalSpiBusHandle* handle, uint8_t* values, size_t length);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Writes values to ST25R3916 PTM F config
|
||||
/** Write PTF memory register
|
||||
*
|
||||
* Accesses ST25R3916 Passive Target Memory F config and writes the given values
|
||||
*
|
||||
* \param[in] values: pointer to a buffer containing the values to be written
|
||||
* to the Passive Target Memory
|
||||
* \param[in] length: Number of values to be written.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param values - pointer to buffer to write
|
||||
* @param length - number of bytes to write
|
||||
*/
|
||||
ReturnCode st25r3916WritePTMemF(const uint8_t* values, uint16_t length);
|
||||
void st25r3916_write_ptf_mem(FuriHalSpiBusHandle* handle, const uint8_t* values, size_t length);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Writes values to ST25R3916 PTM TSN Data
|
||||
/** Read PTTSN memory register
|
||||
*
|
||||
* Accesses ST25R3916 Passive Target Memory TSN data and writes the given values
|
||||
*
|
||||
* \param[in] values: pointer to a buffer containing the values to be written
|
||||
* to the Passive Target Memory.
|
||||
* \param[in] length: Number of values to be written.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param values - pointer to buffer to write
|
||||
* @param length - number of bytes to write
|
||||
*/
|
||||
ReturnCode st25r3916WritePTMemTSN(const uint8_t* values, uint16_t length);
|
||||
void st25r3916_write_pttsn_mem(FuriHalSpiBusHandle* handle, uint8_t* values, size_t length);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Execute a direct command
|
||||
/** Send Direct command
|
||||
*
|
||||
* This function is used to start so-called direct command. These commands
|
||||
* are implemented inside the chip and each command has unique code (see
|
||||
* datasheet).
|
||||
*
|
||||
* \param[in] cmd : code of the direct command to be executed.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param cmd - direct command
|
||||
*/
|
||||
ReturnCode st25r3916ExecuteCommand(uint8_t cmd);
|
||||
void st25r3916_direct_cmd(FuriHalSpiBusHandle* handle, uint8_t cmd);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Read a test register within the ST25R3916
|
||||
*
|
||||
* This function is used to read the content of test address \a reg within the ST25R3916
|
||||
*
|
||||
* \param[in] reg: Address of the register to read
|
||||
* \param[out] val: Returned read value
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
/** Read test register
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param val - pointer to the variable to store the read value
|
||||
*/
|
||||
ReturnCode st25r3916ReadTestRegister(uint8_t reg, uint8_t* val);
|
||||
void st25r3916_read_test_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* val);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Writes a given value to a test register within the ST25R3916
|
||||
/** Write test register
|
||||
*
|
||||
* This function is used to write \a val to test address \a reg within the ST25R3916
|
||||
*
|
||||
* \param[in] reg: Address of the register to write
|
||||
* \param[in] val: Value to be written
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param val - value to write
|
||||
*/
|
||||
ReturnCode st25r3916WriteTestRegister(uint8_t reg, uint8_t val);
|
||||
void st25r3916_write_test_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t val);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Cleart bits on Register
|
||||
/** Clear register bits
|
||||
*
|
||||
* This function clears the given bitmask on the register
|
||||
*
|
||||
* \param[in] reg: Address of the register clear
|
||||
* \param[in] clr_mask: Bitmask of bit to be cleared
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param clr_mask - bit mask to clear
|
||||
*/
|
||||
ReturnCode st25r3916ClrRegisterBits(uint8_t reg, uint8_t clr_mask);
|
||||
void st25r3916_clear_reg_bits(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t clr_mask);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Set bits on Register
|
||||
/** Set register bits
|
||||
*
|
||||
* This function sets the given bitmask on the register
|
||||
*
|
||||
* \param[in] reg: Address of the register clear
|
||||
* \param[in] set_mask: Bitmask of bit to be cleared
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param set_mask - bit mask to set
|
||||
*/
|
||||
ReturnCode st25r3916SetRegisterBits(uint8_t reg, uint8_t set_mask);
|
||||
void st25r3916_set_reg_bits(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t set_mask);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Changes the given bits on a ST25R3916 register
|
||||
/** Change register bits
|
||||
*
|
||||
* This function is used if only a particular bits should be changed within
|
||||
* an ST25R3916 register.
|
||||
*
|
||||
* \param[in] reg: Address of the register to change.
|
||||
* \param[in] valueMask: bitmask of bits to be changed
|
||||
* \param[in] value: the bits to be written on the enabled valueMask bits
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param mask - bit mask to change
|
||||
* @param value - new register value to write
|
||||
*/
|
||||
ReturnCode st25r3916ChangeRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value);
|
||||
void st25r3916_change_reg_bits(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg,
|
||||
uint8_t mask,
|
||||
uint8_t value);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Modifies a value within a ST25R3916 register
|
||||
/** Modify register
|
||||
*
|
||||
* This function is used if only a particular bits should be changed within
|
||||
* an ST25R3916 register.
|
||||
*
|
||||
* \param[in] reg: Address of the register to write.
|
||||
* \param[in] clr_mask: bitmask of bits to be cleared to 0.
|
||||
* \param[in] set_mask: bitmask of bits to be set to 1.
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param clr_mask - bit mask to clear
|
||||
* @param set_mask - bit mask to set
|
||||
*/
|
||||
ReturnCode st25r3916ModifyRegister(uint8_t reg, uint8_t clr_mask, uint8_t set_mask);
|
||||
void st25r3916_modify_reg(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg,
|
||||
uint8_t clr_mask,
|
||||
uint8_t set_mask);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Changes the given bits on a ST25R3916 Test register
|
||||
/** Change test register bits
|
||||
*
|
||||
* This function is used if only a particular bits should be changed within
|
||||
* an ST25R3916 register.
|
||||
*
|
||||
* \param[in] reg: Address of the Test register to change.
|
||||
* \param[in] valueMask: bitmask of bits to be changed
|
||||
* \param[in] value: the bits to be written on the enabled valueMask bits
|
||||
*
|
||||
* \return ERR_NONE : Operation successful
|
||||
* \return ERR_PARAM : Invalid parameter
|
||||
* \return ERR_SEND : Transmission error or acknowledge not received
|
||||
*****************************************************************************
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param mask - bit mask to change
|
||||
* @param value - new register value to write
|
||||
*/
|
||||
ReturnCode st25r3916ChangeTestRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value);
|
||||
void st25r3916_change_test_reg_bits(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t reg,
|
||||
uint8_t mask,
|
||||
uint8_t value);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Checks if register contains a expected value
|
||||
/** Check register
|
||||
*
|
||||
* This function checks if the given reg contains a value that once masked
|
||||
* equals the expected value
|
||||
* @param handle - pointer to FuriHalSpiBusHandle instance
|
||||
* @param reg - register address
|
||||
* @param mask - bit mask to check
|
||||
* @param val - expected register value
|
||||
*
|
||||
* \param reg : the register to check the value
|
||||
* \param mask : the mask apply on register value
|
||||
* \param val : expected value to be compared to
|
||||
*
|
||||
* \return true when reg contains the expected value | false otherwise
|
||||
* @return true if register value matches the expected value, false otherwise
|
||||
*/
|
||||
bool st25r3916CheckReg(uint8_t reg, uint8_t mask, uint8_t val);
|
||||
bool st25r3916_check_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t mask, uint8_t val);
|
||||
|
||||
/*!
|
||||
*****************************************************************************
|
||||
* \brief Check if register ID is valid
|
||||
*
|
||||
* Checks if the given register ID a valid ST25R3916 register
|
||||
*
|
||||
* \param[in] reg: Address of register to check
|
||||
*
|
||||
* \return true if is a valid register ID
|
||||
* \return false otherwise
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
bool st25r3916IsRegValid(uint8_t reg);
|
||||
|
||||
#endif /* ST25R3916_COM_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -15,6 +15,9 @@ env.Append(
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("micro-ecc/uECC.h"),
|
||||
File("nanopb/pb.h"),
|
||||
File("nanopb/pb_decode.h"),
|
||||
File("nanopb/pb_encode.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+40
-7
@@ -5,20 +5,53 @@ env.Append(
|
||||
"#/lib/nfc",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
# Main
|
||||
File("nfc.h"),
|
||||
File("nfc_device.h"),
|
||||
File("nfc_worker.h"),
|
||||
File("nfc_types.h"),
|
||||
File("helpers/mfkey32.h"),
|
||||
File("parsers/nfc_supported_card.h"),
|
||||
File("helpers/nfc_generators.h"),
|
||||
File("protocols/nfc_util.h"),
|
||||
File("nfc_listener.h"),
|
||||
File("nfc_poller.h"),
|
||||
File("nfc_scanner.h"),
|
||||
# Protocols
|
||||
File("protocols/iso14443_3a/iso14443_3a.h"),
|
||||
File("protocols/iso14443_3b/iso14443_3b.h"),
|
||||
File("protocols/iso14443_4a/iso14443_4a.h"),
|
||||
File("protocols/iso14443_4b/iso14443_4b.h"),
|
||||
File("protocols/mf_ultralight/mf_ultralight.h"),
|
||||
File("protocols/mf_classic/mf_classic.h"),
|
||||
File("protocols/mf_desfire/mf_desfire.h"),
|
||||
File("protocols/slix/slix.h"),
|
||||
File("protocols/st25tb/st25tb.h"),
|
||||
# Pollers
|
||||
File("protocols/iso14443_3a/iso14443_3a_poller.h"),
|
||||
File("protocols/iso14443_3b/iso14443_3b_poller.h"),
|
||||
File("protocols/iso14443_4a/iso14443_4a_poller.h"),
|
||||
File("protocols/iso14443_4b/iso14443_4b_poller.h"),
|
||||
File("protocols/mf_ultralight/mf_ultralight_poller.h"),
|
||||
File("protocols/mf_classic/mf_classic_poller.h"),
|
||||
File("protocols/mf_desfire/mf_desfire_poller.h"),
|
||||
File("protocols/st25tb/st25tb_poller.h"),
|
||||
# Listeners
|
||||
File("protocols/iso14443_3a/iso14443_3a_listener.h"),
|
||||
File("protocols/iso14443_4a/iso14443_4a_listener.h"),
|
||||
File("protocols/mf_ultralight/mf_ultralight_listener.h"),
|
||||
File("protocols/mf_classic/mf_classic_listener.h"),
|
||||
# Sync API
|
||||
File("protocols/iso14443_3a/iso14443_3a_poller_sync_api.h"),
|
||||
File("protocols/mf_ultralight/mf_ultralight_poller_sync_api.h"),
|
||||
File("protocols/mf_classic/mf_classic_poller_sync_api.h"),
|
||||
# Misc
|
||||
File("helpers/nfc_util.h"),
|
||||
File("helpers/iso14443_crc.h"),
|
||||
File("helpers/iso13239_crc.h"),
|
||||
File("helpers/nfc_data_generator.h"),
|
||||
File("helpers/nfc_dict.h"),
|
||||
],
|
||||
)
|
||||
|
||||
libenv = env.Clone(FW_LIB_NAME="nfc")
|
||||
libenv.ApplyLibFlags()
|
||||
|
||||
sources = libenv.GlobRecursive("*.c*")
|
||||
sources = libenv.GlobRecursive("*.c*", exclude="deprecated/*c")
|
||||
|
||||
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
|
||||
libenv.Install("${LIB_DIST_DIR}", lib)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "felica_crc.h"
|
||||
|
||||
#include <furi/furi.h>
|
||||
|
||||
#define FELICA_CRC_POLY (0x1021U) // Polynomial: x^16 + x^12 + x^5 + 1
|
||||
#define FELICA_CRC_INIT (0x0000U)
|
||||
|
||||
uint16_t felica_crc_calculate(const uint8_t* data, size_t length) {
|
||||
uint16_t crc = FELICA_CRC_INIT;
|
||||
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
crc ^= ((uint16_t)data[i] << 8);
|
||||
for(size_t j = 0; j < 8; j++) {
|
||||
if(crc & 0x8000) {
|
||||
crc <<= 1;
|
||||
crc ^= FELICA_CRC_POLY;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (crc << 8) | (crc >> 8);
|
||||
}
|
||||
|
||||
void felica_crc_append(BitBuffer* buf) {
|
||||
const uint8_t* data = bit_buffer_get_data(buf);
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
|
||||
const uint16_t crc = felica_crc_calculate(data, data_size);
|
||||
bit_buffer_append_bytes(buf, (const uint8_t*)&crc, FELICA_CRC_SIZE);
|
||||
}
|
||||
|
||||
bool felica_crc_check(const BitBuffer* buf) {
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
if(data_size <= FELICA_CRC_SIZE) return false;
|
||||
|
||||
uint16_t crc_received;
|
||||
bit_buffer_write_bytes_mid(buf, &crc_received, data_size - FELICA_CRC_SIZE, FELICA_CRC_SIZE);
|
||||
|
||||
const uint8_t* data = bit_buffer_get_data(buf);
|
||||
const uint16_t crc_calc = felica_crc_calculate(data, data_size - FELICA_CRC_SIZE);
|
||||
|
||||
return (crc_calc == crc_received);
|
||||
}
|
||||
|
||||
void felica_crc_trim(BitBuffer* buf) {
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
furi_assert(data_size > FELICA_CRC_SIZE);
|
||||
|
||||
bit_buffer_set_size_bytes(buf, data_size - FELICA_CRC_SIZE);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "bit_buffer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FELICA_CRC_SIZE sizeof(uint16_t)
|
||||
|
||||
void felica_crc_append(BitBuffer* buf);
|
||||
|
||||
bool felica_crc_check(const BitBuffer* buf);
|
||||
|
||||
void felica_crc_trim(BitBuffer* buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "iso13239_crc.h"
|
||||
|
||||
#include <core/check.h>
|
||||
|
||||
#define ISO13239_CRC_INIT_DEFAULT (0xFFFFU)
|
||||
#define ISO13239_CRC_INIT_PICOPASS (0xE012U)
|
||||
#define ISO13239_CRC_POLY (0x8408U)
|
||||
|
||||
static uint16_t
|
||||
iso13239_crc_calculate(Iso13239CrcType type, const uint8_t* data, size_t data_size) {
|
||||
uint16_t crc;
|
||||
|
||||
if(type == Iso13239CrcTypeDefault) {
|
||||
crc = ISO13239_CRC_INIT_DEFAULT;
|
||||
} else if(type == Iso13239CrcTypePicopass) {
|
||||
crc = ISO13239_CRC_INIT_PICOPASS;
|
||||
} else {
|
||||
furi_crash("Wrong ISO13239 CRC type");
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
crc ^= (uint16_t)data[i];
|
||||
for(size_t j = 0; j < 8; ++j) {
|
||||
if(crc & 1U) {
|
||||
crc = (crc >> 1) ^ ISO13239_CRC_POLY;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type == Iso13239CrcTypePicopass ? crc : ~crc;
|
||||
}
|
||||
|
||||
void iso13239_crc_append(Iso13239CrcType type, BitBuffer* buf) {
|
||||
const uint8_t* data = bit_buffer_get_data(buf);
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
|
||||
const uint16_t crc = iso13239_crc_calculate(type, data, data_size);
|
||||
bit_buffer_append_bytes(buf, (const uint8_t*)&crc, ISO13239_CRC_SIZE);
|
||||
}
|
||||
|
||||
bool iso13239_crc_check(Iso13239CrcType type, const BitBuffer* buf) {
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
if(data_size <= ISO13239_CRC_SIZE) return false;
|
||||
|
||||
uint16_t crc_received;
|
||||
bit_buffer_write_bytes_mid(
|
||||
buf, &crc_received, data_size - ISO13239_CRC_SIZE, ISO13239_CRC_SIZE);
|
||||
|
||||
const uint8_t* data = bit_buffer_get_data(buf);
|
||||
const uint16_t crc_calc = iso13239_crc_calculate(type, data, data_size - ISO13239_CRC_SIZE);
|
||||
|
||||
return (crc_calc == crc_received);
|
||||
}
|
||||
|
||||
void iso13239_crc_trim(BitBuffer* buf) {
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
furi_assert(data_size > ISO13239_CRC_SIZE);
|
||||
|
||||
bit_buffer_set_size_bytes(buf, data_size - ISO13239_CRC_SIZE);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <toolbox/bit_buffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ISO13239_CRC_SIZE sizeof(uint16_t)
|
||||
|
||||
typedef enum {
|
||||
Iso13239CrcTypeDefault,
|
||||
Iso13239CrcTypePicopass,
|
||||
} Iso13239CrcType;
|
||||
|
||||
void iso13239_crc_append(Iso13239CrcType type, BitBuffer* buf);
|
||||
|
||||
bool iso13239_crc_check(Iso13239CrcType type, const BitBuffer* buf);
|
||||
|
||||
void iso13239_crc_trim(BitBuffer* buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "iso14443_4_layer.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define ISO14443_4_BLOCK_PCB (1U << 1)
|
||||
#define ISO14443_4_BLOCK_PCB_I (0U)
|
||||
#define ISO14443_4_BLOCK_PCB_R (5U << 5)
|
||||
#define ISO14443_4_BLOCK_PCB_S (3U << 6)
|
||||
|
||||
struct Iso14443_4Layer {
|
||||
uint8_t pcb;
|
||||
uint8_t pcb_prev;
|
||||
};
|
||||
|
||||
static inline void iso14443_4_layer_update_pcb(Iso14443_4Layer* instance) {
|
||||
instance->pcb_prev = instance->pcb;
|
||||
instance->pcb ^= (uint8_t)0x01;
|
||||
}
|
||||
|
||||
Iso14443_4Layer* iso14443_4_layer_alloc() {
|
||||
Iso14443_4Layer* instance = malloc(sizeof(Iso14443_4Layer));
|
||||
|
||||
iso14443_4_layer_reset(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void iso14443_4_layer_free(Iso14443_4Layer* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void iso14443_4_layer_reset(Iso14443_4Layer* instance) {
|
||||
furi_assert(instance);
|
||||
instance->pcb = ISO14443_4_BLOCK_PCB_I | ISO14443_4_BLOCK_PCB;
|
||||
}
|
||||
|
||||
void iso14443_4_layer_encode_block(
|
||||
Iso14443_4Layer* instance,
|
||||
const BitBuffer* input_data,
|
||||
BitBuffer* block_data) {
|
||||
furi_assert(instance);
|
||||
|
||||
bit_buffer_append_byte(block_data, instance->pcb);
|
||||
bit_buffer_append(block_data, input_data);
|
||||
|
||||
iso14443_4_layer_update_pcb(instance);
|
||||
}
|
||||
|
||||
bool iso14443_4_layer_decode_block(
|
||||
Iso14443_4Layer* instance,
|
||||
BitBuffer* output_data,
|
||||
const BitBuffer* block_data) {
|
||||
furi_assert(instance);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
do {
|
||||
if(!bit_buffer_starts_with_byte(block_data, instance->pcb_prev)) break;
|
||||
bit_buffer_copy_right(output_data, block_data, 1);
|
||||
ret = true;
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <toolbox/bit_buffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Iso14443_4Layer Iso14443_4Layer;
|
||||
|
||||
Iso14443_4Layer* iso14443_4_layer_alloc();
|
||||
|
||||
void iso14443_4_layer_free(Iso14443_4Layer* instance);
|
||||
|
||||
void iso14443_4_layer_reset(Iso14443_4Layer* instance);
|
||||
|
||||
void iso14443_4_layer_encode_block(
|
||||
Iso14443_4Layer* instance,
|
||||
const BitBuffer* input_data,
|
||||
BitBuffer* block_data);
|
||||
|
||||
bool iso14443_4_layer_decode_block(
|
||||
Iso14443_4Layer* instance,
|
||||
BitBuffer* output_data,
|
||||
const BitBuffer* block_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "iso14443_crc.h"
|
||||
|
||||
#include <core/check.h>
|
||||
|
||||
#define ISO14443_3A_CRC_INIT (0x6363U)
|
||||
#define ISO14443_3B_CRC_INIT (0xFFFFU)
|
||||
|
||||
static uint16_t
|
||||
iso14443_crc_calculate(Iso14443CrcType type, const uint8_t* data, size_t data_size) {
|
||||
uint16_t crc;
|
||||
|
||||
if(type == Iso14443CrcTypeA) {
|
||||
crc = ISO14443_3A_CRC_INIT;
|
||||
} else if(type == Iso14443CrcTypeB) {
|
||||
crc = ISO14443_3B_CRC_INIT;
|
||||
} else {
|
||||
furi_crash("Wrong ISO14443 CRC type");
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < data_size; i++) {
|
||||
uint8_t byte = data[i];
|
||||
byte ^= (uint8_t)(crc & 0xff);
|
||||
byte ^= byte << 4;
|
||||
crc = (crc >> 8) ^ (((uint16_t)byte) << 8) ^ (((uint16_t)byte) << 3) ^ (byte >> 4);
|
||||
}
|
||||
|
||||
return type == Iso14443CrcTypeA ? crc : ~crc;
|
||||
}
|
||||
|
||||
void iso14443_crc_append(Iso14443CrcType type, BitBuffer* buf) {
|
||||
const uint8_t* data = bit_buffer_get_data(buf);
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
|
||||
const uint16_t crc = iso14443_crc_calculate(type, data, data_size);
|
||||
bit_buffer_append_bytes(buf, (const uint8_t*)&crc, ISO14443_CRC_SIZE);
|
||||
}
|
||||
|
||||
bool iso14443_crc_check(Iso14443CrcType type, const BitBuffer* buf) {
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
if(data_size <= ISO14443_CRC_SIZE) return false;
|
||||
|
||||
uint16_t crc_received;
|
||||
bit_buffer_write_bytes_mid(
|
||||
buf, &crc_received, data_size - ISO14443_CRC_SIZE, ISO14443_CRC_SIZE);
|
||||
|
||||
const uint8_t* data = bit_buffer_get_data(buf);
|
||||
const uint16_t crc_calc = iso14443_crc_calculate(type, data, data_size - ISO14443_CRC_SIZE);
|
||||
|
||||
return (crc_calc == crc_received);
|
||||
}
|
||||
|
||||
void iso14443_crc_trim(BitBuffer* buf) {
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
furi_assert(data_size > ISO14443_CRC_SIZE);
|
||||
|
||||
bit_buffer_set_size_bytes(buf, data_size - ISO14443_CRC_SIZE);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <toolbox/bit_buffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ISO14443_CRC_SIZE sizeof(uint16_t)
|
||||
|
||||
typedef enum {
|
||||
Iso14443CrcTypeA,
|
||||
Iso14443CrcTypeB,
|
||||
} Iso14443CrcType;
|
||||
|
||||
void iso14443_crc_append(Iso14443CrcType type, BitBuffer* buf);
|
||||
|
||||
bool iso14443_crc_check(Iso14443CrcType type, const BitBuffer* buf);
|
||||
|
||||
void iso14443_crc_trim(BitBuffer* buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,349 +0,0 @@
|
||||
#include "mf_classic_dict.h"
|
||||
|
||||
#include <lib/toolbox/args.h>
|
||||
#include <lib/flipper_format/flipper_format.h>
|
||||
|
||||
#define MF_CLASSIC_DICT_FLIPPER_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc")
|
||||
#define MF_CLASSIC_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc")
|
||||
#define MF_CLASSIC_DICT_UNIT_TEST_PATH EXT_PATH("unit_tests/mf_classic_dict.nfc")
|
||||
|
||||
#define TAG "MfClassicDict"
|
||||
|
||||
#define NFC_MF_CLASSIC_KEY_LEN (13)
|
||||
|
||||
struct MfClassicDict {
|
||||
Stream* stream;
|
||||
uint32_t total_keys;
|
||||
};
|
||||
|
||||
bool mf_classic_dict_check_presence(MfClassicDictType dict_type) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
bool dict_present = false;
|
||||
if(dict_type == MfClassicDictTypeSystem) {
|
||||
dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_FLIPPER_PATH, NULL) == FSE_OK;
|
||||
} else if(dict_type == MfClassicDictTypeUser) {
|
||||
dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_USER_PATH, NULL) == FSE_OK;
|
||||
} else if(dict_type == MfClassicDictTypeUnitTest) {
|
||||
dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_UNIT_TEST_PATH, NULL) ==
|
||||
FSE_OK;
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return dict_present;
|
||||
}
|
||||
|
||||
MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) {
|
||||
MfClassicDict* dict = malloc(sizeof(MfClassicDict));
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
dict->stream = buffered_file_stream_alloc(storage);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
bool dict_loaded = false;
|
||||
do {
|
||||
if(dict_type == MfClassicDictTypeSystem) {
|
||||
if(!buffered_file_stream_open(
|
||||
dict->stream,
|
||||
MF_CLASSIC_DICT_FLIPPER_PATH,
|
||||
FSAM_READ_WRITE,
|
||||
FSOM_OPEN_EXISTING)) {
|
||||
buffered_file_stream_close(dict->stream);
|
||||
break;
|
||||
}
|
||||
} else if(dict_type == MfClassicDictTypeUser) {
|
||||
if(!buffered_file_stream_open(
|
||||
dict->stream, MF_CLASSIC_DICT_USER_PATH, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) {
|
||||
buffered_file_stream_close(dict->stream);
|
||||
break;
|
||||
}
|
||||
} else if(dict_type == MfClassicDictTypeUnitTest) {
|
||||
if(!buffered_file_stream_open(
|
||||
dict->stream,
|
||||
MF_CLASSIC_DICT_UNIT_TEST_PATH,
|
||||
FSAM_READ_WRITE,
|
||||
FSOM_OPEN_ALWAYS)) {
|
||||
buffered_file_stream_close(dict->stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for new line ending
|
||||
if(!stream_eof(dict->stream)) {
|
||||
if(!stream_seek(dict->stream, -1, StreamOffsetFromEnd)) break;
|
||||
uint8_t last_char = 0;
|
||||
if(stream_read(dict->stream, &last_char, 1) != 1) break;
|
||||
if(last_char != '\n') {
|
||||
FURI_LOG_D(TAG, "Adding new line ending");
|
||||
if(stream_write_char(dict->stream, '\n') != 1) break;
|
||||
}
|
||||
if(!stream_rewind(dict->stream)) break;
|
||||
}
|
||||
|
||||
// Read total amount of keys
|
||||
FuriString* next_line;
|
||||
next_line = furi_string_alloc();
|
||||
while(true) {
|
||||
if(!stream_read_line(dict->stream, next_line)) {
|
||||
FURI_LOG_T(TAG, "No keys left in dict");
|
||||
break;
|
||||
}
|
||||
FURI_LOG_T(
|
||||
TAG,
|
||||
"Read line: %s, len: %zu",
|
||||
furi_string_get_cstr(next_line),
|
||||
furi_string_size(next_line));
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||
dict->total_keys++;
|
||||
}
|
||||
furi_string_free(next_line);
|
||||
stream_rewind(dict->stream);
|
||||
|
||||
dict_loaded = true;
|
||||
FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", dict->total_keys);
|
||||
} while(false);
|
||||
|
||||
if(!dict_loaded) {
|
||||
buffered_file_stream_close(dict->stream);
|
||||
free(dict);
|
||||
dict = NULL;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
void mf_classic_dict_free(MfClassicDict* dict) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
buffered_file_stream_close(dict->stream);
|
||||
stream_free(dict->stream);
|
||||
free(dict);
|
||||
}
|
||||
|
||||
static void mf_classic_dict_int_to_str(uint8_t* key_int, FuriString* key_str) {
|
||||
furi_string_reset(key_str);
|
||||
for(size_t i = 0; i < 6; i++) {
|
||||
furi_string_cat_printf(key_str, "%02X", key_int[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void mf_classic_dict_str_to_int(FuriString* key_str, uint64_t* key_int) {
|
||||
uint8_t key_byte_tmp;
|
||||
|
||||
*key_int = 0ULL;
|
||||
for(uint8_t i = 0; i < 12; i += 2) {
|
||||
args_char_to_hex(
|
||||
furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp);
|
||||
*key_int |= (uint64_t)key_byte_tmp << (8 * (5 - i / 2));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict) {
|
||||
furi_assert(dict);
|
||||
|
||||
return dict->total_keys;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_rewind(MfClassicDict* dict) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
return stream_rewind(dict->stream);
|
||||
}
|
||||
|
||||
bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, FuriString* key) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
bool key_read = false;
|
||||
furi_string_reset(key);
|
||||
while(!key_read) {
|
||||
if(!stream_read_line(dict->stream, key)) break;
|
||||
if(furi_string_get_char(key, 0) == '#') continue;
|
||||
if(furi_string_size(key) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||
furi_string_left(key, 12);
|
||||
key_read = true;
|
||||
}
|
||||
|
||||
return key_read;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
FuriString* temp_key;
|
||||
temp_key = furi_string_alloc();
|
||||
bool key_read = mf_classic_dict_get_next_key_str(dict, temp_key);
|
||||
if(key_read) {
|
||||
mf_classic_dict_str_to_int(temp_key, key);
|
||||
}
|
||||
furi_string_free(temp_key);
|
||||
return key_read;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, FuriString* key) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
FuriString* next_line;
|
||||
next_line = furi_string_alloc();
|
||||
|
||||
bool key_found = false;
|
||||
stream_rewind(dict->stream);
|
||||
while(!key_found) { //-V654
|
||||
if(!stream_read_line(dict->stream, next_line)) break;
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||
furi_string_left(next_line, 12);
|
||||
if(!furi_string_equal(key, next_line)) continue;
|
||||
key_found = true;
|
||||
}
|
||||
|
||||
furi_string_free(next_line);
|
||||
return key_found;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key) {
|
||||
FuriString* temp_key;
|
||||
|
||||
temp_key = furi_string_alloc();
|
||||
mf_classic_dict_int_to_str(key, temp_key);
|
||||
bool key_found = mf_classic_dict_is_key_present_str(dict, temp_key);
|
||||
furi_string_free(temp_key);
|
||||
return key_found;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_add_key_str(MfClassicDict* dict, FuriString* key) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
furi_string_cat_printf(key, "\n");
|
||||
|
||||
bool key_added = false;
|
||||
do {
|
||||
if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break;
|
||||
if(!stream_insert_string(dict->stream, key)) break;
|
||||
dict->total_keys++;
|
||||
key_added = true;
|
||||
} while(false);
|
||||
|
||||
furi_string_left(key, 12);
|
||||
return key_added;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
FuriString* temp_key;
|
||||
temp_key = furi_string_alloc();
|
||||
mf_classic_dict_int_to_str(key, temp_key);
|
||||
bool key_added = mf_classic_dict_add_key_str(dict, temp_key);
|
||||
|
||||
furi_string_free(temp_key);
|
||||
return key_added;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, FuriString* key, uint32_t target) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
FuriString* next_line;
|
||||
uint32_t index = 0;
|
||||
next_line = furi_string_alloc();
|
||||
furi_string_reset(key);
|
||||
|
||||
bool key_found = false;
|
||||
while(!key_found) {
|
||||
if(!stream_read_line(dict->stream, next_line)) break;
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||
if(index++ != target) continue;
|
||||
furi_string_set_n(key, next_line, 0, 12);
|
||||
key_found = true;
|
||||
}
|
||||
|
||||
furi_string_free(next_line);
|
||||
return key_found;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
FuriString* temp_key;
|
||||
temp_key = furi_string_alloc();
|
||||
bool key_found = mf_classic_dict_get_key_at_index_str(dict, temp_key, target);
|
||||
if(key_found) {
|
||||
mf_classic_dict_str_to_int(temp_key, key);
|
||||
}
|
||||
furi_string_free(temp_key);
|
||||
return key_found;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_find_index_str(MfClassicDict* dict, FuriString* key, uint32_t* target) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
FuriString* next_line;
|
||||
next_line = furi_string_alloc();
|
||||
|
||||
bool key_found = false;
|
||||
uint32_t index = 0;
|
||||
stream_rewind(dict->stream);
|
||||
while(!key_found) { //-V654
|
||||
if(!stream_read_line(dict->stream, next_line)) break;
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||
furi_string_left(next_line, 12);
|
||||
if(!furi_string_equal(key, next_line)) continue;
|
||||
key_found = true;
|
||||
*target = index;
|
||||
}
|
||||
|
||||
furi_string_free(next_line);
|
||||
return key_found;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
FuriString* temp_key;
|
||||
temp_key = furi_string_alloc();
|
||||
mf_classic_dict_int_to_str(key, temp_key);
|
||||
bool key_found = mf_classic_dict_find_index_str(dict, temp_key, target);
|
||||
|
||||
furi_string_free(temp_key);
|
||||
return key_found;
|
||||
}
|
||||
|
||||
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target) {
|
||||
furi_assert(dict);
|
||||
furi_assert(dict->stream);
|
||||
|
||||
FuriString* next_line;
|
||||
next_line = furi_string_alloc();
|
||||
uint32_t index = 0;
|
||||
|
||||
bool key_removed = false;
|
||||
stream_rewind(dict->stream);
|
||||
while(!key_removed) {
|
||||
if(!stream_read_line(dict->stream, next_line)) break;
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||
if(index++ != target) continue;
|
||||
stream_seek(dict->stream, -NFC_MF_CLASSIC_KEY_LEN, StreamOffsetFromCurrent);
|
||||
if(!stream_delete(dict->stream, NFC_MF_CLASSIC_KEY_LEN)) break;
|
||||
dict->total_keys--;
|
||||
key_removed = true;
|
||||
}
|
||||
|
||||
stream_rewind(dict->stream);
|
||||
|
||||
furi_string_free(next_line);
|
||||
return key_removed;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <storage/storage.h>
|
||||
#include <lib/flipper_format/flipper_format.h>
|
||||
#include <lib/toolbox/stream/file_stream.h>
|
||||
#include <lib/toolbox/stream/buffered_file_stream.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MfClassicDictTypeUser,
|
||||
MfClassicDictTypeSystem,
|
||||
MfClassicDictTypeUnitTest,
|
||||
} MfClassicDictType;
|
||||
|
||||
typedef struct MfClassicDict MfClassicDict;
|
||||
|
||||
bool mf_classic_dict_check_presence(MfClassicDictType dict_type);
|
||||
|
||||
/** Allocate MfClassicDict instance
|
||||
*
|
||||
* @param[in] dict_type The dictionary type
|
||||
*
|
||||
* @return MfClassicDict instance
|
||||
*/
|
||||
MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type);
|
||||
|
||||
/** Free MfClassicDict instance
|
||||
*
|
||||
* @param dict MfClassicDict instance
|
||||
*/
|
||||
void mf_classic_dict_free(MfClassicDict* dict);
|
||||
|
||||
/** Get total keys count
|
||||
*
|
||||
* @param dict MfClassicDict instance
|
||||
*
|
||||
* @return total keys count
|
||||
*/
|
||||
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict);
|
||||
|
||||
/** Rewind to the beginning
|
||||
*
|
||||
* @param dict MfClassicDict instance
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool mf_classic_dict_rewind(MfClassicDict* dict);
|
||||
|
||||
bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key);
|
||||
|
||||
bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, FuriString* key);
|
||||
|
||||
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key);
|
||||
|
||||
bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, FuriString* key);
|
||||
|
||||
/** Get key at target offset as uint64_t
|
||||
*
|
||||
* @param dict MfClassicDict instance
|
||||
* @param[out] key Pointer to the uint64_t key
|
||||
* @param[in] target Target offset from current position
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target);
|
||||
|
||||
/** Get key at target offset as FuriString*
|
||||
*
|
||||
* @param dict MfClassicDict instance
|
||||
* @param[out] key Found key destination buffer
|
||||
* @param[in] target Target offset from current position
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, FuriString* key, uint32_t target);
|
||||
|
||||
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key);
|
||||
|
||||
/** Add string representation of the key
|
||||
*
|
||||
* @param dict MfClassicDict instance
|
||||
* @param[in] key String representation of the key
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool mf_classic_dict_add_key_str(MfClassicDict* dict, FuriString* key);
|
||||
|
||||
bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target);
|
||||
|
||||
bool mf_classic_dict_find_index_str(MfClassicDict* dict, FuriString* key, uint32_t* target);
|
||||
|
||||
/** Delete key at target offset
|
||||
*
|
||||
* @param dict MfClassicDict instance
|
||||
* @param[in] target Target offset from current position
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,228 +0,0 @@
|
||||
#include "mfkey32.h"
|
||||
|
||||
#include <furi/furi.h>
|
||||
#include <storage/storage.h>
|
||||
#include <stream/stream.h>
|
||||
#include <stream/buffered_file_stream.h>
|
||||
#include <m-array.h>
|
||||
|
||||
#include <lib/nfc/protocols/mifare_classic.h>
|
||||
#include <lib/nfc/protocols/nfc_util.h>
|
||||
|
||||
#define TAG "Mfkey32"
|
||||
|
||||
#define MFKEY32_LOGS_PATH EXT_PATH("nfc/.mfkey32.log")
|
||||
|
||||
typedef enum {
|
||||
Mfkey32StateIdle,
|
||||
Mfkey32StateAuthReceived,
|
||||
Mfkey32StateAuthNtSent,
|
||||
Mfkey32StateAuthArNrReceived,
|
||||
} Mfkey32State;
|
||||
|
||||
typedef struct {
|
||||
uint32_t cuid;
|
||||
uint8_t sector;
|
||||
MfClassicKey key;
|
||||
uint32_t nt0;
|
||||
uint32_t nr0;
|
||||
uint32_t ar0;
|
||||
uint32_t nt1;
|
||||
uint32_t nr1;
|
||||
uint32_t ar1;
|
||||
} Mfkey32Params;
|
||||
|
||||
ARRAY_DEF(Mfkey32Params, Mfkey32Params, M_POD_OPLIST);
|
||||
|
||||
typedef struct {
|
||||
uint8_t sector;
|
||||
MfClassicKey key;
|
||||
uint32_t nt;
|
||||
uint32_t nr;
|
||||
uint32_t ar;
|
||||
} Mfkey32Nonce;
|
||||
|
||||
struct Mfkey32 {
|
||||
Mfkey32State state;
|
||||
Stream* file_stream;
|
||||
Mfkey32Params_t params_arr;
|
||||
Mfkey32Nonce nonce;
|
||||
uint32_t cuid;
|
||||
Mfkey32ParseDataCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
Mfkey32* mfkey32_alloc(uint32_t cuid) {
|
||||
Mfkey32* instance = malloc(sizeof(Mfkey32));
|
||||
instance->cuid = cuid;
|
||||
instance->state = Mfkey32StateIdle;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
instance->file_stream = buffered_file_stream_alloc(storage);
|
||||
if(!buffered_file_stream_open(
|
||||
instance->file_stream, MFKEY32_LOGS_PATH, FSAM_WRITE, FSOM_OPEN_APPEND)) {
|
||||
buffered_file_stream_close(instance->file_stream);
|
||||
stream_free(instance->file_stream);
|
||||
free(instance);
|
||||
instance = NULL;
|
||||
} else {
|
||||
Mfkey32Params_init(instance->params_arr);
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void mfkey32_free(Mfkey32* instance) {
|
||||
furi_assert(instance != NULL);
|
||||
|
||||
Mfkey32Params_clear(instance->params_arr);
|
||||
buffered_file_stream_close(instance->file_stream);
|
||||
stream_free(instance->file_stream);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
static bool mfkey32_write_params(Mfkey32* instance, Mfkey32Params* params) {
|
||||
FuriString* str = furi_string_alloc_printf(
|
||||
"Sec %d key %c cuid %08lx nt0 %08lx nr0 %08lx ar0 %08lx nt1 %08lx nr1 %08lx ar1 %08lx\n",
|
||||
params->sector,
|
||||
params->key == MfClassicKeyA ? 'A' : 'B',
|
||||
params->cuid,
|
||||
params->nt0,
|
||||
params->nr0,
|
||||
params->ar0,
|
||||
params->nt1,
|
||||
params->nr1,
|
||||
params->ar1);
|
||||
bool write_success = stream_write_string(instance->file_stream, str);
|
||||
furi_string_free(str);
|
||||
return write_success;
|
||||
}
|
||||
|
||||
static void mfkey32_add_params(Mfkey32* instance) {
|
||||
Mfkey32Nonce* nonce = &instance->nonce;
|
||||
bool nonce_added = false;
|
||||
// Search if we partially collected params
|
||||
if(Mfkey32Params_size(instance->params_arr)) {
|
||||
Mfkey32Params_it_t it;
|
||||
for(Mfkey32Params_it(it, instance->params_arr); !Mfkey32Params_end_p(it);
|
||||
Mfkey32Params_next(it)) {
|
||||
Mfkey32Params* params = Mfkey32Params_ref(it);
|
||||
if((params->sector == nonce->sector) && (params->key == nonce->key)) {
|
||||
params->nt1 = nonce->nt;
|
||||
params->nr1 = nonce->nr;
|
||||
params->ar1 = nonce->ar;
|
||||
nonce_added = true;
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Params for sector %d key %c collected",
|
||||
params->sector,
|
||||
params->key == MfClassicKeyA ? 'A' : 'B');
|
||||
// Write on sd card
|
||||
if(mfkey32_write_params(instance, params)) {
|
||||
Mfkey32Params_remove(instance->params_arr, it);
|
||||
if(instance->callback) {
|
||||
instance->callback(Mfkey32EventParamCollected, instance->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!nonce_added) {
|
||||
Mfkey32Params params = {
|
||||
.sector = nonce->sector,
|
||||
.key = nonce->key,
|
||||
.cuid = instance->cuid,
|
||||
.nt0 = nonce->nt,
|
||||
.nr0 = nonce->nr,
|
||||
.ar0 = nonce->ar,
|
||||
};
|
||||
Mfkey32Params_push_back(instance->params_arr, params);
|
||||
}
|
||||
}
|
||||
|
||||
void mfkey32_process_data(
|
||||
Mfkey32* instance,
|
||||
uint8_t* data,
|
||||
uint16_t len,
|
||||
bool reader_to_tag,
|
||||
bool crc_dropped) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data);
|
||||
|
||||
Mfkey32Nonce* nonce = &instance->nonce;
|
||||
uint16_t data_len = len;
|
||||
if((data_len > 3) && !crc_dropped) {
|
||||
data_len -= 2;
|
||||
}
|
||||
|
||||
bool data_processed = false;
|
||||
if(instance->state == Mfkey32StateIdle) {
|
||||
if(reader_to_tag) {
|
||||
if((data[0] == 0x60) || (data[0] == 0x61)) {
|
||||
nonce->key = data[0] == 0x60 ? MfClassicKeyA : MfClassicKeyB;
|
||||
nonce->sector = mf_classic_get_sector_by_block(data[1]);
|
||||
instance->state = Mfkey32StateAuthReceived;
|
||||
data_processed = true;
|
||||
}
|
||||
}
|
||||
} else if(instance->state == Mfkey32StateAuthReceived) {
|
||||
if(!reader_to_tag) {
|
||||
if(len == 4) {
|
||||
nonce->nt = nfc_util_bytes2num(data, 4);
|
||||
instance->state = Mfkey32StateAuthNtSent;
|
||||
data_processed = true;
|
||||
}
|
||||
}
|
||||
} else if(instance->state == Mfkey32StateAuthNtSent) {
|
||||
if(reader_to_tag) {
|
||||
if(len == 8) {
|
||||
nonce->nr = nfc_util_bytes2num(data, 4);
|
||||
nonce->ar = nfc_util_bytes2num(&data[4], 4);
|
||||
mfkey32_add_params(instance);
|
||||
instance->state = Mfkey32StateIdle;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!data_processed) {
|
||||
instance->state = Mfkey32StateIdle;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t mfkey32_get_auth_sectors(FuriString* data_str) {
|
||||
furi_assert(data_str);
|
||||
|
||||
uint16_t nonces_num = 0;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
Stream* file_stream = buffered_file_stream_alloc(storage);
|
||||
FuriString* temp_str;
|
||||
temp_str = furi_string_alloc();
|
||||
|
||||
do {
|
||||
if(!buffered_file_stream_open(
|
||||
file_stream, MFKEY32_LOGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING))
|
||||
break;
|
||||
while(true) {
|
||||
if(!stream_read_line(file_stream, temp_str)) break;
|
||||
size_t uid_pos = furi_string_search(temp_str, "cuid");
|
||||
furi_string_left(temp_str, uid_pos);
|
||||
furi_string_push_back(temp_str, '\n');
|
||||
furi_string_cat(data_str, temp_str);
|
||||
nonces_num++;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
buffered_file_stream_close(file_stream);
|
||||
stream_free(file_stream);
|
||||
furi_string_free(temp_str);
|
||||
|
||||
return nonces_num;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/nfc/protocols/mifare_classic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct Mfkey32 Mfkey32;
|
||||
|
||||
typedef enum {
|
||||
Mfkey32EventParamCollected,
|
||||
} Mfkey32Event;
|
||||
|
||||
typedef void (*Mfkey32ParseDataCallback)(Mfkey32Event event, void* context);
|
||||
|
||||
Mfkey32* mfkey32_alloc(uint32_t cuid);
|
||||
|
||||
void mfkey32_free(Mfkey32* instance);
|
||||
|
||||
void mfkey32_process_data(
|
||||
Mfkey32* instance,
|
||||
uint8_t* data,
|
||||
uint16_t len,
|
||||
bool reader_to_tag,
|
||||
bool crc_dropped);
|
||||
|
||||
void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, void* context);
|
||||
|
||||
uint16_t mfkey32_get_auth_sectors(FuriString* string);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,566 @@
|
||||
#include "nfc_data_generator.h"
|
||||
|
||||
#include <furi/furi.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
|
||||
|
||||
#define NXP_MANUFACTURER_ID (0x04)
|
||||
|
||||
typedef void (*NfcDataGeneratorHandler)(NfcDevice* nfc_device);
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
NfcDataGeneratorHandler handler;
|
||||
} NfcDataGenerator;
|
||||
|
||||
static const uint8_t version_bytes_mf0ulx1[] = {0x00, 0x04, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03};
|
||||
static const uint8_t version_bytes_ntag21x[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x03};
|
||||
static const uint8_t version_bytes_ntag_i2c[] = {0x00, 0x04, 0x04, 0x05, 0x02, 0x00, 0x00, 0x03};
|
||||
static const uint8_t default_data_ntag203[] =
|
||||
{0xE1, 0x10, 0x12, 0x00, 0x01, 0x03, 0xA0, 0x10, 0x44, 0x03, 0x00, 0xFE};
|
||||
static const uint8_t default_data_ntag213[] = {0x01, 0x03, 0xA0, 0x0C, 0x34, 0x03, 0x00, 0xFE};
|
||||
static const uint8_t default_data_ntag215_216[] = {0x03, 0x00, 0xFE};
|
||||
static const uint8_t default_data_ntag_i2c[] = {0xE1, 0x10, 0x00, 0x00, 0x03, 0x00, 0xFE};
|
||||
static const uint8_t default_config_ntag_i2c[] = {0x01, 0x00, 0xF8, 0x48, 0x08, 0x01, 0x00, 0x00};
|
||||
|
||||
static void nfc_generate_mf_ul_uid(uint8_t* uid) {
|
||||
uid[0] = NXP_MANUFACTURER_ID;
|
||||
furi_hal_random_fill_buf(&uid[1], 6);
|
||||
// I'm not sure how this is generated, but the upper nybble always seems to be 8
|
||||
uid[6] &= 0x0F;
|
||||
uid[6] |= 0x80;
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_common(MfUltralightData* mfu_data) {
|
||||
mfu_data->iso14443_3a_data->uid_len = 7;
|
||||
nfc_generate_mf_ul_uid(mfu_data->iso14443_3a_data->uid);
|
||||
mfu_data->iso14443_3a_data->atqa[0] = 0x44;
|
||||
mfu_data->iso14443_3a_data->atqa[1] = 0x00;
|
||||
mfu_data->iso14443_3a_data->sak = 0x00;
|
||||
}
|
||||
|
||||
static void nfc_generate_calc_bcc(uint8_t* uid, uint8_t* bcc0, uint8_t* bcc1) {
|
||||
*bcc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2];
|
||||
*bcc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6];
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_copy_uid_with_bcc(MfUltralightData* mfu_data) {
|
||||
memcpy(mfu_data->page[0].data, mfu_data->iso14443_3a_data->uid, 3);
|
||||
memcpy(mfu_data->page[1].data, &mfu_data->iso14443_3a_data->uid[3], 4);
|
||||
|
||||
nfc_generate_calc_bcc(
|
||||
mfu_data->iso14443_3a_data->uid, &mfu_data->page[0].data[3], &mfu_data->page[2].data[0]);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_orig(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
nfc_generate_mf_ul_common(mfu_data);
|
||||
|
||||
mfu_data->type = MfUltralightTypeUnknown;
|
||||
mfu_data->pages_total = 16;
|
||||
mfu_data->pages_read = 16;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(mfu_data);
|
||||
memset(&mfu_data->page[4], 0xff, sizeof(MfUltralightPage));
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_with_config_common(MfUltralightData* mfu_data, uint8_t num_pages) {
|
||||
nfc_generate_mf_ul_common(mfu_data);
|
||||
|
||||
mfu_data->pages_total = num_pages;
|
||||
mfu_data->pages_read = num_pages;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(mfu_data);
|
||||
uint16_t config_index = (num_pages - 4);
|
||||
mfu_data->page[config_index].data[0] = 0x04; // STRG_MOD_EN
|
||||
mfu_data->page[config_index].data[3] = 0xff; // AUTH0
|
||||
mfu_data->page[config_index + 1].data[1] = 0x05; // VCTID
|
||||
memset(&mfu_data->page[config_index + 2], 0xff, sizeof(MfUltralightPage)); // Default PWD
|
||||
if(num_pages > 20) {
|
||||
mfu_data->page[config_index - 1].data[3] = MF_ULTRALIGHT_TEARING_FLAG_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_ev1_common(MfUltralightData* mfu_data, uint8_t num_pages) {
|
||||
nfc_generate_mf_ul_with_config_common(mfu_data, num_pages);
|
||||
memcpy(&mfu_data->version, version_bytes_mf0ulx1, sizeof(MfUltralightVersion));
|
||||
for(size_t i = 0; i < 3; ++i) {
|
||||
mfu_data->tearing_flag[i].data = MF_ULTRALIGHT_TEARING_FLAG_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_11(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_mf_ul_ev1_common(mfu_data, 20);
|
||||
mfu_data->type = MfUltralightTypeUL11;
|
||||
mfu_data->version.prod_subtype = 0x01;
|
||||
mfu_data->version.storage_size = 0x0B;
|
||||
mfu_data->page[16].data[0] = 0x00; // Low capacitance version does not have STRG_MOD_EN
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_h11(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_mf_ul_ev1_common(mfu_data, 20);
|
||||
mfu_data->type = MfUltralightTypeUL11;
|
||||
mfu_data->version.prod_subtype = 0x02;
|
||||
mfu_data->version.storage_size = 0x0B;
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_21(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_mf_ul_ev1_common(mfu_data, 41);
|
||||
mfu_data->type = MfUltralightTypeUL21;
|
||||
mfu_data->version.prod_subtype = 0x01;
|
||||
mfu_data->version.storage_size = 0x0E;
|
||||
mfu_data->page[37].data[0] = 0x00; // Low capacitance version does not have STRG_MOD_EN
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_h21(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_mf_ul_ev1_common(mfu_data, 41);
|
||||
mfu_data->type = MfUltralightTypeUL21;
|
||||
mfu_data->version.prod_subtype = 0x02;
|
||||
mfu_data->version.storage_size = 0x0E;
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag203(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_mf_ul_common(mfu_data);
|
||||
mfu_data->type = MfUltralightTypeNTAG203;
|
||||
mfu_data->pages_total = 42;
|
||||
mfu_data->pages_read = 42;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(mfu_data);
|
||||
mfu_data->page[2].data[1] = 0x48; // Internal byte
|
||||
memcpy(&mfu_data->page[3], default_data_ntag203, sizeof(MfUltralightPage)); //-V1086
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag21x_common(MfUltralightData* mfu_data, uint8_t num_pages) {
|
||||
nfc_generate_mf_ul_with_config_common(mfu_data, num_pages);
|
||||
memcpy(&mfu_data->version, version_bytes_ntag21x, sizeof(MfUltralightVersion));
|
||||
mfu_data->page[2].data[1] = 0x48; // Internal byte
|
||||
// Capability container
|
||||
mfu_data->page[3].data[0] = 0xE1;
|
||||
mfu_data->page[3].data[1] = 0x10;
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag213(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_ntag21x_common(mfu_data, 45);
|
||||
mfu_data->type = MfUltralightTypeNTAG213;
|
||||
mfu_data->version.storage_size = 0x0F;
|
||||
mfu_data->page[3].data[2] = 0x12;
|
||||
// Default contents
|
||||
memcpy(&mfu_data->page[4], default_data_ntag213, sizeof(default_data_ntag213));
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag215(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_ntag21x_common(mfu_data, 135);
|
||||
mfu_data->type = MfUltralightTypeNTAG215;
|
||||
mfu_data->version.storage_size = 0x11;
|
||||
mfu_data->page[3].data[2] = 0x3E;
|
||||
// Default contents
|
||||
memcpy(&mfu_data->page[4], default_data_ntag215_216, sizeof(default_data_ntag215_216));
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag216(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_ntag21x_common(mfu_data, 231);
|
||||
mfu_data->type = MfUltralightTypeNTAG216;
|
||||
mfu_data->version.storage_size = 0x13;
|
||||
mfu_data->page[3].data[2] = 0x6D;
|
||||
// Default contents
|
||||
memcpy(&mfu_data->page[4], default_data_ntag215_216, sizeof(default_data_ntag215_216));
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_common(
|
||||
MfUltralightData* mfu_data,
|
||||
MfUltralightType type,
|
||||
uint16_t num_pages) {
|
||||
nfc_generate_mf_ul_common(mfu_data);
|
||||
|
||||
mfu_data->type = type;
|
||||
memcpy(&mfu_data->version, version_bytes_ntag_i2c, sizeof(version_bytes_ntag_i2c));
|
||||
mfu_data->pages_total = num_pages;
|
||||
mfu_data->pages_read = num_pages;
|
||||
memcpy(
|
||||
mfu_data->page[0].data,
|
||||
mfu_data->iso14443_3a_data->uid,
|
||||
mfu_data->iso14443_3a_data->uid_len);
|
||||
mfu_data->page[1].data[3] = mfu_data->iso14443_3a_data->sak;
|
||||
mfu_data->page[2].data[0] = mfu_data->iso14443_3a_data->atqa[0];
|
||||
mfu_data->page[2].data[1] = mfu_data->iso14443_3a_data->atqa[1];
|
||||
|
||||
uint16_t config_register_page = 0;
|
||||
uint16_t session_register_page = 0;
|
||||
|
||||
// Sync with mifare_ultralight.c
|
||||
switch(type) {
|
||||
case MfUltralightTypeNTAGI2C1K:
|
||||
config_register_page = 227;
|
||||
session_register_page = 229;
|
||||
break;
|
||||
case MfUltralightTypeNTAGI2C2K:
|
||||
config_register_page = 481;
|
||||
session_register_page = 483;
|
||||
break;
|
||||
case MfUltralightTypeNTAGI2CPlus1K:
|
||||
case MfUltralightTypeNTAGI2CPlus2K:
|
||||
config_register_page = 232;
|
||||
session_register_page = 234;
|
||||
break;
|
||||
default:
|
||||
furi_crash("Unknown MFUL");
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(
|
||||
&mfu_data->page[config_register_page],
|
||||
default_config_ntag_i2c,
|
||||
sizeof(default_config_ntag_i2c));
|
||||
memcpy(
|
||||
&mfu_data->page[session_register_page],
|
||||
default_config_ntag_i2c,
|
||||
sizeof(default_config_ntag_i2c));
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_1k(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_ntag_i2c_common(mfu_data, MfUltralightTypeNTAGI2C1K, 231);
|
||||
mfu_data->version.prod_ver_minor = 0x01;
|
||||
mfu_data->version.storage_size = 0x13;
|
||||
memcpy(&mfu_data->page[3], default_data_ntag_i2c, sizeof(default_data_ntag_i2c));
|
||||
mfu_data->page[3].data[2] = 0x6D; // Size of tag in CC
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_2k(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_ntag_i2c_common(mfu_data, MfUltralightTypeNTAGI2C2K, 485);
|
||||
mfu_data->version.prod_ver_minor = 0x01;
|
||||
mfu_data->version.storage_size = 0x15;
|
||||
memcpy(&mfu_data->page[3], default_data_ntag_i2c, sizeof(default_data_ntag_i2c));
|
||||
mfu_data->page[3].data[2] = 0xEA; // Size of tag in CC
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_plus_common(
|
||||
MfUltralightData* mfu_data,
|
||||
MfUltralightType type,
|
||||
uint16_t num_pages) {
|
||||
nfc_generate_ntag_i2c_common(mfu_data, type, num_pages);
|
||||
|
||||
uint16_t config_index = 227;
|
||||
mfu_data->page[config_index].data[3] = 0xff; // AUTH0
|
||||
|
||||
memset(&mfu_data->page[config_index + 2], 0xFF, sizeof(MfUltralightPage)); // Default PWD
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_plus_1k(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_ntag_i2c_plus_common(mfu_data, MfUltralightTypeNTAGI2CPlus1K, 236);
|
||||
mfu_data->version.prod_ver_minor = 0x02;
|
||||
mfu_data->version.storage_size = 0x13;
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_plus_2k(NfcDevice* nfc_device) {
|
||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||
|
||||
nfc_generate_ntag_i2c_plus_common(mfu_data, MfUltralightTypeNTAGI2CPlus2K, 492);
|
||||
mfu_data->version.prod_ver_minor = 0x02;
|
||||
mfu_data->version.storage_size = 0x15;
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfUltralight, mfu_data);
|
||||
mf_ultralight_free(mfu_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_uid(uint8_t* uid, uint8_t length) {
|
||||
uid[0] = NXP_MANUFACTURER_ID;
|
||||
furi_hal_random_fill_buf(&uid[1], length - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
nfc_generate_mf_classic_common(MfClassicData* data, uint8_t uid_len, MfClassicType type) {
|
||||
data->iso14443_3a_data->uid_len = uid_len;
|
||||
data->iso14443_3a_data->atqa[0] = 0x44;
|
||||
data->iso14443_3a_data->atqa[1] = 0x00;
|
||||
data->iso14443_3a_data->sak = 0x08;
|
||||
data->type = type;
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_sector_trailer(MfClassicData* data, uint8_t block) {
|
||||
// All keys are set to FFFF FFFF FFFFh at chip delivery and the bytes 6, 7 and 8 are set to FF0780h.
|
||||
MfClassicSectorTrailer* sec_tr = (MfClassicSectorTrailer*)data->block[block].data;
|
||||
sec_tr->access_bits.data[0] = 0xFF;
|
||||
sec_tr->access_bits.data[1] = 0x07;
|
||||
sec_tr->access_bits.data[2] = 0x80;
|
||||
sec_tr->access_bits.data[3] = 0x69; // Nice
|
||||
|
||||
mf_classic_set_block_read(data, block, &data->block[block]);
|
||||
mf_classic_set_key_found(
|
||||
data, mf_classic_get_sector_by_block(block), MfClassicKeyTypeA, 0xFFFFFFFFFFFF);
|
||||
mf_classic_set_key_found(
|
||||
data, mf_classic_get_sector_by_block(block), MfClassicKeyTypeB, 0xFFFFFFFFFFFF);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_block_0(
|
||||
uint8_t* block,
|
||||
uint8_t uid_len,
|
||||
uint8_t sak,
|
||||
uint8_t atqa0,
|
||||
uint8_t atqa1) {
|
||||
// Block length is always 16 bytes, and the UID can be either 4 or 7 bytes
|
||||
furi_assert(uid_len == 4 || uid_len == 7);
|
||||
furi_assert(block);
|
||||
|
||||
if(uid_len == 4) {
|
||||
// Calculate BCC
|
||||
block[uid_len] = 0;
|
||||
|
||||
for(int i = 0; i < uid_len; i++) {
|
||||
block[uid_len] ^= block[i];
|
||||
}
|
||||
} else {
|
||||
uid_len -= 1;
|
||||
}
|
||||
|
||||
block[uid_len + 1] = sak;
|
||||
block[uid_len + 2] = atqa0;
|
||||
block[uid_len + 3] = atqa1;
|
||||
|
||||
for(int i = uid_len + 4; i < 16; i++) {
|
||||
block[i] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic(NfcDevice* nfc_device, uint8_t uid_len, MfClassicType type) {
|
||||
MfClassicData* mfc_data = mf_classic_alloc();
|
||||
|
||||
nfc_generate_mf_classic_uid(mfc_data->block[0].data, uid_len);
|
||||
nfc_generate_mf_classic_common(mfc_data, uid_len, type);
|
||||
|
||||
// Set the UID
|
||||
mfc_data->iso14443_3a_data->uid[0] = NXP_MANUFACTURER_ID;
|
||||
for(int i = 1; i < uid_len; i++) {
|
||||
mfc_data->iso14443_3a_data->uid[i] = mfc_data->block[0].data[i];
|
||||
}
|
||||
|
||||
mf_classic_set_block_read(mfc_data, 0, &mfc_data->block[0]);
|
||||
|
||||
uint16_t block_num = mf_classic_get_total_block_num(type);
|
||||
if(type == MfClassicType4k) {
|
||||
// Set every block to 0xFF
|
||||
for(uint16_t i = 1; i < block_num; i++) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
nfc_generate_mf_classic_sector_trailer(mfc_data, i);
|
||||
} else {
|
||||
memset(&mfc_data->block[i].data, 0xFF, 16);
|
||||
}
|
||||
mf_classic_set_block_read(mfc_data, i, &mfc_data->block[i]);
|
||||
}
|
||||
// Set SAK to 18
|
||||
mfc_data->iso14443_3a_data->sak = 0x18;
|
||||
} else if(type == MfClassicType1k) {
|
||||
// Set every block to 0xFF
|
||||
for(uint16_t i = 1; i < block_num; i++) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
nfc_generate_mf_classic_sector_trailer(mfc_data, i);
|
||||
} else {
|
||||
memset(&mfc_data->block[i].data, 0xFF, 16);
|
||||
}
|
||||
mf_classic_set_block_read(mfc_data, i, &mfc_data->block[i]);
|
||||
}
|
||||
// Set SAK to 08
|
||||
mfc_data->iso14443_3a_data->sak = 0x08;
|
||||
} else if(type == MfClassicTypeMini) {
|
||||
// Set every block to 0xFF
|
||||
for(uint16_t i = 1; i < block_num; i++) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
nfc_generate_mf_classic_sector_trailer(mfc_data, i);
|
||||
} else {
|
||||
memset(&mfc_data->block[i].data, 0xFF, 16);
|
||||
}
|
||||
mf_classic_set_block_read(mfc_data, i, &mfc_data->block[i]);
|
||||
}
|
||||
// Set SAK to 09
|
||||
mfc_data->iso14443_3a_data->sak = 0x09;
|
||||
}
|
||||
|
||||
nfc_generate_mf_classic_block_0(
|
||||
mfc_data->block[0].data,
|
||||
uid_len,
|
||||
mfc_data->iso14443_3a_data->sak,
|
||||
mfc_data->iso14443_3a_data->atqa[0],
|
||||
mfc_data->iso14443_3a_data->atqa[1]);
|
||||
|
||||
mfc_data->type = type;
|
||||
|
||||
nfc_device_set_data(nfc_device, NfcProtocolMfClassic, mfc_data);
|
||||
mf_classic_free(mfc_data);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_mini(NfcDevice* nfc_device) {
|
||||
nfc_generate_mf_classic(nfc_device, 4, MfClassicTypeMini);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_1k_4b_uid(NfcDevice* nfc_device) {
|
||||
nfc_generate_mf_classic(nfc_device, 4, MfClassicType1k);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_1k_7b_uid(NfcDevice* nfc_device) {
|
||||
nfc_generate_mf_classic(nfc_device, 7, MfClassicType1k);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_4k_4b_uid(NfcDevice* nfc_device) {
|
||||
nfc_generate_mf_classic(nfc_device, 4, MfClassicType4k);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_4k_7b_uid(NfcDevice* nfc_device) {
|
||||
nfc_generate_mf_classic(nfc_device, 7, MfClassicType4k);
|
||||
}
|
||||
|
||||
static const NfcDataGenerator nfc_data_generator[NfcDataGeneratorTypeNum] = {
|
||||
[NfcDataGeneratorTypeMfUltralight] =
|
||||
{
|
||||
.name = "Mifare Ultralight",
|
||||
.handler = nfc_generate_mf_ul_orig,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfUltralightEV1_11] =
|
||||
{
|
||||
.name = "Mifare Ultralight EV1 11",
|
||||
.handler = nfc_generate_mf_ul_11,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfUltralightEV1_H11] =
|
||||
{
|
||||
.name = "Mifare Ultralight EV1 H11",
|
||||
.handler = nfc_generate_mf_ul_h11,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfUltralightEV1_21] =
|
||||
{
|
||||
.name = "Mifare Ultralight EV1 21",
|
||||
.handler = nfc_generate_mf_ul_21,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfUltralightEV1_H21] =
|
||||
{
|
||||
.name = "Mifare Ultralight EV1 H21",
|
||||
.handler = nfc_generate_mf_ul_h21,
|
||||
},
|
||||
[NfcDataGeneratorTypeNTAG203] =
|
||||
{
|
||||
.name = "NTAG203",
|
||||
.handler = nfc_generate_ntag203,
|
||||
},
|
||||
[NfcDataGeneratorTypeNTAG213] =
|
||||
{
|
||||
.name = "NTAG213",
|
||||
.handler = nfc_generate_ntag213,
|
||||
},
|
||||
[NfcDataGeneratorTypeNTAG215] =
|
||||
{
|
||||
.name = "NTAG215",
|
||||
.handler = nfc_generate_ntag215,
|
||||
},
|
||||
[NfcDataGeneratorTypeNTAG216] =
|
||||
{
|
||||
.name = "NTAG216",
|
||||
.handler = nfc_generate_ntag216,
|
||||
},
|
||||
[NfcDataGeneratorTypeNTAGI2C1k] =
|
||||
{
|
||||
.name = "NTAG I2C 1k",
|
||||
.handler = nfc_generate_ntag_i2c_1k,
|
||||
},
|
||||
[NfcDataGeneratorTypeNTAGI2C2k] =
|
||||
{
|
||||
.name = "NTAG I2C 2k",
|
||||
.handler = nfc_generate_ntag_i2c_2k,
|
||||
},
|
||||
[NfcDataGeneratorTypeNTAGI2CPlus1k] =
|
||||
{
|
||||
.name = "NTAG I2C Plus 1k",
|
||||
.handler = nfc_generate_ntag_i2c_plus_1k,
|
||||
},
|
||||
[NfcDataGeneratorTypeNTAGI2CPlus2k] =
|
||||
{
|
||||
.name = "NTAG I2C Plus 2k",
|
||||
.handler = nfc_generate_ntag_i2c_plus_2k,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfClassicMini] =
|
||||
{
|
||||
.name = "Mifare Mini",
|
||||
.handler = nfc_generate_mf_classic_mini,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfClassic1k_4b] =
|
||||
{
|
||||
.name = "Mifare Classic 1k 4byte UID",
|
||||
.handler = nfc_generate_mf_classic_1k_4b_uid,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfClassic1k_7b] =
|
||||
{
|
||||
.name = "Mifare Classic 1k 7byte UID",
|
||||
.handler = nfc_generate_mf_classic_1k_7b_uid,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfClassic4k_4b] =
|
||||
{
|
||||
.name = "Mifare Classic 4k 4byte UID",
|
||||
.handler = nfc_generate_mf_classic_4k_4b_uid,
|
||||
},
|
||||
[NfcDataGeneratorTypeMfClassic4k_7b] =
|
||||
{
|
||||
.name = "Mifare Classic 4k 7byte UID",
|
||||
.handler = nfc_generate_mf_classic_4k_7b_uid,
|
||||
},
|
||||
};
|
||||
|
||||
const char* nfc_data_generator_get_name(NfcDataGeneratorType type) {
|
||||
return nfc_data_generator[type].name;
|
||||
}
|
||||
|
||||
void nfc_data_generator_fill_data(NfcDataGeneratorType type, NfcDevice* nfc_device) {
|
||||
nfc_data_generator[type].handler(nfc_device);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
NfcDataGeneratorTypeMfUltralight,
|
||||
NfcDataGeneratorTypeMfUltralightEV1_11,
|
||||
NfcDataGeneratorTypeMfUltralightEV1_H11,
|
||||
NfcDataGeneratorTypeMfUltralightEV1_21,
|
||||
NfcDataGeneratorTypeMfUltralightEV1_H21,
|
||||
NfcDataGeneratorTypeNTAG203,
|
||||
NfcDataGeneratorTypeNTAG213,
|
||||
NfcDataGeneratorTypeNTAG215,
|
||||
NfcDataGeneratorTypeNTAG216,
|
||||
NfcDataGeneratorTypeNTAGI2C1k,
|
||||
NfcDataGeneratorTypeNTAGI2C2k,
|
||||
NfcDataGeneratorTypeNTAGI2CPlus1k,
|
||||
NfcDataGeneratorTypeNTAGI2CPlus2k,
|
||||
|
||||
NfcDataGeneratorTypeMfClassicMini,
|
||||
NfcDataGeneratorTypeMfClassic1k_4b,
|
||||
NfcDataGeneratorTypeMfClassic1k_7b,
|
||||
NfcDataGeneratorTypeMfClassic4k_4b,
|
||||
NfcDataGeneratorTypeMfClassic4k_7b,
|
||||
|
||||
NfcDataGeneratorTypeNum,
|
||||
|
||||
} NfcDataGeneratorType;
|
||||
|
||||
const char* nfc_data_generator_get_name(NfcDataGeneratorType type);
|
||||
|
||||
void nfc_data_generator_fill_data(NfcDataGeneratorType type, NfcDevice* nfc_device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "nfc_debug_log.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <stream/buffered_file_stream.h>
|
||||
|
||||
#define TAG "NfcDebugLog"
|
||||
|
||||
#define NFC_DEBUG_PCAP_FILENAME EXT_PATH("nfc/debug.txt")
|
||||
|
||||
struct NfcDebugLog {
|
||||
Stream* file_stream;
|
||||
FuriString* data_str;
|
||||
};
|
||||
|
||||
NfcDebugLog* nfc_debug_log_alloc() {
|
||||
NfcDebugLog* instance = malloc(sizeof(NfcDebugLog));
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
instance->file_stream = buffered_file_stream_alloc(storage);
|
||||
|
||||
if(!buffered_file_stream_open(
|
||||
instance->file_stream, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) {
|
||||
buffered_file_stream_close(instance->file_stream);
|
||||
stream_free(instance->file_stream);
|
||||
instance->file_stream = NULL;
|
||||
}
|
||||
|
||||
if(!instance->file_stream) {
|
||||
free(instance);
|
||||
instance = NULL;
|
||||
} else {
|
||||
instance->data_str = furi_string_alloc();
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void nfc_debug_log_free(NfcDebugLog* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->file_stream);
|
||||
furi_assert(instance->data_str);
|
||||
|
||||
buffered_file_stream_close(instance->file_stream);
|
||||
stream_free(instance->file_stream);
|
||||
furi_string_free(instance->data_str);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void nfc_debug_log_process_data(
|
||||
NfcDebugLog* instance,
|
||||
uint8_t* data,
|
||||
uint16_t len,
|
||||
bool reader_to_tag,
|
||||
bool crc_dropped) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->file_stream);
|
||||
furi_assert(instance->data_str);
|
||||
furi_assert(data);
|
||||
UNUSED(crc_dropped);
|
||||
|
||||
furi_string_printf(instance->data_str, "%lu %c:", furi_get_tick(), reader_to_tag ? 'R' : 'T');
|
||||
uint16_t data_len = len;
|
||||
for(size_t i = 0; i < data_len; i++) {
|
||||
furi_string_cat_printf(instance->data_str, " %02x", data[i]);
|
||||
}
|
||||
furi_string_push_back(instance->data_str, '\n');
|
||||
|
||||
stream_write_string(instance->file_stream, instance->data_str);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct NfcDebugLog NfcDebugLog;
|
||||
|
||||
NfcDebugLog* nfc_debug_log_alloc();
|
||||
|
||||
void nfc_debug_log_free(NfcDebugLog* instance);
|
||||
|
||||
void nfc_debug_log_process_data(
|
||||
NfcDebugLog* instance,
|
||||
uint8_t* data,
|
||||
uint16_t len,
|
||||
bool reader_to_tag,
|
||||
bool crc_dropped);
|
||||
@@ -1,130 +0,0 @@
|
||||
#include "nfc_debug_pcap.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <stream/buffered_file_stream.h>
|
||||
#include <furi_hal_nfc.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#define TAG "NfcDebugPcap"
|
||||
|
||||
#define PCAP_MAGIC 0xa1b2c3d4
|
||||
#define PCAP_MAJOR 2
|
||||
#define PCAP_MINOR 4
|
||||
#define DLT_ISO_14443 264
|
||||
|
||||
#define DATA_PICC_TO_PCD 0xFF
|
||||
#define DATA_PCD_TO_PICC 0xFE
|
||||
#define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB
|
||||
#define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA
|
||||
|
||||
#define NFC_DEBUG_PCAP_FILENAME EXT_PATH("nfc/debug.pcap")
|
||||
|
||||
struct NfcDebugPcap {
|
||||
Stream* file_stream;
|
||||
};
|
||||
|
||||
static Stream* nfc_debug_pcap_open(Storage* storage) {
|
||||
Stream* stream = NULL;
|
||||
stream = buffered_file_stream_alloc(storage);
|
||||
if(!buffered_file_stream_open(stream, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) {
|
||||
buffered_file_stream_close(stream);
|
||||
stream_free(stream);
|
||||
stream = NULL;
|
||||
} else {
|
||||
if(!stream_tell(stream)) {
|
||||
struct {
|
||||
uint32_t magic;
|
||||
uint16_t major, minor;
|
||||
uint32_t reserved[2];
|
||||
uint32_t snaplen;
|
||||
uint32_t link_type;
|
||||
} __attribute__((__packed__)) pcap_hdr = {
|
||||
.magic = PCAP_MAGIC,
|
||||
.major = PCAP_MAJOR,
|
||||
.minor = PCAP_MINOR,
|
||||
.snaplen = FURI_HAL_NFC_DATA_BUFF_SIZE,
|
||||
.link_type = DLT_ISO_14443,
|
||||
};
|
||||
if(stream_write(stream, (uint8_t*)&pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) {
|
||||
FURI_LOG_E(TAG, "Failed to write pcap header");
|
||||
buffered_file_stream_close(stream);
|
||||
stream_free(stream);
|
||||
stream = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
NfcDebugPcap* nfc_debug_pcap_alloc() {
|
||||
NfcDebugPcap* instance = malloc(sizeof(NfcDebugPcap));
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
instance->file_stream = nfc_debug_pcap_open(storage);
|
||||
if(!instance->file_stream) {
|
||||
free(instance);
|
||||
instance = NULL;
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void nfc_debug_pcap_free(NfcDebugPcap* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->file_stream);
|
||||
|
||||
buffered_file_stream_close(instance->file_stream);
|
||||
stream_free(instance->file_stream);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void nfc_debug_pcap_process_data(
|
||||
NfcDebugPcap* instance,
|
||||
uint8_t* data,
|
||||
uint16_t len,
|
||||
bool reader_to_tag,
|
||||
bool crc_dropped) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data);
|
||||
FuriHalRtcDateTime datetime;
|
||||
furi_hal_rtc_get_datetime(&datetime);
|
||||
|
||||
uint8_t event = 0;
|
||||
if(reader_to_tag) {
|
||||
if(crc_dropped) {
|
||||
event = DATA_PCD_TO_PICC_CRC_DROPPED;
|
||||
} else {
|
||||
event = DATA_PCD_TO_PICC;
|
||||
}
|
||||
} else {
|
||||
if(crc_dropped) {
|
||||
event = DATA_PICC_TO_PCD_CRC_DROPPED;
|
||||
} else {
|
||||
event = DATA_PICC_TO_PCD;
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
// https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header
|
||||
uint32_t ts_sec;
|
||||
uint32_t ts_usec;
|
||||
uint32_t incl_len;
|
||||
uint32_t orig_len;
|
||||
// https://www.kaiser.cx/posts/pcap-iso14443/#_packet_data
|
||||
uint8_t version;
|
||||
uint8_t event;
|
||||
uint16_t len;
|
||||
} __attribute__((__packed__)) pkt_hdr = {
|
||||
.ts_sec = furi_hal_rtc_datetime_to_timestamp(&datetime),
|
||||
.ts_usec = 0,
|
||||
.incl_len = len + 4,
|
||||
.orig_len = len + 4,
|
||||
.version = 0,
|
||||
.event = event,
|
||||
.len = len << 8 | len >> 8,
|
||||
};
|
||||
stream_write(instance->file_stream, (uint8_t*)&pkt_hdr, sizeof(pkt_hdr));
|
||||
stream_write(instance->file_stream, data, len);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct NfcDebugPcap NfcDebugPcap;
|
||||
|
||||
NfcDebugPcap* nfc_debug_pcap_alloc();
|
||||
|
||||
void nfc_debug_pcap_free(NfcDebugPcap* instance);
|
||||
|
||||
void nfc_debug_pcap_process_data(
|
||||
NfcDebugPcap* instance,
|
||||
uint8_t* data,
|
||||
uint16_t len,
|
||||
bool reader_to_tag,
|
||||
bool crc_dropped);
|
||||
@@ -0,0 +1,270 @@
|
||||
#include "nfc_dict.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
#include <toolbox/args.h>
|
||||
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
|
||||
#define TAG "NfcDict"
|
||||
|
||||
struct NfcDict {
|
||||
Stream* stream;
|
||||
size_t key_size;
|
||||
size_t key_size_symbols;
|
||||
uint32_t total_keys;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char* path;
|
||||
FS_OpenMode open_mode;
|
||||
} NfcDictFile;
|
||||
|
||||
bool nfc_dict_check_presence(const char* path) {
|
||||
furi_assert(path);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
bool dict_present = storage_common_stat(storage, path, NULL) == FSE_OK;
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return dict_present;
|
||||
}
|
||||
|
||||
NfcDict* nfc_dict_alloc(const char* path, NfcDictMode mode, size_t key_size) {
|
||||
furi_assert(path);
|
||||
|
||||
NfcDict* instance = malloc(sizeof(NfcDict));
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
instance->stream = buffered_file_stream_alloc(storage);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
FS_OpenMode open_mode = FSOM_OPEN_EXISTING;
|
||||
if(mode == NfcDictModeOpenAlways) {
|
||||
open_mode = FSOM_OPEN_ALWAYS;
|
||||
}
|
||||
instance->key_size = key_size;
|
||||
// Byte = 2 symbols + 1 end of line
|
||||
instance->key_size_symbols = key_size * 2 + 1;
|
||||
|
||||
bool dict_loaded = false;
|
||||
do {
|
||||
if(!buffered_file_stream_open(instance->stream, path, FSAM_READ_WRITE, open_mode)) {
|
||||
buffered_file_stream_close(instance->stream);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for new line ending
|
||||
if(!stream_eof(instance->stream)) {
|
||||
if(!stream_seek(instance->stream, -1, StreamOffsetFromEnd)) break;
|
||||
uint8_t last_char = 0;
|
||||
if(stream_read(instance->stream, &last_char, 1) != 1) break;
|
||||
if(last_char != '\n') {
|
||||
FURI_LOG_D(TAG, "Adding new line ending");
|
||||
if(stream_write_char(instance->stream, '\n') != 1) break;
|
||||
}
|
||||
if(!stream_rewind(instance->stream)) break;
|
||||
}
|
||||
|
||||
// Read total amount of keys
|
||||
FuriString* next_line;
|
||||
next_line = furi_string_alloc();
|
||||
while(true) {
|
||||
if(!stream_read_line(instance->stream, next_line)) {
|
||||
FURI_LOG_T(TAG, "No keys left in dict");
|
||||
break;
|
||||
}
|
||||
FURI_LOG_T(
|
||||
TAG,
|
||||
"Read line: %s, len: %zu",
|
||||
furi_string_get_cstr(next_line),
|
||||
furi_string_size(next_line));
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != instance->key_size_symbols) continue;
|
||||
instance->total_keys++;
|
||||
}
|
||||
furi_string_free(next_line);
|
||||
stream_rewind(instance->stream);
|
||||
|
||||
dict_loaded = true;
|
||||
FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", instance->total_keys);
|
||||
} while(false);
|
||||
|
||||
if(!dict_loaded) {
|
||||
buffered_file_stream_close(instance->stream);
|
||||
free(instance);
|
||||
instance = NULL;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void nfc_dict_free(NfcDict* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
buffered_file_stream_close(instance->stream);
|
||||
stream_free(instance->stream);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static void nfc_dict_int_to_str(NfcDict* instance, const uint8_t* key_int, FuriString* key_str) {
|
||||
furi_string_reset(key_str);
|
||||
for(size_t i = 0; i < instance->key_size; i++) {
|
||||
furi_string_cat_printf(key_str, "%02X", key_int[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_dict_str_to_int(NfcDict* instance, FuriString* key_str, uint64_t* key_int) {
|
||||
uint8_t key_byte_tmp;
|
||||
|
||||
*key_int = 0ULL;
|
||||
for(uint8_t i = 0; i < instance->key_size * 2; i += 2) {
|
||||
args_char_to_hex(
|
||||
furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp);
|
||||
*key_int |= (uint64_t)key_byte_tmp << (8 * (instance->key_size - 1 - i / 2));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t nfc_dict_get_total_keys(NfcDict* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->total_keys;
|
||||
}
|
||||
|
||||
bool nfc_dict_rewind(NfcDict* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
return stream_rewind(instance->stream);
|
||||
}
|
||||
|
||||
static bool nfc_dict_get_next_key_str(NfcDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
bool key_read = false;
|
||||
furi_string_reset(key);
|
||||
while(!key_read) {
|
||||
if(!stream_read_line(instance->stream, key)) break;
|
||||
if(furi_string_get_char(key, 0) == '#') continue;
|
||||
if(furi_string_size(key) != instance->key_size_symbols) continue;
|
||||
furi_string_left(key, instance->key_size_symbols - 1);
|
||||
key_read = true;
|
||||
}
|
||||
|
||||
return key_read;
|
||||
}
|
||||
|
||||
bool nfc_dict_get_next_key(NfcDict* instance, uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
uint64_t key_int = 0;
|
||||
bool key_read = nfc_dict_get_next_key_str(instance, temp_key);
|
||||
if(key_read) {
|
||||
nfc_dict_str_to_int(instance, temp_key, &key_int);
|
||||
nfc_util_num2bytes(key_int, key_size, key);
|
||||
}
|
||||
furi_string_free(temp_key);
|
||||
return key_read;
|
||||
}
|
||||
|
||||
static bool nfc_dict_is_key_present_str(NfcDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
FuriString* next_line;
|
||||
next_line = furi_string_alloc();
|
||||
|
||||
bool key_found = false;
|
||||
stream_rewind(instance->stream);
|
||||
while(!key_found) { //-V654
|
||||
if(!stream_read_line(instance->stream, next_line)) break;
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != instance->key_size_symbols) continue;
|
||||
furi_string_left(next_line, instance->key_size_symbols - 1);
|
||||
if(!furi_string_equal(key, next_line)) continue;
|
||||
key_found = true;
|
||||
}
|
||||
|
||||
furi_string_free(next_line);
|
||||
return key_found;
|
||||
}
|
||||
|
||||
bool nfc_dict_is_key_present(NfcDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(key);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
nfc_dict_int_to_str(instance, key, temp_key);
|
||||
bool key_found = nfc_dict_is_key_present_str(instance, temp_key);
|
||||
furi_string_free(temp_key);
|
||||
|
||||
return key_found;
|
||||
}
|
||||
|
||||
static bool nfc_dict_add_key_str(NfcDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
furi_string_cat_printf(key, "\n");
|
||||
|
||||
bool key_added = false;
|
||||
do {
|
||||
if(!stream_seek(instance->stream, 0, StreamOffsetFromEnd)) break;
|
||||
if(!stream_insert_string(instance->stream, key)) break;
|
||||
instance->total_keys++;
|
||||
key_added = true;
|
||||
} while(false);
|
||||
|
||||
furi_string_left(key, instance->key_size_symbols - 1);
|
||||
return key_added;
|
||||
}
|
||||
|
||||
bool nfc_dict_add_key(NfcDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(key);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
nfc_dict_int_to_str(instance, key, temp_key);
|
||||
bool key_added = nfc_dict_add_key_str(instance, temp_key);
|
||||
furi_string_free(temp_key);
|
||||
|
||||
return key_added;
|
||||
}
|
||||
|
||||
bool nfc_dict_delete_key(NfcDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(key);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
|
||||
bool key_removed = false;
|
||||
uint8_t* temp_key = malloc(key_size);
|
||||
|
||||
nfc_dict_rewind(instance);
|
||||
while(!key_removed) {
|
||||
if(!nfc_dict_get_next_key(instance, temp_key, key_size)) break;
|
||||
if(memcmp(temp_key, key, key_size) == 0) {
|
||||
int32_t offset = (-1) * (instance->key_size_symbols);
|
||||
stream_seek(instance->stream, offset, StreamOffsetFromCurrent);
|
||||
if(!stream_delete(instance->stream, instance->key_size_symbols)) break;
|
||||
instance->total_keys--;
|
||||
key_removed = true;
|
||||
}
|
||||
}
|
||||
nfc_dict_rewind(instance);
|
||||
free(temp_key);
|
||||
|
||||
return key_removed;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
NfcDictModeOpenExisting,
|
||||
NfcDictModeOpenAlways,
|
||||
} NfcDictMode;
|
||||
|
||||
typedef struct NfcDict NfcDict;
|
||||
|
||||
/** Check dictionary presence
|
||||
*
|
||||
* @param path - dictionary path
|
||||
*
|
||||
* @return true if dictionary exists, false otherwise
|
||||
*/
|
||||
bool nfc_dict_check_presence(const char* path);
|
||||
|
||||
/** Open or create dictionary
|
||||
* Depending on mode, dictionary will be opened or created.
|
||||
*
|
||||
* @param path - dictionary path
|
||||
* @param mode - NfcDictMode value
|
||||
* @param key_size - size of dictionary keys in bytes
|
||||
*
|
||||
* @return NfcDict dictionary instance
|
||||
*/
|
||||
NfcDict* nfc_dict_alloc(const char* path, NfcDictMode mode, size_t key_size);
|
||||
|
||||
/** Close dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
*/
|
||||
void nfc_dict_free(NfcDict* instance);
|
||||
|
||||
/** Get total number of keys in dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
*
|
||||
* @return total number of keys in dictionary
|
||||
*/
|
||||
uint32_t nfc_dict_get_total_keys(NfcDict* instance);
|
||||
|
||||
/** Rewind dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
*
|
||||
* @return true if rewind was successful, false otherwise
|
||||
*/
|
||||
bool nfc_dict_rewind(NfcDict* instance);
|
||||
|
||||
/** Check if key is present in dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
* @param key - key to check
|
||||
* @param key_size - size of key in bytes
|
||||
*
|
||||
* @return true if key is present, false otherwise
|
||||
*/
|
||||
bool nfc_dict_is_key_present(NfcDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
/** Get next key from dictionary
|
||||
* This function will return next key from dictionary. If there are no more
|
||||
* keys, it will return false, and nfc_dict_rewind() should be called.
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
* @param key - buffer to store key
|
||||
* @param key_size - size of key in bytes
|
||||
*
|
||||
* @return true if key was successfully retrieved, false otherwise
|
||||
*/
|
||||
bool nfc_dict_get_next_key(NfcDict* instance, uint8_t* key, size_t key_size);
|
||||
|
||||
/** Add key to dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
* @param key - key to add
|
||||
* @param key_size - size of key in bytes
|
||||
*
|
||||
* @return true if key was successfully added, false otherwise
|
||||
*/
|
||||
bool nfc_dict_add_key(NfcDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
/** Delete key from dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
* @param key - key to delete
|
||||
* @param key_size - size of key in bytes
|
||||
*
|
||||
* @return true if key was successfully deleted, false otherwise
|
||||
*/
|
||||
bool nfc_dict_delete_key(NfcDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,548 +0,0 @@
|
||||
#include <furi_hal_random.h>
|
||||
#include "nfc_generators.h"
|
||||
|
||||
#define NXP_MANUFACTURER_ID (0x04)
|
||||
|
||||
static const uint8_t version_bytes_mf0ulx1[] = {0x00, 0x04, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03};
|
||||
static const uint8_t version_bytes_ntag21x[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x03};
|
||||
static const uint8_t version_bytes_ntag_i2c[] = {0x00, 0x04, 0x04, 0x05, 0x02, 0x00, 0x00, 0x03};
|
||||
static const uint8_t default_data_ntag203[] =
|
||||
{0xE1, 0x10, 0x12, 0x00, 0x01, 0x03, 0xA0, 0x10, 0x44, 0x03, 0x00, 0xFE};
|
||||
static const uint8_t default_data_ntag213[] = {0x01, 0x03, 0xA0, 0x0C, 0x34, 0x03, 0x00, 0xFE};
|
||||
static const uint8_t default_data_ntag215_216[] = {0x03, 0x00, 0xFE};
|
||||
static const uint8_t default_data_ntag_i2c[] = {0xE1, 0x10, 0x00, 0x00, 0x03, 0x00, 0xFE};
|
||||
static const uint8_t default_config_ntag_i2c[] = {0x01, 0x00, 0xF8, 0x48, 0x08, 0x01, 0x00, 0x00};
|
||||
|
||||
static void nfc_generate_common_start(NfcDeviceData* data) {
|
||||
nfc_device_data_clear(data);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_uid(uint8_t* uid) {
|
||||
uid[0] = NXP_MANUFACTURER_ID;
|
||||
furi_hal_random_fill_buf(&uid[1], 6);
|
||||
// I'm not sure how this is generated, but the upper nybble always seems to be 8
|
||||
uid[6] &= 0x0F;
|
||||
uid[6] |= 0x80;
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_uid(uint8_t* uid, uint8_t length) {
|
||||
uid[0] = NXP_MANUFACTURER_ID;
|
||||
furi_hal_random_fill_buf(&uid[1], length - 1);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_block_0(
|
||||
uint8_t* block,
|
||||
uint8_t uid_len,
|
||||
uint8_t sak,
|
||||
uint8_t atqa0,
|
||||
uint8_t atqa1) {
|
||||
// Block length is always 16 bytes, and the UID can be either 4 or 7 bytes
|
||||
furi_assert(uid_len == 4 || uid_len == 7);
|
||||
furi_assert(block);
|
||||
|
||||
if(uid_len == 4) {
|
||||
// Calculate BCC
|
||||
block[uid_len] = 0;
|
||||
|
||||
for(int i = 0; i < uid_len; i++) {
|
||||
block[uid_len] ^= block[i];
|
||||
}
|
||||
} else {
|
||||
uid_len -= 1;
|
||||
}
|
||||
|
||||
block[uid_len + 1] = sak;
|
||||
block[uid_len + 2] = atqa0;
|
||||
block[uid_len + 3] = atqa1;
|
||||
|
||||
for(int i = uid_len + 4; i < 16; i++) {
|
||||
block[i] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_sector_trailer(MfClassicData* data, uint8_t block) {
|
||||
// All keys are set to FFFF FFFF FFFFh at chip delivery and the bytes 6, 7 and 8 are set to FF0780h.
|
||||
MfClassicSectorTrailer* sec_tr = (MfClassicSectorTrailer*)data->block[block].value;
|
||||
sec_tr->access_bits[0] = 0xFF;
|
||||
sec_tr->access_bits[1] = 0x07;
|
||||
sec_tr->access_bits[2] = 0x80;
|
||||
sec_tr->access_bits[3] = 0x69; // Nice
|
||||
|
||||
memset(sec_tr->key_a, 0xff, sizeof(sec_tr->key_a));
|
||||
memset(sec_tr->key_b, 0xff, sizeof(sec_tr->key_b));
|
||||
|
||||
mf_classic_set_block_read(data, block, &data->block[block]);
|
||||
mf_classic_set_key_found(
|
||||
data, mf_classic_get_sector_by_block(block), MfClassicKeyA, 0xFFFFFFFFFFFF);
|
||||
mf_classic_set_key_found(
|
||||
data, mf_classic_get_sector_by_block(block), MfClassicKeyB, 0xFFFFFFFFFFFF);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_common(NfcDeviceData* data) {
|
||||
data->nfc_data.type = FuriHalNfcTypeA;
|
||||
data->nfc_data.interface = FuriHalNfcInterfaceRf;
|
||||
data->nfc_data.uid_len = 7;
|
||||
nfc_generate_mf_ul_uid(data->nfc_data.uid);
|
||||
data->nfc_data.atqa[0] = 0x44;
|
||||
data->nfc_data.atqa[1] = 0x00;
|
||||
data->nfc_data.sak = 0x00;
|
||||
data->protocol = NfcDeviceProtocolMifareUl;
|
||||
}
|
||||
|
||||
static void
|
||||
nfc_generate_mf_classic_common(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) {
|
||||
data->nfc_data.type = FuriHalNfcTypeA;
|
||||
data->nfc_data.interface = FuriHalNfcInterfaceRf;
|
||||
data->nfc_data.uid_len = uid_len;
|
||||
data->nfc_data.atqa[0] = 0x44;
|
||||
data->nfc_data.atqa[1] = 0x00;
|
||||
data->nfc_data.sak = 0x08;
|
||||
data->protocol = NfcDeviceProtocolMifareClassic;
|
||||
data->mf_classic_data.type = type;
|
||||
}
|
||||
|
||||
static void nfc_generate_calc_bcc(uint8_t* uid, uint8_t* bcc0, uint8_t* bcc1) {
|
||||
*bcc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2];
|
||||
*bcc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6];
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_copy_uid_with_bcc(NfcDeviceData* data) {
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
memcpy(mful->data, data->nfc_data.uid, 3);
|
||||
memcpy(&mful->data[4], &data->nfc_data.uid[3], 4);
|
||||
nfc_generate_calc_bcc(data->nfc_data.uid, &mful->data[3], &mful->data[8]);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_orig(NfcDeviceData* data) {
|
||||
nfc_generate_common_start(data);
|
||||
nfc_generate_mf_ul_common(data);
|
||||
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeUnknown;
|
||||
mful->data_size = 16 * 4;
|
||||
mful->data_read = mful->data_size;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(data);
|
||||
// TODO: what's internal byte on page 2?
|
||||
memset(&mful->data[4 * 4], 0xFF, 4);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_ntag203(NfcDeviceData* data) {
|
||||
nfc_generate_common_start(data);
|
||||
nfc_generate_mf_ul_common(data);
|
||||
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeNTAG203;
|
||||
mful->data_size = 42 * 4;
|
||||
mful->data_read = mful->data_size;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(data);
|
||||
mful->data[9] = 0x48; // Internal byte
|
||||
memcpy(&mful->data[3 * 4], default_data_ntag203, sizeof(default_data_ntag203));
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_with_config_common(NfcDeviceData* data, uint8_t num_pages) {
|
||||
nfc_generate_common_start(data);
|
||||
nfc_generate_mf_ul_common(data);
|
||||
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->data_size = num_pages * 4;
|
||||
mful->data_read = mful->data_size;
|
||||
nfc_generate_mf_ul_copy_uid_with_bcc(data);
|
||||
uint16_t config_index = (num_pages - 4) * 4;
|
||||
mful->data[config_index] = 0x04; // STRG_MOD_EN
|
||||
mful->data[config_index + 3] = 0xFF; // AUTH0
|
||||
mful->data[config_index + 5] = 0x05; // VCTID
|
||||
memset(&mful->data[config_index + 8], 0xFF, 4); // Default PWD
|
||||
if(num_pages > 20) mful->data[config_index - 1] = MF_UL_TEARING_FLAG_DEFAULT;
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_ev1_common(NfcDeviceData* data, uint8_t num_pages) {
|
||||
nfc_generate_mf_ul_with_config_common(data, num_pages);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
memcpy(&mful->version, version_bytes_mf0ulx1, sizeof(version_bytes_mf0ulx1));
|
||||
for(size_t i = 0; i < 3; ++i) {
|
||||
mful->tearing[i] = MF_UL_TEARING_FLAG_DEFAULT;
|
||||
}
|
||||
// TODO: what's internal byte on page 2?
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_11(NfcDeviceData* data) {
|
||||
nfc_generate_mf_ul_ev1_common(data, 20);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeUL11;
|
||||
mful->version.prod_subtype = 0x01;
|
||||
mful->version.storage_size = 0x0B;
|
||||
mful->data[16 * 4] = 0x00; // Low capacitance version does not have STRG_MOD_EN
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_h11(NfcDeviceData* data) {
|
||||
nfc_generate_mf_ul_ev1_common(data, 20);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeUL11;
|
||||
mful->version.prod_subtype = 0x02;
|
||||
mful->version.storage_size = 0x0B;
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_21(NfcDeviceData* data) {
|
||||
nfc_generate_mf_ul_ev1_common(data, 41);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeUL21;
|
||||
mful->version.prod_subtype = 0x01;
|
||||
mful->version.storage_size = 0x0E;
|
||||
mful->data[37 * 4] = 0x00; // Low capacitance version does not have STRG_MOD_EN
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_ul_h21(NfcDeviceData* data) {
|
||||
nfc_generate_mf_ul_ev1_common(data, 41);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeUL21;
|
||||
mful->version.prod_subtype = 0x02;
|
||||
mful->version.storage_size = 0x0E;
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag21x_common(NfcDeviceData* data, uint8_t num_pages) {
|
||||
nfc_generate_mf_ul_with_config_common(data, num_pages);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
memcpy(&mful->version, version_bytes_ntag21x, sizeof(version_bytes_mf0ulx1));
|
||||
mful->data[9] = 0x48; // Internal byte
|
||||
// Capability container
|
||||
mful->data[12] = 0xE1;
|
||||
mful->data[13] = 0x10;
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag213(NfcDeviceData* data) {
|
||||
nfc_generate_ntag21x_common(data, 45);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeNTAG213;
|
||||
mful->version.storage_size = 0x0F;
|
||||
mful->data[14] = 0x12;
|
||||
// Default contents
|
||||
memcpy(&mful->data[16], default_data_ntag213, sizeof(default_data_ntag213));
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag215(NfcDeviceData* data) {
|
||||
nfc_generate_ntag21x_common(data, 135);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeNTAG215;
|
||||
mful->version.storage_size = 0x11;
|
||||
mful->data[14] = 0x3E;
|
||||
// Default contents
|
||||
memcpy(&mful->data[16], default_data_ntag215_216, sizeof(default_data_ntag215_216));
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag216(NfcDeviceData* data) {
|
||||
nfc_generate_ntag21x_common(data, 231);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = MfUltralightTypeNTAG216;
|
||||
mful->version.storage_size = 0x13;
|
||||
mful->data[14] = 0x6D;
|
||||
// Default contents
|
||||
memcpy(&mful->data[16], default_data_ntag215_216, sizeof(default_data_ntag215_216));
|
||||
}
|
||||
|
||||
static void
|
||||
nfc_generate_ntag_i2c_common(NfcDeviceData* data, MfUltralightType type, uint16_t num_pages) {
|
||||
nfc_generate_common_start(data);
|
||||
nfc_generate_mf_ul_common(data);
|
||||
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->type = type;
|
||||
memcpy(&mful->version, version_bytes_ntag_i2c, sizeof(version_bytes_ntag_i2c));
|
||||
mful->data_size = num_pages * 4;
|
||||
mful->data_read = mful->data_size;
|
||||
memcpy(mful->data, data->nfc_data.uid, data->nfc_data.uid_len);
|
||||
mful->data[7] = data->nfc_data.sak;
|
||||
mful->data[8] = data->nfc_data.atqa[0];
|
||||
mful->data[9] = data->nfc_data.atqa[1];
|
||||
|
||||
uint16_t config_register_page;
|
||||
uint16_t session_register_page;
|
||||
|
||||
// Sync with mifare_ultralight.c
|
||||
switch(type) {
|
||||
case MfUltralightTypeNTAGI2C1K:
|
||||
config_register_page = 227;
|
||||
session_register_page = 229;
|
||||
break;
|
||||
case MfUltralightTypeNTAGI2C2K:
|
||||
config_register_page = 481;
|
||||
session_register_page = 483;
|
||||
break;
|
||||
case MfUltralightTypeNTAGI2CPlus1K:
|
||||
case MfUltralightTypeNTAGI2CPlus2K:
|
||||
config_register_page = 232;
|
||||
session_register_page = 234;
|
||||
break;
|
||||
default:
|
||||
furi_crash("Unknown MFUL");
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(
|
||||
&mful->data[config_register_page * 4],
|
||||
default_config_ntag_i2c,
|
||||
sizeof(default_config_ntag_i2c));
|
||||
memcpy(
|
||||
&mful->data[session_register_page * 4],
|
||||
default_config_ntag_i2c,
|
||||
sizeof(default_config_ntag_i2c));
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_1k(NfcDeviceData* data) {
|
||||
nfc_generate_ntag_i2c_common(data, MfUltralightTypeNTAGI2C1K, 231);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->version.prod_ver_minor = 0x01;
|
||||
mful->version.storage_size = 0x13;
|
||||
|
||||
memcpy(&mful->data[12], default_data_ntag_i2c, sizeof(default_data_ntag_i2c));
|
||||
mful->data[14] = 0x6D; // Size of tag in CC
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_2k(NfcDeviceData* data) {
|
||||
nfc_generate_ntag_i2c_common(data, MfUltralightTypeNTAGI2C2K, 485);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->version.prod_ver_minor = 0x01;
|
||||
mful->version.storage_size = 0x15;
|
||||
|
||||
memcpy(&mful->data[12], default_data_ntag_i2c, sizeof(default_data_ntag_i2c));
|
||||
mful->data[14] = 0xEA; // Size of tag in CC
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_plus_common(
|
||||
NfcDeviceData* data,
|
||||
MfUltralightType type,
|
||||
uint16_t num_pages) {
|
||||
nfc_generate_ntag_i2c_common(data, type, num_pages);
|
||||
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
uint16_t config_index = 227 * 4;
|
||||
mful->data[config_index + 3] = 0xFF; // AUTH0
|
||||
memset(&mful->data[config_index + 8], 0xFF, 4); // Default PWD
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_plus_1k(NfcDeviceData* data) {
|
||||
nfc_generate_ntag_i2c_plus_common(data, MfUltralightTypeNTAGI2CPlus1K, 236);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->version.prod_ver_minor = 0x02;
|
||||
mful->version.storage_size = 0x13;
|
||||
}
|
||||
|
||||
static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) {
|
||||
nfc_generate_ntag_i2c_plus_common(data, MfUltralightTypeNTAGI2CPlus2K, 492);
|
||||
MfUltralightData* mful = &data->mf_ul_data;
|
||||
mful->version.prod_ver_minor = 0x02;
|
||||
mful->version.storage_size = 0x15;
|
||||
}
|
||||
|
||||
void nfc_generate_mf_classic_ext(
|
||||
NfcDeviceData* data,
|
||||
uint8_t uid_len,
|
||||
MfClassicType type,
|
||||
bool random_uid,
|
||||
uint8_t* uid) {
|
||||
nfc_generate_common_start(data);
|
||||
if(random_uid) {
|
||||
nfc_generate_mf_classic_uid(data->mf_classic_data.block[0].value, uid_len);
|
||||
} else {
|
||||
memcpy(data->mf_classic_data.block[0].value, uid, uid_len);
|
||||
}
|
||||
nfc_generate_mf_classic_common(data, uid_len, type);
|
||||
|
||||
// Set the UID
|
||||
if(random_uid) {
|
||||
data->nfc_data.uid[0] = NXP_MANUFACTURER_ID;
|
||||
for(int i = 1; i < uid_len; i++) {
|
||||
data->nfc_data.uid[i] = data->mf_classic_data.block[0].value[i];
|
||||
}
|
||||
} else {
|
||||
for(int i = 0; i < uid_len; i++) {
|
||||
data->nfc_data.uid[i] = data->mf_classic_data.block[0].value[i];
|
||||
}
|
||||
}
|
||||
|
||||
MfClassicData* mfc = &data->mf_classic_data;
|
||||
mf_classic_set_block_read(mfc, 0, &mfc->block[0]);
|
||||
|
||||
if(type == MfClassicType4k) {
|
||||
// Set every block to 0xFF
|
||||
for(uint16_t i = 1; i < 256; i += 1) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
nfc_generate_mf_classic_sector_trailer(mfc, i);
|
||||
} else {
|
||||
memset(&mfc->block[i].value, 0xFF, 16);
|
||||
}
|
||||
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
|
||||
}
|
||||
// Set SAK to 18
|
||||
data->nfc_data.sak = 0x18;
|
||||
} else if(type == MfClassicType1k) {
|
||||
// Set every block to 0xFF
|
||||
for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
nfc_generate_mf_classic_sector_trailer(mfc, i);
|
||||
} else {
|
||||
memset(&mfc->block[i].value, 0xFF, 16);
|
||||
}
|
||||
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
|
||||
}
|
||||
// Set SAK to 08
|
||||
data->nfc_data.sak = 0x08;
|
||||
} else if(type == MfClassicTypeMini) {
|
||||
// Set every block to 0xFF
|
||||
for(uint16_t i = 1; i < MF_MINI_TOTAL_SECTORS_NUM * 4; i += 1) {
|
||||
if(mf_classic_is_sector_trailer(i)) {
|
||||
nfc_generate_mf_classic_sector_trailer(mfc, i);
|
||||
} else {
|
||||
memset(&mfc->block[i].value, 0xFF, 16);
|
||||
}
|
||||
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
|
||||
}
|
||||
// Set SAK to 09
|
||||
data->nfc_data.sak = 0x09;
|
||||
}
|
||||
|
||||
nfc_generate_mf_classic_block_0(
|
||||
data->mf_classic_data.block[0].value,
|
||||
uid_len,
|
||||
data->nfc_data.sak,
|
||||
data->nfc_data.atqa[0],
|
||||
data->nfc_data.atqa[1]);
|
||||
|
||||
mfc->type = type;
|
||||
}
|
||||
|
||||
void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) {
|
||||
uint8_t uid = 0;
|
||||
nfc_generate_mf_classic_ext(data, uid_len, type, true, &uid);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_mini(NfcDeviceData* data) {
|
||||
nfc_generate_mf_classic(data, 4, MfClassicTypeMini);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_1k_4b_uid(NfcDeviceData* data) {
|
||||
nfc_generate_mf_classic(data, 4, MfClassicType1k);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_1k_7b_uid(NfcDeviceData* data) {
|
||||
nfc_generate_mf_classic(data, 7, MfClassicType1k);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_4k_4b_uid(NfcDeviceData* data) {
|
||||
nfc_generate_mf_classic(data, 4, MfClassicType4k);
|
||||
}
|
||||
|
||||
static void nfc_generate_mf_classic_4k_7b_uid(NfcDeviceData* data) {
|
||||
nfc_generate_mf_classic(data, 7, MfClassicType4k);
|
||||
}
|
||||
|
||||
static const NfcGenerator mf_ul_generator = {
|
||||
.name = "Mifare Ultralight",
|
||||
.generator_func = nfc_generate_mf_ul_orig,
|
||||
};
|
||||
|
||||
static const NfcGenerator mf_ul_11_generator = {
|
||||
.name = "Mifare Ultralight EV1 11",
|
||||
.generator_func = nfc_generate_mf_ul_11,
|
||||
};
|
||||
|
||||
static const NfcGenerator mf_ul_h11_generator = {
|
||||
.name = "Mifare Ultralight EV1 H11",
|
||||
.generator_func = nfc_generate_mf_ul_h11,
|
||||
};
|
||||
|
||||
static const NfcGenerator mf_ul_21_generator = {
|
||||
.name = "Mifare Ultralight EV1 21",
|
||||
.generator_func = nfc_generate_mf_ul_21,
|
||||
};
|
||||
|
||||
static const NfcGenerator mf_ul_h21_generator = {
|
||||
.name = "Mifare Ultralight EV1 H21",
|
||||
.generator_func = nfc_generate_mf_ul_h21,
|
||||
};
|
||||
|
||||
static const NfcGenerator ntag203_generator = {
|
||||
.name = "NTAG203",
|
||||
.generator_func = nfc_generate_mf_ul_ntag203,
|
||||
};
|
||||
|
||||
static const NfcGenerator ntag213_generator = {
|
||||
.name = "NTAG213",
|
||||
.generator_func = nfc_generate_ntag213,
|
||||
};
|
||||
|
||||
static const NfcGenerator ntag215_generator = {
|
||||
.name = "NTAG215",
|
||||
.generator_func = nfc_generate_ntag215,
|
||||
};
|
||||
|
||||
static const NfcGenerator ntag216_generator = {
|
||||
.name = "NTAG216",
|
||||
.generator_func = nfc_generate_ntag216,
|
||||
};
|
||||
|
||||
static const NfcGenerator ntag_i2c_1k_generator = {
|
||||
.name = "NTAG I2C 1k",
|
||||
.generator_func = nfc_generate_ntag_i2c_1k,
|
||||
};
|
||||
|
||||
static const NfcGenerator ntag_i2c_2k_generator = {
|
||||
.name = "NTAG I2C 2k",
|
||||
.generator_func = nfc_generate_ntag_i2c_2k,
|
||||
};
|
||||
|
||||
static const NfcGenerator ntag_i2c_plus_1k_generator = {
|
||||
.name = "NTAG I2C Plus 1k",
|
||||
.generator_func = nfc_generate_ntag_i2c_plus_1k,
|
||||
};
|
||||
|
||||
static const NfcGenerator ntag_i2c_plus_2k_generator = {
|
||||
.name = "NTAG I2C Plus 2k",
|
||||
.generator_func = nfc_generate_ntag_i2c_plus_2k,
|
||||
};
|
||||
|
||||
static const NfcGenerator mifare_mini_generator = {
|
||||
.name = "Mifare Mini",
|
||||
.generator_func = nfc_generate_mf_mini,
|
||||
};
|
||||
|
||||
static const NfcGenerator mifare_classic_1k_4b_uid_generator = {
|
||||
.name = "Mifare Classic 1k 4byte UID",
|
||||
.generator_func = nfc_generate_mf_classic_1k_4b_uid,
|
||||
};
|
||||
|
||||
static const NfcGenerator mifare_classic_1k_7b_uid_generator = {
|
||||
.name = "Mifare Classic 1k 7byte UID",
|
||||
.generator_func = nfc_generate_mf_classic_1k_7b_uid,
|
||||
};
|
||||
|
||||
static const NfcGenerator mifare_classic_4k_4b_uid_generator = {
|
||||
.name = "Mifare Classic 4k 4byte UID",
|
||||
.generator_func = nfc_generate_mf_classic_4k_4b_uid,
|
||||
};
|
||||
|
||||
static const NfcGenerator mifare_classic_4k_7b_uid_generator = {
|
||||
.name = "Mifare Classic 4k 7byte UID",
|
||||
.generator_func = nfc_generate_mf_classic_4k_7b_uid,
|
||||
};
|
||||
|
||||
const NfcGenerator* const nfc_generators[] = {
|
||||
&mf_ul_generator,
|
||||
&mf_ul_11_generator,
|
||||
&mf_ul_h11_generator,
|
||||
&mf_ul_21_generator,
|
||||
&mf_ul_h21_generator,
|
||||
&ntag203_generator,
|
||||
&ntag213_generator,
|
||||
&ntag215_generator,
|
||||
&ntag216_generator,
|
||||
&ntag_i2c_1k_generator,
|
||||
&ntag_i2c_2k_generator,
|
||||
&ntag_i2c_plus_1k_generator,
|
||||
&ntag_i2c_plus_2k_generator,
|
||||
&mifare_mini_generator,
|
||||
&mifare_classic_1k_4b_uid_generator,
|
||||
&mifare_classic_1k_7b_uid_generator,
|
||||
&mifare_classic_4k_4b_uid_generator,
|
||||
&mifare_classic_4k_7b_uid_generator,
|
||||
NULL,
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "../nfc_device.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*NfcGeneratorFunc)(NfcDeviceData* data);
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
NfcGeneratorFunc generator_func;
|
||||
} NfcGenerator;
|
||||
|
||||
extern const NfcGenerator* const nfc_generators[];
|
||||
|
||||
void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type);
|
||||
|
||||
void nfc_generate_mf_classic_ext(
|
||||
NfcDeviceData* data,
|
||||
uint8_t uid_len,
|
||||
MfClassicType type,
|
||||
bool random_uid,
|
||||
uint8_t* uid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user