added driver directories and bsp

master
Ondřej Hruška 7 years ago
parent 018b69cdc8
commit 11ccc7496e
  1. 1
      .gitignore
  2. 46
      .idea/workspace.xml
  3. 208
      Drivers/BSP/Components/sx1272/Release_Notes.html
  4. 1703
      Drivers/BSP/Components/sx1272/sx1272.c
  5. 523
      Drivers/BSP/Components/sx1272/sx1272.h
  6. 1134
      Drivers/BSP/Components/sx1272/sx1272Regs-Fsk.h
  7. 545
      Drivers/BSP/Components/sx1272/sx1272Regs-LoRa.h
  8. 269
      Drivers/BSP/sx1272mb2das/Release_Notes.html
  9. 262
      Drivers/BSP/sx1272mb2das/sx1272mb2das.c
  10. 98
      Drivers/BSP/sx1272mb2das/sx1272mb2das.h
  11. 147
      Middlewares/Third_Party/Lora/Conf/Commissioning_template.h
  12. 154
      Middlewares/Third_Party/Lora/Conf/Inc/hw_gpio_template.h
  13. 181
      Middlewares/Third_Party/Lora/Conf/Inc/hw_rtc_template.h
  14. 128
      Middlewares/Third_Party/Lora/Conf/Inc/hw_spi_template.h
  15. 87
      Middlewares/Third_Party/Lora/Conf/Inc/hw_template.h
  16. 192
      Middlewares/Third_Party/Lora/Conf/Src/hw_gpio_template.c
  17. 632
      Middlewares/Third_Party/Lora/Conf/Src/hw_rtc_template.c
  18. 224
      Middlewares/Third_Party/Lora/Conf/Src/hw_spi_template.c
  19. 773
      Middlewares/Third_Party/Lora/Core/lora.c
  20. 251
      Middlewares/Third_Party/Lora/Core/lora.h
  21. 88
      Middlewares/Third_Party/Lora/Core/lora_mac_version.h
  22. 936
      Middlewares/Third_Party/Lora/Crypto/aes.c
  23. 160
      Middlewares/Third_Party/Lora/Crypto/aes.h
  24. 153
      Middlewares/Third_Party/Lora/Crypto/cmac.c
  25. 63
      Middlewares/Third_Party/Lora/Crypto/cmac.h
  26. 25
      Middlewares/Third_Party/Lora/LICENSE.txt
  27. 3353
      Middlewares/Third_Party/Lora/Mac/LoRaMac.c
  28. 1961
      Middlewares/Third_Party/Lora/Mac/LoRaMac.h
  29. 202
      Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto.c
  30. 111
      Middlewares/Third_Party/Lora/Mac/LoRaMacCrypto.h
  31. 81
      Middlewares/Third_Party/Lora/Mac/LoRaMacTest.h
  32. 1037
      Middlewares/Third_Party/Lora/Mac/region/Region.c
  33. 1492
      Middlewares/Third_Party/Lora/Mac/region/Region.h
  34. 1101
      Middlewares/Third_Party/Lora/Mac/region/RegionAS923.c
  35. 503
      Middlewares/Third_Party/Lora/Mac/region/RegionAS923.h
  36. 863
      Middlewares/Third_Party/Lora/Mac/region/RegionAU915.c
  37. 455
      Middlewares/Third_Party/Lora/Mac/region/RegionAU915.h
  38. 814
      Middlewares/Third_Party/Lora/Mac/region/RegionCN470.c
  39. 441
      Middlewares/Third_Party/Lora/Mac/region/RegionCN470.h
  40. 1051
      Middlewares/Third_Party/Lora/Mac/region/RegionCN779.c
  41. 465
      Middlewares/Third_Party/Lora/Mac/region/RegionCN779.h
  42. 362
      Middlewares/Third_Party/Lora/Mac/region/RegionCommon.c
  43. 367
      Middlewares/Third_Party/Lora/Mac/region/RegionCommon.h
  44. 1051
      Middlewares/Third_Party/Lora/Mac/region/RegionEU433.c
  45. 466
      Middlewares/Third_Party/Lora/Mac/region/RegionEU433.h
  46. 1082
      Middlewares/Third_Party/Lora/Mac/region/RegionEU868.c
  47. 487
      Middlewares/Third_Party/Lora/Mac/region/RegionEU868.h
  48. 1051
      Middlewares/Third_Party/Lora/Mac/region/RegionIN865.c
  49. 468
      Middlewares/Third_Party/Lora/Mac/region/RegionIN865.h
  50. 1052
      Middlewares/Third_Party/Lora/Mac/region/RegionKR920.c
  51. 478
      Middlewares/Third_Party/Lora/Mac/region/RegionKR920.h
  52. 964
      Middlewares/Third_Party/Lora/Mac/region/RegionUS915-Hybrid.c
  53. 448
      Middlewares/Third_Party/Lora/Mac/region/RegionUS915-Hybrid.h
  54. 871
      Middlewares/Third_Party/Lora/Mac/region/RegionUS915.c
  55. 448
      Middlewares/Third_Party/Lora/Mac/region/RegionUS915.h
  56. 86
      Middlewares/Third_Party/Lora/Mac/timer.h
  57. 350
      Middlewares/Third_Party/Lora/Phy/radio.h
  58. 77
      Middlewares/Third_Party/Lora/Utilities/delay.c
  59. 29
      Middlewares/Third_Party/Lora/Utilities/delay.h
  60. 149
      Middlewares/Third_Party/Lora/Utilities/low_power.c
  61. 98
      Middlewares/Third_Party/Lora/Utilities/low_power.h
  62. 406
      Middlewares/Third_Party/Lora/Utilities/timeServer.c
  63. 164
      Middlewares/Third_Party/Lora/Utilities/timeServer.h
  64. 85
      Middlewares/Third_Party/Lora/Utilities/utilities.c
  65. 175
      Middlewares/Third_Party/Lora/Utilities/utilities.h
  66. 750
      Middlewares/Third_Party/Lora/readme.md
  67. 182
      Middlewares/Third_Party/Lora/st_readme.txt

1
.gitignore vendored

@ -3,3 +3,4 @@ cmake-*
*.o
*.elf
*.a
.idea/

@ -11,7 +11,9 @@
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="38654d8d-41ef-479b-814f-5f05e90ab5b0" name="Default" comment="" />
<list default="true" id="38654d8d-41ef-479b-814f-5f05e90ab5b0" name="Default" comment="">
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
</list>
<ignored path="$PROJECT_DIR$/cmake-build-debug/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
@ -22,7 +24,7 @@
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="CMakeLists.txt" pinned="false" current-in-tab="true">
<file leaf-file-name="CMakeLists.txt" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/CMakeLists.txt">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1173">
@ -32,8 +34,21 @@
</provider>
</entry>
</file>
<file leaf-file-name="main.c" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/Src/main.c">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1003">
<caret line="37" column="0" lean-forward="false" selection-start-line="37" selection-start-column="0" selection-end-line="37" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
@ -49,6 +64,7 @@
<option name="width" value="1280" />
<option name="height" value="798" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
<flattenPackages />
@ -76,6 +92,11 @@
<item name="proj" type="462c0819:PsiDirectoryNode" />
<item name="Drivers" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="proj" type="dad4c3:CidrFilesViewHelper$MyProjectTreeStructure$1" />
<item name="proj" type="462c0819:PsiDirectoryNode" />
<item name="Src" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
@ -119,22 +140,23 @@
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1509630149534</updated>
<workItem from="1509630151155" duration="559000" />
<workItem from="1509630151155" duration="770000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="559000" />
<option name="totallyTimeSpent" value="770000" />
</component>
<component name="ToolWindowManager">
<frame x="329" y="246" width="1366" height="738" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="CMake" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
@ -197,18 +219,18 @@
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/Src/main.c">
<entry file="file://$PROJECT_DIR$/CMakeLists.txt">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-2193">
<caret line="37" column="0" lean-forward="true" selection-start-line="37" selection-start-column="0" selection-end-line="37" selection-end-column="0" />
<state relative-caret-position="-1173">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/CMakeLists.txt">
<entry file="file://$PROJECT_DIR$/Src/main.c">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-1173">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<state relative-caret-position="-1003">
<caret line="37" column="0" lean-forward="false" selection-start-line="37" selection-start-column="0" selection-end-line="37" selection-end-column="0" />
<folding />
</state>
</provider>

@ -0,0 +1,208 @@
<!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 SX1272 component</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 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 SX1272 component</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
2017 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 alt="" id="_x0000_i1025" src="../../../../_htmresc/st_logo.png" style="border: 0px solid ; width: 86px; height: 65px;"></span><span style="font-size: 10pt;"><o:p></o:p></span></p>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal"><span style="font-family: Arial; display: none;"><o:p>&nbsp;</o:p></span></p>
<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" width="900">
<tbody>
<tr style="">
<span style="font-family: &quot;Times New Roman&quot;;"></span>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-right: 500pt; width: 200px;">
<span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.1 / 08-September-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;">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;">Retrieve Public Network handling in the radio driver
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
<li class="MsoNormal">
<span style="font-size: 10pt; font-family: Verdana;">Carrier Sense update
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
<li class="MsoNormal">
<span style="font-size: 10pt; font-family: Verdana;">Modem selection update
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
</ul>
<span style="font-family: &quot;Times New Roman&quot;;"></span>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-right: 500pt; width: 200px;">
<span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.0 / 01-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;">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;">First Release
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
</ul>
<span style="font-size: 10pt; font-family: Verdana;"> </span>
<h2 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">
<a name="License"></a>
<span style="font-size: 12pt; color: white;">License<o:p></o:p>
</span>
</h2>
<div style="text-align: justify;">
<div style="text-align: justify;"><font size="-1">
<span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
</span>
<br>
</font>
<ol><li><font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></font></li><li><font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">Redistributions
in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">the documentation and/or other materials provided with the distribution.</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></font></li><li><font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">Neither the name of STMicroelectronics nor the names of its contributors may be used to endorse or promote products derived
</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">from this software without specific prior written permission.</span><br>
</font>
</li></ol>
<font size="-1">
<span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></font>
</div>
<span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></div>
<span style="font-size: 10pt; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;; color: black;"></span> <b><span style="font-size: 10pt; font-family: Verdana; color: black;"></span></b>
<div class="MsoNormal" style="text-align: center;" align="center"><span style="color: black;">
<hr align="center" size="2" width="100%"></span></div>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt; text-align: center;" align="center"><span style="font-size: 10pt; font-family: Verdana; color: black;">For
complete documentation on </span><span style="font-size: 10pt; font-family: Verdana;">STM32<span style="color: black;">&nbsp;Microcontrollers
visit </span><u><span style="color: blue;"><a href="http://www.st.com/internet/mcu/class/1734.jsp" target="_blank">www.st.com/STM32</a></span></u></span><span style="font-size: 10pt; font-family: Verdana;"><a target="_blank" href="http://www.st.com/internet/mcu/family/141.jsp"><u><span style="color: blue;"></span></u></a></span><span style="font-size: 10pt; font-family: Verdana;"><u><span style="color: blue;"></span></u></span><span style="color: black;"><o:p></o:p></span></p>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal"><span style="font-size: 10pt;"><o:p></o:p></span></p>
</td>
</tr>
</tbody>
</table>
</div>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
</div>
</body></html>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,523 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Generic SX1272 driver implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/*******************************************************************************
* @file sx1272.h
* @author MCD Application Team
* @version V1.0.1
* @date 08-September-2017
* @brief Header for driver sx1272.c
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#ifndef __SX1272_H__
#define __SX1272_H__
#include "sx1272Regs-Fsk.h"
#include "sx1272Regs-LoRa.h"
/*!
* Radio wake-up time from sleep
*/
#define RADIO_WAKEUP_TIME 2 // [ms]
/*!
* Sync word for Private LoRa networks
*/
#define LORA_MAC_PRIVATE_SYNCWORD 0x12
/*!
* Sync word for Public LoRa networks
*/
#define LORA_MAC_PUBLIC_SYNCWORD 0x34
/*!
* Radio FSK modem parameters
*/
typedef struct
{
int8_t Power;
uint32_t Fdev;
uint32_t Bandwidth;
uint32_t BandwidthAfc;
uint32_t Datarate;
uint16_t PreambleLen;
bool FixLen;
uint8_t PayloadLen;
bool CrcOn;
bool IqInverted;
bool RxContinuous;
uint32_t TxTimeout;
uint32_t RxSingleTimeout;
}RadioFskSettings_t;
/*!
* Radio FSK packet handler state
*/
typedef struct
{
uint8_t PreambleDetected;
uint8_t SyncWordDetected;
int8_t RssiValue;
int32_t AfcValue;
uint8_t RxGain;
uint16_t Size;
uint16_t NbBytes;
uint8_t FifoThresh;
uint8_t ChunkSize;
}RadioFskPacketHandler_t;
/*!
* Radio LoRa modem parameters
*/
typedef struct
{
int8_t Power;
uint32_t Bandwidth;
uint32_t Datarate;
bool LowDatarateOptimize;
uint8_t Coderate;
uint16_t PreambleLen;
bool FixLen;
uint8_t PayloadLen;
bool CrcOn;
bool FreqHopOn;
uint8_t HopPeriod;
bool IqInverted;
bool RxContinuous;
uint32_t TxTimeout;
bool PublicNetwork;
}RadioLoRaSettings_t;
/*!
* Radio LoRa packet handler state
*/
typedef struct
{
int8_t SnrValue;
int16_t RssiValue;
uint8_t Size;
}RadioLoRaPacketHandler_t;
/*!
* Radio Settings
*/
typedef struct
{
RadioState_t State;
RadioModems_t Modem;
uint32_t Channel;
RadioFskSettings_t Fsk;
RadioFskPacketHandler_t FskPacketHandler;
RadioLoRaSettings_t LoRa;
RadioLoRaPacketHandler_t LoRaPacketHandler;
}RadioSettings_t;
/*!
* Radio hardware and global parameters
*/
typedef struct SX1272_s
{
uint8_t RxTx;
RadioSettings_t Settings;
}SX1272_t;
extern SX1272_t SX1272;
/*!
* Hardware IO IRQ callback function definition
*/
typedef void ( DioIrqHandler )( void );
/*!
* SX1272 definitions
*/
#define XTAL_FREQ 32000000
#define FREQ_STEP 61.03515625
#define FREQ_STEP_8 15625 /* FREQ_STEP<<8 */
/*!
* \brief Radio hardware registers initialization definition
*
* \remark Can be automatically generated by the SX1272 GUI (not yet implemented)
*/
#define RADIO_INIT_REGISTERS_VALUE \
{ \
{ MODEM_FSK , REG_LNA , 0x23 },\
{ MODEM_FSK , REG_RXCONFIG , 0x1E },\
{ MODEM_FSK , REG_RSSICONFIG , 0xD2 },\
{ MODEM_FSK , REG_AFCFEI , 0x01 },\
{ MODEM_FSK , REG_PREAMBLEDETECT , 0xAA },\
{ MODEM_FSK , REG_OSC , 0x07 },\
{ MODEM_FSK , REG_SYNCCONFIG , 0x12 },\
{ MODEM_FSK , REG_SYNCVALUE1 , 0xC1 },\
{ MODEM_FSK , REG_SYNCVALUE2 , 0x94 },\
{ MODEM_FSK , REG_SYNCVALUE3 , 0xC1 },\
{ MODEM_FSK , REG_PACKETCONFIG1 , 0xD8 },\
{ MODEM_FSK , REG_FIFOTHRESH , 0x8F },\
{ MODEM_FSK , REG_IMAGECAL , 0x02 },\
{ MODEM_FSK , REG_DIOMAPPING1 , 0x00 },\
{ MODEM_FSK , REG_DIOMAPPING2 , 0x30 },\
{ MODEM_LORA, REG_LR_DETECTOPTIMIZE , 0x43 },\
{ MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40 },\
} \
/* Freq = channel * FREQ_STEP */
#define SX_CHANNEL_TO_FREQ( channel, freq ) \
do \
{ \
uint32_t initialChanInt, initialChanFrac; \
initialChanInt = channel >> 8; \
initialChanFrac = channel - ( initialChanInt << 8 ); \
freq = initialChanInt * FREQ_STEP_8 + ( ( initialChanFrac * FREQ_STEP_8 + ( 128 ) ) >> 8 ); \
}while( 0 )
/* channel = Freq / FREQ_STEP */
#define SX_FREQ_TO_CHANNEL( channel, freq ) \
do \
{ \
uint32_t initialFreqInt, initialFreqFrac; \
initialFreqInt = freq / FREQ_STEP_8; \
initialFreqFrac = freq - ( initialFreqInt * FREQ_STEP_8 ); \
channel = ( initialFreqInt << 8 ) + ( ( ( initialFreqFrac << 8 ) + ( FREQ_STEP_8 / 2 ) ) / FREQ_STEP_8 ); \
}while( 0 )
#define RX_BUFFER_SIZE 256
typedef struct sBoardCallback
{
/*!
* \brief Set XO state on the board
*/
void ( *SX1272BoardSetXO )( uint8_t state );
/*!
* \brief Get Board Wake Up time
*/
uint32_t ( *SX1272BoardGetWakeTime )( void );
/*!
* \brief Initializes the radio I/Os Irq
*/
void ( *SX1272BoardIoIrqInit )( DioIrqHandler **irqHandlers );
/*!
* \brief Sets the radio output power.
*
* \param [IN] power Sets the RF output power
*/
void ( *SX1272BoardSetRfTxPower )( int8_t power );
/*!
* \brief Set the RF Switch I/Os pins in Low Power mode
*
* \param [IN] status enable or disable
*/
void ( *SX1272BoardSetAntSwLowPower )( bool status );
/*!
* \brief Controls the antena switch if necessary.
*
* \remark see errata note
*
* \param [IN] opMode Current radio operating mode
*/
void ( *SX1272BoardSetAntSw )( uint8_t opMode );
}LoRaBoardCallback_t;
/*!
* ============================================================================
* Public functions prototypes
* ============================================================================
*/
void SX1272BoardInit( LoRaBoardCallback_t *callbacks );
/*!
* \brief Initializes the radio
*
* \param [IN] events Structure containing the driver callback functions
* \param [OUT] returns the wake up time of the radio and associated board
*/
uint32_t SX1272Init( RadioEvents_t *events );
/*!
* Return current radio status
*
* \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING]
*/
RadioState_t SX1272GetStatus( void );
/*!
* \brief Configures the radio with the given modem
*
* \param [IN] modem Modem to be used [0: FSK, 1: LoRa]
*/
void SX1272SetModem( RadioModems_t modem );
/*!
* \brief Sets the channel configuration
*
* \param [IN] freq Channel RF frequency
*/
void SX1272SetChannel( uint32_t freq );
/*!
* \brief Checks if the channel is free for the given time
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] freq Channel RF frequency
* \param [IN] rssiThresh RSSI threshold
* \param [IN] maxCarrierSenseTime Max time while the RSSI is measured
*
* \retval isFree [true: Channel is free, false: Channel is not free]
*/
bool SX1272IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime );
/*!
* \brief Generates a 32 bits random value based on the RSSI readings
*
* \remark This function sets the radio in LoRa modem mode and disables
* all interrupts.
* After calling this function either SX1272SetRxConfig or
* SX1272SetTxConfig functions must be called.
*
* \retval randomValue 32 bits random value
*/
uint32_t SX1272Random( void );
/*!
* \brief Sets the reception parameters
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] bandwidth Sets the bandwidth
* FSK : >= 2600 and <= 250000 Hz
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only)
* FSK : >= 2600 and <= 250000 Hz
* LoRa: N/A ( set to 0 )
* \param [IN] preambleLen Sets the Preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] symbTimeout Sets the RxSingle timeout value
* FSK : timeout number of bytes
* LoRa: timeout in symbols
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] payloadLen Sets payload length when fixed length is used
* \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
* \param [IN] freqHopOn Enables disables the intra-packet frequency hopping
* FSK : N/A ( set to 0 )
* LoRa: [0: OFF, 1: ON]
* \param [IN] hopPeriod Number of symbols between each hop
* FSK : N/A ( set to 0 )
* LoRa: Number of symbols
* \param [IN] iqInverted Inverts IQ signals (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [0: not inverted, 1: inverted]
* \param [IN] rxContinuous Sets the reception in continuous mode
* [false: single mode, true: continuous mode]
*/
void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint32_t bandwidthAfc, uint16_t preambleLen,
uint16_t symbTimeout, bool fixLen,
uint8_t payloadLen,
bool crcOn, bool freqHopOn, uint8_t hopPeriod,
bool iqInverted, bool rxContinuous );
/*!
* \brief Sets the transmission parameters
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] power Sets the output power [dBm]
* \param [IN] fdev Sets the frequency deviation (FSK only)
* FSK : [Hz]
* LoRa: 0
* \param [IN] bandwidth Sets the bandwidth (LoRa only)
* FSK : 0
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] preambleLen Sets the preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON]
* \param [IN] freqHopOn Enables disables the intra-packet frequency hopping
* FSK : N/A ( set to 0 )
* LoRa: [0: OFF, 1: ON]
* \param [IN] hopPeriod Number of symbols between each hop
* FSK : N/A ( set to 0 )
* LoRa: Number of symbols
* \param [IN] iqInverted Inverts IQ signals (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [0: not inverted, 1: inverted]
* \param [IN] timeout Transmission timeout [ms]
*/
void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
uint32_t bandwidth, uint32_t datarate,
uint8_t coderate, uint16_t preambleLen,
bool fixLen, bool crcOn, bool freqHopOn,
uint8_t hopPeriod, bool iqInverted, uint32_t timeout );
/*!
* \brief Computes the packet time on air in ms for the given payload
*
* \Remark Can only be called once SetRxConfig or SetTxConfig have been called
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] pktLen Packet payload length
*
* \retval airTime Computed airTime (ms) for the given packet payload length
*/
uint32_t SX1272GetTimeOnAir( RadioModems_t modem, uint8_t pktLen );
/*!
* \brief Sends the buffer of size. Prepares the packet to be sent and sets
* the radio in transmission
*
* \param [IN]: buffer Buffer pointer
* \param [IN]: size Buffer size
*/
void SX1272Send( uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the radio in sleep mode
*/
void SX1272SetSleep( void );
/*!
* \brief Sets the radio in standby mode
*/
void SX1272SetStby( void );
/*!
* \brief Sets the radio in reception mode for the given time
* \param [IN] timeout Reception timeout [ms] [0: continuous, others timeout]
*/
void SX1272SetRx( uint32_t timeout );
/*!
* \brief Start a Channel Activity Detection
*/
void SX1272StartCad( void );
/*!
* \brief Sets the radio in continuous wave transmission mode
*
* \param [IN]: freq Channel RF frequency
* \param [IN]: power Sets the output power [dBm]
* \param [IN]: time Transmission mode timeout [s]
*/
void SX1272SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time );
/*!
* \brief Reads the current RSSI value
*
* \retval rssiValue Current RSSI value in [dBm]
*/
int16_t SX1272ReadRssi( RadioModems_t modem );
/*!
* \brief Writes the radio register at the specified address
*
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
void SX1272Write( uint8_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
*
* \param [IN]: addr Register address
* \retval data Register value
*/
uint8_t SX1272Read( uint8_t addr );
/*!
* \brief Writes multiple radio registers starting at address
*
* \param [IN] addr First Radio register address
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
void SX1272WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
*
* \param [IN] addr First Radio register address
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
void SX1272ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] max Maximum payload length in bytes
*/
void SX1272SetMaxPayloadLength( RadioModems_t modem, uint8_t max );
/*!
* \brief Sets the network to public or private. Updates the sync byte.
*
* \remark Applies to LoRa modem only
*
* \param [IN] enable if true, it enables a public network
*/
void SX1272SetPublicNetwork( bool enable );
/*!
* \brief Service to get the radio wake-up time.
*
* \retval Value of the radio wake-up time.
*/
uint32_t SX1272GetRadioWakeUpTime( void );
#endif /* __SX1272_H__ */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,545 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: SX1272 LoRa modem registers and bits definitions
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
#ifndef __SX1272_REGS_LORA_H__
#define __SX1272_REGS_LORA_H__
/*!
* ============================================================================
* SX1272 Internal registers Address
* ============================================================================
*/
#define REG_LR_FIFO 0x00
// Common settings
#define REG_LR_OPMODE 0x01
#define REG_LR_FRFMSB 0x06
#define REG_LR_FRFMID 0x07
#define REG_LR_FRFLSB 0x08
// Tx settings
#define REG_LR_PACONFIG 0x09
#define REG_LR_PARAMP 0x0A
#define REG_LR_OCP 0x0B
// Rx settings
#define REG_LR_LNA 0x0C
// LoRa registers
#define REG_LR_FIFOADDRPTR 0x0D
#define REG_LR_FIFOTXBASEADDR 0x0E
#define REG_LR_FIFORXBASEADDR 0x0F
#define REG_LR_FIFORXCURRENTADDR 0x10
#define REG_LR_IRQFLAGSMASK 0x11
#define REG_LR_IRQFLAGS 0x12
#define REG_LR_RXNBBYTES 0x13
#define REG_LR_RXHEADERCNTVALUEMSB 0x14
#define REG_LR_RXHEADERCNTVALUELSB 0x15
#define REG_LR_RXPACKETCNTVALUEMSB 0x16
#define REG_LR_RXPACKETCNTVALUELSB 0x17
#define REG_LR_MODEMSTAT 0x18
#define REG_LR_PKTSNRVALUE 0x19
#define REG_LR_PKTRSSIVALUE 0x1A
#define REG_LR_RSSIVALUE 0x1B
#define REG_LR_HOPCHANNEL 0x1C
#define REG_LR_MODEMCONFIG1 0x1D
#define REG_LR_MODEMCONFIG2 0x1E
#define REG_LR_SYMBTIMEOUTLSB 0x1F
#define REG_LR_PREAMBLEMSB 0x20
#define REG_LR_PREAMBLELSB 0x21
#define REG_LR_PAYLOADLENGTH 0x22
#define REG_LR_PAYLOADMAXLENGTH 0x23
#define REG_LR_HOPPERIOD 0x24
#define REG_LR_FIFORXBYTEADDR 0x25
#define REG_LR_FEIMSB 0x28
#define REG_LR_FEIMID 0x29
#define REG_LR_FEILSB 0x2A
#define REG_LR_RSSIWIDEBAND 0x2C
#define REG_LR_DETECTOPTIMIZE 0x31
#define REG_LR_INVERTIQ 0x33
#define REG_LR_DETECTIONTHRESHOLD 0x37
#define REG_LR_SYNCWORD 0x39
#define REG_LR_INVERTIQ2 0x3B
// end of documented register in datasheet
// I/O settings
#define REG_LR_DIOMAPPING1 0x40
#define REG_LR_DIOMAPPING2 0x41
// Version
#define REG_LR_VERSION 0x42
// Additional settings
#define REG_LR_AGCREF 0x43
#define REG_LR_AGCTHRESH1 0x44
#define REG_LR_AGCTHRESH2 0x45
#define REG_LR_AGCTHRESH3 0x46
#define REG_LR_PLLHOP 0x4B
#define REG_LR_TCXO 0x58
#define REG_LR_PADAC 0x5A
#define REG_LR_PLL 0x5C
#define REG_LR_PLLLOWPN 0x5E
#define REG_LR_FORMERTEMP 0x6C
/*!
* ============================================================================
* SX1272 LoRa bits control definition
* ============================================================================
*/
/*!
* RegFifo
*/
/*!
* RegOpMode
*/
#define RFLR_OPMODE_LONGRANGEMODE_MASK 0x7F
#define RFLR_OPMODE_LONGRANGEMODE_OFF 0x00 // Default
#define RFLR_OPMODE_LONGRANGEMODE_ON 0x80
#define RFLR_OPMODE_ACCESSSHAREDREG_MASK 0xBF
#define RFLR_OPMODE_ACCESSSHAREDREG_ENABLE 0x40
#define RFLR_OPMODE_ACCESSSHAREDREG_DISABLE 0x00 // Default
#define RFLR_OPMODE_MASK 0xF8
#define RFLR_OPMODE_SLEEP 0x00
#define RFLR_OPMODE_STANDBY 0x01 // Default
#define RFLR_OPMODE_SYNTHESIZER_TX 0x02
#define RFLR_OPMODE_TRANSMITTER 0x03
#define RFLR_OPMODE_SYNTHESIZER_RX 0x04
#define RFLR_OPMODE_RECEIVER 0x05
// LoRa specific modes
#define RFLR_OPMODE_RECEIVER_SINGLE 0x06
#define RFLR_OPMODE_CAD 0x07
/*!
* RegFrf (MHz)
*/
#define RFLR_FRFMSB_915_MHZ 0xE4 // Default
#define RFLR_FRFMID_915_MHZ 0xC0 // Default
#define RFLR_FRFLSB_915_MHZ 0x00 // Default
/*!
* RegPaConfig
*/
#define RFLR_PACONFIG_PASELECT_MASK 0x7F
#define RFLR_PACONFIG_PASELECT_PABOOST 0x80
#define RFLR_PACONFIG_PASELECT_RFO 0x00 // Default
#define RFLR_PACONFIG_OUTPUTPOWER_MASK 0xF0
/*!
* RegPaRamp
*/
#define RFLR_PARAMP_LOWPNTXPLL_MASK 0xE0
#define RFLR_PARAMP_LOWPNTXPLL_OFF 0x10 // Default
#define RFLR_PARAMP_LOWPNTXPLL_ON 0x00
#define RFLR_PARAMP_MASK 0xF0
#define RFLR_PARAMP_3400_US 0x00
#define RFLR_PARAMP_2000_US 0x01
#define RFLR_PARAMP_1000_US 0x02
#define RFLR_PARAMP_0500_US 0x03
#define RFLR_PARAMP_0250_US 0x04
#define RFLR_PARAMP_0125_US 0x05
#define RFLR_PARAMP_0100_US 0x06
#define RFLR_PARAMP_0062_US 0x07
#define RFLR_PARAMP_0050_US 0x08
#define RFLR_PARAMP_0040_US 0x09 // Default
#define RFLR_PARAMP_0031_US 0x0A
#define RFLR_PARAMP_0025_US 0x0B
#define RFLR_PARAMP_0020_US 0x0C
#define RFLR_PARAMP_0015_US 0x0D
#define RFLR_PARAMP_0012_US 0x0E
#define RFLR_PARAMP_0010_US 0x0F
/*!
* RegOcp
*/
#define RFLR_OCP_MASK 0xDF
#define RFLR_OCP_ON 0x20 // Default
#define RFLR_OCP_OFF 0x00
#define RFLR_OCP_TRIM_MASK 0xE0
#define RFLR_OCP_TRIM_045_MA 0x00
#define RFLR_OCP_TRIM_050_MA 0x01
#define RFLR_OCP_TRIM_055_MA 0x02
#define RFLR_OCP_TRIM_060_MA 0x03
#define RFLR_OCP_TRIM_065_MA 0x04
#define RFLR_OCP_TRIM_070_MA 0x05
#define RFLR_OCP_TRIM_075_MA 0x06
#define RFLR_OCP_TRIM_080_MA 0x07
#define RFLR_OCP_TRIM_085_MA 0x08
#define RFLR_OCP_TRIM_090_MA 0x09
#define RFLR_OCP_TRIM_095_MA 0x0A
#define RFLR_OCP_TRIM_100_MA 0x0B // Default
#define RFLR_OCP_TRIM_105_MA 0x0C
#define RFLR_OCP_TRIM_110_MA 0x0D
#define RFLR_OCP_TRIM_115_MA 0x0E
#define RFLR_OCP_TRIM_120_MA 0x0F
#define RFLR_OCP_TRIM_130_MA 0x10
#define RFLR_OCP_TRIM_140_MA 0x11
#define RFLR_OCP_TRIM_150_MA 0x12
#define RFLR_OCP_TRIM_160_MA 0x13
#define RFLR_OCP_TRIM_170_MA 0x14
#define RFLR_OCP_TRIM_180_MA 0x15
#define RFLR_OCP_TRIM_190_MA 0x16
#define RFLR_OCP_TRIM_200_MA 0x17
#define RFLR_OCP_TRIM_210_MA 0x18
#define RFLR_OCP_TRIM_220_MA 0x19
#define RFLR_OCP_TRIM_230_MA 0x1A
#define RFLR_OCP_TRIM_240_MA 0x1B
/*!
* RegLna
*/
#define RFLR_LNA_GAIN_MASK 0x1F
#define RFLR_LNA_GAIN_G1 0x20 // Default
#define RFLR_LNA_GAIN_G2 0x40
#define RFLR_LNA_GAIN_G3 0x60
#define RFLR_LNA_GAIN_G4 0x80
#define RFLR_LNA_GAIN_G5 0xA0
#define RFLR_LNA_GAIN_G6 0xC0
#define RFLR_LNA_BOOST_MASK 0xFC
#define RFLR_LNA_BOOST_OFF 0x00 // Default
#define RFLR_LNA_BOOST_ON 0x03
/*!
* RegFifoAddrPtr
*/
#define RFLR_FIFOADDRPTR 0x00 // Default
/*!
* RegFifoTxBaseAddr
*/
#define RFLR_FIFOTXBASEADDR 0x80 // Default
/*!
* RegFifoTxBaseAddr
*/
#define RFLR_FIFORXBASEADDR 0x00 // Default
/*!
* RegFifoRxCurrentAddr (Read Only)
*/
/*!
* RegIrqFlagsMask
*/
#define RFLR_IRQFLAGS_RXTIMEOUT_MASK 0x80
#define RFLR_IRQFLAGS_RXDONE_MASK 0x40
#define RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK 0x20
#define RFLR_IRQFLAGS_VALIDHEADER_MASK 0x10
#define RFLR_IRQFLAGS_TXDONE_MASK 0x08
#define RFLR_IRQFLAGS_CADDONE_MASK 0x04
#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL_MASK 0x02
#define RFLR_IRQFLAGS_CADDETECTED_MASK 0x01
/*!
* RegIrqFlags
*/
#define RFLR_IRQFLAGS_RXTIMEOUT 0x80
#define RFLR_IRQFLAGS_RXDONE 0x40
#define RFLR_IRQFLAGS_PAYLOADCRCERROR 0x20
#define RFLR_IRQFLAGS_VALIDHEADER 0x10
#define RFLR_IRQFLAGS_TXDONE 0x08
#define RFLR_IRQFLAGS_CADDONE 0x04
#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL 0x02
#define RFLR_IRQFLAGS_CADDETECTED 0x01
/*!
* RegFifoRxNbBytes (Read Only)
*/
/*!
* RegRxHeaderCntValueMsb (Read Only)
*/
/*!
* RegRxHeaderCntValueLsb (Read Only)
*/
/*!
* RegRxPacketCntValueMsb (Read Only)
*/
/*!
* RegRxPacketCntValueLsb (Read Only)
*/
/*!
* RegModemStat (Read Only)
*/
#define RFLR_MODEMSTAT_RX_CR_MASK 0x1F
#define RFLR_MODEMSTAT_MODEM_STATUS_MASK 0xE0
/*!
* RegPktSnrValue (Read Only)
*/
/*!
* RegPktRssiValue (Read Only)
*/
/*!
* RegRssiValue (Read Only)
*/
/*!
* RegHopChannel (Read Only)
*/
#define RFLR_HOPCHANNEL_PLL_LOCK_TIMEOUT_MASK 0x7F
#define RFLR_HOPCHANNEL_PLL_LOCK_FAIL 0x80
#define RFLR_HOPCHANNEL_PLL_LOCK_SUCCEED 0x00 // Default
#define RFLR_HOPCHANNEL_CRCONPAYLOAD_MASK 0xBF
#define RFLR_HOPCHANNEL_CRCONPAYLOAD_ON 0x40
#define RFLR_HOPCHANNEL_CRCONPAYLOAD_OFF 0x00 // Default
#define RFLR_HOPCHANNEL_CHANNEL_MASK 0x3F
/*!
* RegModemConfig1
*/
#define RFLR_MODEMCONFIG1_BW_MASK 0x3F
#define RFLR_MODEMCONFIG1_BW_125_KHZ 0x00 // Default
#define RFLR_MODEMCONFIG1_BW_250_KHZ 0x40
#define RFLR_MODEMCONFIG1_BW_500_KHZ 0x80
#define RFLR_MODEMCONFIG1_CODINGRATE_MASK 0xC7
#define RFLR_MODEMCONFIG1_CODINGRATE_4_5 0x08
#define RFLR_MODEMCONFIG1_CODINGRATE_4_6 0x10 // Default
#define RFLR_MODEMCONFIG1_CODINGRATE_4_7 0x18
#define RFLR_MODEMCONFIG1_CODINGRATE_4_8 0x20
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK 0xFB
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_ON 0x04
#define RFLR_MODEMCONFIG1_IMPLICITHEADER_OFF 0x00 // Default
#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_MASK 0xFD
#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_ON 0x02
#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_OFF 0x00 // Default
#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_MASK 0xFE
#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_ON 0x01
#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_OFF 0x00 // Default
/*!
* RegModemConfig2
*/
#define RFLR_MODEMCONFIG2_SF_MASK 0x0F
#define RFLR_MODEMCONFIG2_SF_6 0x60
#define RFLR_MODEMCONFIG2_SF_7 0x70 // Default
#define RFLR_MODEMCONFIG2_SF_8 0x80
#define RFLR_MODEMCONFIG2_SF_9 0x90
#define RFLR_MODEMCONFIG2_SF_10 0xA0
#define RFLR_MODEMCONFIG2_SF_11 0xB0
#define RFLR_MODEMCONFIG2_SF_12 0xC0
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_MASK 0xF7
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_ON 0x08
#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_OFF 0x00
#define RFLR_MODEMCONFIG2_AGCAUTO_MASK 0xFB
#define RFLR_MODEMCONFIG2_AGCAUTO_ON 0x04 // Default
#define RFLR_MODEMCONFIG2_AGCAUTO_OFF 0x00
#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK 0xFC
#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB 0x00 // Default
/*!
* RegSymbTimeoutLsb
*/
#define RFLR_SYMBTIMEOUTLSB_SYMBTIMEOUT 0x64 // Default
/*!
* RegPreambleLengthMsb
*/
#define RFLR_PREAMBLELENGTHMSB 0x00 // Default
/*!
* RegPreambleLengthLsb
*/
#define RFLR_PREAMBLELENGTHLSB 0x08 // Default
/*!
* RegPayloadLength
*/
#define RFLR_PAYLOADLENGTH 0x0E // Default
/*!
* RegPayloadMaxLength
*/
#define RFLR_PAYLOADMAXLENGTH 0xFF // Default
/*!
* RegHopPeriod
*/
#define RFLR_HOPPERIOD_FREQFOPPINGPERIOD 0x00 // Default
/*!
* RegFifoRxByteAddr (Read Only)
*/
/*!
* RegFeiMsb (Read Only)
*/
/*!
* RegFeiMid (Read Only)
*/
/*!
* RegFeiLsb (Read Only)
*/
/*!
* RegRssiWideband (Read Only)
*/
/*!
* RegDetectOptimize
*/
#define RFLR_DETECTIONOPTIMIZE_MASK 0xF8
#define RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 0x03 // Default
#define RFLR_DETECTIONOPTIMIZE_SF6 0x05
/*!
* RegInvertIQ
*/
#define RFLR_INVERTIQ_RX_MASK 0xBF
#define RFLR_INVERTIQ_RX_OFF 0x00
#define RFLR_INVERTIQ_RX_ON 0x40
#define RFLR_INVERTIQ_TX_MASK 0xFE
#define RFLR_INVERTIQ_TX_OFF 0x01
#define RFLR_INVERTIQ_TX_ON 0x00
/*!
* RegDetectionThreshold
*/
#define RFLR_DETECTIONTHRESH_SF7_TO_SF12 0x0A // Default
#define RFLR_DETECTIONTHRESH_SF6 0x0C
/*!
* RegInvertIQ2
*/
#define RFLR_INVERTIQ2_ON 0x19
#define RFLR_INVERTIQ2_OFF 0x1D
/*!
* RegDioMapping1
*/
#define RFLR_DIOMAPPING1_DIO0_MASK 0x3F
#define RFLR_DIOMAPPING1_DIO0_00 0x00 // Default
#define RFLR_DIOMAPPING1_DIO0_01 0x40
#define RFLR_DIOMAPPING1_DIO0_10 0x80
#define RFLR_DIOMAPPING1_DIO0_11 0xC0
#define RFLR_DIOMAPPING1_DIO1_MASK 0xCF
#define RFLR_DIOMAPPING1_DIO1_00 0x00 // Default
#define RFLR_DIOMAPPING1_DIO1_01 0x10
#define RFLR_DIOMAPPING1_DIO1_10 0x20
#define RFLR_DIOMAPPING1_DIO1_11 0x30
#define RFLR_DIOMAPPING1_DIO2_MASK 0xF3
#define RFLR_DIOMAPPING1_DIO2_00 0x00 // Default
#define RFLR_DIOMAPPING1_DIO2_01 0x04
#define RFLR_DIOMAPPING1_DIO2_10 0x08
#define RFLR_DIOMAPPING1_DIO2_11 0x0C
#define RFLR_DIOMAPPING1_DIO3_MASK 0xFC
#define RFLR_DIOMAPPING1_DIO3_00 0x00 // Default
#define RFLR_DIOMAPPING1_DIO3_01 0x01
#define RFLR_DIOMAPPING1_DIO3_10 0x02
#define RFLR_DIOMAPPING1_DIO3_11 0x03
/*!
* RegDioMapping2
*/
#define RFLR_DIOMAPPING2_DIO4_MASK 0x3F
#define RFLR_DIOMAPPING2_DIO4_00 0x00 // Default
#define RFLR_DIOMAPPING2_DIO4_01 0x40
#define RFLR_DIOMAPPING2_DIO4_10 0x80
#define RFLR_DIOMAPPING2_DIO4_11 0xC0
#define RFLR_DIOMAPPING2_DIO5_MASK 0xCF
#define RFLR_DIOMAPPING2_DIO5_00 0x00 // Default
#define RFLR_DIOMAPPING2_DIO5_01 0x10
#define RFLR_DIOMAPPING2_DIO5_10 0x20
#define RFLR_DIOMAPPING2_DIO5_11 0x30
#define RFLR_DIOMAPPING2_MAP_MASK 0xFE
#define RFLR_DIOMAPPING2_MAP_PREAMBLEDETECT 0x01
#define RFLR_DIOMAPPING2_MAP_RSSI 0x00 // Default
/*!
* RegVersion (Read Only)
*/
/*!
* RegAgcRef
*/
/*!
* RegAgcThresh1
*/
/*!
* RegAgcThresh2
*/
/*!
* RegAgcThresh3
*/
/*!
* RegPllHop
*/
#define RFLR_PLLHOP_FASTHOP_MASK 0x7F
#define RFLR_PLLHOP_FASTHOP_ON 0x80
#define RFLR_PLLHOP_FASTHOP_OFF 0x00 // Default
/*!
* RegTcxo
*/
#define RFLR_TCXO_TCXOINPUT_MASK 0xEF
#define RFLR_TCXO_TCXOINPUT_ON 0x10
#define RFLR_TCXO_TCXOINPUT_OFF 0x00 // Default
/*!
* RegPaDac
*/
#define RFLR_PADAC_20DBM_MASK 0xF8
#define RFLR_PADAC_20DBM_ON 0x07
#define RFLR_PADAC_20DBM_OFF 0x04 // Default
/*!
* RegPll
*/
#define RFLR_PLL_BANDWIDTH_MASK 0x3F
#define RFLR_PLL_BANDWIDTH_75 0x00
#define RFLR_PLL_BANDWIDTH_150 0x40
#define RFLR_PLL_BANDWIDTH_225 0x80
#define RFLR_PLL_BANDWIDTH_300 0xC0 // Default
/*!
* RegPllLowPn
*/
#define RFLR_PLLLOWPN_BANDWIDTH_MASK 0x3F
#define RFLR_PLLLOWPN_BANDWIDTH_75 0x00
#define RFLR_PLLLOWPN_BANDWIDTH_150 0x40
#define RFLR_PLLLOWPN_BANDWIDTH_225 0x80
#define RFLR_PLLLOWPN_BANDWIDTH_300 0xC0 // Default
/*!
* RegFormerTemp
*/
#endif // __SX1272_REGS_LORA_H__

@ -0,0 +1,269 @@
<!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 sx1272mb2das Board Drivers</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 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 sx1272mb2das Board Drivers</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
2017 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 alt="" id="_x0000_i1025" src="../../../_htmresc/st_logo.png" style="border: 0px solid ; width: 86px; height: 65px;"></span><span style="font-size: 10pt;"><o:p></o:p></span></p>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal"><span style="font-family: Arial; display: none;"><o:p>&nbsp;</o:p></span></p>
<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" width="900">
<tbody>
<tr style="">
<td style="padding: 0cm;" valign="top">
<span style="font-family: &quot;Times New Roman&quot;;">
</span>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-right: 500pt; width: 200px;">
<span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.4 / 08-September-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;">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;">Retrieve Public Network handling in the radio driver
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
</ul>
<span style="font-family: &quot;Times New Roman&quot;;">
</span>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-right: 500pt; width: 200px;">
<span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.3 / 01-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;">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;">SX1272 radio driver externalized as component
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
</ul>
<span style="font-family: &quot;Times New Roman&quot;;">
</span>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-right: 500pt; width: 200px;">
<span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.2 / 27-February-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;">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;">Power settings now board dependent
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
</ul>
<span style="font-family: &quot;Times New Roman&quot;;">
</span>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-right: 500pt; width: 200px;">
<span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.1 / 15-September-2016
</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;">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;">Interrupt handling
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
</ul>
<span style="font-family: &quot;Times New Roman&quot;;">
</span>
<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-right: 500pt; width: 200px;">
<span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.0 / 01-July-2016
</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;">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;">First Release
<span style="font-weight: bold; font-style: italic;">
</span>
</span>
</li>
</ul>
<span style="font-size: 10pt; font-family: Verdana;">
</span>
<h2 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;">
<a name="License"></a>
<span style="font-size: 12pt; color: white;">License<o:p></o:p>
</span>
</h2>
<div style="text-align: justify;">
<div style="text-align: justify;"><font size="-1">
<span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
</span>
<br>
</font>
<ol><li><font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></font></li><li><font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">Redistributions
in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">the documentation and/or other materials provided with the distribution.</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></font></li><li><font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">Neither the name of STMicroelectronics nor the names of its contributors may be used to endorse or promote products derived
</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">from this software without specific prior written permission.</span><br>
</font>
</li></ol>
<font size="-1">
<span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR </span><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></font>
</div>
<span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"></span></div>
<span style="font-size: 10pt; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;; color: black;"></span> <b><span style="font-size: 10pt; font-family: Verdana; color: black;"></span></b>
<div class="MsoNormal" style="text-align: center;" align="center"><span style="color: black;">
<hr align="center" size="2" width="100%"></span></div>
<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt; text-align: center;" align="center"><span style="font-size: 10pt; font-family: Verdana; color: black;">For
complete documentation on </span><span style="font-size: 10pt; font-family: Verdana;">STM32<span style="color: black;">&nbsp;Microcontrollers
visit </span><u><span style="color: blue;"><a href="http://www.st.com/internet/mcu/class/1734.jsp" target="_blank">www.st.com/STM32</a></span></u></span><span style="font-size: 10pt; font-family: Verdana;"><a target="_blank" href="http://www.st.com/internet/mcu/family/141.jsp"><u><span style="color: blue;"></span></u></a></span><span style="font-size: 10pt; font-family: Verdana;"><u><span style="color: blue;"></span></u></span><span style="color: black;"><o:p></o:p></span></p>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal"><span style="font-size: 10pt;"><o:p></o:p></span></p>
</td>
</tr>
</tbody>
</table>
</div>
<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
</div>
</body></html>

@ -0,0 +1,262 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: SX1272 driver specific target board functions implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/*******************************************************************************
* @file sx1272mb2das.c
* @author MCD Application Team
* @version V1.0.4
* @date 08-September-2017
* @brief driver sx1272mb2das board
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "hw.h"
#include "radio.h"
#include "sx1272.h"
#include "sx1272mb2das.h"
#define IRQ_HIGH_PRIORITY 0
/*!
* Flag used to set the RF switch control pins in low power mode when the radio is not active.
*/
void SX1272SetXO( uint8_t state );
uint32_t SX1272GetWakeTime( void );
void SX1272IoIrqInit( DioIrqHandler **irqHandlers );
uint8_t SX1272GetPaSelect( uint32_t channel );
void SX1272SetAntSwLowPower( bool status );
void SX1272SetRfTxPower( int8_t power );
void SX1272SetAntSw( uint8_t opMode );
/*!
* \brief Controls the antena switch if necessary.
*
* \remark see errata note
*
* \param [IN] opMode Current radio operating mode
*/
static LoRaBoardCallback_t BoardCallbacks = { SX1272SetXO,
SX1272GetWakeTime,
SX1272IoIrqInit,
SX1272SetRfTxPower,
SX1272SetAntSwLowPower,
SX1272SetAntSw};
/*!
* Radio driver structure initialization
*/
const struct Radio_s Radio =
{
SX1272IoInit,
SX1272IoDeInit,
SX1272Init,
SX1272GetStatus,
SX1272SetModem,
SX1272SetChannel,
SX1272IsChannelFree,
SX1272Random,
SX1272SetRxConfig,
SX1272SetTxConfig,
SX1272CheckRfFrequency,
SX1272GetTimeOnAir,
SX1272Send,
SX1272SetSleep,
SX1272SetStby,
SX1272SetRx,
SX1272StartCad,
SX1272SetTxContinuousWave,
SX1272ReadRssi,
SX1272Write,
SX1272Read,
SX1272WriteBuffer,
SX1272ReadBuffer,
SX1272SetMaxPayloadLength,
SX1272SetPublicNetwork,
SX1272GetRadioWakeUpTime
};
uint32_t SX1272GetWakeTime( void )
{
return BOARD_WAKEUP_TIME;
}
void SX1272SetXO( uint8_t state )
{
}
void SX1272IoInit( void )
{
GPIO_InitTypeDef initStruct={0};
SX1272BoardInit( &BoardCallbacks );
initStruct.Mode = GPIO_MODE_IT_RISING;
initStruct.Pull = GPIO_PULLDOWN;
initStruct.Speed = GPIO_SPEED_HIGH;
HW_GPIO_Init( RADIO_DIO_0_PORT, RADIO_DIO_0_PIN, &initStruct );
HW_GPIO_Init( RADIO_DIO_1_PORT, RADIO_DIO_1_PIN, &initStruct );
HW_GPIO_Init( RADIO_DIO_2_PORT, RADIO_DIO_2_PIN, &initStruct );
HW_GPIO_Init( RADIO_DIO_3_PORT, RADIO_DIO_3_PIN, &initStruct );
}
void SX1272IoIrqInit( DioIrqHandler **irqHandlers )
{
HW_GPIO_SetIrq( RADIO_DIO_0_PORT, RADIO_DIO_0_PIN, IRQ_HIGH_PRIORITY, irqHandlers[0] );
HW_GPIO_SetIrq( RADIO_DIO_1_PORT, RADIO_DIO_1_PIN, IRQ_HIGH_PRIORITY, irqHandlers[1] );
HW_GPIO_SetIrq( RADIO_DIO_2_PORT, RADIO_DIO_2_PIN, IRQ_HIGH_PRIORITY, irqHandlers[2] );
HW_GPIO_SetIrq( RADIO_DIO_3_PORT, RADIO_DIO_3_PIN, IRQ_HIGH_PRIORITY, irqHandlers[3] );
}
void SX1272IoDeInit( void )
{
GPIO_InitTypeDef initStruct={0};
initStruct.Mode = GPIO_MODE_IT_RISING ;//GPIO_MODE_ANALOG;
initStruct.Pull = GPIO_PULLDOWN;
HW_GPIO_Init( RADIO_DIO_0_PORT, RADIO_DIO_0_PIN, &initStruct );
HW_GPIO_Init( RADIO_DIO_1_PORT, RADIO_DIO_1_PIN, &initStruct );
HW_GPIO_Init( RADIO_DIO_2_PORT, RADIO_DIO_2_PIN, &initStruct );
HW_GPIO_Init( RADIO_DIO_3_PORT, RADIO_DIO_3_PIN, &initStruct );
}
void SX1272SetRfTxPower( int8_t power )
{
uint8_t paConfig = 0;
uint8_t paDac = 0;
paConfig = SX1272Read( REG_PACONFIG );
paDac = SX1272Read( REG_PADAC );
paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | SX1272GetPaSelect( SX1272.Settings.Channel );
if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
{
if( power > 17 )
{
paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON;
}
else
{
paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF;
}
if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON )
{
if( power < 5 )
{
power = 5;
}
if( power > 20 )
{
power = 20;
}
paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F );
}
else
{
if( power < 2 )
{
power = 2;
}
if( power > 17 )
{
power = 17;
}
paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F );
}
}
else
{
if( power < -1 )
{
power = -1;
}
if( power > 14 )
{
power = 14;
}
paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F );
}
SX1272Write( REG_PACONFIG, paConfig );
SX1272Write( REG_PADAC, paDac );
}
uint8_t SX1272GetPaSelect( uint32_t channel )
{
return RF_PACONFIG_PASELECT_RFO;
}
void SX1272SetAntSwLowPower( bool status )
{
//Ant Switch Controlled by SX1272 IC
}
void SX1272SetAntSw( uint8_t opMode )
{
switch( opMode )
{
case RFLR_OPMODE_TRANSMITTER:
SX1272.RxTx = 1;
break;
case RFLR_OPMODE_RECEIVER:
case RFLR_OPMODE_RECEIVER_SINGLE:
case RFLR_OPMODE_CAD:
default:
SX1272.RxTx = 0;
break;
}
}
bool SX1272CheckRfFrequency( uint32_t frequency )
{
// Implement check. Currently all frequencies are supported
return true;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,98 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: SX1272 driver specific target board functions implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/*******************************************************************************
* @file sx1272mb2das.c
* @author MCD Application Team
* @version V1.0.4
* @date 08-September-2017
* @brief driver sx1272 board ( sx1272mb2das )
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SX1272MB2DAS__
#define __SX1272MB2DAS__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#define BOARD_WAKEUP_TIME 0 // no TCXO
/* Exported functions ------------------------------------------------------- */
/*!
* \brief Initializes the radio I/Os pins interface
*/
void SX1272IoInit( void );
/*!
* \brief De-initializes the radio I/Os pins interface.
*
* \remark Useful when going in MCU low power modes
*/
void SX1272IoDeInit( void );
/*!
* \brief Checks if the given RF frequency is supported by the hardware
*
* \param [IN] frequency RF frequency to be checked
* \retval isSupported [true: supported, false: unsupported]
*/
bool SX1272CheckRfFrequency( uint32_t frequency );
/*!
* Radio hardware and global parameters
*/
extern SX1272_t SX1272;
#ifdef __cplusplus
}
#endif
#endif /* __SX1272MB2DAS__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,147 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2015 Semtech
Description: End device commissioning parameters
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file commissioning.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief End device commissioning parameters
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LORA_COMMISSIONING_H__
#define __LORA_COMMISSIONING_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* When set to 1 the application uses the Over-the-Air activation procedure
* When set to 0 the application uses the Personalization activation procedure
*/
#define OVER_THE_AIR_ACTIVATION 1
/*!
* Indicates if the end-device is to be connected to a private or public network
*/
#define LORAWAN_PUBLIC_NETWORK true
/*!
* When set to 1 DevEui is LORAWAN_DEVICE_EUI
* When set to 0 DevEui is automatically generated by calling
* BoardGetUniqueId function
*/
#define STATIC_DEVICE_EUI 0
/*!
* Mote device IEEE EUI (big endian)
*
* \remark see STATIC_DEVICE_EUI comments
*/
#define LORAWAN_DEVICE_EUI { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }
/*!
* Application IEEE EUI (big endian)
*/
#define LORAWAN_APPLICATION_EUI { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }
/*!
* AES encryption/decryption cipher application key
*/
#define LORAWAN_APPLICATION_KEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
#if( OVER_THE_AIR_ACTIVATION == 0 )
/*!
* Current network ID
*/
#define LORAWAN_NETWORK_ID ( uint32_t )0
/*!
* When set to 1 DevAdd is LORAWAN_DEVICE_ADDRESS
* When set to 0 DevAdd is automatically generated using
* a pseudo random generator seeded with a value derived from
* BoardUniqueId value
*/
#define STATIC_DEVICE_ADDRESS 0
/*!
* Device address on the network (big endian)
*
* \remark see STATIC_DEVICE_ADDRESS comments
*/
#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x0100000a
/*!
* AES encryption/decryption cipher network session key
*/
#define LORAWAN_NWKSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
/*!
* AES encryption/decryption cipher application session key
*/
#define LORAWAN_APPSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
#endif /* OVER_THE_AIR_ACTIVATION == 0 */
#ifdef __cplusplus
}
#endif
#endif /* __LORA_COMMISSIONING_H__ */

@ -0,0 +1,154 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Bleeper board GPIO driver implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file hw_gpio.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief Header for driver hw_rtc.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#if 0
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __HW_GPIO_H__
#define __HW_GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
typedef void( GpioIrqHandler )( void );
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* GPIO IRQ handler function prototype
*/
IRQn_Type MSP_GetIRQn( uint16_t gpioPin);
/*!
* @brief Initializes the given GPIO object
*
* @param GPIOx: where x can be (A..E and H)
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @param [IN] initStruct GPIO_InitTypeDef intit structure
* @retval none
*/
void HW_GPIO_Init( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_InitTypeDef* initStruct);
/*!
* @brief Records the interrupt handler for the GPIO object
*
* @param GPIOx: where x can be (A..E and H)
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @param [IN] prio NVIC priority (0 is highest)
* @param [IN] irqHandler points to the function to execute
* @retval none
*/
void HW_GPIO_SetIrq( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint32_t prio, GpioIrqHandler *irqHandler );
/*!
* @brief Execute the interrupt from the object
*
* @param GPIOx: where x can be (A..E and H)
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @retval none
*/
void HW_GPIO_IrqHandler( uint16_t GPIO_Pin );
/*!
* @brief Writes the given value to the GPIO output
*
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @param [IN] value New GPIO output value
* @retval none
*/
void HW_GPIO_Write( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint32_t value );
/*!
* @brief Reads the current GPIO input value
*
* @param GPIOx: where x can be (A..E and H)
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @retval value Current GPIO input value
*/
uint32_t HW_GPIO_Read( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin );
#ifdef __cplusplus
}
#endif
#endif /* __HW_GPIO_H__ */
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,181 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Bleeper board GPIO driver implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file hw_rtc.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief Header for driver hw_rtc.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#if 0
#ifndef __HW_RTC_H__
#define __HW_RTC_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "utilities.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* @brief Initializes the RTC timer
* @note The timer is based on the RTC
* @param none
* @retval none
*/
void HW_RTC_Init( void );
/*!
* @brief Stop the Alarm
* @param none
* @retval none
*/
void HW_RTC_StopAlarm( void );
/*!
* @brief Return the minimum timeout the RTC is able to handle
* @param none
* @retval minimum value for a timeout
*/
uint32_t HW_RTC_GetMinimumTimeout( void );
/*!
* @brief Set the alarm
* @note The alarm is set at Reference + timeout
* @param timeout Duration of the Timer in ticks
*/
void HW_RTC_SetAlarm( uint32_t timeout );
/*!
* @brief Get the RTC timer elapsed time since the last Reference was set
* @retval RTC Elapsed time in ticks
*/
uint32_t HW_RTC_GetTimerElapsedTime( void );
/*!
* @brief Get the RTC timer value
* @retval none
*/
uint32_t HW_RTC_GetTimerValue( void );
/*!
* @brief Set the RTC timer Reference
* @retval Timer Reference Value in Ticks
*/
uint32_t HW_RTC_SetTimerContext( void );
/*!
* @brief Get the RTC timer Reference
* @retval Timer Value in Ticks
*/
uint32_t HW_RTC_GetTimerContext( void );
/*!
* @brief RTC IRQ Handler on the RTC Alarm
* @param none
* @retval none
*/
void HW_RTC_IrqHandler ( void );
/*!
* @brief a delay of delay ms by polling RTC
* @param delay in ms
* @param none
* @retval none
*/
void HW_RTC_DelayMs( uint32_t delay );
/*!
* @brief calculates the wake up time between wake up and mcu start
* @note resolution in RTC_ALARM_TIME_BASE
* @param none
* @retval none
*/
void HW_RTC_setMcuWakeUpTime( void );
/*!
* @brief returns the wake up time in us
* @param none
* @retval wake up time in ticks
*/
int16_t HW_RTC_getMcuWakeUpTime( void );
/*!
* @brief converts time in ms to time in ticks
* @param [IN] time in milliseconds
* @retval returns time in timer ticks
*/
uint32_t HW_RTC_ms2Tick( TimerTime_t timeMicroSec );
/*!
* @brief converts time in ticks to time in ms
* @param [IN] time in timer ticks
* @retval returns time in timer milliseconds
*/
TimerTime_t HW_RTC_Tick2ms( uint32_t tick );
#ifdef __cplusplus
}
#endif
#endif /* __HW_RTC_H__ */
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,128 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Header for driver hw spi module
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file hw_spi.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief Header for driver hw_spi.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#if 0
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __HW_SPI_H__
#define __HW_SPI_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* @brief Initializes the SPI object and MCU peripheral
*
* @param [IN] none
*/
void HW_SPI_Init( void );
/*!
* @brief De-initializes the SPI object and MCU peripheral
*
* @param [IN] none
*/
void HW_SPI_DeInit( void );
/*!
* @brief Initializes the SPI IOs
*
* @param [IN] none
*/
void HW_SPI_IoInit( void );
/*!
* @brief De-initializes the SPI IOs
*
* @param [IN] none
*/
void HW_SPI_IoDeInit( void );
/*!
* @brief Sends outData and receives inData
*
* @param [IN] outData Byte to be sent
* @retval inData Received byte.
*/
uint16_t HW_SPI_InOut( uint16_t outData );
#ifdef __cplusplus
}
#endif
#endif /* __HW_SPI_H__ */
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,87 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: contains all hardware driver
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file hw.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief contains all hardware driver
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#if 0
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __HW_H__
#define __HW_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include "hw_conf.h"
#include "hw_gpio.h"
#include "hw_spi.h"
#include "hw_rtc.h"
#include "hw_msp.h"
#include "debug.h"
#ifdef __cplusplus
}
#endif
#endif /* __HW_H__ */
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,192 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Bleeper board GPIO driver implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file hw_gpio.c
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief driver for GPIO
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#if 0
/* Includes ------------------------------------------------------------------*/
#include "hw.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static GpioIrqHandler *GpioIrq[16] = { NULL };
/* Private function prototypes -----------------------------------------------*/
static uint8_t HW_GPIO_GetBitPos(uint16_t GPIO_Pin);
/* Exported functions ---------------------------------------------------------*/
/*!
* @brief Initializes the given GPIO object
*
* @param GPIOx: where x can be (A..E and H)
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @param [IN] initStruct GPIO_InitTypeDef intit structure
* @retval none
*/
void HW_GPIO_Init( GPIO_TypeDef* port, uint16_t GPIO_Pin, GPIO_InitTypeDef* initStruct)
{
RCC_GPIO_CLK_ENABLE( (uint32_t) port);
initStruct->Pin = GPIO_Pin ;
HAL_GPIO_Init( port, initStruct );
}
/*!
* @brief Records the interrupt handler for the GPIO object
*
* @param GPIOx: where x can be (A..E and H)
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @param [IN] prio NVIC priority (0 is highest)
* @param [IN] irqHandler points to the function to execute
* @retval none
*/
void HW_GPIO_SetIrq( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint32_t prio, GpioIrqHandler *irqHandler )
{
IRQn_Type IRQnb;
uint32_t BitPos = HW_GPIO_GetBitPos( GPIO_Pin ) ;
if ( irqHandler != NULL)
{
GpioIrq[ BitPos ] = irqHandler;
IRQnb = MSP_GetIRQn( GPIO_Pin );
HAL_NVIC_SetPriority( IRQnb , prio, 0);
HAL_NVIC_EnableIRQ( IRQnb );
}
}
/*!
* @brief Execute the interrupt from the object
*
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @retval none
*/
void HW_GPIO_IrqHandler( uint16_t GPIO_Pin )
{
uint32_t BitPos = HW_GPIO_GetBitPos( GPIO_Pin );
if ( GpioIrq[ BitPos ] != NULL)
{
GpioIrq[ BitPos ] ( );
}
}
/*!
* @brief Writes the given value to the GPIO output
*
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @param [IN] value New GPIO output value
* @retval none
*/
void HW_GPIO_Write( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint32_t value )
{
HAL_GPIO_WritePin( GPIOx, GPIO_Pin , (GPIO_PinState) value );
}
/*!
* @brief Reads the current GPIO input value
*
* @param GPIOx: where x can be (A..E and H)
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @retval value Current GPIO input value
*/
uint32_t HW_GPIO_Read( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin )
{
return HAL_GPIO_ReadPin( GPIOx, GPIO_Pin);
}
/* Private functions ---------------------------------------------------------*/
/*!
* @brief Get the position of the bit set in the GPIO_Pin
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* All port bits are not necessarily available on all GPIOs.
* @retval the position of the bit
*/
static uint8_t HW_GPIO_GetBitPos(uint16_t GPIO_Pin)
{
uint8_t PinPos=0;
if ( ( GPIO_Pin & 0xFF00 ) != 0) { PinPos |= 0x8; }
if ( ( GPIO_Pin & 0xF0F0 ) != 0) { PinPos |= 0x4; }
if ( ( GPIO_Pin & 0xCCCC ) != 0) { PinPos |= 0x2; }
if ( ( GPIO_Pin & 0xAAAA ) != 0) { PinPos |= 0x1; }
return PinPos;
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,632 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: MCU RTC timer
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/*******************************************************************************
* @file hw_rtc.c
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief driver for RTC
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#if 0
/* Includes ------------------------------------------------------------------*/
#include "hw.h"
#include "low_power.h"
/* Private typedef -----------------------------------------------------------*/
typedef struct
{
TimerTime_t Rtc_Time; /* Reference time */
RTC_TimeTypeDef RTC_Calndr_Time; /* Reference time in calendar format */
RTC_DateTypeDef RTC_Calndr_Date; /* Reference date in calendar format */
} RtcTimerContext_t;
/* Private define ------------------------------------------------------------*/
/* MCU Wake Up Time */
#define MIN_ALARM_DELAY 3 /* in ticks */
/* subsecond number of bits */
#define N_PREDIV_S 10
/* Synchonuous prediv */
#define PREDIV_S ((1<<N_PREDIV_S)-1)
/* Asynchonuous prediv */
#define PREDIV_A (1<<(15-N_PREDIV_S))-1
/* Sub-second mask definition */
#if (N_PREDIV_S == 10)
#define HW_RTC_ALARMSUBSECONDMASK RTC_ALARMSUBSECONDMASK_SS14_10
#else
#error "Please define HW_RTC_ALARMSUBSECONDMASK"
#endif
/* RTC Time base in us */
#define USEC_NUMBER 1000000
#define MSEC_NUMBER (USEC_NUMBER/1000)
#define RTC_ALARM_TIME_BASE (USEC_NUMBER>>N_PREDIV_S)
#define COMMON_FACTOR 3
#define CONV_NUMER (MSEC_NUMBER>>COMMON_FACTOR)
#define CONV_DENOM (1<<(N_PREDIV_S-COMMON_FACTOR))
#define DAYS_IN_LEAP_YEAR (uint32_t) 366
#define DAYS_IN_YEAR (uint32_t) 365
#define SECONDS_IN_1DAY (uint32_t) 86400
#define SECONDS_IN_1HOUR (uint32_t) 3600
#define SECONDS_IN_1MINUTE (uint32_t) 60
#define MINUTES_IN_1HOUR (uint32_t) 60
#define HOURS_IN_1DAY (uint32_t) 24
#define DAYS_IN_MONTH_CORRECTION_NORM ((uint32_t) 0x99AAA0 )
#define DAYS_IN_MONTH_CORRECTION_LEAP ((uint32_t) 0x445550 )
/* Calculates ceiling(X/N) */
#define DIVC(X,N) ( ( (X) + (N) -1 ) / (N) )
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/*!
* \brief Indicates if the RTC is already Initalized or not
*/
static bool HW_RTC_Initalized = false;
/*!
* \brief compensates MCU wakeup time
*/
static bool McuWakeUpTimeInitialized = false;
/*!
* \brief compensates MCU wakeup time
*/
static int16_t McuWakeUpTimeCal = 0;
/*!
* Number of days in each month on a normal year
*/
static const uint8_t DaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
/*!
* Number of days in each month on a leap year
*/
static const uint8_t DaysInMonthLeapYear[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static RTC_HandleTypeDef RtcHandle={0};
static RTC_AlarmTypeDef RTC_AlarmStructure;
/*!
* Keep the value of the RTC timer when the RTC alarm is set
* Set with the HW_RTC_SetTimerContext function
* Value is kept as a Reference to calculate alarm
*/
static RtcTimerContext_t RtcTimerContext;
/* Private function prototypes -----------------------------------------------*/
static void HW_RTC_SetConfig( void );
static void HW_RTC_SetAlarmConfig( void );
static void HW_RTC_StartWakeUpAlarm( uint32_t timeoutValue );
static TimerTime_t HW_RTC_GetCalendarValue( RTC_DateTypeDef* RTC_DateStruct, RTC_TimeTypeDef* RTC_TimeStruct );
/* Exported functions ---------------------------------------------------------*/
/*!
* @brief Initializes the RTC timer
* @note The timer is based on the RTC
* @param none
* @retval none
*/
void HW_RTC_Init( void )
{
if( HW_RTC_Initalized == false )
{
HW_RTC_SetConfig( );
HW_RTC_SetAlarmConfig( );
HW_RTC_SetTimerContext( );
HW_RTC_Initalized = true;
}
}
/*!
* @brief Configures the RTC timer
* @note The timer is based on the RTC
* @param none
* @retval none
*/
static void HW_RTC_SetConfig( void )
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
RtcHandle.Instance = RTC;
RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
RtcHandle.Init.AsynchPrediv = PREDIV_A; /* RTC_ASYNCH_PREDIV; */
RtcHandle.Init.SynchPrediv = PREDIV_S; /* RTC_SYNCH_PREDIV; */
RtcHandle.Init.OutPut = RTC_OUTPUT;
RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
HAL_RTC_Init( &RtcHandle );
/*Monday 1st January 2016*/
RTC_DateStruct.Year = 0;
RTC_DateStruct.Month = RTC_MONTH_JANUARY;
RTC_DateStruct.Date = 1;
RTC_DateStruct.WeekDay = RTC_WEEKDAY_MONDAY;
HAL_RTC_SetDate(&RtcHandle , &RTC_DateStruct, RTC_FORMAT_BIN);
/*at 0:0:0*/
RTC_TimeStruct.Hours = 0;
RTC_TimeStruct.Minutes = 0;
RTC_TimeStruct.Seconds = 0;
RTC_TimeStruct.TimeFormat = 0;
RTC_TimeStruct.SubSeconds = 0;
RTC_TimeStruct.StoreOperation = RTC_DAYLIGHTSAVING_NONE;
RTC_TimeStruct.DayLightSaving = RTC_STOREOPERATION_RESET;
HAL_RTC_SetTime(&RtcHandle , &RTC_TimeStruct, RTC_FORMAT_BIN);
/*Enable Direct Read of the calendar registers (not through Shadow) */
HAL_RTCEx_EnableBypassShadow(&RtcHandle);
}
/*!
* @brief calculates the wake up time between wake up and mcu start
* @note resulotion in RTC_ALARM_TIME_BASE in timer ticks
* @param none
* @retval none
*/
void HW_RTC_setMcuWakeUpTime( void )
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
TimerTime_t now, hit;
int16_t McuWakeUpTime;
if ((McuWakeUpTimeInitialized == false) &&
( HAL_NVIC_GetPendingIRQ( RTC_Alarm_IRQn ) == 1))
{ /* warning: works ok if now is below 30 days
it is ok since it's done once at first alarm wake-up*/
McuWakeUpTimeInitialized = true;
now = HW_RTC_GetCalendarValue( &RTC_DateStruct, &RTC_TimeStruct );
DBG_GPIO_SET(GPIOB, GPIO_PIN_13);
DBG_GPIO_RST(GPIOB, GPIO_PIN_13);
HAL_RTC_GetAlarm(&RtcHandle, &RTC_AlarmStructure, RTC_ALARM_A, RTC_FORMAT_BIN );
hit = RTC_AlarmStructure.AlarmTime.Seconds+
60*(RTC_AlarmStructure.AlarmTime.Minutes+
60*(RTC_AlarmStructure.AlarmTime.Hours+
24*(RTC_AlarmStructure.AlarmDateWeekDay)));
hit = ( hit << N_PREDIV_S ) + (PREDIV_S - RTC_AlarmStructure.AlarmTime.SubSeconds);
McuWakeUpTime = (int16_t) ((now-hit));
McuWakeUpTimeCal += McuWakeUpTime;
DBG_PRINTF("Cal=%d, %d\n\r",McuWakeUpTimeCal, McuWakeUpTime);
}
}
int16_t HW_RTC_getMcuWakeUpTime( void )
{
return McuWakeUpTimeCal;
}
/*!
* @brief returns the wake up time in ticks
* @param none
* @retval wake up time in ticks
*/
uint32_t HW_RTC_GetMinimumTimeout( void )
{
return( MIN_ALARM_DELAY );
}
/*!
* @brief converts time in ms to time in ticks
* @param [IN] time in milliseconds
* @retval returns time in timer ticks
*/
uint32_t HW_RTC_ms2Tick( TimerTime_t timeMicroSec )
{
/*return( ( timeMicroSec / RTC_ALARM_TIME_BASE ) ); */
return ( uint32_t) ( ( ((uint64_t)timeMicroSec) * CONV_DENOM ) / CONV_NUMER );
}
/*!
* @brief converts time in ticks to time in ms
* @param [IN] time in timer ticks
* @retval returns time in milliseconds
*/
TimerTime_t HW_RTC_Tick2ms( uint32_t tick )
{
/*return( ( timeMicroSec * RTC_ALARM_TIME_BASE ) ); */
return ( ( (uint64_t)( tick )* CONV_NUMER ) / CONV_DENOM );
}
/*!
* @brief Set the alarm
* @note The alarm is set at now (read in this funtion) + timeout
* @param timeout Duration of the Timer ticks
*/
void HW_RTC_SetAlarm( uint32_t timeout )
{
/* we don't go in Low Power mode for timeout below MIN_ALARM_DELAY */
if ( (MIN_ALARM_DELAY + McuWakeUpTimeCal ) < ((timeout - HW_RTC_GetTimerElapsedTime( ) )) )
{
LowPower_Enable( e_LOW_POWER_RTC );
}
else
{
LowPower_Disable( e_LOW_POWER_RTC );
}
if( LowPower_GetState() == 0 )
{
LowPower_Enable( e_LOW_POWER_RTC );
timeout = timeout - McuWakeUpTimeCal;
}
HW_RTC_StartWakeUpAlarm( timeout );
}
/*!
* @brief Get the RTC timer elapsed time since the last Alarm was set
* @param none
* @retval RTC Elapsed time in ticks
*/
uint32_t HW_RTC_GetTimerElapsedTime( void )
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
TimerTime_t CalendarValue = HW_RTC_GetCalendarValue(&RTC_DateStruct, &RTC_TimeStruct );
return( ( uint32_t )( CalendarValue - RtcTimerContext.Rtc_Time ));
}
/*!
* @brief Get the RTC timer value
* @param none
* @retval RTC Timer value in ticks
*/
uint32_t HW_RTC_GetTimerValue( void )
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
uint32_t CalendarValue = (uint32_t) HW_RTC_GetCalendarValue(&RTC_DateStruct, &RTC_TimeStruct );
return( CalendarValue );
}
/*!
* @brief Stop the Alarm
* @param none
* @retval none
*/
void HW_RTC_StopAlarm( void )
{
/* Clear RTC Alarm Flag */
__HAL_RTC_ALARM_CLEAR_FLAG( &RtcHandle, RTC_FLAG_ALRAF);
/* Disable the Alarm A interrupt */
HAL_RTC_DeactivateAlarm(&RtcHandle, RTC_ALARM_A );
}
/*!
* @brief RTC IRQ Handler on the RTC Alarm
* @param none
* @retval none
*/
void HW_RTC_IrqHandler ( void )
{
RTC_HandleTypeDef* hrtc=&RtcHandle;
/* enable low power at irq*/
LowPower_Enable( e_LOW_POWER_RTC );
/* Get the AlarmA interrupt source enable status */
if(__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != RESET)
{
/* Get the pending status of the AlarmA Interrupt */
if(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != RESET)
{
/* Clear the AlarmA interrupt pending bit */
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
/* Clear the EXTI's line Flag for RTC Alarm */
__HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
/* AlarmA callback */
HAL_RTC_AlarmAEventCallback(hrtc);
}
}
}
/*!
* @brief a delay of delay ms by polling RTC
* @param delay in ms
* @retval none
*/
void HW_RTC_DelayMs( uint32_t delay )
{
TimerTime_t delayValue = 0;
TimerTime_t timeout = 0;
delayValue = HW_RTC_ms2Tick( delay );
/* Wait delay ms */
timeout = HW_RTC_GetTimerValue( );
while( ( ( HW_RTC_GetTimerValue( ) - timeout ) ) < delayValue )
{
__NOP( );
}
}
/*!
* @brief set Time Reference set also the RTC_DateStruct and RTC_TimeStruct
* @param none
* @retval Timer Value
*/
uint32_t HW_RTC_SetTimerContext( void )
{
RtcTimerContext.Rtc_Time = HW_RTC_GetCalendarValue( &RtcTimerContext.RTC_Calndr_Date, &RtcTimerContext.RTC_Calndr_Time );
return ( uint32_t ) RtcTimerContext.Rtc_Time;
}
/*!
* @brief Get the RTC timer Reference
* @param none
* @retval Timer Value in Ticks
*/
uint32_t HW_RTC_GetTimerContext( void )
{
return (uint32_t) RtcTimerContext.Rtc_Time;
}
/* Private functions ---------------------------------------------------------*/
/*!
* @brief configure alarm at init
* @param none
* @retval none
*/
static void HW_RTC_SetAlarmConfig( void )
{
HAL_RTC_DeactivateAlarm(&RtcHandle, RTC_ALARM_A);
}
/*!
* @brief start wake up alarm
* @note alarm in RtcTimerContext.Rtc_Time + timeoutValue
* @param timeoutValue in ticks
* @retval none
*/
static void HW_RTC_StartWakeUpAlarm( uint32_t timeoutValue )
{
uint16_t rtcAlarmSubSeconds = 0;
uint16_t rtcAlarmSeconds = 0;
uint16_t rtcAlarmMinutes = 0;
uint16_t rtcAlarmHours = 0;
uint16_t rtcAlarmDays = 0;
RTC_TimeTypeDef RTC_TimeStruct = RtcTimerContext.RTC_Calndr_Time;
RTC_DateTypeDef RTC_DateStruct = RtcTimerContext.RTC_Calndr_Date;
HW_RTC_StopAlarm( );
DBG_GPIO_SET(GPIOB, GPIO_PIN_13);
/*reverse counter */
rtcAlarmSubSeconds = PREDIV_S - RTC_TimeStruct.SubSeconds;
rtcAlarmSubSeconds += ( timeoutValue & PREDIV_S);
/* convert timeout to seconds */
timeoutValue >>= N_PREDIV_S; /* convert timeout in seconds */
/*convert microsecs to RTC format and add to 'Now' */
rtcAlarmDays = RTC_DateStruct.Date;
while (timeoutValue >= SECONDS_IN_1DAY)
{
timeoutValue -= SECONDS_IN_1DAY;
rtcAlarmDays++;
}
/* calc hours */
rtcAlarmHours = RTC_TimeStruct.Hours;
while (timeoutValue >= SECONDS_IN_1HOUR)
{
timeoutValue -= SECONDS_IN_1HOUR;
rtcAlarmHours++;
}
/* calc minutes */
rtcAlarmMinutes = RTC_TimeStruct.Minutes;
while (timeoutValue >= SECONDS_IN_1MINUTE)
{
timeoutValue -= SECONDS_IN_1MINUTE;
rtcAlarmMinutes++;
}
/* calc seconds */
rtcAlarmSeconds = RTC_TimeStruct.Seconds + timeoutValue;
/***** correct for modulo********/
while (rtcAlarmSubSeconds >= (PREDIV_S+1))
{
rtcAlarmSubSeconds -= (PREDIV_S+1);
rtcAlarmSeconds++;
}
while (rtcAlarmSeconds >= SECONDS_IN_1MINUTE)
{
rtcAlarmSeconds -= SECONDS_IN_1MINUTE;
rtcAlarmMinutes++;
}
while (rtcAlarmMinutes >= MINUTES_IN_1HOUR)
{
rtcAlarmMinutes -= MINUTES_IN_1HOUR;
rtcAlarmHours++;
}
while (rtcAlarmHours >= HOURS_IN_1DAY)
{
rtcAlarmHours -= HOURS_IN_1DAY;
rtcAlarmDays++;
}
if( RTC_DateStruct.Year % 4 == 0 )
{
if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.Month - 1 ] )
{
rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.Month - 1 ];
}
}
else
{
if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.Month - 1 ] )
{
rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.Month - 1 ];
}
}
/* Set RTC_AlarmStructure with calculated values*/
RTC_AlarmStructure.AlarmTime.SubSeconds = PREDIV_S-rtcAlarmSubSeconds;
RTC_AlarmStructure.AlarmSubSecondMask = HW_RTC_ALARMSUBSECONDMASK;
RTC_AlarmStructure.AlarmTime.Seconds = rtcAlarmSeconds;
RTC_AlarmStructure.AlarmTime.Minutes = rtcAlarmMinutes;
RTC_AlarmStructure.AlarmTime.Hours = rtcAlarmHours;
RTC_AlarmStructure.AlarmDateWeekDay = ( uint8_t )rtcAlarmDays;
RTC_AlarmStructure.AlarmTime.TimeFormat = RTC_TimeStruct.TimeFormat;
RTC_AlarmStructure.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_NONE;
RTC_AlarmStructure.Alarm = RTC_ALARM_A;
RTC_AlarmStructure.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
RTC_AlarmStructure.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
/* Set RTC_Alarm */
HAL_RTC_SetAlarm_IT( &RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN );
/* Debug Printf*/
DBG( HW_RTC_GetCalendarValue( &RTC_DateStruct, &RTC_TimeStruct ); );
DBG_PRINTF("it's %d:%d:%d:%d ", RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds, ((PREDIV_S - RTC_TimeStruct.SubSeconds)*1000)>>N_PREDIV_S);
DBG_PRINTF("WU@ %d:%d:%d:%d\n\r", rtcAlarmHours, rtcAlarmMinutes, rtcAlarmSeconds, (rtcAlarmSubSeconds*1000)>>N_PREDIV_S );
DBG_GPIO_RST(GPIOB, GPIO_PIN_13);
}
/*!
* @brief get current time from calendar in ticks
* @param pointer to RTC_DateStruct
* @param pointer to RTC_TimeStruct
* @retval time in ticks
*/
static TimerTime_t HW_RTC_GetCalendarValue( RTC_DateTypeDef* RTC_DateStruct, RTC_TimeTypeDef* RTC_TimeStruct )
{
TimerTime_t calendarValue = 0;
uint32_t first_read;
uint32_t correction;
/* Get Time and Date*/
HAL_RTC_GetTime( &RtcHandle, RTC_TimeStruct, RTC_FORMAT_BIN );
/* make sure it is correct due to asynchronus nature of RTC*/
do {
first_read = RTC_TimeStruct->SubSeconds;
HAL_RTC_GetDate( &RtcHandle, RTC_DateStruct, RTC_FORMAT_BIN );
HAL_RTC_GetTime( &RtcHandle, RTC_TimeStruct, RTC_FORMAT_BIN );
} while (first_read != RTC_TimeStruct->SubSeconds);
/* calculte amount of elapsed days since 01/01/2000 */
calendarValue= DIVC( (DAYS_IN_YEAR*3 + DAYS_IN_LEAP_YEAR)* RTC_DateStruct->Year , 4);
correction = ( (RTC_DateStruct->Year % 4) == 0 ) ? DAYS_IN_MONTH_CORRECTION_LEAP : DAYS_IN_MONTH_CORRECTION_NORM ;
calendarValue +=( DIVC( (RTC_DateStruct->Month-1)*(30+31) ,2 ) - (((correction>> ((RTC_DateStruct->Month-1)*2) )&0x3)));
calendarValue += (RTC_DateStruct->Date -1);
/* convert from days to seconds */
calendarValue *= SECONDS_IN_1DAY;
calendarValue += ( ( uint32_t )RTC_TimeStruct->Seconds +
( ( uint32_t )RTC_TimeStruct->Minutes * SECONDS_IN_1MINUTE ) +
( ( uint32_t )RTC_TimeStruct->Hours * SECONDS_IN_1HOUR ) ) ;
calendarValue = (calendarValue<<N_PREDIV_S) + ( PREDIV_S - RTC_TimeStruct->SubSeconds);
return( calendarValue );
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,224 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Bleeper board SPI driver implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/*******************************************************************************
* @file hw_spi.c
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief manages the SPI interface
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#if 0
/* Includes ------------------------------------------------------------------*/
#include "hw.h"
#include "utilities.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static SPI_HandleTypeDef hspi;
/* Private function prototypes -----------------------------------------------*/
/*!
* @brief Calculates Spi Divisor based on Spi Frequency and Mcu Frequency
*
* @param [IN] Spi Frequency
* @retval Spi divisor
*/
static uint32_t SpiFrequency( uint32_t hz );
/* Exported functions ---------------------------------------------------------*/
/*!
* @brief Initializes the SPI object and MCU peripheral
*
* @param [IN] none
*/
void HW_SPI_Init( void )
{
/*##-1- Configure the SPI peripheral */
/* Set the SPI parameters */
hspi.Instance = SPI1;
hspi.Init.BaudRatePrescaler = SpiFrequency( 10000000 );
hspi.Init.Direction = SPI_DIRECTION_2LINES;
hspi.Init.Mode = SPI_MODE_MASTER;
hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi.Init.DataSize = SPI_DATASIZE_8BIT;
hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi.Init.NSS = SPI_NSS_SOFT;
hspi.Init.TIMode = SPI_TIMODE_DISABLE;
SPI_CLK_ENABLE();
if(HAL_SPI_Init( &hspi) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Configure the SPI GPIOs */
HW_SPI_IoInit( );
}
/*!
* @brief De-initializes the SPI object and MCU peripheral
*
* @param [IN] none
*/
void HW_SPI_DeInit( void )
{
HAL_SPI_DeInit( &hspi);
/*##-1- Reset peripherals ####*/
__HAL_RCC_SPI1_FORCE_RESET();
__HAL_RCC_SPI1_RELEASE_RESET();
/*##-2- Configure the SPI GPIOs */
HW_SPI_IoDeInit( );
}
void HW_SPI_IoInit( void )
{
GPIO_InitTypeDef initStruct={0};
initStruct.Mode =GPIO_MODE_AF_PP;
initStruct.Pull = GPIO_PULLDOWN;
initStruct.Speed = GPIO_SPEED_HIGH;
initStruct.Alternate= SPI1_AF ;
HW_GPIO_Init( RADIO_SCLK_PORT, RADIO_SCLK_PIN, &initStruct);
HW_GPIO_Init( RADIO_MISO_PORT, RADIO_MISO_PIN, &initStruct);
HW_GPIO_Init( RADIO_MOSI_PORT, RADIO_MOSI_PIN, &initStruct);
initStruct.Mode = GPIO_MODE_OUTPUT_PP;
initStruct.Pull = GPIO_PULLUP;
HW_GPIO_Init( RADIO_NSS_PORT, RADIO_NSS_PIN, &initStruct );
HW_GPIO_Write ( RADIO_NSS_PORT, RADIO_NSS_PIN, 1 );
}
void HW_SPI_IoDeInit( void )
{
GPIO_InitTypeDef initStruct={0};
initStruct.Mode =GPIO_MODE_OUTPUT_PP;
initStruct.Pull =GPIO_PULLDOWN ;
HW_GPIO_Init ( RADIO_MOSI_PORT, RADIO_MOSI_PIN, &initStruct );
HW_GPIO_Write( RADIO_MOSI_PORT, RADIO_MOSI_PIN, 0 );
initStruct.Pull =GPIO_PULLDOWN;
HW_GPIO_Init ( RADIO_MISO_PORT, RADIO_MISO_PIN, &initStruct );
HW_GPIO_Write( RADIO_MISO_PORT, RADIO_MISO_PIN, 0 );
initStruct.Pull =GPIO_PULLDOWN ;
HW_GPIO_Init ( RADIO_SCLK_PORT, RADIO_SCLK_PIN, &initStruct );
HW_GPIO_Write( RADIO_SCLK_PORT, RADIO_SCLK_PIN, 0 );
initStruct.Pull = GPIO_PULLUP;
HW_GPIO_Init ( RADIO_NSS_PORT, RADIO_NSS_PIN , &initStruct );
HW_GPIO_Write( RADIO_NSS_PORT, RADIO_NSS_PIN , 1 );
}
/*!
* @brief Sends outData and receives inData
*
* @param [IN] outData Byte to be sent
* @retval inData Received byte.
*/
uint16_t HW_SPI_InOut( uint16_t txData )
{
uint16_t rxData ;
HAL_SPI_TransmitReceive( &hspi, ( uint8_t * ) &txData, ( uint8_t* ) &rxData, 1, HAL_MAX_DELAY);
return rxData;
}
/* Private functions ---------------------------------------------------------*/
static uint32_t SpiFrequency( uint32_t hz )
{
uint32_t divisor = 0;
uint32_t SysClkTmp = SystemCoreClock;
uint32_t baudRate;
while( SysClkTmp > hz)
{
divisor++;
SysClkTmp= ( SysClkTmp >> 1);
if (divisor >= 7)
break;
}
baudRate =((( divisor & 0x4 ) == 0 )? 0x0 : SPI_CR1_BR_2 )|
((( divisor & 0x2 ) == 0 )? 0x0 : SPI_CR1_BR_1 )|
((( divisor & 0x1 ) == 0 )? 0x0 : SPI_CR1_BR_0 );
return baudRate;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#endif

@ -0,0 +1,773 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: LoRaMac classA device implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis, Gregory Cristian and Wael Guibene
*/
/******************************************************************************
* @file lora.c
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief lora API to drive the lora state Machine
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "hw.h"
#include "timeServer.h"
#include "LoRaMac.h"
#include "lora.h"
/*!
* Join requests trials duty cycle.
*/
#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE 10000 // 10 [s] value in ms
#if defined( REGION_EU868 )
#include "LoRaMacTest.h"
/*!
* LoRaWAN ETSI duty cycle control enable/disable
*
* \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes
*/
#define LORAWAN_DUTYCYCLE_ON true
#define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP 0
#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 )
#define LC4 { 867100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC5 { 867300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC6 { 867500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC7 { 867700000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC8 { 867900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
#define LC9 { 868800000, 0, { ( ( DR_7 << 4 ) | DR_7 ) }, 2 }
#define LC10 { 868300000, 0, { ( ( DR_6 << 4 ) | DR_6 ) }, 1 }
#endif
#endif
static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
#if( OVER_THE_AIR_ACTIVATION == 0 )
static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
static uint8_t AppSKey[] = LORAWAN_APPSKEY;
/*!
* Device address
*/
static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
#endif
/*!
* User application data buffer size
*/
#define LORAWAN_APP_DATA_BUFF_SIZE 64
/*!
* User application data
*/
static uint8_t AppDataBuff[LORAWAN_APP_DATA_BUFF_SIZE];
/*!
* User application data structure
*/
static lora_AppData_t AppData={ AppDataBuff, 0 ,0 };
/*!
* Indicates if the node is sending confirmed or unconfirmed messages
*/
static FunctionalState IsTxConfirmed ;
/*!
* Defines the LoRa parameters at Init
*/
static LoRaParam_t* LoRaParamInit;
/*!
* Timer to handle the application data transmission duty cycle
*/
static TimerEvent_t TxNextPacketTimer;
static DeviceState_t DeviceState = DEVICE_STATE_INIT ;
/*!
* Timer to handle the state of LED1
*/
static LoRaMacPrimitives_t LoRaMacPrimitives;
static LoRaMacCallback_t LoRaMacCallbacks;
static MibRequestConfirm_t mibReq;
static LoRaMainCallback_t *LoRaMainCallbacks;
/*!
* Indicates if a new packet can be sent
*/
static bool NextTx = true;
/*!
* LoRaWAN compliance tests support data
*/
struct ComplianceTest_s
{
bool Running;
uint8_t State;
FunctionalState IsTxConfirmed;
uint8_t AppPort;
uint8_t AppDataSize;
uint8_t *AppDataBuffer;
uint16_t DownLinkCounter;
bool LinkCheck;
uint8_t DemodMargin;
uint8_t NbGateways;
}ComplianceTest;
/*!
* \brief Prepares the payload of the frame
*/
static void PrepareTxFrame( )
{
if( ComplianceTest.Running == true )
{
if( ComplianceTest.LinkCheck == true )
{
ComplianceTest.LinkCheck = false;
AppData.BuffSize = 3;
AppData.Buff[0] = 5;
AppData.Buff[1] = ComplianceTest.DemodMargin;
AppData.Buff[2] = ComplianceTest.NbGateways;
ComplianceTest.State = 1;
}
else
{
switch( ComplianceTest.State )
{
case 4:
ComplianceTest.State = 1;
break;
case 1:
AppData.BuffSize = 2;
AppData.Buff[0] = ComplianceTest.DownLinkCounter >> 8;
AppData.Buff[1] = ComplianceTest.DownLinkCounter;
break;
}
}
}
else
{
LoRaMainCallbacks->LoraTxData(&AppData, &IsTxConfirmed);
}
}
/*!
* \brief Prepares the payload of the frame
*
* \retval [0: frame could be send, 1: error]
*/
static bool SendFrame( void )
{
McpsReq_t mcpsReq;
LoRaMacTxInfo_t txInfo;
if( LoRaMacQueryTxPossible( AppData.BuffSize, &txInfo ) != LORAMAC_STATUS_OK )
{
// Send empty frame in order to flush MAC commands
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fBuffer = NULL;
mcpsReq.Req.Unconfirmed.fBufferSize = 0;
mcpsReq.Req.Unconfirmed.Datarate = LoRaParamInit->TxDatarate;
}
else
{
if( IsTxConfirmed == DISABLE )
{
mcpsReq.Type = MCPS_UNCONFIRMED;
mcpsReq.Req.Unconfirmed.fPort = AppData.Port;
mcpsReq.Req.Unconfirmed.fBuffer = AppData.Buff;
mcpsReq.Req.Unconfirmed.fBufferSize = AppData.BuffSize;
mcpsReq.Req.Unconfirmed.Datarate = LoRaParamInit->TxDatarate;
}
else
{
mcpsReq.Type = MCPS_CONFIRMED;
mcpsReq.Req.Confirmed.fPort = AppData.Port;
mcpsReq.Req.Confirmed.fBuffer = AppData.Buff;
mcpsReq.Req.Confirmed.fBufferSize = AppData.BuffSize;
mcpsReq.Req.Confirmed.NbTrials = 8;
mcpsReq.Req.Confirmed.Datarate = LoRaParamInit->TxDatarate;
}
}
if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
{
return false;
}
return true;
}
void OnSendEvent( void )
{
MibRequestConfirm_t mibReq;
LoRaMacStatus_t status;
mibReq.Type = MIB_NETWORK_JOINED;
status = LoRaMacMibGetRequestConfirm( &mibReq );
if( status == LORAMAC_STATUS_OK )
{
if( mibReq.Param.IsNetworkJoined == true )
{
DeviceState = DEVICE_STATE_SEND;
NextTx = true;
}
else
{
DeviceState = DEVICE_STATE_JOIN;
}
}
}
/*!
* \brief Function executed on TxNextPacket Timeout event
*/
static void OnTxNextPacketTimerEvent( void )
{
TimerStop( &TxNextPacketTimer );
OnSendEvent();
}
/*!
* \brief MCPS-Confirm event function
*
* \param [IN] McpsConfirm - Pointer to the confirm structure,
* containing confirm attributes.
*/
static void McpsConfirm( McpsConfirm_t *mcpsConfirm )
{
if( mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
{
switch( mcpsConfirm->McpsRequest )
{
case MCPS_UNCONFIRMED:
{
// Check Datarate
// Check TxPower
break;
}
case MCPS_CONFIRMED:
{
// Check Datarate
// Check TxPower
// Check AckReceived
// Check NbTrials
break;
}
case MCPS_PROPRIETARY:
{
break;
}
default:
break;
}
}
NextTx = true;
}
/*!
* \brief MCPS-Indication event function
*
* \param [IN] mcpsIndication - Pointer to the indication structure,
* containing indication attributes.
*/
static void McpsIndication( McpsIndication_t *mcpsIndication )
{
if( mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
{
return;
}
switch( mcpsIndication->McpsIndication )
{
case MCPS_UNCONFIRMED:
{
break;
}
case MCPS_CONFIRMED:
{
break;
}
case MCPS_PROPRIETARY:
{
break;
}
case MCPS_MULTICAST:
{
break;
}
default:
break;
}
// Check Multicast
// Check Port
// Check Datarate
// Check FramePending
// Check Buffer
// Check BufferSize
// Check Rssi
// Check Snr
// Check RxSlot
if( ComplianceTest.Running == true )
{
ComplianceTest.DownLinkCounter++;
}
if( mcpsIndication->RxData == true )
{
switch( mcpsIndication->Port )
{
case 224:
if( ComplianceTest.Running == false )
{
// Check compliance test enable command (i)
if( ( mcpsIndication->BufferSize == 4 ) &&
( mcpsIndication->Buffer[0] == 0x01 ) &&
( mcpsIndication->Buffer[1] == 0x01 ) &&
( mcpsIndication->Buffer[2] == 0x01 ) &&
( mcpsIndication->Buffer[3] == 0x01 ) )
{
IsTxConfirmed = DISABLE;
AppData.Port = 224;
AppData.BuffSize = 2;
ComplianceTest.DownLinkCounter = 0;
ComplianceTest.LinkCheck = false;
ComplianceTest.DemodMargin = 0;
ComplianceTest.NbGateways = 0;
ComplianceTest.Running = true;
ComplianceTest.State = 1;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = true;
LoRaMacMibSetRequestConfirm( &mibReq );
#if defined( REGION_EU868 )
LoRaMacTestSetDutyCycleOn( false );
#endif
}
}
else
{
ComplianceTest.State = mcpsIndication->Buffer[0];
switch( ComplianceTest.State )
{
case 0: // Check compliance test disable command (ii)
ComplianceTest.DownLinkCounter = 0;
ComplianceTest.Running = false;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = LoRaParamInit->AdrEnable;
LoRaMacMibSetRequestConfirm( &mibReq );
#if defined( REGION_EU868 )
LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
#endif
break;
case 1: // (iii, iv)
AppData.BuffSize = 2;
break;
case 2: // Enable confirmed messages (v)
IsTxConfirmed = ENABLE;
ComplianceTest.State = 1;
break;
case 3: // Disable confirmed messages (vi)
IsTxConfirmed = DISABLE;
ComplianceTest.State = 1;
break;
case 4: // (vii)
AppData.BuffSize = mcpsIndication->BufferSize;
AppData.Buff[0] = 4;
for( uint8_t i = 1; i < AppData.BuffSize; i++ )
{
AppData.Buff[i] = mcpsIndication->Buffer[i] + 1;
}
break;
case 5: // (viii)
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_LINK_CHECK;
LoRaMacMlmeRequest( &mlmeReq );
}
break;
case 6: // (ix)
{
MlmeReq_t mlmeReq;
// Disable TestMode and revert back to normal operation
ComplianceTest.DownLinkCounter = 0;
ComplianceTest.Running = false;
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = LoRaParamInit->AdrEnable;
LoRaMacMibSetRequestConfirm( &mibReq );
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join.DevEui = DevEui;
mlmeReq.Req.Join.AppEui = AppEui;
mlmeReq.Req.Join.AppKey = AppKey;
mlmeReq.Req.Join.NbTrials = 3;
LoRaMacMlmeRequest( &mlmeReq );
DeviceState = DEVICE_STATE_SLEEP;
}
break;
case 7: // (x)
{
if( mcpsIndication->BufferSize == 3 )
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_TXCW;
mlmeReq.Req.TxCw.Timeout = ( uint16_t )( ( mcpsIndication->Buffer[1] << 8 ) | mcpsIndication->Buffer[2] );
LoRaMacMlmeRequest( &mlmeReq );
}
else if( mcpsIndication->BufferSize == 7 )
{
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_TXCW_1;
mlmeReq.Req.TxCw.Timeout = ( uint16_t )( ( mcpsIndication->Buffer[1] << 8 ) | mcpsIndication->Buffer[2] );
mlmeReq.Req.TxCw.Frequency = ( uint32_t )( ( mcpsIndication->Buffer[3] << 16 ) | ( mcpsIndication->Buffer[4] << 8 ) | mcpsIndication->Buffer[5] ) * 100;
mlmeReq.Req.TxCw.Power = mcpsIndication->Buffer[6];
LoRaMacMlmeRequest( &mlmeReq );
}
ComplianceTest.State = 1;
}
break;
default:
break;
}
}
break;
default:
AppData.Port = mcpsIndication->Port;
AppData.BuffSize = mcpsIndication->BufferSize;
memcpy1( AppData.Buff, mcpsIndication->Buffer, AppData.BuffSize );
LoRaMainCallbacks->LoraRxData( &AppData );
break;
}
}
}
/*!
* \brief MLME-Confirm event function
*
* \param [IN] MlmeConfirm - Pointer to the confirm structure,
* containing confirm attributes.
*/
static void MlmeConfirm( MlmeConfirm_t *mlmeConfirm )
{
switch( mlmeConfirm->MlmeRequest )
{
case MLME_JOIN:
{
if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
{
// Status is OK, node has joined the network
DeviceState = DEVICE_STATE_JOINED;
}
else
{
// Join was not successful. Try to join again
DeviceState = DEVICE_STATE_JOIN;
}
break;
}
case MLME_LINK_CHECK:
{
if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
{
// Check DemodMargin
// Check NbGateways
if( ComplianceTest.Running == true )
{
ComplianceTest.LinkCheck = true;
ComplianceTest.DemodMargin = mlmeConfirm->DemodMargin;
ComplianceTest.NbGateways = mlmeConfirm->NbGateways;
}
}
break;
}
default:
break;
}
NextTx = true;
}
/**
* lora Init
*/
void lora_Init (LoRaMainCallback_t *callbacks, LoRaParam_t* LoRaParam )
{
/* init the DeviceState*/
DeviceState= DEVICE_STATE_INIT;
/* init the Tx Duty Cycle*/
LoRaParamInit = LoRaParam;
/* init the main call backs*/
LoRaMainCallbacks = callbacks;
#if (STATIC_DEVICE_EUI != 1)
LoRaMainCallbacks->BoardGetUniqueId( DevEui );
#endif
#if( OVER_THE_AIR_ACTIVATION != 0 )
PRINTF("OTAA\n\r");
PRINTF("DevEui= %02X", DevEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", DevEui[i]); }; PRINTF("\n\r");
PRINTF("AppEui= %02X", AppEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", AppEui[i]); }; PRINTF("\n\r");
PRINTF("AppKey= %02X", AppKey[0]) ;for(int i=1; i<16; i++) {PRINTF(" %02X", AppKey[i]); }; PRINTF("\n\n\r");
#else
#if (STATIC_DEVICE_ADDRESS != 1)
// Random seed initialization
srand1( LoRaMainCallbacks->BoardGetRandomSeed( ) );
// Choose a random device address
DevAddr = randr( 0, 0x01FFFFFF );
#endif
PRINTF("ABP\n\r");
PRINTF("DevEui= %02X", DevEui[0]) ;for(int i=1; i<8 ; i++) {PRINTF("-%02X", DevEui[i]); }; PRINTF("\n\r");
PRINTF("DevAdd= %08X\n\r", DevAddr) ;
PRINTF("NwkSKey= %02X", NwkSKey[0]) ;for(int i=1; i<16 ; i++) {PRINTF(" %02X", NwkSKey[i]); }; PRINTF("\n\r");
PRINTF("AppSKey= %02X", AppSKey[0]) ;for(int i=1; i<16 ; i++) {PRINTF(" %02X", AppSKey[i]); }; PRINTF("\n\r");
#endif
}
/**
* lora class A state machine
*/
void lora_fsm( void)
{
switch( DeviceState )
{
case DEVICE_STATE_INIT:
{
LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
LoRaMacCallbacks.GetBatteryLevel = LoRaMainCallbacks->BoardGetBatteryLevel;
#if defined( REGION_AS923 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_AS923 );
#elif defined( REGION_AU915 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_AU915 );
#elif defined( REGION_CN470 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_CN470 );
#elif defined( REGION_CN779 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_CN779 );
#elif defined( REGION_EU433 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_EU433 );
#elif defined( REGION_IN865 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_IN865 );
#elif defined( REGION_EU868 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_EU868 );
#elif defined( REGION_KR920 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_KR920 );
#elif defined( REGION_US915 )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_US915 );
#elif defined( REGION_US915_HYBRID )
LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_US915_HYBRID );
#else
#error "Please define a region in the compiler options."
#endif
TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
mibReq.Type = MIB_ADR;
mibReq.Param.AdrEnable = LoRaParamInit->AdrEnable;
LoRaMacMibSetRequestConfirm( &mibReq );
mibReq.Type = MIB_PUBLIC_NETWORK;
mibReq.Param.EnablePublicNetwork = LoRaParamInit->EnablePublicNetwork;
LoRaMacMibSetRequestConfirm( &mibReq );
mibReq.Type = MIB_DEVICE_CLASS;
mibReq.Param.Class= LoRaParamInit->Class;
LoRaMacMibSetRequestConfirm( &mibReq );
#if defined( REGION_EU868 )
LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 )
LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 );
LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 );
LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 );
LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 );
LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 );
LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 );
LoRaMacChannelAdd( 9, ( ChannelParams_t )LC10 );
mibReq.Type = MIB_RX2_DEFAULT_CHANNEL;
mibReq.Param.Rx2DefaultChannel = ( Rx2ChannelParams_t ){ 869525000, DR_3 };
LoRaMacMibSetRequestConfirm( &mibReq );
mibReq.Type = MIB_RX2_CHANNEL;
mibReq.Param.Rx2Channel = ( Rx2ChannelParams_t ){ 869525000, DR_3 };
LoRaMacMibSetRequestConfirm( &mibReq );
#endif
#endif
DeviceState = DEVICE_STATE_JOIN;
break;
}
case DEVICE_STATE_JOIN:
{
#if( OVER_THE_AIR_ACTIVATION != 0 )
MlmeReq_t mlmeReq;
mlmeReq.Type = MLME_JOIN;
mlmeReq.Req.Join.DevEui = DevEui;
mlmeReq.Req.Join.AppEui = AppEui;
mlmeReq.Req.Join.AppKey = AppKey;
mlmeReq.Req.Join.NbTrials = LoRaParamInit->NbTrials;
if( NextTx == true )
{
LoRaMacMlmeRequest( &mlmeReq );
}
DeviceState = DEVICE_STATE_SLEEP;
#else
mibReq.Type = MIB_NET_ID;
mibReq.Param.NetID = LORAWAN_NETWORK_ID;
LoRaMacMibSetRequestConfirm( &mibReq );
mibReq.Type = MIB_DEV_ADDR;
mibReq.Param.DevAddr = DevAddr;
LoRaMacMibSetRequestConfirm( &mibReq );
mibReq.Type = MIB_NWK_SKEY;
mibReq.Param.NwkSKey = NwkSKey;
LoRaMacMibSetRequestConfirm( &mibReq );
mibReq.Type = MIB_APP_SKEY;
mibReq.Param.AppSKey = AppSKey;
LoRaMacMibSetRequestConfirm( &mibReq );
mibReq.Type = MIB_NETWORK_JOINED;
mibReq.Param.IsNetworkJoined = true;
LoRaMacMibSetRequestConfirm( &mibReq );
DeviceState = DEVICE_STATE_SEND;
#endif
break;
}
case DEVICE_STATE_JOINED:
{
PRINTF("JOINED\n\r");
DeviceState = DEVICE_STATE_SEND;
break;
}
case DEVICE_STATE_SEND:
{
if( NextTx == true )
{
PrepareTxFrame( );
NextTx = SendFrame( );
}
if( ComplianceTest.Running == true )
{
// Schedule next packet transmission as soon as possible
TimerSetValue( &TxNextPacketTimer, 5000); /* 5s */
TimerStart( &TxNextPacketTimer );
}
else if (LoRaParamInit->TxEvent == TX_ON_TIMER )
{
// Schedule next packet transmission
TimerSetValue( &TxNextPacketTimer, LoRaParamInit->TxDutyCycleTime );
TimerStart( &TxNextPacketTimer );
}
DeviceState = DEVICE_STATE_SLEEP;
break;
}
case DEVICE_STATE_SLEEP:
{
// Wake up through events
break;
}
default:
{
DeviceState = DEVICE_STATE_INIT;
break;
}
}
}
DeviceState_t lora_getDeviceState( void )
{
return DeviceState;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,251 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: LoRaMac classA device implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis, Gregory Cristian and Wael Guibene
*/
/******************************************************************************
* @file lora.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief lora API to drive the lora state Machine
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LORA_MAIN_H__
#define __LORA_MAIN_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "Commissioning.h"
#include "LoRaMac.h"
#include "region/Region.h"
/* Exported constants --------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/*!
* Application Data structure
*/
typedef struct
{
/*point to the LoRa App data buffer*/
uint8_t* Buff;
/*LoRa App data buffer size*/
uint8_t BuffSize;
/*Port on which the LoRa App is data is sent/ received*/
uint8_t Port;
} lora_AppData_t;
/*!
* LoRa State Machine states
*/
typedef enum eDevicState
{
DEVICE_STATE_INIT,
DEVICE_STATE_JOIN,
DEVICE_STATE_JOINED,
DEVICE_STATE_SEND,
DEVICE_STATE_CYCLE,
DEVICE_STATE_SLEEP
} DeviceState_t;
/*!
* LoRa State Machine states
*/
typedef enum eTxEventType
{
/*!
* @brief AppdataTransmition issue based on timer every TxDutyCycleTime
*/
TX_ON_TIMER,
/*!
* @brief AppdataTransmition external event plugged on OnSendEvent( )
*/
TX_ON_EVENT
} TxEventType_t;
/*!
* LoRa State Machine states
*/
typedef struct sLoRaParam
{
/*!
* @brief Event type
*
* @retval value battery level ( 0: very low, 254: fully charged )
*/
TxEventType_t TxEvent;
/*!
* @brief Application data transmission duty cycle in ms
*
* @note when TX_ON_TIMER Event type is selected
*/
uint32_t TxDutyCycleTime;
/*!
* @brief LoRaWAN device class
*/
DeviceClass_t Class;
/*!
* @brief Activation state of adaptativeDatarate
*/
bool AdrEnable;
/*!
* @brief Uplink datarate, if AdrEnable is off
*/
int8_t TxDatarate;
/*!
* @brief Enable or disable a public network
*
*/
bool EnablePublicNetwork;
/*!
* @brief Number of trials for the join request.
*/
uint8_t NbTrials;
} LoRaParam_t;
/* Lora Main callbacks*/
typedef struct sLoRaMainCallback
{
/*!
* @brief Get the current battery level
*
* @retval value battery level ( 0: very low, 254: fully charged )
*/
uint8_t ( *BoardGetBatteryLevel )( void );
/*!
* @brief Gets the board 64 bits unique ID
*
* @param [IN] id Pointer to an array that will contain the Unique ID
*/
void ( *BoardGetUniqueId ) ( uint8_t *id);
/*!
* Returns a pseudo random seed generated using the MCU Unique ID
*
* @retval seed Generated pseudo random seed
*/
uint32_t ( *BoardGetRandomSeed ) (void);
/*!
* @brief Prepares Tx Data to be sent on Lora network
*
* @param [IN] AppData is a buffer to fill
*
* @param [IN] port is a Application port on wicth Appdata will be sent
*
* @param [IN] length of the AppDataBuffer to send
*
* @param [IN] requests a confirmed Frame from the Network
*/
void ( *LoraTxData ) ( lora_AppData_t *AppData, FunctionalState* IsTxConfirmed);
/*!
* @brief Process Rx Data received from Lora network
*
* @param [IN] AppData is a buffer to process
*
* @param [IN] port is a Application port on wicth Appdata will be sent
*
* @param [IN] length is the number of recieved bytes
*/
void ( *LoraRxData ) ( lora_AppData_t *AppData);
} LoRaMainCallback_t;
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Lora Initialisation
* @param [IN] LoRaMainCallback_t
* @param [IN] application parmaters
* @retval none
*/
void lora_Init (LoRaMainCallback_t *callbacks, LoRaParam_t* LoRaParam );
/**
* @brief run Lora classA state Machine
* @param [IN] none
* @retval none
*/
void lora_fsm( void );
/**
* @brief functionl requesting loRa state machine to send data
* @note function to link in mode TX_ON_EVENT
* @param none
* @retval none
*/
void OnSendEvent( void );
/**
* @brief API returns the state of the lora state machine
* @note return @DeviceState_t state
* @param [IN] none
* @retval return @FlagStatus
*/
DeviceState_t lora_getDeviceState( void );
#ifdef __cplusplus
}
#endif
#endif /*__LORA_MAIN_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,88 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: LoRaMac classA device implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis, Gregory Cristian and Wael Guibene
*/
/******************************************************************************
* @file lora_mac_version.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief defines the lora mac version
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LORA_MAC_VERSION_H__
#define __LORA_MAC_VERSION_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/*the 3 MSBs define the version based on Github version */
/*https://github.com/Lora-net/LoRaMac-node/wiki/LoRaMAC-node-Wiki*/
/* version 4.4.0 from develop branch */
#define LORA_MAC_VERSION (uint32_t) 0x44030000
/* Exported types ------------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /*__LORA_MAC_VERSION_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,936 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue 09/09/2006
This is an AES implementation that uses only 8-bit byte operations on the
cipher state (there are options to use 32-bit types if available).
The combination of mix columns and byte substitution used here is based on
that developed by Karl Malbrain. His contribution is acknowledged.
*/
/* define if you have a fast memcpy function on your system */
#if 0
# define HAVE_MEMCPY
# include <string.h>
# if defined( _MSC_VER )
# include <intrin.h>
# pragma intrinsic( memcpy )
# endif
#endif
#include <stdlib.h>
#include <stdint.h>
/* define if you have fast 32-bit types on your system */
#if 0
# define HAVE_UINT_32T
#endif
/* define if you don't want any tables */
#if 1
# define USE_TABLES
#endif
/* On Intel Core 2 duo VERSION_1 is faster */
/* alternative versions (test for performance on your system) */
#if 1
# define VERSION_1
#endif
#include "aes.h"
//#if defined( HAVE_UINT_32T )
// typedef unsigned long uint32_t;
//#endif
/* functions for finite field multiplication in the AES Galois field */
#define WPOLY 0x011b
#define BPOLY 0x1b
#define DPOLY 0x008d
#define f1(x) (x)
#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \
^ (((x >> 5) & 4) * WPOLY))
#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
#define f3(x) (f2(x) ^ x)
#define f9(x) (f8(x) ^ x)
#define fb(x) (f8(x) ^ f2(x) ^ x)
#define fd(x) (f8(x) ^ f4(x) ^ x)
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
#if defined( USE_TABLES )
#define sb_data(w) { /* S Box data values */ \
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
#define isb_data(w) { /* inverse S Box data values */ \
w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
#define mm_data(w) { /* basic data for forming finite field tables */ \
w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
static const uint8_t sbox[256] = sb_data(f1);
#if defined( AES_DEC_PREKEYED )
static const uint8_t isbox[256] = isb_data(f1);
#endif
static const uint8_t gfm2_sbox[256] = sb_data(f2);
static const uint8_t gfm3_sbox[256] = sb_data(f3);
#if defined( AES_DEC_PREKEYED )
static const uint8_t gfmul_9[256] = mm_data(f9);
static const uint8_t gfmul_b[256] = mm_data(fb);
static const uint8_t gfmul_d[256] = mm_data(fd);
static const uint8_t gfmul_e[256] = mm_data(fe);
#endif
#define s_box(x) sbox[(x)]
#if defined( AES_DEC_PREKEYED )
#define is_box(x) isbox[(x)]
#endif
#define gfm2_sb(x) gfm2_sbox[(x)]
#define gfm3_sb(x) gfm3_sbox[(x)]
#if defined( AES_DEC_PREKEYED )
#define gfm_9(x) gfmul_9[(x)]
#define gfm_b(x) gfmul_b[(x)]
#define gfm_d(x) gfmul_d[(x)]
#define gfm_e(x) gfmul_e[(x)]
#endif
#else
/* this is the high bit of x right shifted by 1 */
/* position. Since the starting polynomial has */
/* 9 bits (0x11b), this right shift keeps the */
/* values of all top bits within a byte */
static uint8_t hibit(const uint8_t x)
{ uint8_t r = (uint8_t)((x >> 1) | (x >> 2));
r |= (r >> 2);
r |= (r >> 4);
return (r + 1) >> 1;
}
/* return the inverse of the finite field element x */
static uint8_t gf_inv(const uint8_t x)
{ uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
if(x < 2)
return x;
for( ; ; )
{
if(n1)
while(n2 >= n1) /* divide polynomial p2 by p1 */
{
n2 /= n1; /* shift smaller polynomial left */
p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */
v2 ^= (v1 * n2); /* shift accumulated value and */
n2 = hibit(p2); /* add into result */
}
else
return v1;
if(n2) /* repeat with values swapped */
while(n1 >= n2)
{
n1 /= n2;
p1 ^= p2 * n1;
v1 ^= v2 * n1;
n1 = hibit(p1);
}
else
return v2;
}
}
/* The forward and inverse affine transformations used in the S-box */
uint8_t fwd_affine(const uint8_t x)
{
#if defined( HAVE_UINT_32T )
uint32_t w = x;
w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
#else
return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4)
^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4);
#endif
}
uint8_t inv_affine(const uint8_t x)
{
#if defined( HAVE_UINT_32T )
uint32_t w = x;
w = (w << 1) ^ (w << 3) ^ (w << 6);
return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
#else
return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6)
^ (x >> 7) ^ (x >> 5) ^ (x >> 2);
#endif
}
#define s_box(x) fwd_affine(gf_inv(x))
#define is_box(x) gf_inv(inv_affine(x))
#define gfm2_sb(x) f2(s_box(x))
#define gfm3_sb(x) f3(s_box(x))
#define gfm_9(x) f9(x)
#define gfm_b(x) fb(x)
#define gfm_d(x) fd(x)
#define gfm_e(x) fe(x)
#endif
#if defined( HAVE_MEMCPY )
# define block_copy_nn(d, s, l) memcpy(d, s, l)
# define block_copy(d, s) memcpy(d, s, N_BLOCK)
#else
# define block_copy_nn(d, s, l) copy_block_nn(d, s, l)
# define block_copy(d, s) copy_block(d, s)
#endif
static void copy_block( void *d, const void *s )
{
#if defined( HAVE_UINT_32T )
((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0];
((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1];
((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2];
((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3];
#else
((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0];
((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1];
((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2];
((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3];
((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4];
((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5];
((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6];
((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7];
((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8];
((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9];
((uint8_t*)d)[10] = ((uint8_t*)s)[10];
((uint8_t*)d)[11] = ((uint8_t*)s)[11];
((uint8_t*)d)[12] = ((uint8_t*)s)[12];
((uint8_t*)d)[13] = ((uint8_t*)s)[13];
((uint8_t*)d)[14] = ((uint8_t*)s)[14];
((uint8_t*)d)[15] = ((uint8_t*)s)[15];
#endif
}
static void copy_block_nn( uint8_t * d, const uint8_t *s, uint8_t nn )
{
while( nn-- )
//*((uint8_t*)d)++ = *((uint8_t*)s)++;
*d++ = *s++;
}
static void xor_block( void *d, const void *s )
{
#if defined( HAVE_UINT_32T )
((uint32_t*)d)[ 0] ^= ((uint32_t*)s)[ 0];
((uint32_t*)d)[ 1] ^= ((uint32_t*)s)[ 1];
((uint32_t*)d)[ 2] ^= ((uint32_t*)s)[ 2];
((uint32_t*)d)[ 3] ^= ((uint32_t*)s)[ 3];
#else
((uint8_t*)d)[ 0] ^= ((uint8_t*)s)[ 0];
((uint8_t*)d)[ 1] ^= ((uint8_t*)s)[ 1];
((uint8_t*)d)[ 2] ^= ((uint8_t*)s)[ 2];
((uint8_t*)d)[ 3] ^= ((uint8_t*)s)[ 3];
((uint8_t*)d)[ 4] ^= ((uint8_t*)s)[ 4];
((uint8_t*)d)[ 5] ^= ((uint8_t*)s)[ 5];
((uint8_t*)d)[ 6] ^= ((uint8_t*)s)[ 6];
((uint8_t*)d)[ 7] ^= ((uint8_t*)s)[ 7];
((uint8_t*)d)[ 8] ^= ((uint8_t*)s)[ 8];
((uint8_t*)d)[ 9] ^= ((uint8_t*)s)[ 9];
((uint8_t*)d)[10] ^= ((uint8_t*)s)[10];
((uint8_t*)d)[11] ^= ((uint8_t*)s)[11];
((uint8_t*)d)[12] ^= ((uint8_t*)s)[12];
((uint8_t*)d)[13] ^= ((uint8_t*)s)[13];
((uint8_t*)d)[14] ^= ((uint8_t*)s)[14];
((uint8_t*)d)[15] ^= ((uint8_t*)s)[15];
#endif
}
static void copy_and_key( void *d, const void *s, const void *k )
{
#if defined( HAVE_UINT_32T )
((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0] ^ ((uint32_t*)k)[ 0];
((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1] ^ ((uint32_t*)k)[ 1];
((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2] ^ ((uint32_t*)k)[ 2];
((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3] ^ ((uint32_t*)k)[ 3];
#elif 1
((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0] ^ ((uint8_t*)k)[ 0];
((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1] ^ ((uint8_t*)k)[ 1];
((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2] ^ ((uint8_t*)k)[ 2];
((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3] ^ ((uint8_t*)k)[ 3];
((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4] ^ ((uint8_t*)k)[ 4];
((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5] ^ ((uint8_t*)k)[ 5];
((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6] ^ ((uint8_t*)k)[ 6];
((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7] ^ ((uint8_t*)k)[ 7];
((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8] ^ ((uint8_t*)k)[ 8];
((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9] ^ ((uint8_t*)k)[ 9];
((uint8_t*)d)[10] = ((uint8_t*)s)[10] ^ ((uint8_t*)k)[10];
((uint8_t*)d)[11] = ((uint8_t*)s)[11] ^ ((uint8_t*)k)[11];
((uint8_t*)d)[12] = ((uint8_t*)s)[12] ^ ((uint8_t*)k)[12];
((uint8_t*)d)[13] = ((uint8_t*)s)[13] ^ ((uint8_t*)k)[13];
((uint8_t*)d)[14] = ((uint8_t*)s)[14] ^ ((uint8_t*)k)[14];
((uint8_t*)d)[15] = ((uint8_t*)s)[15] ^ ((uint8_t*)k)[15];
#else
block_copy(d, s);
xor_block(d, k);
#endif
}
static void add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] )
{
xor_block(d, k);
}
static void shift_sub_rows( uint8_t st[N_BLOCK] )
{ uint8_t tt;
st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]);
st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]);
tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]);
st[ 9] = s_box(st[13]); st[13] = s_box( tt );
tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt );
tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt );
tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]);
st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt );
}
#if defined( AES_DEC_PREKEYED )
static void inv_shift_sub_rows( uint8_t st[N_BLOCK] )
{ uint8_t tt;
st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]);
st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]);
tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]);
st[ 5] = is_box(st[1]); st[ 1] = is_box( tt );
tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt );
tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt );
tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]);
st[11] = is_box(st[15]); st[15] = is_box( tt );
}
#endif
#if defined( VERSION_1 )
static void mix_sub_columns( uint8_t dt[N_BLOCK] )
{ uint8_t st[N_BLOCK];
block_copy(st, dt);
#else
static void mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] )
{
#endif
dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]);
dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]);
dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]);
dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]);
dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]);
dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]);
dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]);
dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]);
dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]);
dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]);
dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]);
dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]);
dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]);
dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]);
dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]);
dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]);
}
#if defined( AES_DEC_PREKEYED )
#if defined( VERSION_1 )
static void inv_mix_sub_columns( uint8_t dt[N_BLOCK] )
{ uint8_t st[N_BLOCK];
block_copy(st, dt);
#else
static void inv_mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] )
{
#endif
dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3]));
dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3]));
dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3]));
dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3]));
dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7]));
dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7]));
dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7]));
dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7]));
dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11]));
dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11]));
dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11]));
dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11]));
dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15]));
dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15]));
dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15]));
dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15]));
}
#endif
#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
/* Set the cipher key for the pre-keyed version */
return_type aes_set_key( const uint8_t key[], length_type keylen, aes_context ctx[1] )
{
uint8_t cc, rc, hi;
switch( keylen )
{
case 16:
case 24:
case 32:
break;
default:
ctx->rnd = 0;
return ( uint8_t )-1;
}
block_copy_nn(ctx->ksch, key, keylen);
hi = (keylen + 28) << 2;
ctx->rnd = (hi >> 4) - 1;
for( cc = keylen, rc = 1; cc < hi; cc += 4 )
{ uint8_t tt, t0, t1, t2, t3;
t0 = ctx->ksch[cc - 4];
t1 = ctx->ksch[cc - 3];
t2 = ctx->ksch[cc - 2];
t3 = ctx->ksch[cc - 1];
if( cc % keylen == 0 )
{
tt = t0;
t0 = s_box(t1) ^ rc;
t1 = s_box(t2);
t2 = s_box(t3);
t3 = s_box(tt);
rc = f2(rc);
}
else if( keylen > 24 && cc % keylen == 16 )
{
t0 = s_box(t0);
t1 = s_box(t1);
t2 = s_box(t2);
t3 = s_box(t3);
}
tt = cc - keylen;
ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0;
ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1;
ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2;
ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3;
}
return 0;
}
#endif
#if defined( AES_ENC_PREKEYED )
/* Encrypt a single block of 16 bytes */
return_type aes_encrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] )
{
if( ctx->rnd )
{
uint8_t s1[N_BLOCK], r;
copy_and_key( s1, in, ctx->ksch );
for( r = 1 ; r < ctx->rnd ; ++r )
#if defined( VERSION_1 )
{
mix_sub_columns( s1 );
add_round_key( s1, ctx->ksch + r * N_BLOCK);
}
#else
{ uint8_t s2[N_BLOCK];
mix_sub_columns( s2, s1 );
copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK);
}
#endif
shift_sub_rows( s1 );
copy_and_key( out, s1, ctx->ksch + r * N_BLOCK );
}
else
return ( uint8_t )-1;
return 0;
}
/* CBC encrypt a number of blocks (input and return an IV) */
return_type aes_cbc_encrypt( const uint8_t *in, uint8_t *out,
int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] )
{
while(n_block--)
{
xor_block(iv, in);
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
//memcpy(out, iv, N_BLOCK);
block_copy(out, iv);
in += N_BLOCK;
out += N_BLOCK;
}
return EXIT_SUCCESS;
}
#endif
#if defined( AES_DEC_PREKEYED )
/* Decrypt a single block of 16 bytes */
return_type aes_decrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] )
{
if( ctx->rnd )
{
uint8_t s1[N_BLOCK], r;
copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK );
inv_shift_sub_rows( s1 );
for( r = ctx->rnd ; --r ; )
#if defined( VERSION_1 )
{
add_round_key( s1, ctx->ksch + r * N_BLOCK );
inv_mix_sub_columns( s1 );
}
#else
{ uint8_t s2[N_BLOCK];
copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK );
inv_mix_sub_columns( s1, s2 );
}
#endif
copy_and_key( out, s1, ctx->ksch );
}
else
return -1;
return 0;
}
/* CBC decrypt a number of blocks (input and return an IV) */
return_type aes_cbc_decrypt( const uint8_t *in, uint8_t *out,
int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] )
{
while(n_block--)
{ uint8_t tmp[N_BLOCK];
//memcpy(tmp, in, N_BLOCK);
block_copy(tmp, in);
if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS)
return EXIT_FAILURE;
xor_block(out, iv);
//memcpy(iv, tmp, N_BLOCK);
block_copy(iv, tmp);
in += N_BLOCK;
out += N_BLOCK;
}
return EXIT_SUCCESS;
}
#endif
#if defined( AES_ENC_128_OTFK )
/* The 'on the fly' encryption key update for for 128 bit keys */
static void update_encrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc )
{ uint8_t cc;
k[0] ^= s_box(k[13]) ^ *rc;
k[1] ^= s_box(k[14]);
k[2] ^= s_box(k[15]);
k[3] ^= s_box(k[12]);
*rc = f2( *rc );
for(cc = 4; cc < 16; cc += 4 )
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
}
/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
void aes_encrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] )
{ uint8_t s1[N_BLOCK], r, rc = 1;
if(o_key != key)
block_copy( o_key, key );
copy_and_key( s1, in, o_key );
for( r = 1 ; r < 10 ; ++r )
#if defined( VERSION_1 )
{
mix_sub_columns( s1 );
update_encrypt_key_128( o_key, &rc );
add_round_key( s1, o_key );
}
#else
{ uint8_t s2[N_BLOCK];
mix_sub_columns( s2, s1 );
update_encrypt_key_128( o_key, &rc );
copy_and_key( s1, s2, o_key );
}
#endif
shift_sub_rows( s1 );
update_encrypt_key_128( o_key, &rc );
copy_and_key( out, s1, o_key );
}
#endif
#if defined( AES_DEC_128_OTFK )
/* The 'on the fly' decryption key update for for 128 bit keys */
static void update_decrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc )
{ uint8_t cc;
for( cc = 12; cc > 0; cc -= 4 )
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
*rc = d2(*rc);
k[0] ^= s_box(k[13]) ^ *rc;
k[1] ^= s_box(k[14]);
k[2] ^= s_box(k[15]);
k[3] ^= s_box(k[12]);
}
/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
void aes_decrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] )
{
uint8_t s1[N_BLOCK], r, rc = 0x6c;
if(o_key != key)
block_copy( o_key, key );
copy_and_key( s1, in, o_key );
inv_shift_sub_rows( s1 );
for( r = 10 ; --r ; )
#if defined( VERSION_1 )
{
update_decrypt_key_128( o_key, &rc );
add_round_key( s1, o_key );
inv_mix_sub_columns( s1 );
}
#else
{ uint8_t s2[N_BLOCK];
update_decrypt_key_128( o_key, &rc );
copy_and_key( s2, s1, o_key );
inv_mix_sub_columns( s1, s2 );
}
#endif
update_decrypt_key_128( o_key, &rc );
copy_and_key( out, s1, o_key );
}
#endif
#if defined( AES_ENC_256_OTFK )
/* The 'on the fly' encryption key update for for 256 bit keys */
static void update_encrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc )
{ uint8_t cc;
k[0] ^= s_box(k[29]) ^ *rc;
k[1] ^= s_box(k[30]);
k[2] ^= s_box(k[31]);
k[3] ^= s_box(k[28]);
*rc = f2( *rc );
for(cc = 4; cc < 16; cc += 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
k[16] ^= s_box(k[12]);
k[17] ^= s_box(k[13]);
k[18] ^= s_box(k[14]);
k[19] ^= s_box(k[15]);
for( cc = 20; cc < 32; cc += 4 )
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
}
/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */
void aes_encrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] )
{
uint8_t s1[N_BLOCK], r, rc = 1;
if(o_key != key)
{
block_copy( o_key, key );
block_copy( o_key + 16, key + 16 );
}
copy_and_key( s1, in, o_key );
for( r = 1 ; r < 14 ; ++r )
#if defined( VERSION_1 )
{
mix_sub_columns(s1);
if( r & 1 )
add_round_key( s1, o_key + 16 );
else
{
update_encrypt_key_256( o_key, &rc );
add_round_key( s1, o_key );
}
}
#else
{ uint8_t s2[N_BLOCK];
mix_sub_columns( s2, s1 );
if( r & 1 )
copy_and_key( s1, s2, o_key + 16 );
else
{
update_encrypt_key_256( o_key, &rc );
copy_and_key( s1, s2, o_key );
}
}
#endif
shift_sub_rows( s1 );
update_encrypt_key_256( o_key, &rc );
copy_and_key( out, s1, o_key );
}
#endif
#if defined( AES_DEC_256_OTFK )
/* The 'on the fly' encryption key update for for 256 bit keys */
static void update_decrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc )
{ uint8_t cc;
for(cc = 28; cc > 16; cc -= 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
k[16] ^= s_box(k[12]);
k[17] ^= s_box(k[13]);
k[18] ^= s_box(k[14]);
k[19] ^= s_box(k[15]);
for(cc = 12; cc > 0; cc -= 4)
{
k[cc + 0] ^= k[cc - 4];
k[cc + 1] ^= k[cc - 3];
k[cc + 2] ^= k[cc - 2];
k[cc + 3] ^= k[cc - 1];
}
*rc = d2(*rc);
k[0] ^= s_box(k[29]) ^ *rc;
k[1] ^= s_box(k[30]);
k[2] ^= s_box(k[31]);
k[3] ^= s_box(k[28]);
}
/* Decrypt a single block of 16 bytes with 'on the fly'
256 bit keying
*/
void aes_decrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] )
{
uint8_t s1[N_BLOCK], r, rc = 0x80;
if(o_key != key)
{
block_copy( o_key, key );
block_copy( o_key + 16, key + 16 );
}
copy_and_key( s1, in, o_key );
inv_shift_sub_rows( s1 );
for( r = 14 ; --r ; )
#if defined( VERSION_1 )
{
if( ( r & 1 ) )
{
update_decrypt_key_256( o_key, &rc );
add_round_key( s1, o_key + 16 );
}
else
add_round_key( s1, o_key );
inv_mix_sub_columns( s1 );
}
#else
{ uint8_t s2[N_BLOCK];
if( ( r & 1 ) )
{
update_decrypt_key_256( o_key, &rc );
copy_and_key( s2, s1, o_key + 16 );
}
else
copy_and_key( s2, s1, o_key );
inv_mix_sub_columns( s1, s2 );
}
#endif
copy_and_key( out, s1, o_key );
}
#endif

@ -0,0 +1,160 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue 09/09/2006
This is an AES implementation that uses only 8-bit byte operations on the
cipher state.
*/
#ifndef AES_H
#define AES_H
#if 1
# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */
#endif
#if 0
# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */
#endif
#if 0
# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */
#endif
#if 0
# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */
#endif
#if 0
# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */
#endif
#if 0
# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */
#endif
#define N_ROW 4
#define N_COL 4
#define N_BLOCK (N_ROW * N_COL)
#define N_MAX_ROUNDS 14
typedef uint8_t return_type;
/* Warning: The key length for 256 bit keys overflows a byte
(see comment below)
*/
typedef uint8_t length_type;
typedef struct
{ uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
uint8_t rnd;
} aes_context;
/* The following calls are for a precomputed key schedule
NOTE: If the length_type used for the key length is an
unsigned 8-bit character, a key length of 256 bits must
be entered as a length in bytes (valid inputs are hence
128, 192, 16, 24 and 32).
*/
#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
return_type aes_set_key( const uint8_t key[],
length_type keylen,
aes_context ctx[1] );
#endif
#if defined( AES_ENC_PREKEYED )
return_type aes_encrypt( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const aes_context ctx[1] );
return_type aes_cbc_encrypt( const uint8_t *in,
uint8_t *out,
int32_t n_block,
uint8_t iv[N_BLOCK],
const aes_context ctx[1] );
#endif
#if defined( AES_DEC_PREKEYED )
return_type aes_decrypt( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const aes_context ctx[1] );
return_type aes_cbc_decrypt( const uint8_t *in,
uint8_t *out,
int32_t n_block,
uint8_t iv[N_BLOCK],
const aes_context ctx[1] );
#endif
/* The following calls are for 'on the fly' keying. In this case the
encryption and decryption keys are different.
The encryption subroutines take a key in an array of bytes in
key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
192, and 256 bits respectively. They then encrypts the input
data, in[] with this key and put the reult in the output array
out[]. In addition, the second key array, o_key[L], is used
to output the key that is needed by the decryption subroutine
to reverse the encryption operation. The two key arrays can
be the same array but in this case the original key will be
overwritten.
In the same way, the decryption subroutines output keys that
can be used to reverse their effect when used for encryption.
Only 128 and 256 bit keys are supported in these 'on the fly'
modes.
*/
#if defined( AES_ENC_128_OTFK )
void aes_encrypt_128( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK],
uint8_t o_key[N_BLOCK] );
#endif
#if defined( AES_DEC_128_OTFK )
void aes_decrypt_128( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[N_BLOCK],
uint8_t o_key[N_BLOCK] );
#endif
#if defined( AES_ENC_256_OTFK )
void aes_encrypt_256( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK],
uint8_t o_key[2 * N_BLOCK] );
#endif
#if defined( AES_DEC_256_OTFK )
void aes_decrypt_256( const uint8_t in[N_BLOCK],
uint8_t out[N_BLOCK],
const uint8_t key[2 * N_BLOCK],
uint8_t o_key[2 * N_BLOCK] );
#endif
#endif

@ -0,0 +1,153 @@
/**************************************************************************
Copyright (C) 2009 Lander Casado, Philippas Tsigas
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers. Redistributions in
binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimers in the documentation and/or
other materials provided with the distribution.
In no event shall the authors or copyright holders be liable for any special,
incidental, indirect or consequential damages of any kind, or any damages
whatsoever resulting from loss of use, data or profits, whether or not
advised of the possibility of damage, and on any theory of liability,
arising out of or in connection with the use or performance of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS WITH THE SOFTWARE
*****************************************************************************/
//#include <sys/param.h>
//#include <sys/systm.h>
#include <stdint.h>
#include "aes.h"
#include "cmac.h"
#include "utilities.h"
#define LSHIFT(v, r) do { \
int32_t i; \
for (i = 0; i < 15; i++) \
(r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \
(r)[15] = (v)[15] << 1; \
} while (0)
#define XOR(v, r) do { \
int32_t i; \
for (i = 0; i < 16; i++) \
{ \
(r)[i] = (r)[i] ^ (v)[i]; \
} \
} while (0) \
void AES_CMAC_Init(AES_CMAC_CTX *ctx)
{
memset1(ctx->X, 0, sizeof ctx->X);
ctx->M_n = 0;
memset1(ctx->rijndael.ksch, '\0', 240);
}
void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH])
{
//rijndael_set_key_enc_only(&ctx->rijndael, key, 128);
aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael);
}
void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len)
{
uint32_t mlen;
uint8_t in[16];
if (ctx->M_n > 0) {
mlen = MIN(16 - ctx->M_n, len);
memcpy1(ctx->M_last + ctx->M_n, data, mlen);
ctx->M_n += mlen;
if (ctx->M_n < 16 || len == mlen)
return;
XOR(ctx->M_last, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
aes_encrypt( ctx->X, ctx->X, &ctx->rijndael);
data += mlen;
len -= mlen;
}
while (len > 16) { /* not last block */
XOR(data, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
aes_encrypt( in, in, &ctx->rijndael);
memcpy1(&ctx->X[0], in, 16);
data += 16;
len -= 16;
}
/* potential last block, save it */
memcpy1(ctx->M_last, data, len);
ctx->M_n = len;
}
void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)
{
uint8_t K[16];
uint8_t in[16];
/* generate subkey K1 */
memset1(K, '\0', 16);
//rijndael_encrypt(&ctx->rijndael, K, K);
aes_encrypt( K, K, &ctx->rijndael);
if (K[0] & 0x80) {
LSHIFT(K, K);
K[15] ^= 0x87;
} else
LSHIFT(K, K);
if (ctx->M_n == 16) {
/* last block was a complete block */
XOR(K, ctx->M_last);
} else {
/* generate subkey K2 */
if (K[0] & 0x80) {
LSHIFT(K, K);
K[15] ^= 0x87;
} else
LSHIFT(K, K);
/* padding(M_last) */
ctx->M_last[ctx->M_n] = 0x80;
while (++ctx->M_n < 16)
ctx->M_last[ctx->M_n] = 0;
XOR(K, ctx->M_last);
}
XOR(ctx->M_last, ctx->X);
//rijndael_encrypt(&ctx->rijndael, ctx->X, digest);
memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
aes_encrypt(in, digest, &ctx->rijndael);
memset1(K, 0, sizeof K);
}

@ -0,0 +1,63 @@
/**************************************************************************
Copyright (C) 2009 Lander Casado, Philippas Tsigas
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal with the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers. Redistributions in
binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimers in the documentation and/or
other materials provided with the distribution.
In no event shall the authors or copyright holders be liable for any special,
incidental, indirect or consequential damages of any kind, or any damages
whatsoever resulting from loss of use, data or profits, whether or not
advised of the possibility of damage, and on any theory of liability,
arising out of or in connection with the use or performance of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS WITH THE SOFTWARE
*****************************************************************************/
#ifndef _CMAC_H_
#define _CMAC_H_
#include "aes.h"
#define AES_CMAC_KEY_LENGTH 16
#define AES_CMAC_DIGEST_LENGTH 16
typedef struct _AES_CMAC_CTX {
aes_context rijndael;
uint8_t X[16];
uint8_t M_last[16];
uint32_t M_n;
} AES_CMAC_CTX;
//#include <sys/cdefs.h>
//__BEGIN_DECLS
void AES_CMAC_Init(AES_CMAC_CTX * ctx);
void AES_CMAC_SetKey(AES_CMAC_CTX * ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]);
void AES_CMAC_Update(AES_CMAC_CTX * ctx, const uint8_t * data, uint32_t len);
// __attribute__((__bounded__(__string__,2,3)));
void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX * ctx);
// __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
//__END_DECLS
#endif /* _CMAC_H_ */

@ -0,0 +1,25 @@
--- Revised BSD License ---
Copyright (c) 2013, SEMTECH S.A.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Semtech corporation nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,202 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC layer implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
#include <stdlib.h>
#include <stdint.h>
#include "utilities.h"
#include "aes.h"
#include "cmac.h"
#include "LoRaMacCrypto.h"
/*!
* CMAC/AES Message Integrity Code (MIC) Block B0 size
*/
#define LORAMAC_MIC_BLOCK_B0_SIZE 16
/*!
* MIC field computation initial data
*/
static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/*!
* Contains the computed MIC field.
*
* \remark Only the 4 first bytes are used
*/
static uint8_t Mic[16];
/*!
* Encryption aBlock and sBlock
*/
static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/*!
* AES computation context variable
*/
static aes_context AesContext;
/*!
* CMAC computation context variable
*/
static AES_CMAC_CTX AesCmacCtx[1];
/*!
* \brief Computes the LoRaMAC frame MIC field
*
* \param [IN] buffer Data buffer
* \param [IN] size Data buffer size
* \param [IN] key AES key to be used
* \param [IN] address Frame address
* \param [IN] dir Frame direction [0: uplink, 1: downlink]
* \param [IN] sequenceCounter Frame sequence counter
* \param [OUT] mic Computed MIC field
*/
void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic )
{
MicBlockB0[5] = dir;
MicBlockB0[6] = ( address ) & 0xFF;
MicBlockB0[7] = ( address >> 8 ) & 0xFF;
MicBlockB0[8] = ( address >> 16 ) & 0xFF;
MicBlockB0[9] = ( address >> 24 ) & 0xFF;
MicBlockB0[10] = ( sequenceCounter ) & 0xFF;
MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF;
MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF;
MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF;
MicBlockB0[15] = size & 0xFF;
AES_CMAC_Init( AesCmacCtx );
AES_CMAC_SetKey( AesCmacCtx, key );
AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE );
AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
AES_CMAC_Final( Mic, AesCmacCtx );
*mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
}
void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer )
{
uint16_t i;
uint8_t bufferIndex = 0;
uint16_t ctr = 1;
memset1( AesContext.ksch, '\0', 240 );
aes_set_key( key, 16, &AesContext );
aBlock[5] = dir;
aBlock[6] = ( address ) & 0xFF;
aBlock[7] = ( address >> 8 ) & 0xFF;
aBlock[8] = ( address >> 16 ) & 0xFF;
aBlock[9] = ( address >> 24 ) & 0xFF;
aBlock[10] = ( sequenceCounter ) & 0xFF;
aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;
while( size >= 16 )
{
aBlock[15] = ( ( ctr ) & 0xFF );
ctr++;
aes_encrypt( aBlock, sBlock, &AesContext );
for( i = 0; i < 16; i++ )
{
encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
}
size -= 16;
bufferIndex += 16;
}
if( size > 0 )
{
aBlock[15] = ( ( ctr ) & 0xFF );
aes_encrypt( aBlock, sBlock, &AesContext );
for( i = 0; i < size; i++ )
{
encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
}
}
}
void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer )
{
LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer );
}
void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
{
AES_CMAC_Init( AesCmacCtx );
AES_CMAC_SetKey( AesCmacCtx, key );
AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
AES_CMAC_Final( Mic, AesCmacCtx );
*mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
}
void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
{
memset1( AesContext.ksch, '\0', 240 );
aes_set_key( key, 16, &AesContext );
aes_encrypt( buffer, decBuffer, &AesContext );
// Check if optional CFList is included
if( size >= 16 )
{
aes_encrypt( buffer + 16, decBuffer + 16, &AesContext );
}
}
void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey )
{
uint8_t nonce[16];
uint8_t *pDevNonce = ( uint8_t * )&devNonce;
memset1( AesContext.ksch, '\0', 240 );
aes_set_key( key, 16, &AesContext );
memset1( nonce, 0, sizeof( nonce ) );
nonce[0] = 0x01;
memcpy1( nonce + 1, appNonce, 6 );
memcpy1( nonce + 7, pDevNonce, 2 );
aes_encrypt( nonce, nwkSKey, &AesContext );
memset1( nonce, 0, sizeof( nonce ) );
nonce[0] = 0x02;
memcpy1( nonce + 1, appNonce, 6 );
memcpy1( nonce + 7, pDevNonce, 2 );
aes_encrypt( nonce, appSKey, &AesContext );
}

@ -0,0 +1,111 @@
/*!
* \file LoRaMacCrypto.h
*
* \brief LoRa MAC layer cryptography implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup LORAMAC_CRYPTO LoRa MAC layer cryptography implementation
* This module covers the implementation of cryptographic functions
* of the LoRaMAC layer.
* \{
*/
#ifndef __LORAMAC_CRYPTO_H__
#define __LORAMAC_CRYPTO_H__
/*!
* Computes the LoRaMAC frame MIC field
*
* \param [IN] buffer - Data buffer
* \param [IN] size - Data buffer size
* \param [IN] key - AES key to be used
* \param [IN] address - Frame address
* \param [IN] dir - Frame direction [0: uplink, 1: downlink]
* \param [IN] sequenceCounter - Frame sequence counter
* \param [OUT] mic - Computed MIC field
*/
void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic );
/*!
* Computes the LoRaMAC payload encryption
*
* \param [IN] buffer - Data buffer
* \param [IN] size - Data buffer size
* \param [IN] key - AES key to be used
* \param [IN] address - Frame address
* \param [IN] dir - Frame direction [0: uplink, 1: downlink]
* \param [IN] sequenceCounter - Frame sequence counter
* \param [OUT] encBuffer - Encrypted buffer
*/
void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer );
/*!
* Computes the LoRaMAC payload decryption
*
* \param [IN] buffer - Data buffer
* \param [IN] size - Data buffer size
* \param [IN] key - AES key to be used
* \param [IN] address - Frame address
* \param [IN] dir - Frame direction [0: uplink, 1: downlink]
* \param [IN] sequenceCounter - Frame sequence counter
* \param [OUT] decBuffer - Decrypted buffer
*/
void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer );
/*!
* Computes the LoRaMAC Join Request frame MIC field
*
* \param [IN] buffer - Data buffer
* \param [IN] size - Data buffer size
* \param [IN] key - AES key to be used
* \param [OUT] mic - Computed MIC field
*/
void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic );
/*!
* Computes the LoRaMAC join frame decryption
*
* \param [IN] buffer - Data buffer
* \param [IN] size - Data buffer size
* \param [IN] key - AES key to be used
* \param [OUT] decBuffer - Decrypted buffer
*/
void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer );
/*!
* Computes the LoRaMAC join frame decryption
*
* \param [IN] key - AES key to be used
* \param [IN] appNonce - Application nonce
* \param [IN] devNonce - Device nonce
* \param [OUT] nwkSKey - Network session key
* \param [OUT] appSKey - Application session key
*/
void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey );
/*! \} defgroup LORAMAC */
#endif // __LORAMAC_CRYPTO_H__

@ -0,0 +1,81 @@
/*!
* \file LoRaMacTest.h
*
* \brief LoRa MAC layer test function implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup LORAMACTEST LoRa MAC layer test function implementation
* This module specifies the API implementation of test function of the LoRaMAC layer.
* The functions in this file are only for testing purposes only.
* \{
*/
#ifndef __LORAMACTEST_H__
#define __LORAMACTEST_H__
/*!
* \brief Enabled or disables the reception windows
*
* \details This is a test function. It shall be used for testing purposes only.
* Changing this attribute may lead to a non-conformance LoRaMac operation.
*
* \param [IN] enable - Enabled or disables the reception windows
*/
void LoRaMacTestRxWindowsOn( bool enable );
/*!
* \brief Enables the MIC field test
*
* \details This is a test function. It shall be used for testing purposes only.
* Changing this attribute may lead to a non-conformance LoRaMac operation.
*
* \param [IN] txPacketCounter - Fixed Tx packet counter value
*/
void LoRaMacTestSetMic( uint16_t txPacketCounter );
/*!
* \brief Enabled or disables the duty cycle
*
* \details This is a test function. It shall be used for testing purposes only.
* Changing this attribute may lead to a non-conformance LoRaMac operation.
*
* \param [IN] enable - Enabled or disables the duty cycle
*/
void LoRaMacTestSetDutyCycleOn( bool enable );
/*!
* \brief Sets the channel index
*
* \details This is a test function. It shall be used for testing purposes only.
* Changing this attribute may lead to a non-conformance LoRaMac operation.
*
* \param [IN] channel - Channel index
*/
void LoRaMacTestSetChannel( uint8_t channel );
/*! \} defgroup LORAMACTEST */
#endif // __LORAMACTEST_H__

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

@ -0,0 +1,503 @@
/*!
* \file RegionAS923.h
*
* \brief Region definition for AS923
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONAS923 Region AS923
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_AS923_H__
#define __REGION_AS923_H__
/*!
* LoRaMac maximum number of channels
*/
#define AS923_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define AS923_NUMB_DEFAULT_CHANNELS 2
/*!
* Number of channels to apply for the CF list
*/
#define AS923_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define AS923_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define AS923_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define AS923_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define AS923_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define AS923_DEFAULT_DATARATE DR_2
/*!
* The minimum datarate which is used when the
* dwell time is limited.
*/
#define AS923_DWELL_LIMIT_DATARATE DR_2
/*!
* Minimal Rx1 receive datarate offset
*/
#define AS923_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define AS923_MAX_RX1_DR_OFFSET 7
/*!
* Default Rx1 receive datarate offset
*/
#define AS923_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define AS923_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define AS923_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define AS923_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default uplink dwell time configuration
*/
#define AS923_DEFAULT_UPLINK_DWELL_TIME 1
/*!
* Default downlink dwell time configuration
*/
#define AS923_DEFAULT_DOWNLINK_DWELL_TIME 1
/*!
* Default Max EIRP
*/
#define AS923_DEFAULT_MAX_EIRP 16.0f
/*!
* Default antenna gain
*/
#define AS923_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define AS923_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define AS923_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define AS923_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define AS923_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define AS923_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define AS923_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define AS923_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define AS923_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define AS923_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define AS923_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define AS923_ACK_TIMEOUT_RND 1000
#if ( AS923_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define AS923_RX_WND_2_FREQ 923200000
/*!
* Second reception window channel datarate definition.
*/
#define AS923_RX_WND_2_DR DR_2
/*!
* Maximum number of bands
*/
#define AS923_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define AS923_LC1 { 923200000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define AS923_LC2 { 923400000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define AS923_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) )
/*!
* RSSI threshold for a free channel [dBm]
*/
#define AS923_RSSI_FREE_TH -85
/*!
* Specifies the time the node performs a carrier sense
*/
#define AS923_CARRIER_SENSE_TIME 6
/*!
* Data rates table definition
*/
static const uint8_t DataratesAS923[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsAS923[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell0AS923[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
* The table is valid for the dwell time configuration of 0 for uplinks and downlinks. The table provides
* repeater support.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AS923[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* Maximum payload with respect to the datarate index. Can operate with and without repeater.
* The table proides repeater support. The table is only valid for uplinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell1UpAS923[] = { 0, 0, 11, 53, 125, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with and without repeater.
* The table proides repeater support. The table is only valid for downlinks.
*/
static const uint8_t MaxPayloadOfDatarateDwell1DownAS923[] = { 0, 0, 11, 53, 126, 242, 242, 242 };
/*!
* Effective datarate offsets for receive window 1.
*/
static const int8_t EffectiveRx1DrOffsetAS923[] = { 0, 1, 2, 3, 4, 5, -1, -2 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionAS923InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionAS923Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionAS923ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionAS923ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionAS923AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionAS923ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionAS923TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAS923LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAS923RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAS923NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionAS923TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAS923DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionAS923AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionAS923CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionAS923ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionAS923SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionAS923ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONAS923 */
#endif // __REGION_AS923_H__

@ -0,0 +1,863 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC region AU915 implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include "radio.h"
#include "timer.h"
#include "LoRaMac.h"
#include "utilities.h"
#include "Region.h"
#include "RegionCommon.h"
#include "RegionAU915.h"
#include "debug.h"
// Definitions
#define CHANNELS_MASK_SIZE 6
// Global attributes
/*!
* LoRaMAC channels
*/
static ChannelParams_t Channels[AU915_MAX_NB_CHANNELS];
/*!
* LoRaMac bands
*/
static Band_t Bands[AU915_MAX_NB_BANDS] =
{
AU915_BAND0
};
/*!
* LoRaMac channels mask
*/
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
/*!
* LoRaMac channels remaining
*/
static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
/*!
* LoRaMac channels default mask
*/
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
{
uint8_t nextLowerDr = 0;
if( dr == minDr )
{
nextLowerDr = minDr;
}
else
{
nextLowerDr = dr - 1;
}
return nextLowerDr;
}
static uint32_t GetBandwidth( uint32_t drIndex )
{
switch( BandwidthsAU915[drIndex] )
{
default:
case 125000:
return 0;
case 250000:
return 1;
case 500000:
return 2;
}
}
static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
{
int8_t txPowerResult = txPower;
// Limit tx power to the band max
txPowerResult = MAX( txPower, maxBandTxPower );
return txPowerResult;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
for( uint8_t i = 0, k = 0; i < AU915_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
}
PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
{
PhyParam_t phyParam = { 0 };
switch( getPhy->Attribute )
{
case PHY_MIN_RX_DR:
{
phyParam.Value = AU915_RX_MIN_DATARATE;
break;
}
case PHY_MIN_TX_DR:
{
phyParam.Value = AU915_TX_MIN_DATARATE;
break;
}
case PHY_DEF_TX_DR:
{
phyParam.Value = AU915_DEFAULT_DATARATE;
break;
}
case PHY_NEXT_LOWER_TX_DR:
{
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, AU915_TX_MIN_DATARATE );
break;
}
case PHY_DEF_TX_POWER:
{
phyParam.Value = AU915_DEFAULT_TX_POWER;
break;
}
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateAU915[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterAU915[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = AU915_DUTY_CYCLE_ENABLED;
break;
}
case PHY_MAX_RX_WINDOW:
{
phyParam.Value = AU915_MAX_RX_WINDOW;
break;
}
case PHY_RECEIVE_DELAY1:
{
phyParam.Value = AU915_RECEIVE_DELAY1;
break;
}
case PHY_RECEIVE_DELAY2:
{
phyParam.Value = AU915_RECEIVE_DELAY2;
break;
}
case PHY_JOIN_ACCEPT_DELAY1:
{
phyParam.Value = AU915_JOIN_ACCEPT_DELAY1;
break;
}
case PHY_JOIN_ACCEPT_DELAY2:
{
phyParam.Value = AU915_JOIN_ACCEPT_DELAY2;
break;
}
case PHY_MAX_FCNT_GAP:
{
phyParam.Value = AU915_MAX_FCNT_GAP;
break;
}
case PHY_ACK_TIMEOUT:
{
phyParam.Value = ( AU915_ACKTIMEOUT + randr( -AU915_ACK_TIMEOUT_RND, AU915_ACK_TIMEOUT_RND ) );
break;
}
case PHY_DEF_DR1_OFFSET:
{
phyParam.Value = AU915_DEFAULT_RX1_DR_OFFSET;
break;
}
case PHY_DEF_RX2_FREQUENCY:
{
phyParam.Value = AU915_RX_WND_2_FREQ;
break;
}
case PHY_DEF_RX2_DR:
{
phyParam.Value = AU915_RX_WND_2_DR;
break;
}
case PHY_CHANNELS_MASK:
{
phyParam.ChannelsMask = ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
phyParam.ChannelsMask = ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
{
phyParam.Value = AU915_MAX_NB_CHANNELS;
break;
}
case PHY_CHANNELS:
{
phyParam.Channels = Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
case PHY_DEF_DOWNLINK_DWELL_TIME:
{
phyParam.Value = 0;
break;
}
case PHY_DEF_MAX_EIRP:
{
phyParam.fValue = AU915_DEFAULT_MAX_EIRP;
break;
}
case PHY_DEF_ANTENNA_GAIN:
{
phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN;
break;
}
case PHY_NB_JOIN_TRIALS:
case PHY_DEF_NB_JOIN_TRIALS:
{
phyParam.Value = 2;
break;
}
default:
{
break;
}
}
return phyParam;
}
void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
void RegionAU915InitDefaults( InitType_t type )
{
switch( type )
{
case INIT_TYPE_INIT:
{
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ )
{
Channels[i].Frequency = 915200000 + i * 200000;
Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
Channels[i].Band = 0;
}
// 500 kHz channels
for( uint8_t i = AU915_MAX_NB_CHANNELS - 8; i < AU915_MAX_NB_CHANNELS; i++ )
{
Channels[i].Frequency = 915900000 + ( i - ( AU915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6;
Channels[i].Band = 0;
}
// Initialize channels default mask
ChannelsDefaultMask[0] = 0xFFFF;
ChannelsDefaultMask[1] = 0xFFFF;
ChannelsDefaultMask[2] = 0xFFFF;
ChannelsDefaultMask[3] = 0xFFFF;
ChannelsDefaultMask[4] = 0x00FF;
ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
break;
}
case INIT_TYPE_RESTORE:
{
// Copy channels default mask
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
ChannelsMaskRemaining[i] &= ChannelsMask[i];
}
break;
}
default:
{
break;
}
}
}
bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_TX_DR:
case PHY_DEF_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE );
}
case PHY_RX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE );
}
case PHY_DEF_TX_POWER:
case PHY_TX_POWER:
{
// Remark: switched min and max!
return RegionCommonValueInRange( verify->TxPower, AU915_MAX_TX_POWER, AU915_MIN_TX_POWER );
}
case PHY_DUTY_CYCLE:
{
return AU915_DUTY_CYCLE_ENABLED;
}
case PHY_NB_JOIN_TRIALS:
{
if( verify->NbJoinTrials < 2 )
{
return false;
}
break;
}
default:
return false;
}
return true;
}
void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList )
{
return;
}
bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
uint8_t nbChannels = RegionCommonCountChannels( chanMaskSet->ChannelsMaskIn, 0, 4 );
// Check the number of active channels
// According to ACMA regulation, we require at least 20 125KHz channels, if
// the node shall utilize 125KHz channels.
if( ( nbChannels < 20 ) &&
( nbChannels > 0 ) )
{
return false;
}
switch( chanMaskSet->ChannelsMaskType )
{
case CHANNELS_MASK:
{
RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
ChannelsMaskRemaining[i] &= ChannelsMask[i];
}
break;
}
case CHANNELS_DEFAULT_MASK:
{
RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
default:
return false;
}
return true;
}
bool RegionAU915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
{
bool adrAckReq = false;
int8_t datarate = adrNext->Datarate;
int8_t txPower = adrNext->TxPower;
GetPhyParams_t getPhy;
PhyParam_t phyParam;
// Report back the adr ack counter
*adrAckCounter = adrNext->AdrAckCounter;
if( adrNext->AdrEnabled == true )
{
if( datarate == AU915_TX_MIN_DATARATE )
{
*adrAckCounter = 0;
adrAckReq = false;
}
else
{
if( adrNext->AdrAckCounter >= AU915_ADR_ACK_LIMIT )
{
adrAckReq = true;
txPower = AU915_MAX_TX_POWER;
}
else
{
adrAckReq = false;
}
if( adrNext->AdrAckCounter >= ( AU915_ADR_ACK_LIMIT + AU915_ADR_ACK_DELAY ) )
{
if( ( adrNext->AdrAckCounter % AU915_ADR_ACK_DELAY ) == 1 )
{
// Decrease the datarate
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
getPhy.Datarate = datarate;
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
phyParam = RegionAU915GetPhyParam( &getPhy );
datarate = phyParam.Value;
if( datarate == AU915_TX_MIN_DATARATE )
{
// We must set adrAckReq to false as soon as we reach the lowest datarate
adrAckReq = false;
if( adrNext->UpdateChanMask == true )
{
// Re-enable default channels
ChannelsMask[0] = 0xFFFF;
ChannelsMask[1] = 0xFFFF;
ChannelsMask[2] = 0xFFFF;
ChannelsMask[3] = 0xFFFF;
ChannelsMask[4] = 0x00FF;
ChannelsMask[5] = 0x0000;
}
}
}
}
}
}
*drOut = datarate;
*txPowOut = txPower;
return adrAckReq;
}
void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
uint32_t radioWakeUpTime;
// Get the datarate, perform a boundary check
rxConfigParams->Datarate = MIN( datarate, AU915_RX_MAX_DATARATE );
rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesAU915[rxConfigParams->Datarate], BandwidthsAU915[rxConfigParams->Datarate] );
radioWakeUpTime = Radio.GetRadioWakeUpTime( );
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, radioWakeUpTime, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
if( Radio.GetStatus( ) != RF_IDLE )
{
return false;
}
if( rxConfig->Window == 0 )
{
// Apply window 1 frequency
frequency = AU915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * AU915_STEPWIDTH_RX1_CHANNEL;
}
// Read the physical datarate from the datarates table
phyDr = DataratesAU915[dr];
Radio.SetChannel( frequency );
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterAU915[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateAU915[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
DBG_PRINTF( "RX on freq %d Hz at DR %d\n\r", frequency, dr );
*datarate = (uint8_t) dr;
return true;
}
bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesAU915[txConfig->Datarate];
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
Radio.SetChannel( Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
DBG_PRINTF( "TX on freq %d Hz at DR %d\n\r", Channels[txConfig->Channel].Frequency, txConfig->Datarate );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
}
uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
{
uint8_t status = 0x07;
RegionCommonLinkAdrParams_t linkAdrParams;
uint8_t nextIndex = 0;
uint8_t bytesProcessed = 0;
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
GetPhyParams_t getPhy;
PhyParam_t phyParam;
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
if( nextIndex == 0 )
break; // break loop, since no more request has been found
// Update bytes processed
bytesProcessed += nextIndex;
// Revert status, as we only check the last ADR request for the channel mask KO
status = 0x07;
if( linkAdrParams.ChMaskCtrl == 6 )
{
// Enable all 125 kHz channels
channelsMask[0] = 0xFFFF;
channelsMask[1] = 0xFFFF;
channelsMask[2] = 0xFFFF;
channelsMask[3] = 0xFFFF;
// Apply chMask to channels 64 to 71
channelsMask[4] = linkAdrParams.ChMask;
}
else if( linkAdrParams.ChMaskCtrl == 7 )
{
// Disable all 125 kHz channels
channelsMask[0] = 0x0000;
channelsMask[1] = 0x0000;
channelsMask[2] = 0x0000;
channelsMask[3] = 0x0000;
// Apply chMask to channels 64 to 71
channelsMask[4] = linkAdrParams.ChMask;
}
else if( linkAdrParams.ChMaskCtrl == 5 )
{
// RFU
status &= 0xFE; // Channel mask KO
}
else
{
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
}
}
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
if( ( linkAdrParams.Datarate < DR_6 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) )
{
status &= 0xFE; // Channel mask KO
}
// Get the minimum possible datarate
getPhy.Attribute = PHY_MIN_TX_DR;
getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
phyParam = RegionAU915GetPhyParam( &getPhy );
linkAdrVerifyParams.Status = status;
linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
linkAdrVerifyParams.NbChannels = AU915_MAX_NB_CHANNELS;
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = AU915_TX_MAX_DATARATE;
linkAdrVerifyParams.Channels = Channels;
linkAdrVerifyParams.MinTxPower = AU915_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = AU915_MAX_TX_POWER;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
// Update channelsMask if everything is correct
if( status == 0x07 )
{
// Copy Mask
RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
ChannelsMaskRemaining[0] &= ChannelsMask[0];
ChannelsMaskRemaining[1] &= ChannelsMask[1];
ChannelsMaskRemaining[2] &= ChannelsMask[2];
ChannelsMaskRemaining[3] &= ChannelsMask[3];
ChannelsMaskRemaining[4] = ChannelsMask[4];
ChannelsMaskRemaining[5] = ChannelsMask[5];
}
// Update status variables
*drOut = linkAdrParams.Datarate;
*txPowOut = linkAdrParams.TxPower;
*nbRepOut = linkAdrParams.NbRep;
*nbBytesParsed = bytesProcessed;
return status;
}
uint8_t RegionAU915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
uint32_t freq = rxParamSetupReq->Frequency;
// Verify radio frequency
if( ( Radio.CheckRfFrequency( freq ) == false ) ||
( freq < AU915_FIRST_RX1_CHANNEL ) ||
( freq > AU915_LAST_RX1_CHANNEL ) ||
( ( ( freq - ( uint32_t ) AU915_FIRST_RX1_CHANNEL ) % ( uint32_t ) AU915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
{
status &= 0xFE; // Channel frequency KO
}
// Verify datarate
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE ) == false )
{
status &= 0xFD; // Datarate KO
}
if( ( rxParamSetupReq->Datarate == DR_7 ) ||
( rxParamSetupReq->Datarate > DR_13 ) )
{
status &= 0xFD; // Datarate KO
}
// Verify datarate offset
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, AU915_MIN_RX1_DR_OFFSET, AU915_MAX_RX1_DR_OFFSET ) == false )
{
status &= 0xFB; // Rx1DrOffset range KO
}
return status;
}
uint8_t RegionAU915NewChannelReq( NewChannelReqParams_t* newChannelReq )
{
// Datarate and frequency KO
return 0;
}
int8_t RegionAU915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
{
return -1;
}
uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq )
{
return 0;
}
int8_t RegionAU915AlternateDr( AlternateDrParams_t* alternateDr )
{
int8_t datarate = 0;
// Re-enable 500 kHz default channels
ChannelsMask[4] = 0x00FF;
if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
{
datarate = DR_6;
}
else
{
datarate = DR_0;
}
return datarate;
}
void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = Channels;
calcBackOffParams.Bands = Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
bool RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[AU915_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
// Count 125kHz channels
if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
{ // Reactivate default channels
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
}
// Check other channels
if( nextChanParams->Datarate >= DR_6 )
{
if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
{
ChannelsMaskRemaining[4] = ChannelsMask[4];
}
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, AU915_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
ChannelsMaskRemaining, Channels,
Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 )
{
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
// Disable the channel in the mask
RegionCommonChanDisable( ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS - 8 );
*time = 0;
return true;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return true;
}
// Datarate not supported by any channel
*time = 0;
return false;
}
}
LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelRemove )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
int8_t phyTxPower = 0;
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
}
uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
{
int8_t datarate = DatarateOffsetsAU915[dr][drOffset];
if( datarate < 0 )
{
datarate = DR_0;
}
return datarate;
}

@ -0,0 +1,455 @@
/*!
* \file RegionAU915.h
*
* \brief Region definition for AU915
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONAU915 Region AU915
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_AU915_H__
#define __REGION_AU915_H__
/*!
* LoRaMac maximum number of channels
*/
#define AU915_MAX_NB_CHANNELS 72
/*!
* Minimal datarate that can be used by the node
*/
#define AU915_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define AU915_TX_MAX_DATARATE DR_6
/*!
* Minimal datarate that can be used by the node
*/
#define AU915_RX_MIN_DATARATE DR_8
/*!
* Maximal datarate that can be used by the node
*/
#define AU915_RX_MAX_DATARATE DR_13
/*!
* Default datarate used by the node
*/
#define AU915_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define AU915_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define AU915_MAX_RX1_DR_OFFSET 6
/*!
* Default Rx1 receive datarate offset
*/
#define AU915_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define AU915_MIN_TX_POWER TX_POWER_10
/*!
* Maximal Tx output power that can be used by the node
*/
#define AU915_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define AU915_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define AU915_DEFAULT_MAX_EIRP 30.0f
/*!
* Default antenna gain
*/
#define AU915_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define AU915_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define AU915_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define AU915_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define AU915_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define AU915_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define AU915_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define AU915_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define AU915_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define AU915_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define AU915_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define AU915_ACK_TIMEOUT_RND 1000
/*!
* Second reception window channel frequency definition.
*/
#define AU915_RX_WND_2_FREQ 923300000
/*!
* Second reception window channel datarate definition.
*/
#define AU915_RX_WND_2_DR DR_8
/*!
* LoRaMac maximum number of bands
*/
#define AU915_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
*/
#define AU915_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )
/*!
* Defines the last channel for RX window 1 for US band
*/
#define AU915_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define AU915_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )
/*!
* Data rates table definition
*/
static const uint8_t DataratesAU915[] = { 12, 11, 10, 9, 8, 7, 8, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsAU915[] = { 125000, 125000, 125000, 125000, 125000, 125000, 500000, 0, 500000, 500000, 500000, 500000, 500000, 500000, 0, 0 };
/*!
* Up/Down link data rates offset definition
*/
static const int8_t DatarateOffsetsAU915[7][6] =
{
{ DR_8 , DR_8 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_0
{ DR_9 , DR_8 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_1
{ DR_10, DR_9 , DR_8 , DR_8 , DR_8 , DR_8 }, // DR_2
{ DR_11, DR_10, DR_9 , DR_8 , DR_8 , DR_8 }, // DR_3
{ DR_12, DR_11, DR_10, DR_9 , DR_8 , DR_8 }, // DR_4
{ DR_13, DR_12, DR_11, DR_10, DR_9 , DR_8 }, // DR_5
{ DR_13, DR_13, DR_12, DR_11, DR_10, DR_9 }, // DR_6
};
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateAU915[] = { 51, 51, 51, 115, 242, 242, 242, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterAU915[] = { 51, 51, 51, 115, 222, 222, 222, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionAU915InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionAU915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAU915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAU915NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionAU915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionAU915AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONAU915 */
#endif // __REGION_AU915_H__

@ -0,0 +1,814 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC region CN470 implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include "radio.h"
#include "timer.h"
#include "LoRaMac.h"
#include "utilities.h"
#include "Region.h"
#include "RegionCommon.h"
#include "RegionCN470.h"
#include "debug.h"
// Definitions
#define CHANNELS_MASK_SIZE 6
// Global attributes
/*!
* LoRaMAC channels
*/
static ChannelParams_t Channels[CN470_MAX_NB_CHANNELS];
/*!
* LoRaMac bands
*/
static Band_t Bands[CN470_MAX_NB_BANDS] =
{
CN470_BAND0
};
/*!
* LoRaMac channels mask
*/
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
/*!
* LoRaMac channels default mask
*/
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
{
uint8_t nextLowerDr = 0;
if( dr == minDr )
{
nextLowerDr = minDr;
}
else
{
nextLowerDr = dr - 1;
}
return nextLowerDr;
}
static uint32_t GetBandwidth( uint32_t drIndex )
{
switch( BandwidthsCN470[drIndex] )
{
default:
case 125000:
return 0;
case 250000:
return 1;
case 500000:
return 2;
}
}
static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
{
int8_t txPowerResult = txPower;
// Limit tx power to the band max
txPowerResult = MAX( txPower, maxBandTxPower );
return txPowerResult;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
for( uint8_t i = 0, k = 0; i < CN470_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
}
PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
{
PhyParam_t phyParam = { 0 };
switch( getPhy->Attribute )
{
case PHY_MIN_RX_DR:
{
phyParam.Value = CN470_RX_MIN_DATARATE;
break;
}
case PHY_MIN_TX_DR:
{
phyParam.Value = CN470_TX_MIN_DATARATE;
break;
}
case PHY_DEF_TX_DR:
{
phyParam.Value = CN470_DEFAULT_DATARATE;
break;
}
case PHY_NEXT_LOWER_TX_DR:
{
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, CN470_TX_MIN_DATARATE );
break;
}
case PHY_DEF_TX_POWER:
{
phyParam.Value = CN470_DEFAULT_TX_POWER;
break;
}
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateCN470[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterCN470[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = CN470_DUTY_CYCLE_ENABLED;
break;
}
case PHY_MAX_RX_WINDOW:
{
phyParam.Value = CN470_MAX_RX_WINDOW;
break;
}
case PHY_RECEIVE_DELAY1:
{
phyParam.Value = CN470_RECEIVE_DELAY1;
break;
}
case PHY_RECEIVE_DELAY2:
{
phyParam.Value = CN470_RECEIVE_DELAY2;
break;
}
case PHY_JOIN_ACCEPT_DELAY1:
{
phyParam.Value = CN470_JOIN_ACCEPT_DELAY1;
break;
}
case PHY_JOIN_ACCEPT_DELAY2:
{
phyParam.Value = CN470_JOIN_ACCEPT_DELAY2;
break;
}
case PHY_MAX_FCNT_GAP:
{
phyParam.Value = CN470_MAX_FCNT_GAP;
break;
}
case PHY_ACK_TIMEOUT:
{
phyParam.Value = ( CN470_ACKTIMEOUT + randr( -CN470_ACK_TIMEOUT_RND, CN470_ACK_TIMEOUT_RND ) );
break;
}
case PHY_DEF_DR1_OFFSET:
{
phyParam.Value = CN470_DEFAULT_RX1_DR_OFFSET;
break;
}
case PHY_DEF_RX2_FREQUENCY:
{
phyParam.Value = CN470_RX_WND_2_FREQ;
break;
}
case PHY_DEF_RX2_DR:
{
phyParam.Value = CN470_RX_WND_2_DR;
break;
}
case PHY_CHANNELS_MASK:
{
phyParam.ChannelsMask = ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
phyParam.ChannelsMask = ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
{
phyParam.Value = CN470_MAX_NB_CHANNELS;
break;
}
case PHY_CHANNELS:
{
phyParam.Channels = Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
case PHY_DEF_DOWNLINK_DWELL_TIME:
{
phyParam.Value = 0;
break;
}
case PHY_DEF_MAX_EIRP:
{
phyParam.fValue = CN470_DEFAULT_MAX_EIRP;
break;
}
case PHY_DEF_ANTENNA_GAIN:
{
phyParam.fValue = CN470_DEFAULT_ANTENNA_GAIN;
break;
}
case PHY_NB_JOIN_TRIALS:
case PHY_DEF_NB_JOIN_TRIALS:
{
phyParam.Value = 48;
break;
}
default:
{
break;
}
}
return phyParam;
}
void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
void RegionCN470InitDefaults( InitType_t type )
{
switch( type )
{
case INIT_TYPE_INIT:
{
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ )
{
Channels[i].Frequency = 470300000 + i * 200000;
Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
Channels[i].Band = 0;
}
// Initialize the channels default mask
ChannelsDefaultMask[0] = 0xFFFF;
ChannelsDefaultMask[1] = 0xFFFF;
ChannelsDefaultMask[2] = 0xFFFF;
ChannelsDefaultMask[3] = 0xFFFF;
ChannelsDefaultMask[4] = 0xFFFF;
ChannelsDefaultMask[5] = 0xFFFF;
// Update the channels mask
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
break;
}
case INIT_TYPE_RESTORE:
{
// Restore channels default mask
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
break;
}
default:
{
break;
}
}
}
bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_TX_DR:
case PHY_DEF_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN470_TX_MIN_DATARATE, CN470_TX_MAX_DATARATE );
}
case PHY_RX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN470_RX_MIN_DATARATE, CN470_RX_MAX_DATARATE );
}
case PHY_DEF_TX_POWER:
case PHY_TX_POWER:
{
// Remark: switched min and max!
return RegionCommonValueInRange( verify->TxPower, CN470_MAX_TX_POWER, CN470_MIN_TX_POWER );
}
case PHY_DUTY_CYCLE:
{
return CN470_DUTY_CYCLE_ENABLED;
}
case PHY_NB_JOIN_TRIALS:
{
if( verify->NbJoinTrials < 48 )
{
return false;
}
break;
}
default:
return false;
}
return true;
}
void RegionCN470ApplyCFList( ApplyCFListParams_t* applyCFList )
{
return;
}
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
switch( chanMaskSet->ChannelsMaskType )
{
case CHANNELS_MASK:
{
RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
default:
return false;
}
return true;
}
bool RegionCN470AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
{
bool adrAckReq = false;
int8_t datarate = adrNext->Datarate;
int8_t txPower = adrNext->TxPower;
GetPhyParams_t getPhy;
PhyParam_t phyParam;
// Report back the adr ack counter
*adrAckCounter = adrNext->AdrAckCounter;
if( adrNext->AdrEnabled == true )
{
if( datarate == CN470_TX_MIN_DATARATE )
{
*adrAckCounter = 0;
adrAckReq = false;
}
else
{
if( adrNext->AdrAckCounter >= CN470_ADR_ACK_LIMIT )
{
adrAckReq = true;
txPower = CN470_MAX_TX_POWER;
}
else
{
adrAckReq = false;
}
if( adrNext->AdrAckCounter >= ( CN470_ADR_ACK_LIMIT + CN470_ADR_ACK_DELAY ) )
{
if( ( adrNext->AdrAckCounter % CN470_ADR_ACK_DELAY ) == 1 )
{
// Decrease the datarate
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
getPhy.Datarate = datarate;
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
phyParam = RegionCN470GetPhyParam( &getPhy );
datarate = phyParam.Value;
if( datarate == CN470_TX_MIN_DATARATE )
{
// We must set adrAckReq to false as soon as we reach the lowest datarate
adrAckReq = false;
if( adrNext->UpdateChanMask == true )
{
// Re-enable default channels
ChannelsMask[0] = 0xFFFF;
ChannelsMask[1] = 0xFFFF;
ChannelsMask[2] = 0xFFFF;
ChannelsMask[3] = 0xFFFF;
ChannelsMask[4] = 0xFFFF;
ChannelsMask[5] = 0xFFFF;
}
}
}
}
}
}
*drOut = datarate;
*txPowOut = txPower;
return adrAckReq;
}
void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
uint32_t radioWakeUpTime;
// Get the datarate, perform a boundary check
rxConfigParams->Datarate = MIN( datarate, CN470_RX_MAX_DATARATE );
rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesCN470[rxConfigParams->Datarate], BandwidthsCN470[rxConfigParams->Datarate] );
radioWakeUpTime = Radio.GetRadioWakeUpTime( );
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, radioWakeUpTime, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
if( Radio.GetStatus( ) != RF_IDLE )
{
return false;
}
if( rxConfig->Window == 0 )
{
// Apply window 1 frequency
frequency = CN470_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 48 ) * CN470_STEPWIDTH_RX1_CHANNEL;
}
// Read the physical datarate from the datarates table
phyDr = DataratesCN470[dr];
Radio.SetChannel( frequency );
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterCN470[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateCN470[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
DBG_PRINTF( "RX on freq %d Hz at DR %d\n\r", frequency, dr );
*datarate = (uint8_t) dr;
return true;
}
bool RegionCN470TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesCN470[txConfig->Datarate];
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
int8_t phyTxPower = 0;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
Radio.SetChannel( Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
DBG_PRINTF( "TX on freq %d Hz at DR %d\n\r", Channels[txConfig->Channel].Frequency, txConfig->Datarate );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
}
uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
{
uint8_t status = 0x07;
RegionCommonLinkAdrParams_t linkAdrParams;
uint8_t nextIndex = 0;
uint8_t bytesProcessed = 0;
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
GetPhyParams_t getPhy;
PhyParam_t phyParam;
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
// Get ADR request parameters
nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
if( nextIndex == 0 )
break; // break loop, since no more request has been found
// Update bytes processed
bytesProcessed += nextIndex;
// Revert status, as we only check the last ADR request for the channel mask KO
status = 0x07;
if( linkAdrParams.ChMaskCtrl == 6 )
{
// Enable all 125 kHz channels
channelsMask[0] = 0xFFFF;
channelsMask[1] = 0xFFFF;
channelsMask[2] = 0xFFFF;
channelsMask[3] = 0xFFFF;
channelsMask[4] = 0xFFFF;
channelsMask[5] = 0xFFFF;
}
else if( linkAdrParams.ChMaskCtrl == 7 )
{
status &= 0xFE; // Channel mask KO
}
else
{
for( uint8_t i = 0; i < 16; i++ )
{
if( ( ( linkAdrParams.ChMask & ( 1 << i ) ) != 0 ) &&
( Channels[linkAdrParams.ChMaskCtrl * 16 + i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
}
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
}
}
// Get the minimum possible datarate
getPhy.Attribute = PHY_MIN_TX_DR;
getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
phyParam = RegionCN470GetPhyParam( &getPhy );
linkAdrVerifyParams.Status = status;
linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
linkAdrVerifyParams.NbChannels = CN470_MAX_NB_CHANNELS;
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = CN470_TX_MAX_DATARATE;
linkAdrVerifyParams.Channels = Channels;
linkAdrVerifyParams.MinTxPower = CN470_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = CN470_MAX_TX_POWER;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
// Update channelsMask if everything is correct
if( status == 0x07 )
{
// Copy Mask
RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
}
// Update status variables
*drOut = linkAdrParams.Datarate;
*txPowOut = linkAdrParams.TxPower;
*nbRepOut = linkAdrParams.NbRep;
*nbBytesParsed = bytesProcessed;
return status;
}
uint8_t RegionCN470RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
uint32_t freq = rxParamSetupReq->Frequency;
// Verify radio frequency
if( ( Radio.CheckRfFrequency( freq ) == false ) ||
( freq < CN470_FIRST_RX1_CHANNEL ) ||
( freq > CN470_LAST_RX1_CHANNEL ) ||
( ( ( freq - ( uint32_t ) CN470_FIRST_RX1_CHANNEL ) % ( uint32_t ) CN470_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
{
status &= 0xFE; // Channel frequency KO
}
// Verify datarate
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, CN470_RX_MIN_DATARATE, CN470_RX_MAX_DATARATE ) == false )
{
status &= 0xFD; // Datarate KO
}
// Verify datarate offset
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, CN470_MIN_RX1_DR_OFFSET, CN470_MAX_RX1_DR_OFFSET ) == false )
{
status &= 0xFB; // Rx1DrOffset range KO
}
return status;
}
uint8_t RegionCN470NewChannelReq( NewChannelReqParams_t* newChannelReq )
{
// Datarate and frequency KO
return 0;
}
int8_t RegionCN470TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
{
return -1;
}
uint8_t RegionCN470DlChannelReq( DlChannelReqParams_t* dlChannelReq )
{
return 0;
}
int8_t RegionCN470AlternateDr( AlternateDrParams_t* alternateDr )
{
int8_t datarate = 0;
if( ( alternateDr->NbTrials % 48 ) == 0 )
{
datarate = DR_0;
}
else if( ( alternateDr->NbTrials % 32 ) == 0 )
{
datarate = DR_1;
}
else if( ( alternateDr->NbTrials % 24 ) == 0 )
{
datarate = DR_2;
}
else if( ( alternateDr->NbTrials % 16 ) == 0 )
{
datarate = DR_3;
}
else if( ( alternateDr->NbTrials % 8 ) == 0 )
{
datarate = DR_4;
}
else
{
datarate = DR_5;
}
return datarate;
}
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = Channels;
calcBackOffParams.Bands = Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
bool RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[CN470_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
// Count 125kHz channels
if( RegionCommonCountChannels( ChannelsMask, 0, 6 ) == 0 )
{ // Reactivate default channels
ChannelsMask[0] = 0xFFFF;
ChannelsMask[1] = 0xFFFF;
ChannelsMask[2] = 0xFFFF;
ChannelsMask[3] = 0xFFFF;
ChannelsMask[4] = 0xFFFF;
ChannelsMask[5] = 0xFFFF;
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, CN470_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
ChannelsMask, Channels,
Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 )
{
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
return true;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return true;
}
// Datarate not supported by any channel
*time = 0;
return false;
}
}
LoRaMacStatus_t RegionCN470ChannelAdd( ChannelAddParams_t* channelAdd )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
bool RegionCN470ChannelsRemove( ChannelRemoveParams_t* channelRemove )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
void RegionCN470SetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
int8_t phyTxPower = 0;
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
}
uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
{
int8_t datarate = dr - drOffset;
if( datarate < 0 )
{
datarate = DR_0;
}
return datarate;
}

@ -0,0 +1,441 @@
/*!
* \file RegionCN470.h
*
* \brief Region definition for CN470
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONCN470 Region CN470
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_CN470_H__
#define __REGION_CN470_H__
/*!
* LoRaMac maximum number of channels
*/
#define CN470_MAX_NB_CHANNELS 96
/*!
* Minimal datarate that can be used by the node
*/
#define CN470_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN470_TX_MAX_DATARATE DR_5
/*!
* Minimal datarate that can be used by the node
*/
#define CN470_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN470_RX_MAX_DATARATE DR_5
/*!
* Default datarate used by the node
*/
#define CN470_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define CN470_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define CN470_MAX_RX1_DR_OFFSET 3
/*!
* Default Rx1 receive datarate offset
*/
#define CN470_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define CN470_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define CN470_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define CN470_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define CN470_DEFAULT_MAX_EIRP 19.15f
/*!
* Default antenna gain
*/
#define CN470_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define CN470_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define CN470_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define CN470_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define CN470_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define CN470_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define CN470_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define CN470_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define CN470_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define CN470_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define CN470_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define CN470_ACK_TIMEOUT_RND 1000
/*!
* Second reception window channel frequency definition.
*/
#define CN470_RX_WND_2_FREQ 505300000
/*!
* Second reception window channel datarate definition.
*/
#define CN470_RX_WND_2_DR DR_0
/*!
* LoRaMac maximum number of bands
*/
#define CN470_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for CN470 band
*/
#define CN470_FIRST_RX1_CHANNEL ( (uint32_t) 500300000 )
/*!
* Defines the last channel for RX window 1 for CN470 band
*/
#define CN470_LAST_RX1_CHANNEL ( (uint32_t) 509700000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define CN470_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 200000 )
/*!
* Data rates table definition
*/
static const uint8_t DataratesCN470[] = { 12, 11, 10, 9, 8, 7 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsCN470[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 222, 222 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterCN470[] = { 51, 51, 51, 115, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionCN470InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionCN470ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionCN470AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN470TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionCN470TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN470DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionCN470AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionCN470ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionCN470ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionCN470SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONCN470 */
#endif // __REGION_CN470_H__

File diff suppressed because it is too large Load Diff

@ -0,0 +1,465 @@
/*!
* \file RegionCN779.h
*
* \brief Region definition for CN779
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONCN779 Region CN779
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_CN779_H__
#define __REGION_CN779_H__
/*!
* LoRaMac maximum number of channels
*/
#define CN779_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define CN779_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define CN779_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define CN779_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN779_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define CN779_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define CN779_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define CN779_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define CN779_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define CN779_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define CN779_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define CN779_MIN_TX_POWER TX_POWER_5
/*!
* Maximal Tx output power that can be used by the node
*/
#define CN779_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define CN779_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define CN779_DEFAULT_MAX_EIRP 12.15f
/*!
* Default antenna gain
*/
#define CN779_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define CN779_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define CN779_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define CN779_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define CN779_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define CN779_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define CN779_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define CN779_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define CN779_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define CN779_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define CN779_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define CN779_ACK_TIMEOUT_RND 1000
/*!
* Verification of default datarate
*/
#if ( CN779_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define CN779_RX_WND_2_FREQ 786000000
/*!
* Second reception window channel datarate definition.
*/
#define CN779_RX_WND_2_DR DR_0
/*!
* LoRaMac maximum number of bands
*/
#define CN779_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define CN779_LC1 { 779500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define CN779_LC2 { 779700000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define CN779_LC3 { 779900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define CN779_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesCN779[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsCN779[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateCN779[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterCN779[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionCN779SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionCN779InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionCN779Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionCN779ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionCN779ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionCN779AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionCN779ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN779RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionCN779TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN779LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN779RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN779NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionCN779TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionCN779DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionCN779AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionCN779CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionCN779ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionCN779ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionCN779SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionCN779ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONCN779 */
#endif // __REGION_CN779_H__

@ -0,0 +1,362 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC common region implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include "timer.h"
#include "utilities.h"
#include "LoRaMac.h"
#include "RegionCommon.h"
#define BACKOFF_DC_1_HOUR 100
#define BACKOFF_DC_10_HOURS 1000
#define BACKOFF_DC_24_HOURS 10000
static uint8_t CountChannels( uint16_t mask, uint8_t nbBits )
{
uint8_t nbActiveBits = 0;
for( uint8_t j = 0; j < nbBits; j++ )
{
if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
{
nbActiveBits++;
}
}
return nbActiveBits;
}
uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime )
{
uint16_t dutyCycle = 0;
if( elapsedTime < 3600000 )
{
dutyCycle = BACKOFF_DC_1_HOUR;
}
else if( elapsedTime < ( 3600000 + 36000000 ) )
{
dutyCycle = BACKOFF_DC_10_HOURS;
}
else
{
dutyCycle = BACKOFF_DC_24_HOURS;
}
return dutyCycle;
}
bool RegionCommonChanVerifyDr( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr, int8_t minDr, int8_t maxDr, ChannelParams_t* channels )
{
if( RegionCommonValueInRange( dr, minDr, maxDr ) == 0 )
{
return false;
}
for( uint8_t i = 0, k = 0; i < nbChannels; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) )
{// Check datarate validity for enabled channels
if( RegionCommonValueInRange( dr, ( channels[i + j].DrRange.Fields.Min & 0x0F ),
( channels[i + j].DrRange.Fields.Max & 0x0F ) ) == 1 )
{
// At least 1 channel has been found we can return OK.
return true;
}
}
}
}
return false;
}
uint8_t RegionCommonValueInRange( int8_t value, int8_t min, int8_t max )
{
if( ( value >= min ) && ( value <= max ) )
{
return 1;
}
return 0;
}
bool RegionCommonChanDisable( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels )
{
uint8_t index = id / 16;
if( ( index > ( maxChannels / 16 ) ) || ( id >= maxChannels ) )
{
return false;
}
// Deactivate channel
channelsMask[index] &= ~( 1 << ( id % 16 ) );
return true;
}
uint8_t RegionCommonCountChannels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx )
{
uint8_t nbChannels = 0;
if( channelsMask == NULL )
{
return 0;
}
for( uint8_t i = startIdx; i < stopIdx; i++ )
{
nbChannels += CountChannels( channelsMask[i], 16 );
}
return nbChannels;
}
void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len )
{
if( ( channelsMaskDest != NULL ) && ( channelsMaskSrc != NULL ) )
{
for( uint8_t i = 0; i < len; i++ )
{
channelsMaskDest[i] = channelsMaskSrc[i];
}
}
}
void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone )
{
if( joined == true )
{
band->LastTxDoneTime = lastTxDone;
}
else
{
band->LastTxDoneTime = lastTxDone;
band->LastJoinTxDoneTime = lastTxDone;
}
}
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands )
{
TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
// Update bands Time OFF
for( uint8_t i = 0; i < nbBands; i++ )
{
if( joined == false )
{
uint32_t txDoneTime = MAX( TimerGetElapsedTime( bands[i].LastJoinTxDoneTime ),
( dutyCycle == true ) ? TimerGetElapsedTime( bands[i].LastTxDoneTime ) : 0 );
if( bands[i].TimeOff <= txDoneTime )
{
bands[i].TimeOff = 0;
}
if( bands[i].TimeOff != 0 )
{
nextTxDelay = MIN( bands[i].TimeOff - txDoneTime, nextTxDelay );
}
}
else
{
if( dutyCycle == true )
{
if( bands[i].TimeOff <= TimerGetElapsedTime( bands[i].LastTxDoneTime ) )
{
bands[i].TimeOff = 0;
}
if( bands[i].TimeOff != 0 )
{
nextTxDelay = MIN( bands[i].TimeOff - TimerGetElapsedTime( bands[i].LastTxDoneTime ),
nextTxDelay );
}
}
else
{
nextTxDelay = 0;
bands[i].TimeOff = 0;
}
}
}
return nextTxDelay;
}
uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* linkAdrParams )
{
uint8_t retIndex = 0;
if( payload[0] == SRV_MAC_LINK_ADR_REQ )
{
// Parse datarate and tx power
linkAdrParams->Datarate = payload[1];
linkAdrParams->TxPower = linkAdrParams->Datarate & 0x0F;
linkAdrParams->Datarate = ( linkAdrParams->Datarate >> 4 ) & 0x0F;
// Parse ChMask
linkAdrParams->ChMask = ( uint16_t )payload[2];
linkAdrParams->ChMask |= ( uint16_t )payload[3] << 8;
// Parse ChMaskCtrl and nbRep
linkAdrParams->NbRep = payload[4];
linkAdrParams->ChMaskCtrl = ( linkAdrParams->NbRep >> 4 ) & 0x07;
linkAdrParams->NbRep &= 0x0F;
// LinkAdrReq has 4 bytes length + 1 byte CMD
retIndex = 5;
}
return retIndex;
}
uint8_t RegionCommonLinkAdrReqVerifyParams( RegionCommonLinkAdrReqVerifyParams_t* verifyParams, int8_t* dr, int8_t* txPow, uint8_t* nbRep )
{
uint8_t status = verifyParams->Status;
int8_t datarate = verifyParams->Datarate;
int8_t txPower = verifyParams->TxPower;
int8_t nbRepetitions = verifyParams->NbRep;
// Handle the case when ADR is off.
if( verifyParams->AdrEnabled == false )
{
// When ADR is off, we are allowed to change the channels mask and the NbRep,
// if the datarate and the TX power of the LinkAdrReq are set to 0x0F.
if( ( verifyParams->Datarate != 0x0F ) || ( verifyParams->TxPower != 0x0F ) )
{
status = 0;
nbRepetitions = verifyParams->CurrentNbRep;
}
// Get the current datarate and tx power
datarate = verifyParams->CurrentDatarate;
txPower = verifyParams->CurrentTxPower;
}
if( status != 0 )
{
// Verify datarate. The variable phyParam. Value contains the minimum allowed datarate.
if( RegionCommonChanVerifyDr( verifyParams->NbChannels, verifyParams->ChannelsMask, datarate,
verifyParams->MinDatarate, verifyParams->MaxDatarate, verifyParams->Channels ) == false )
{
status &= 0xFD; // Datarate KO
}
// Verify tx power
if( RegionCommonValueInRange( txPower, verifyParams->MaxTxPower, verifyParams->MinTxPower ) == 0 )
{
// Verify if the maximum TX power is exceeded
if( verifyParams->MaxTxPower > txPower )
{ // Apply maximum TX power. Accept TX power.
txPower = verifyParams->MaxTxPower;
}
else
{
status &= 0xFB; // TxPower KO
}
}
}
// If the status is ok, verify the NbRep
if( status == 0x07 )
{
if( nbRepetitions == 0 )
{ // Keep the current one
nbRepetitions = verifyParams->CurrentNbRep;
}
}
// Apply changes
*dr = datarate;
*txPow = txPower;
*nbRep = nbRepetitions;
return status;
}
double RegionCommonComputeSymbolTimeLoRa( uint8_t phyDr, uint32_t bandwidth )
{
return ( ( double )( 1 << phyDr ) / ( double )bandwidth ) * 1000;
}
double RegionCommonComputeSymbolTimeFsk( uint8_t phyDr )
{
return ( 8.0 / ( double )phyDr ); // 1 symbol equals 1 byte
}
void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset )
{
*windowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * minRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), minRxSymbols ); // Computed number of symbols
*windowOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( *windowTimeout * tSymbol ) / 2.0 ) - wakeUpTime );
}
int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain )
{
int8_t phyTxPower = 0;
phyTxPower = ( int8_t )floor( ( maxEirp - ( txPowerIndex * 2U ) ) - antennaGain );
return phyTxPower;
}
void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams )
{
uint8_t bandIdx = calcBackOffParams->Channels[calcBackOffParams->Channel].Band;
uint16_t dutyCycle = calcBackOffParams->Bands[bandIdx].DCycle;
uint16_t joinDutyCycle = 0;
// Reset time-off to initial value.
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
if( calcBackOffParams->Joined == false )
{
// Get the join duty cycle
joinDutyCycle = RegionCommonGetJoinDc( calcBackOffParams->ElapsedTime );
// Apply the most restricting duty cycle
dutyCycle = MAX( dutyCycle, joinDutyCycle );
// Reset the timeoff if the last frame was not a join request and when the duty cycle is not enabled
if( ( calcBackOffParams->DutyCycleEnabled == false ) && ( calcBackOffParams->LastTxIsJoinRequest == false ) )
{
// This is the case when the duty cycle is off and the last uplink frame was not a join.
// This could happen in case of a rejoin, e.g. in compliance test mode.
// In this special case we have to set the time off to 0, since the join duty cycle shall only
// be applied after the first join request.
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
}
else
{
// Apply band time-off.
calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
}
}
else
{
if( calcBackOffParams->DutyCycleEnabled == true )
{
calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir;
}
else
{
calcBackOffParams->Bands[bandIdx].TimeOff = 0;
}
}
}

@ -0,0 +1,367 @@
/*!
* \file RegionCommon.h
*
* \brief Region independent implementations which are common to all regions.
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONCOMMON Common region implementation
* Region independent implementations which are common to all regions.
* \{
*/
#ifndef __REGIONCOMMON_H__
#define __REGIONCOMMON_H__
typedef struct sRegionCommonLinkAdrParams
{
/*!
* Number of repetitions.
*/
uint8_t NbRep;
/*!
* Datarate.
*/
int8_t Datarate;
/*!
* Tx power.
*/
int8_t TxPower;
/*!
* Channels mask control field.
*/
uint8_t ChMaskCtrl;
/*!
* Channels mask field.
*/
uint16_t ChMask;
}RegionCommonLinkAdrParams_t;
typedef struct sRegionCommonLinkAdrReqVerifyParams
{
/*!
* The current status of the AdrLinkRequest.
*/
uint8_t Status;
/*!
* Set to true, if ADR is enabled.
*/
bool AdrEnabled;
/*!
* The datarate the AdrLinkRequest wants to set.
*/
int8_t Datarate;
/*!
* The TX power the AdrLinkRequest wants to set.
*/
int8_t TxPower;
/*!
* The number of repetitions the AdrLinkRequest wants to set.
*/
uint8_t NbRep;
/*!
* The current datarate the node is using.
*/
int8_t CurrentDatarate;
/*!
* The current TX power the node is using.
*/
int8_t CurrentTxPower;
/*!
* The current number of repetitions the node is using.
*/
int8_t CurrentNbRep;
/*!
* The number of channels.
*/
uint8_t NbChannels;
/*!
* Pointer to the first element of the channels mask.
*/
uint16_t* ChannelsMask;
/*!
* The minimum possible datarate.
*/
int8_t MinDatarate;
/*!
* The maximum possible datarate.
*/
int8_t MaxDatarate;
/*!
* Pointer to the channels.
*/
ChannelParams_t* Channels;
/*!
* The minimum possible TX power.
*/
int8_t MinTxPower;
/*!
* The maximum possible TX power.
*/
int8_t MaxTxPower;
}RegionCommonLinkAdrReqVerifyParams_t;
typedef struct sRegionCommonCalcBackOffParams
{
/*!
* A pointer to region specific channels.
*/
ChannelParams_t* Channels;
/*!
* A pointer to region specific bands.
*/
Band_t* Bands;
/*!
* Set to true, if the last uplink was a join request.
*/
bool LastTxIsJoinRequest;
/*!
* Set to true, if the node is joined.
*/
bool Joined;
/*!
* Set to true, if the duty cycle is enabled.
*/
bool DutyCycleEnabled;
/*!
* The current channel.
*/
uint8_t Channel;
/*!
* The elapsed time since initialization.
*/
TimerTime_t ElapsedTime;
/*!
* The time on air of the last Tx frame.
*/
TimerTime_t TxTimeOnAir;
}RegionCommonCalcBackOffParams_t;
/*!
* \brief Calculates the join duty cycle.
* This is a generic function and valid for all regions.
*
* \param [IN] elapsedTime Elapsed time since the start of the device.
*
* \retval Duty cycle restriction.
*/
uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime );
/*!
* \brief Verifies, if a value is in a given range.
* This is a generic function and valid for all regions.
*
* \param [IN] value Value to verify, if it is in range.
*
* \param [IN] min Minimum possible value.
*
* \param [IN] max Maximum possible value.
*
* \retval Returns 1 if the value is in range, otherwise 0.
*/
uint8_t RegionCommonValueInRange( int8_t value, int8_t min, int8_t max );
/*!
* \brief Verifies, if a datarate is available on an active channel.
* This is a generic function and valid for all regions.
*
* \param [IN] nbChannels Number of channels.
*
* \param [IN] channelsMask The channels mask of the region.
*
* \param [IN] dr The datarate to verify.
*
* \param [IN] minDr Minimum datarate.
*
* \param [IN] maxDr Maximum datarate.
*
* \param [IN] channels The channels of the region.
*
* \retval Returns true if the datarate is supported, false if not.
*/
bool RegionCommonChanVerifyDr( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr,
int8_t minDr, int8_t maxDr, ChannelParams_t* channels );
/*!
* \brief Disables a channel in a given channels mask.
* This is a generic function and valid for all regions.
*
* \param [IN] channelsMask The channels mask of the region.
*
* \param [IN] id The id of the channels mask to disable.
*
* \param [IN] maxChannels Maximum number of channels.
*
* \retval Returns true if the channel could be disabled, false if not.
*/
bool RegionCommonChanDisable( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels );
/*!
* \brief Counts the number of active channels in a given channels mask.
* This is a generic function and valid for all regions.
*
* \param [IN] channelsMask The channels mask of the region.
*
* \param [IN] startIdx Start index.
*
* \param [IN] stopIdx Stop index ( the channels of this index will not be counted ).
*
* \retval Returns the number of active channels.
*/
uint8_t RegionCommonCountChannels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx );
/*!
* \brief Copy a channels mask.
* This is a generic function and valid for all regions.
*
* \param [IN] channelsMaskDest The destination channels mask.
*
* \param [IN] channelsMaskSrc The source channels mask.
*
* \param [IN] len The index length to copy.
*/
void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len );
/*!
* \brief Sets the last tx done property.
* This is a generic function and valid for all regions.
*
* \param [IN] joined Set to true, if the node has joined the network
*
* \param [IN] band The band to be updated.
*
* \param [IN] lastTxDone The time of the last TX done.
*/
void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone );
/*!
* \brief Updates the time-offs of the bands.
* This is a generic function and valid for all regions.
*
* \param [IN] joined Set to true, if the node has joined the network
*
* \param [IN] dutyCycle Set to true, if the duty cycle is enabled.
*
* \param [IN] bands A pointer to the bands.
*
* \param [IN] nbBands The number of bands available.
*
* \retval Returns the time which must be waited to perform the next uplink.
*/
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands );
/*!
* \brief Parses the parameter of an LinkAdrRequest.
* This is a generic function and valid for all regions.
*
* \param [IN] payload Pointer to the payload containing the MAC commands. The payload
* must contain the CMD identifier, following by the parameters.
*
* \param [OUT] parseLinkAdr The function fills the structure with the ADR parameters.
*
* \retval Returns the length of the ADR request, if a request was found. Otherwise, the
* function returns 0.
*/
uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* parseLinkAdr );
/*!
* \brief Verifies and updates the datarate, the TX power and the number of repetitions
* of a LinkAdrRequest. This depends on the configuration of ADR also.
*
* \param [IN] verifyParams Pointer to a structure containing input parameters.
*
* \param [OUT] dr The updated datarate.
*
* \param [OUT] txPow The updated TX power.
*
* \param [OUT] nbRep The updated number of repetitions.
*
* \retval Returns the status according to the LinkAdrRequest definition.
*/
uint8_t RegionCommonLinkAdrReqVerifyParams( RegionCommonLinkAdrReqVerifyParams_t* verifyParams, int8_t* dr, int8_t* txPow, uint8_t* nbRep );
/*!
* \brief Computes the symbol time for LoRa modulation.
*
* \param [IN] phyDr Physical datarate to use.
*
* \param [IN] bandwidth Bandwidth to use.
*
* \retval Returns the symbol time.
*/
double RegionCommonComputeSymbolTimeLoRa( uint8_t phyDr, uint32_t bandwidth );
/*!
* \brief Computes the symbol time for FSK modulation.
*
* \param [IN] phyDr Physical datarate to use.
*
* \param [IN] bandwidth Bandwidth to use.
*
* \retval Returns the symbol time.
*/
double RegionCommonComputeSymbolTimeFsk( uint8_t phyDr );
/*!
* \brief Computes the RX window timeout and the RX window offset.
*
* \param [IN] tSymbol Symbol timeout.
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms interval around RxOffset.
*
* \param [IN] wakeUpTime Wakeup time of the system.
*
* \param [OUT] windowTimeout RX window timeout.
*
* \param [OUT] windowOffset RX window time offset to be applied to the RX delay.
*/
void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset );
/*!
* \brief Computes the txPower, based on the max EIRP and the antenna gain.
*
* \param [IN] txPower TX power index.
*
* \param [IN] maxEirp Maximum EIRP.
*
* \param [IN] antennaGain Antenna gain.
*
* \retval Returns the physical TX power.
*/
int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain );
/*!
* \brief Calculates the duty cycle for the current band.
*
* \param [IN] calcBackOffParams A pointer to the input parameters.
*/
void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams );
/*! \} defgroup REGIONCOMMON */
#endif // __REGIONCOMMON_H__

File diff suppressed because it is too large Load Diff

@ -0,0 +1,466 @@
/*!
* \file RegionEU433.h
*
* \brief Region definition for EU433
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONEU433 Region EU433
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_EU433_H__
#define __REGION_EU433_H__
/*!
* LoRaMac maximum number of channels
*/
#define EU433_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define EU433_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define EU433_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define EU433_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define EU433_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define EU433_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define EU433_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define EU433_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define EU433_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define EU433_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define EU433_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define EU433_MIN_TX_POWER TX_POWER_5
/*!
* Maximal Tx output power that can be used by the node
*/
#define EU433_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define EU433_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define EU433_DEFAULT_MAX_EIRP 12.15f
/*!
* Default antenna gain
*/
#define EU433_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define EU433_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define EU433_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define EU433_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define EU433_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define EU433_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define EU433_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define EU433_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define EU433_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define EU433_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define EU433_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define EU433_ACK_TIMEOUT_RND 1000
/*!
* Verification of default datarate
*/
#if ( EU433_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define EU433_RX_WND_2_FREQ 434665000
/*!
* Second reception window channel datarate definition.
*/
#define EU433_RX_WND_2_DR DR_0
/*!
* LoRaMac maximum number of bands
*/
#define EU433_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU433_LC1 { 433175000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU433_LC2 { 433375000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU433_LC3 { 433575000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define EU433_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesEU433[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsEU433[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateEU433[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterEU433[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionEU433InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionEU433Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionEU433ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionEU433ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionEU433AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionEU433ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionEU433RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionEU433TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU433LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU433RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU433NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionEU433TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionEU433AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionEU433CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionEU433ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionEU433SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONEU433 */
#endif // __REGION_EU433_H__

File diff suppressed because it is too large Load Diff

@ -0,0 +1,487 @@
/*!
* \file RegionEU868.h
*
* \brief Region definition for EU868
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONEU868 Region EU868
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_EU868_H__
#define __REGION_EU868_H__
/*!
* LoRaMac maximum number of channels
*/
#define EU868_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define EU868_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define EU868_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define EU868_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define EU868_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define EU868_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define EU868_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define EU868_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define EU868_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define EU868_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define EU868_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define EU868_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define EU868_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define EU868_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define EU868_DEFAULT_MAX_EIRP 16.0f
/*!
* Default antenna gain
*/
#define EU868_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define EU868_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define EU868_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define EU868_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define EU868_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define EU868_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define EU868_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define EU868_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define EU868_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define EU868_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define EU868_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define EU868_ACK_TIMEOUT_RND 1000
#if ( EU868_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define EU868_RX_WND_2_FREQ 869525000
/*!
* Second reception window channel datarate definition.
*/
#define EU868_RX_WND_2_DR DR_0
/*!
* Maximum number of bands
*/
#define EU868_MAX_NB_BANDS 5
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
/*!
* Band 1 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
/*!
* Band 2 definition
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0 } // 0.1 %
/*!
* Band 2 definition
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0 } // 10.0 %
/*!
* Band 2 definition
* Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU868_LC1 { 868100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU868_LC2 { 868300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define EU868_LC3 { 868500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define EU868_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesEU868[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsEU868[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateEU868[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterEU868[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionEU868SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionEU868InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionEU868Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionEU868ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionEU868ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionEU868AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionEU868ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionEU868RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionEU868TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU868LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU868RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU868NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionEU868TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionEU868DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionEU868AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionEU868CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionEU868ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionEU868ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionEU868SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionEU868ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONEU868 */
#endif // __REGION_EU868_H__

File diff suppressed because it is too large Load Diff

@ -0,0 +1,468 @@
/*!
* \file RegionIN865.h
*
* \brief Region definition for IN865
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONIN865 Region IN865
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_IN865_H__
#define __REGION_IN865_H__
/*!
* LoRaMac maximum number of channels
*/
#define IN865_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define IN865_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define IN865_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define IN865_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define IN865_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
*/
#define IN865_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define IN865_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
*/
#define IN865_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define IN865_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define IN865_MAX_RX1_DR_OFFSET 7
/*!
* Default Rx1 receive datarate offset
*/
#define IN865_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define IN865_MIN_TX_POWER TX_POWER_10
/*!
* Maximal Tx output power that can be used by the node
*/
#define IN865_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define IN865_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP
*/
#define IN865_DEFAULT_MAX_EIRP 30.0f
/*!
* Default antenna gain
*/
#define IN865_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define IN865_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define IN865_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define IN865_DUTY_CYCLE_ENABLED 1
/*!
* Maximum RX window duration
*/
#define IN865_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define IN865_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define IN865_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define IN865_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define IN865_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define IN865_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define IN865_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define IN865_ACK_TIMEOUT_RND 1000
#if ( IN865_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define IN865_RX_WND_2_FREQ 866550000
/*!
* Second reception window channel datarate definition.
*/
#define IN865_RX_WND_2_DR DR_2
/*!
* Maximum number of bands
*/
#define IN865_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0 } // 100.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define IN865_LC1 { 865062500, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define IN865_LC2 { 865402500, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define IN865_LC3 { 865985000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define IN865_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* Data rates table definition
*/
static const uint8_t DataratesIN865[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsIN865[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateIN865[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterIN865[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* Effective datarate offsets for receive window 1.
*/
static const int8_t EffectiveRx1DrOffsetIN865[] = { 0, 1, 2, 3, 4, 5, -1, -2 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionIN865SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionIN865InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionIN865Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionIN865ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionIN865ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionIN865AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionIN865ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionIN865RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionIN865TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionIN865LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionIN865RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionIN865NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionIN865TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionIN865DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionIN865AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionIN865CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionIN865ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionIN865ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionIN865SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionIN865ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONIN865 */
#endif // __REGION_IN865_H__

File diff suppressed because it is too large Load Diff

@ -0,0 +1,478 @@
/*!
* \file RegionKR920.h
*
* \brief Region definition for KR920
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONKR920 Region KR920
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_KR920_H__
#define __REGION_KR920_H__
/*!
* LoRaMac maximum number of channels
*/
#define KR920_MAX_NB_CHANNELS 16
/*!
* Number of default channels
*/
#define KR920_NUMB_DEFAULT_CHANNELS 3
/*!
* Number of channels to apply for the CF list
*/
#define KR920_NUMB_CHANNELS_CF_LIST 5
/*!
* Minimal datarate that can be used by the node
*/
#define KR920_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define KR920_TX_MAX_DATARATE DR_5
/*!
* Minimal datarate that can be used by the node
*/
#define KR920_RX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define KR920_RX_MAX_DATARATE DR_5
/*!
* Default datarate used by the node
*/
#define KR920_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define KR920_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define KR920_MAX_RX1_DR_OFFSET 5
/*!
* Default Rx1 receive datarate offset
*/
#define KR920_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define KR920_MIN_TX_POWER TX_POWER_7
/*!
* Maximal Tx output power that can be used by the node
*/
#define KR920_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define KR920_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max EIRP for frequency 920.9 MHz - 921.9 MHz
*/
#define KR920_DEFAULT_MAX_EIRP_LOW 10.0f
/*!
* Default Max EIRP for frequency 922.1 MHz - 923.3 MHz
*/
#define KR920_DEFAULT_MAX_EIRP_HIGH 14.0f
/*!
* Default antenna gain
*/
#define KR920_DEFAULT_ANTENNA_GAIN 2.15f
/*!
* ADR Ack limit
*/
#define KR920_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define KR920_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define KR920_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define KR920_MAX_RX_WINDOW 4000
/*!
* Receive delay 1
*/
#define KR920_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define KR920_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define KR920_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define KR920_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define KR920_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define KR920_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define KR920_ACK_TIMEOUT_RND 1000
#if ( KR920_DEFAULT_DATARATE > DR_5 )
#error "A default DR higher than DR_5 may lead to connectivity loss."
#endif
/*!
* Second reception window channel frequency definition.
*/
#define KR920_RX_WND_2_FREQ 921900000
/*!
* Second reception window channel datarate definition.
*/
#define KR920_RX_WND_2_DR DR_0
/*!
* Maximum number of bands
*/
#define KR920_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0 } // 100.0 %
/*!
* LoRaMac default channel 1
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define KR920_LC1 { 922100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 2
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define KR920_LC2 { 922300000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac default channel 3
* Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
*/
#define KR920_LC3 { 922500000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define KR920_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
/*!
* RSSI threshold for a free channel [dBm]
*/
#define KR920_RSSI_FREE_TH -65
/*!
* Specifies the time the node performs a carrier sense
*/
#define KR920_CARRIER_SENSE_TIME 6
/*!
* Data rates table definition
*/
static const uint8_t DataratesKR920[] = { 12, 11, 10, 9, 8, 7 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsKR920[] = { 125000, 125000, 125000, 125000, 125000, 125000 };
/*!
* Maximum payload with respect to the datarate index. Can operate with and without a repeater.
*/
static const uint8_t MaxPayloadOfDatarateKR920[] = { 51, 51, 51, 115, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterKR920[] = { 51, 51, 51, 115, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionKR920SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionKR920InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionKR920Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionKR920ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionKR920ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionKR920AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionKR920ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionKR920TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionKR920LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionKR920RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionKR920NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionKR920TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionKR920DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionKR920AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionKR920CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionKR920ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionKR920SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionKR920ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONKR920 */
#endif // __REGION_KR920_H__

@ -0,0 +1,964 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC region US915 Hybrid implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include "radio.h"
#include "timer.h"
#include "LoRaMac.h"
#include "utilities.h"
#include "Region.h"
#include "RegionCommon.h"
#include "RegionUS915-Hybrid.h"
#include "debug.h"
// Definitions
#define CHANNELS_MASK_SIZE 6
// Global attributes
/*!
* LoRaMAC channels
*/
static ChannelParams_t Channels[US915_HYBRID_MAX_NB_CHANNELS];
/*!
* LoRaMac bands
*/
static Band_t Bands[US915_HYBRID_MAX_NB_BANDS] =
{
US915_HYBRID_BAND0
};
/*!
* LoRaMac channels mask
*/
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
/*!
* LoRaMac channels remaining
*/
static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
/*!
* LoRaMac channels default mask
*/
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
{
uint8_t nextLowerDr = 0;
if( dr == minDr )
{
nextLowerDr = minDr;
}
else
{
nextLowerDr = dr - 1;
}
return nextLowerDr;
}
static uint32_t GetBandwidth( uint32_t drIndex )
{
switch( BandwidthsUS915_HYBRID[drIndex] )
{
default:
case 125000:
return 0;
case 250000:
return 1;
case 500000:
return 2;
}
}
static void ReenableChannels( uint16_t mask, uint16_t* channelsMask )
{
uint16_t blockMask = mask;
for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
{
channelsMask[i] = 0;
if( ( blockMask & ( 1 << j ) ) != 0 )
{
channelsMask[i] |= 0x00FF;
}
if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
{
channelsMask[i] |= 0xFF00;
}
}
channelsMask[4] = blockMask;
channelsMask[5] = 0x0000;
}
static uint8_t CountBits( uint16_t mask, uint8_t nbBits )
{
uint8_t nbActiveBits = 0;
for( uint8_t j = 0; j < nbBits; j++ )
{
if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
{
nbActiveBits++;
}
}
return nbActiveBits;
}
static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
{
int8_t txPowerResult = txPower;
// Limit tx power to the band max
txPowerResult = MAX( txPower, maxBandTxPower );
if( datarate == DR_4 )
{// Limit tx power to max 26dBm
txPowerResult = MAX( txPower, TX_POWER_2 );
}
else
{
if( RegionCommonCountChannels( channelsMask, 0, 4 ) < 50 )
{// Limit tx power to max 21dBm
txPowerResult = MAX( txPower, TX_POWER_5 );
}
}
return txPowerResult;
}
static bool ValidateChannelsMask( uint16_t* channelsMask )
{
bool chanMaskState = false;
uint16_t block1 = 0;
uint16_t block2 = 0;
uint8_t index = 0;
uint16_t channelsMaskCpy[6];
// Copy channels mask to not change the input
for( uint8_t i = 0; i < 4; i++ )
{
channelsMaskCpy[i] = channelsMask[i];
}
for( uint8_t i = 0; i < 4; i++ )
{
block1 = channelsMaskCpy[i] & 0x00FF;
block2 = channelsMaskCpy[i] & 0xFF00;
if( CountBits( block1, 16 ) > 5 )
{
channelsMaskCpy[i] &= block1;
channelsMaskCpy[4] = 1 << ( i * 2 );
chanMaskState = true;
index = i;
break;
}
else if( CountBits( block2, 16 ) > 5 )
{
channelsMaskCpy[i] &= block2;
channelsMaskCpy[4] = 1 << ( i * 2 + 1 );
chanMaskState = true;
index = i;
break;
}
}
// Do only change the channel mask, if we have found a valid block.
if( chanMaskState == true )
{
// Copy channels mask back again
for( uint8_t i = 0; i < 4; i++ )
{
channelsMask[i] = channelsMaskCpy[i];
if( i != index )
{
channelsMask[i] = 0;
}
}
channelsMask[4] = channelsMaskCpy[4];
}
return chanMaskState;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
for( uint8_t i = 0, k = 0; i < US915_HYBRID_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
}
PhyParam_t RegionUS915HybridGetPhyParam( GetPhyParams_t* getPhy )
{
PhyParam_t phyParam = { 0 };
switch( getPhy->Attribute )
{
case PHY_MIN_RX_DR:
{
phyParam.Value = US915_HYBRID_RX_MIN_DATARATE;
break;
}
case PHY_MIN_TX_DR:
{
phyParam.Value = US915_HYBRID_TX_MIN_DATARATE;
break;
}
case PHY_DEF_TX_DR:
{
phyParam.Value = US915_HYBRID_DEFAULT_DATARATE;
break;
}
case PHY_NEXT_LOWER_TX_DR:
{
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, US915_HYBRID_TX_MIN_DATARATE );
break;
}
case PHY_DEF_TX_POWER:
{
phyParam.Value = US915_HYBRID_DEFAULT_TX_POWER;
break;
}
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateUS915_HYBRID[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterUS915_HYBRID[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = US915_HYBRID_DUTY_CYCLE_ENABLED;
break;
}
case PHY_MAX_RX_WINDOW:
{
phyParam.Value = US915_HYBRID_MAX_RX_WINDOW;
break;
}
case PHY_RECEIVE_DELAY1:
{
phyParam.Value = US915_HYBRID_RECEIVE_DELAY1;
break;
}
case PHY_RECEIVE_DELAY2:
{
phyParam.Value = US915_HYBRID_RECEIVE_DELAY2;
break;
}
case PHY_JOIN_ACCEPT_DELAY1:
{
phyParam.Value = US915_HYBRID_JOIN_ACCEPT_DELAY1;
break;
}
case PHY_JOIN_ACCEPT_DELAY2:
{
phyParam.Value = US915_HYBRID_JOIN_ACCEPT_DELAY2;
break;
}
case PHY_MAX_FCNT_GAP:
{
phyParam.Value = US915_HYBRID_MAX_FCNT_GAP;
break;
}
case PHY_ACK_TIMEOUT:
{
phyParam.Value = ( US915_HYBRID_ACKTIMEOUT + randr( -US915_HYBRID_ACK_TIMEOUT_RND, US915_HYBRID_ACK_TIMEOUT_RND ) );
break;
}
case PHY_DEF_DR1_OFFSET:
{
phyParam.Value = US915_HYBRID_DEFAULT_RX1_DR_OFFSET;
break;
}
case PHY_DEF_RX2_FREQUENCY:
{
phyParam.Value = US915_HYBRID_RX_WND_2_FREQ;
break;
}
case PHY_DEF_RX2_DR:
{
phyParam.Value = US915_HYBRID_RX_WND_2_DR;
break;
}
case PHY_CHANNELS_MASK:
{
phyParam.ChannelsMask = ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
phyParam.ChannelsMask = ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
{
phyParam.Value = US915_HYBRID_MAX_NB_CHANNELS;
break;
}
case PHY_CHANNELS:
{
phyParam.Channels = Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
case PHY_DEF_DOWNLINK_DWELL_TIME:
{
phyParam.Value = 0;
break;
}
case PHY_DEF_MAX_EIRP:
case PHY_DEF_ANTENNA_GAIN:
{
phyParam.fValue = 0;
break;
}
case PHY_NB_JOIN_TRIALS:
case PHY_DEF_NB_JOIN_TRIALS:
{
phyParam.Value = 2;
break;
}
default:
{
break;
}
}
return phyParam;
}
void RegionUS915HybridSetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
void RegionUS915HybridInitDefaults( InitType_t type )
{
switch( type )
{
case INIT_TYPE_INIT:
{
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < US915_HYBRID_MAX_NB_CHANNELS - 8; i++ )
{
Channels[i].Frequency = 902300000 + i * 200000;
Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
Channels[i].Band = 0;
}
// 500 kHz channels
for( uint8_t i = US915_HYBRID_MAX_NB_CHANNELS - 8; i < US915_HYBRID_MAX_NB_CHANNELS; i++ )
{
Channels[i].Frequency = 903000000 + ( i - ( US915_HYBRID_MAX_NB_CHANNELS - 8 ) ) * 1600000;
Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
Channels[i].Band = 0;
}
// ChannelsMask
ChannelsDefaultMask[0] = 0x00FF;
ChannelsDefaultMask[1] = 0x0000;
ChannelsDefaultMask[2] = 0x0000;
ChannelsDefaultMask[3] = 0x0000;
ChannelsDefaultMask[4] = 0x0001;
ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
break;
}
case INIT_TYPE_RESTORE:
{
ReenableChannels( ChannelsDefaultMask[4], ChannelsMask );
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
ChannelsMaskRemaining[i] &= ChannelsMask[i];
}
}
default:
{
break;
}
}
}
bool RegionUS915HybridVerify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_HYBRID_TX_MIN_DATARATE, US915_HYBRID_TX_MAX_DATARATE );
}
case PHY_DEF_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
}
case PHY_RX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_HYBRID_RX_MIN_DATARATE, US915_HYBRID_RX_MAX_DATARATE );
}
case PHY_DEF_TX_POWER:
case PHY_TX_POWER:
{
// Remark: switched min and max!
return RegionCommonValueInRange( verify->TxPower, US915_HYBRID_MAX_TX_POWER, US915_HYBRID_MIN_TX_POWER );
}
case PHY_DUTY_CYCLE:
{
return US915_HYBRID_DUTY_CYCLE_ENABLED;
}
case PHY_NB_JOIN_TRIALS:
{
if( verify->NbJoinTrials < 2 )
{
return false;
}
break;
}
default:
return false;
}
return true;
}
void RegionUS915HybridApplyCFList( ApplyCFListParams_t* applyCFList )
{
return;
}
bool RegionUS915HybridChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
uint8_t nbChannels = RegionCommonCountChannels( chanMaskSet->ChannelsMaskIn, 0, 4 );
// Check the number of active channels
if( ( nbChannels < 2 ) &&
( nbChannels > 0 ) )
{
return false;
}
// Validate the channels mask
if( ValidateChannelsMask( chanMaskSet->ChannelsMaskIn ) == false )
{
return false;
}
switch( chanMaskSet->ChannelsMaskType )
{
case CHANNELS_MASK:
{
RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
ChannelsMaskRemaining[i] &= ChannelsMask[i];
}
break;
}
case CHANNELS_DEFAULT_MASK:
{
RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
default:
return false;
}
return true;
}
bool RegionUS915HybridAdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
{
bool adrAckReq = false;
int8_t datarate = adrNext->Datarate;
int8_t txPower = adrNext->TxPower;
GetPhyParams_t getPhy;
PhyParam_t phyParam;
// Report back the adr ack counter
*adrAckCounter = adrNext->AdrAckCounter;
if( adrNext->AdrEnabled == true )
{
if( datarate == US915_HYBRID_TX_MIN_DATARATE )
{
*adrAckCounter = 0;
adrAckReq = false;
}
else
{
if( adrNext->AdrAckCounter >= US915_HYBRID_ADR_ACK_LIMIT )
{
adrAckReq = true;
txPower = US915_HYBRID_MAX_TX_POWER;
}
else
{
adrAckReq = false;
}
if( adrNext->AdrAckCounter >= ( US915_HYBRID_ADR_ACK_LIMIT + US915_HYBRID_ADR_ACK_DELAY ) )
{
if( ( adrNext->AdrAckCounter % US915_HYBRID_ADR_ACK_DELAY ) == 1 )
{
// Decrease the datarate
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
getPhy.Datarate = datarate;
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
phyParam = RegionUS915HybridGetPhyParam( &getPhy );
datarate = phyParam.Value;
if( datarate == US915_HYBRID_TX_MIN_DATARATE )
{
// We must set adrAckReq to false as soon as we reach the lowest datarate
adrAckReq = false;
if( adrNext->UpdateChanMask == true )
{
// Re-enable default channels
ReenableChannels( ChannelsMask[4], ChannelsMask );
}
}
}
}
}
}
*drOut = datarate;
*txPowOut = txPower;
return adrAckReq;
}
void RegionUS915HybridComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
uint32_t radioWakeUpTime;
// Get the datarate, perform a boundary check
rxConfigParams->Datarate = MIN( datarate, US915_HYBRID_RX_MAX_DATARATE );
rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesUS915_HYBRID[rxConfigParams->Datarate], BandwidthsUS915_HYBRID[rxConfigParams->Datarate] );
radioWakeUpTime = Radio.GetRadioWakeUpTime( );
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, radioWakeUpTime, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionUS915HybridRxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
if( Radio.GetStatus( ) != RF_IDLE )
{
return false;
}
if( rxConfig->Window == 0 )
{
// Apply window 1 frequency
frequency = US915_HYBRID_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * US915_HYBRID_STEPWIDTH_RX1_CHANNEL;
}
// Read the physical datarate from the datarates table
phyDr = DataratesUS915_HYBRID[dr];
Radio.SetChannel( frequency );
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterUS915_HYBRID[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateUS915_HYBRID[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
DBG_PRINTF( "RX on freq %d Hz at DR %d\n\r", frequency, dr );
*datarate = (uint8_t) dr;
return true;
}
bool RegionUS915HybridTxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesUS915_HYBRID[txConfig->Datarate];
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_HYBRID_DEFAULT_MAX_ERP, 0 );
// Setup the radio frequency
Radio.SetChannel( Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
DBG_PRINTF( "TX on freq %d Hz at DR %d\n\r", Channels[txConfig->Channel].Frequency, txConfig->Datarate );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
}
uint8_t RegionUS915HybridLinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
{
uint8_t status = 0x07;
RegionCommonLinkAdrParams_t linkAdrParams;
uint8_t nextIndex = 0;
uint8_t bytesProcessed = 0;
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
GetPhyParams_t getPhy;
PhyParam_t phyParam;
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
if( nextIndex == 0 )
break; // break loop, since no more request has been found
// Update bytes processed
bytesProcessed += nextIndex;
// Revert status, as we only check the last ADR request for the channel mask KO
status = 0x07;
if( linkAdrParams.ChMaskCtrl == 6 )
{
// Enable all 125 kHz channels
channelsMask[0] = 0xFFFF;
channelsMask[1] = 0xFFFF;
channelsMask[2] = 0xFFFF;
channelsMask[3] = 0xFFFF;
// Apply chMask to channels 64 to 71
channelsMask[4] = linkAdrParams.ChMask;
}
else if( linkAdrParams.ChMaskCtrl == 7 )
{
// Disable all 125 kHz channels
channelsMask[0] = 0x0000;
channelsMask[1] = 0x0000;
channelsMask[2] = 0x0000;
channelsMask[3] = 0x0000;
// Apply chMask to channels 64 to 71
channelsMask[4] = linkAdrParams.ChMask;
}
else if( linkAdrParams.ChMaskCtrl == 5 )
{
// RFU
status &= 0xFE; // Channel mask KO
}
else
{
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
}
}
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
if( ( linkAdrParams.Datarate < DR_4 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) )
{
status &= 0xFE; // Channel mask KO
}
if( ValidateChannelsMask( channelsMask ) == false )
{
status &= 0xFE; // Channel mask KO
}
// Get the minimum possible datarate
getPhy.Attribute = PHY_MIN_TX_DR;
getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
phyParam = RegionUS915HybridGetPhyParam( &getPhy );
linkAdrVerifyParams.Status = status;
linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
linkAdrVerifyParams.NbChannels = US915_HYBRID_MAX_NB_CHANNELS;
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = US915_HYBRID_TX_MAX_DATARATE;
linkAdrVerifyParams.Channels = Channels;
linkAdrVerifyParams.MinTxPower = US915_HYBRID_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = US915_HYBRID_MAX_TX_POWER;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
// Update channelsMask if everything is correct
if( status == 0x07 )
{
// Copy Mask
RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
ChannelsMaskRemaining[0] &= ChannelsMask[0];
ChannelsMaskRemaining[1] &= ChannelsMask[1];
ChannelsMaskRemaining[2] &= ChannelsMask[2];
ChannelsMaskRemaining[3] &= ChannelsMask[3];
ChannelsMaskRemaining[4] = ChannelsMask[4];
ChannelsMaskRemaining[5] = ChannelsMask[5];
}
// Update status variables
*drOut = linkAdrParams.Datarate;
*txPowOut = linkAdrParams.TxPower;
*nbRepOut = linkAdrParams.NbRep;
*nbBytesParsed = bytesProcessed;
return status;
}
uint8_t RegionUS915HybridRxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
uint32_t freq = rxParamSetupReq->Frequency;
// Verify radio frequency
if( ( Radio.CheckRfFrequency( freq ) == false ) ||
( freq < US915_HYBRID_FIRST_RX1_CHANNEL ) ||
( freq > US915_HYBRID_LAST_RX1_CHANNEL ) ||
( ( ( freq - ( uint32_t ) US915_HYBRID_FIRST_RX1_CHANNEL ) % ( uint32_t ) US915_HYBRID_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
{
status &= 0xFE; // Channel frequency KO
}
// Verify datarate
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, US915_HYBRID_RX_MIN_DATARATE, US915_HYBRID_RX_MAX_DATARATE ) == false )
{
status &= 0xFD; // Datarate KO
}
if( ( RegionCommonValueInRange( rxParamSetupReq->Datarate, DR_5, DR_7 ) == true ) ||
( rxParamSetupReq->Datarate > DR_13 ) )
{
status &= 0xFD; // Datarate KO
}
// Verify datarate offset
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, US915_HYBRID_MIN_RX1_DR_OFFSET, US915_HYBRID_MAX_RX1_DR_OFFSET ) == false )
{
status &= 0xFB; // Rx1DrOffset range KO
}
return status;
}
uint8_t RegionUS915HybridNewChannelReq( NewChannelReqParams_t* newChannelReq )
{
// Datarate and frequency KO
return 0;
}
int8_t RegionUS915HybridTxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
{
return -1;
}
uint8_t RegionUS915HybridDlChannelReq( DlChannelReqParams_t* dlChannelReq )
{
return 0;
}
int8_t RegionUS915HybridAlternateDr( AlternateDrParams_t* alternateDr )
{
int8_t datarate = 0;
// Re-enable 500 kHz default channels
ReenableChannels( ChannelsMask[4], ChannelsMask );
if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
{
datarate = DR_4;
}
else
{
datarate = DR_0;
}
return datarate;
}
void RegionUS915HybridCalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = Channels;
calcBackOffParams.Bands = Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
bool RegionUS915HybridNextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[US915_HYBRID_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
// Count 125kHz channels
if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
{ // Reactivate default channels
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
}
// Check other channels
if( nextChanParams->Datarate >= DR_4 )
{
if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
{
ChannelsMaskRemaining[4] = ChannelsMask[4];
}
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, US915_HYBRID_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
ChannelsMaskRemaining, Channels,
Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 )
{
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
// Disable the channel in the mask
RegionCommonChanDisable( ChannelsMaskRemaining, *channel, US915_HYBRID_MAX_NB_CHANNELS - 8 );
*time = 0;
return true;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return true;
}
// Datarate not supported by any channel
*time = 0;
return false;
}
}
LoRaMacStatus_t RegionUS915HybridChannelAdd( ChannelAddParams_t* channelAdd )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
bool RegionUS915HybridChannelsRemove( ChannelRemoveParams_t* channelRemove )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
void RegionUS915HybridSetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
int8_t phyTxPower = 0;
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_HYBRID_DEFAULT_MAX_ERP, 0 );
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
}
uint8_t RegionUS915HybridApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
{
int8_t datarate = DatarateOffsetsUS915_HYBRID[dr][drOffset];
if( datarate < 0 )
{
datarate = DR_0;
}
return datarate;
}

@ -0,0 +1,448 @@
/*!
* \file RegionUS915Hybrid-Hybrid.h
*
* \brief Region definition for US915
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONUS915HYB Region US915 in hybrid mode
* This is a hybrid implementation for US915, supporting 16 uplink channels only.
* \{
*/
#ifndef __REGION_US915_HYBRID_H__
#define __REGION_US915_HYBRID_H__
/*!
* LoRaMac maximum number of channels
*/
#define US915_HYBRID_MAX_NB_CHANNELS 72
/*!
* Minimal datarate that can be used by the node
*/
#define US915_HYBRID_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define US915_HYBRID_TX_MAX_DATARATE DR_4
/*!
* Minimal datarate that can be used by the node
*/
#define US915_HYBRID_RX_MIN_DATARATE DR_8
/*!
* Maximal datarate that can be used by the node
*/
#define US915_HYBRID_RX_MAX_DATARATE DR_13
/*!
* Default datarate used by the node
*/
#define US915_HYBRID_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define US915_HYBRID_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define US915_HYBRID_MAX_RX1_DR_OFFSET 3
/*!
* Default Rx1 receive datarate offset
*/
#define US915_HYBRID_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define US915_HYBRID_MIN_TX_POWER TX_POWER_10
/*!
* Maximal Tx output power that can be used by the node
*/
#define US915_HYBRID_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define US915_HYBRID_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max ERP
*/
#define US915_HYBRID_DEFAULT_MAX_ERP 30.0f
/*!
* ADR Ack limit
*/
#define US915_HYBRID_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define US915_HYBRID_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define US915_HYBRID_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define US915_HYBRID_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define US915_HYBRID_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define US915_HYBRID_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define US915_HYBRID_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define US915_HYBRID_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define US915_HYBRID_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define US915_HYBRID_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define US915_HYBRID_ACK_TIMEOUT_RND 1000
/*!
* Second reception window channel frequency definition.
*/
#define US915_HYBRID_RX_WND_2_FREQ 923300000
/*!
* Second reception window channel datarate definition.
*/
#define US915_HYBRID_RX_WND_2_DR DR_8
/*!
* LoRaMac maximum number of bands
*/
#define US915_HYBRID_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define US915_HYBRID_BAND0 { 1, US915_HYBRID_MAX_TX_POWER, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
*/
#define US915_HYBRID_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )
/*!
* Defines the last channel for RX window 1 for US band
*/
#define US915_HYBRID_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define US915_HYBRID_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )
/*!
* Data rates table definition
*/
static const uint8_t DataratesUS915_HYBRID[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsUS915_HYBRID[] = { 125000, 125000, 125000, 125000, 500000, 0, 0, 0, 500000, 500000, 500000, 500000, 500000, 500000, 0, 0 };
/*!
* Up/Down link data rates offset definition
*/
static const int8_t DatarateOffsetsUS915_HYBRID[5][4] =
{
{ DR_10, DR_9 , DR_8 , DR_8 }, // DR_0
{ DR_11, DR_10, DR_9 , DR_8 }, // DR_1
{ DR_12, DR_11, DR_10, DR_9 }, // DR_2
{ DR_13, DR_12, DR_11, DR_10 }, // DR_3
{ DR_13, DR_13, DR_12, DR_11 }, // DR_4
};
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateUS915_HYBRID[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterUS915_HYBRID[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionUS915HybridGetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionUS915HybridSetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionUS915HybridInitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionUS915HybridVerify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionUS915HybridApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionUS915HybridChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionUS915HybridAdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionUS915HybridComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionUS915HybridRxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionUS915HybridTxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915HybridLinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915HybridRxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915HybridNewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionUS915HybridTxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915HybridDlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionUS915HybridAlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionUS915HybridCalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionUS915HybridNextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionUS915HybridChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionUS915HybridChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionUS915HybridSetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionUS915HybridApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONUS915HYB */
#endif // __REGION_US915_HYBRID_H__

@ -0,0 +1,871 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
___ _____ _ ___ _ _____ ___ ___ ___ ___
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============
Description: LoRa MAC region US915 implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include "radio.h"
#include "timer.h"
#include "LoRaMac.h"
#include "utilities.h"
#include "Region.h"
#include "RegionCommon.h"
#include "RegionUS915.h"
#include "debug.h"
// Definitions
#define CHANNELS_MASK_SIZE 6
// Global attributes
/*!
* LoRaMAC channels
*/
static ChannelParams_t Channels[US915_MAX_NB_CHANNELS];
/*!
* LoRaMac bands
*/
static Band_t Bands[US915_MAX_NB_BANDS] =
{
US915_BAND0
};
/*!
* LoRaMac channels mask
*/
static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
/*!
* LoRaMac channels remaining
*/
static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
/*!
* LoRaMac channels default mask
*/
static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
{
uint8_t nextLowerDr = 0;
if( dr == minDr )
{
nextLowerDr = minDr;
}
else
{
nextLowerDr = dr - 1;
}
return nextLowerDr;
}
static uint32_t GetBandwidth( uint32_t drIndex )
{
switch( BandwidthsUS915[drIndex] )
{
default:
case 125000:
return 0;
case 250000:
return 1;
case 500000:
return 2;
}
}
static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
{
int8_t txPowerResult = txPower;
// Limit tx power to the band max
txPowerResult = MAX( txPower, maxBandTxPower );
if( datarate == DR_4 )
{// Limit tx power to max 26dBm
txPowerResult = MAX( txPower, TX_POWER_2 );
}
else
{
if( RegionCommonCountChannels( channelsMask, 0, 4 ) < 50 )
{// Limit tx power to max 21dBm
txPowerResult = MAX( txPower, TX_POWER_5 );
}
}
return txPowerResult;
}
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTransmission = 0;
for( uint8_t i = 0, k = 0; i < US915_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
{
if( channels[i + j].Frequency == 0 )
{ // Check if the channel is enabled
continue;
}
if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
channels[i + j].DrRange.Fields.Max ) == false )
{ // Check if the current channel selection supports the given datarate
continue;
}
if( bands[channels[i + j].Band].TimeOff > 0 )
{ // Check if the band is available for transmission
delayTransmission++;
continue;
}
enabledChannels[nbEnabledChannels++] = i + j;
}
}
}
*delayTx = delayTransmission;
return nbEnabledChannels;
}
PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
{
PhyParam_t phyParam = { 0 };
switch( getPhy->Attribute )
{
case PHY_MIN_RX_DR:
{
phyParam.Value = US915_RX_MIN_DATARATE;
break;
}
case PHY_MIN_TX_DR:
{
phyParam.Value = US915_TX_MIN_DATARATE;
break;
}
case PHY_DEF_TX_DR:
{
phyParam.Value = US915_DEFAULT_DATARATE;
break;
}
case PHY_NEXT_LOWER_TX_DR:
{
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, US915_TX_MIN_DATARATE );
break;
}
case PHY_DEF_TX_POWER:
{
phyParam.Value = US915_DEFAULT_TX_POWER;
break;
}
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateUS915[getPhy->Datarate];
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
phyParam.Value = MaxPayloadOfDatarateRepeaterUS915[getPhy->Datarate];
break;
}
case PHY_DUTY_CYCLE:
{
phyParam.Value = US915_DUTY_CYCLE_ENABLED;
break;
}
case PHY_MAX_RX_WINDOW:
{
phyParam.Value = US915_MAX_RX_WINDOW;
break;
}
case PHY_RECEIVE_DELAY1:
{
phyParam.Value = US915_RECEIVE_DELAY1;
break;
}
case PHY_RECEIVE_DELAY2:
{
phyParam.Value = US915_RECEIVE_DELAY2;
break;
}
case PHY_JOIN_ACCEPT_DELAY1:
{
phyParam.Value = US915_JOIN_ACCEPT_DELAY1;
break;
}
case PHY_JOIN_ACCEPT_DELAY2:
{
phyParam.Value = US915_JOIN_ACCEPT_DELAY2;
break;
}
case PHY_MAX_FCNT_GAP:
{
phyParam.Value = US915_MAX_FCNT_GAP;
break;
}
case PHY_ACK_TIMEOUT:
{
phyParam.Value = ( US915_ACKTIMEOUT + randr( -US915_ACK_TIMEOUT_RND, US915_ACK_TIMEOUT_RND ) );
break;
}
case PHY_DEF_DR1_OFFSET:
{
phyParam.Value = US915_DEFAULT_RX1_DR_OFFSET;
break;
}
case PHY_DEF_RX2_FREQUENCY:
{
phyParam.Value = US915_RX_WND_2_FREQ;
break;
}
case PHY_DEF_RX2_DR:
{
phyParam.Value = US915_RX_WND_2_DR;
break;
}
case PHY_CHANNELS_MASK:
{
phyParam.ChannelsMask = ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
phyParam.ChannelsMask = ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
{
phyParam.Value = US915_MAX_NB_CHANNELS;
break;
}
case PHY_CHANNELS:
{
phyParam.Channels = Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
case PHY_DEF_DOWNLINK_DWELL_TIME:
{
phyParam.Value = 0;
break;
}
case PHY_DEF_MAX_EIRP:
case PHY_DEF_ANTENNA_GAIN:
{
phyParam.fValue = 0;
break;
}
case PHY_NB_JOIN_TRIALS:
case PHY_DEF_NB_JOIN_TRIALS:
{
phyParam.Value = 2;
break;
}
default:
{
break;
}
}
return phyParam;
}
void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
void RegionUS915InitDefaults( InitType_t type )
{
switch( type )
{
case INIT_TYPE_INIT:
{
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++ )
{
Channels[i].Frequency = 902300000 + i * 200000;
Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
Channels[i].Band = 0;
}
// 500 kHz channels
for( uint8_t i = US915_MAX_NB_CHANNELS - 8; i < US915_MAX_NB_CHANNELS; i++ )
{
Channels[i].Frequency = 903000000 + ( i - ( US915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
Channels[i].Band = 0;
}
// ChannelsMask
ChannelsDefaultMask[0] = 0xFFFF;
ChannelsDefaultMask[1] = 0xFFFF;
ChannelsDefaultMask[2] = 0xFFFF;
ChannelsDefaultMask[3] = 0xFFFF;
ChannelsDefaultMask[4] = 0x00FF;
ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
break;
}
case INIT_TYPE_RESTORE:
{
// Copy channels default mask
RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
ChannelsMaskRemaining[i] &= ChannelsMask[i];
}
break;
}
default:
{
break;
}
}
}
bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_TX_MIN_DATARATE, US915_TX_MAX_DATARATE );
}
case PHY_DEF_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
}
case PHY_RX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_RX_MIN_DATARATE, US915_RX_MAX_DATARATE );
}
case PHY_DEF_TX_POWER:
case PHY_TX_POWER:
{
// Remark: switched min and max!
return RegionCommonValueInRange( verify->TxPower, US915_MAX_TX_POWER, US915_MIN_TX_POWER );
}
case PHY_DUTY_CYCLE:
{
return US915_DUTY_CYCLE_ENABLED;
}
case PHY_NB_JOIN_TRIALS:
{
if( verify->NbJoinTrials < 2 )
{
return false;
}
break;
}
default:
return false;
}
return true;
}
void RegionUS915ApplyCFList( ApplyCFListParams_t* applyCFList )
{
return;
}
bool RegionUS915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
uint8_t nbChannels = RegionCommonCountChannels( chanMaskSet->ChannelsMaskIn, 0, 4 );
// Check the number of active channels
if( ( nbChannels < 2 ) &&
( nbChannels > 0 ) )
{
return false;
}
switch( chanMaskSet->ChannelsMaskType )
{
case CHANNELS_MASK:
{
RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
ChannelsMaskRemaining[i] &= ChannelsMask[i];
}
break;
}
case CHANNELS_DEFAULT_MASK:
{
RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
default:
return false;
}
return true;
}
bool RegionUS915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
{
bool adrAckReq = false;
int8_t datarate = adrNext->Datarate;
int8_t txPower = adrNext->TxPower;
GetPhyParams_t getPhy;
PhyParam_t phyParam;
// Report back the adr ack counter
*adrAckCounter = adrNext->AdrAckCounter;
if( adrNext->AdrEnabled == true )
{
if( datarate == US915_TX_MIN_DATARATE )
{
*adrAckCounter = 0;
adrAckReq = false;
}
else
{
if( adrNext->AdrAckCounter >= US915_ADR_ACK_LIMIT )
{
adrAckReq = true;
txPower = US915_MAX_TX_POWER;
}
else
{
adrAckReq = false;
}
if( adrNext->AdrAckCounter >= ( US915_ADR_ACK_LIMIT + US915_ADR_ACK_DELAY ) )
{
if( ( adrNext->AdrAckCounter % US915_ADR_ACK_DELAY ) == 1 )
{
// Decrease the datarate
getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
getPhy.Datarate = datarate;
getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
phyParam = RegionUS915GetPhyParam( &getPhy );
datarate = phyParam.Value;
if( datarate == US915_TX_MIN_DATARATE )
{
// We must set adrAckReq to false as soon as we reach the lowest datarate
adrAckReq = false;
if( adrNext->UpdateChanMask == true )
{
// Re-enable default channels
ChannelsMask[0] = 0xFFFF;
ChannelsMask[1] = 0xFFFF;
ChannelsMask[2] = 0xFFFF;
ChannelsMask[3] = 0xFFFF;
ChannelsMask[4] = 0x00FF;
ChannelsMask[5] = 0x0000;
}
}
}
}
}
}
*drOut = datarate;
*txPowOut = txPower;
return adrAckReq;
}
void RegionUS915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
uint32_t radioWakeUpTime;
// Get the datarate, perform a boundary check
rxConfigParams->Datarate = MIN( datarate, US915_RX_MAX_DATARATE );
rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesUS915[rxConfigParams->Datarate], BandwidthsUS915[rxConfigParams->Datarate] );
radioWakeUpTime = Radio.GetRadioWakeUpTime( );
RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, radioWakeUpTime, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
{
int8_t dr = rxConfig->Datarate;
uint8_t maxPayload = 0;
int8_t phyDr = 0;
uint32_t frequency = rxConfig->Frequency;
if( Radio.GetStatus( ) != RF_IDLE )
{
return false;
}
if( rxConfig->Window == 0 )
{
// Apply window 1 frequency
frequency = US915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * US915_STEPWIDTH_RX1_CHANNEL;
}
// Read the physical datarate from the datarates table
phyDr = DataratesUS915[dr];
Radio.SetChannel( frequency );
// Radio configuration
Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
if( rxConfig->RepeaterSupport == true )
{
maxPayload = MaxPayloadOfDatarateRepeaterUS915[dr];
}
else
{
maxPayload = MaxPayloadOfDatarateUS915[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
DBG_PRINTF( "RX on freq %d Hz at DR %d\n\r", frequency, dr );
*datarate = (uint8_t) dr;
return true;
}
bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesUS915[txConfig->Datarate];
int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_DEFAULT_MAX_ERP, 0 );
// Setup the radio frequency
Radio.SetChannel( Channels[txConfig->Channel].Frequency );
Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
DBG_PRINTF( "TX on freq %d Hz at DR %d\n\r", Channels[txConfig->Channel].Frequency, txConfig->Datarate );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
*txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
*txPower = txPowerLimited;
return true;
}
uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
{
uint8_t status = 0x07;
RegionCommonLinkAdrParams_t linkAdrParams;
uint8_t nextIndex = 0;
uint8_t bytesProcessed = 0;
uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
GetPhyParams_t getPhy;
PhyParam_t phyParam;
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
if( nextIndex == 0 )
break; // break loop, since no more request has been found
// Update bytes processed
bytesProcessed += nextIndex;
// Revert status, as we only check the last ADR request for the channel mask KO
status = 0x07;
if( linkAdrParams.ChMaskCtrl == 6 )
{
// Enable all 125 kHz channels
channelsMask[0] = 0xFFFF;
channelsMask[1] = 0xFFFF;
channelsMask[2] = 0xFFFF;
channelsMask[3] = 0xFFFF;
// Apply chMask to channels 64 to 71
channelsMask[4] = linkAdrParams.ChMask;
}
else if( linkAdrParams.ChMaskCtrl == 7 )
{
// Disable all 125 kHz channels
channelsMask[0] = 0x0000;
channelsMask[1] = 0x0000;
channelsMask[2] = 0x0000;
channelsMask[3] = 0x0000;
// Apply chMask to channels 64 to 71
channelsMask[4] = linkAdrParams.ChMask;
}
else if( linkAdrParams.ChMaskCtrl == 5 )
{
// RFU
status &= 0xFE; // Channel mask KO
}
else
{
channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
}
}
// FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
if( ( linkAdrParams.Datarate < DR_4 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) )
{
status &= 0xFE; // Channel mask KO
}
// Get the minimum possible datarate
getPhy.Attribute = PHY_MIN_TX_DR;
getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
phyParam = RegionUS915GetPhyParam( &getPhy );
linkAdrVerifyParams.Status = status;
linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
linkAdrVerifyParams.NbChannels = US915_MAX_NB_CHANNELS;
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = US915_TX_MAX_DATARATE;
linkAdrVerifyParams.Channels = Channels;
linkAdrVerifyParams.MinTxPower = US915_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = US915_MAX_TX_POWER;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
// Update channelsMask if everything is correct
if( status == 0x07 )
{
// Copy Mask
RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
ChannelsMaskRemaining[0] &= ChannelsMask[0];
ChannelsMaskRemaining[1] &= ChannelsMask[1];
ChannelsMaskRemaining[2] &= ChannelsMask[2];
ChannelsMaskRemaining[3] &= ChannelsMask[3];
ChannelsMaskRemaining[4] = ChannelsMask[4];
ChannelsMaskRemaining[5] = ChannelsMask[5];
}
// Update status variables
*drOut = linkAdrParams.Datarate;
*txPowOut = linkAdrParams.TxPower;
*nbRepOut = linkAdrParams.NbRep;
*nbBytesParsed = bytesProcessed;
return status;
}
uint8_t RegionUS915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
uint32_t freq = rxParamSetupReq->Frequency;
// Verify radio frequency
if( ( Radio.CheckRfFrequency( freq ) == false ) ||
( freq < US915_FIRST_RX1_CHANNEL ) ||
( freq > US915_LAST_RX1_CHANNEL ) ||
( ( ( freq - ( uint32_t ) US915_FIRST_RX1_CHANNEL ) % ( uint32_t ) US915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
{
status &= 0xFE; // Channel frequency KO
}
// Verify datarate
if( RegionCommonValueInRange( rxParamSetupReq->Datarate, US915_RX_MIN_DATARATE, US915_RX_MAX_DATARATE ) == false )
{
status &= 0xFD; // Datarate KO
}
if( ( RegionCommonValueInRange( rxParamSetupReq->Datarate, DR_5, DR_7 ) == true ) ||
( rxParamSetupReq->Datarate > DR_13 ) )
{
status &= 0xFD; // Datarate KO
}
// Verify datarate offset
if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, US915_MIN_RX1_DR_OFFSET, US915_MAX_RX1_DR_OFFSET ) == false )
{
status &= 0xFB; // Rx1DrOffset range KO
}
return status;
}
uint8_t RegionUS915NewChannelReq( NewChannelReqParams_t* newChannelReq )
{
// Datarate and frequency KO
return 0;
}
int8_t RegionUS915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
{
return -1;
}
uint8_t RegionUS915DlChannelReq( DlChannelReqParams_t* dlChannelReq )
{
return 0;
}
int8_t RegionUS915AlternateDr( AlternateDrParams_t* alternateDr )
{
int8_t datarate = 0;
// Re-enable 500 kHz default channels
ChannelsMask[4] = 0x00FF;
if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
{
datarate = DR_4;
}
else
{
datarate = DR_0;
}
return datarate;
}
void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
calcBackOffParams.Channels = Channels;
calcBackOffParams.Bands = Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
calcBackOffParams.Channel = calcBackOff->Channel;
calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
RegionCommonCalcBackOff( &calcBackOffParams );
}
bool RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[US915_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
// Count 125kHz channels
if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
{ // Reactivate default channels
RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
}
// Check other channels
if( nextChanParams->Datarate >= DR_4 )
{
if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
{
ChannelsMaskRemaining[4] = ChannelsMask[4];
}
}
if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, US915_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
ChannelsMaskRemaining, Channels,
Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
}
if( nbEnabledChannels > 0 )
{
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
// Disable the channel in the mask
RegionCommonChanDisable( ChannelsMaskRemaining, *channel, US915_MAX_NB_CHANNELS - 8 );
*time = 0;
return true;
}
else
{
if( delayTx > 0 )
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
return true;
}
// Datarate not supported by any channel
*time = 0;
return false;
}
}
LoRaMacStatus_t RegionUS915ChannelAdd( ChannelAddParams_t* channelAdd )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
bool RegionUS915ChannelsRemove( ChannelRemoveParams_t* channelRemove )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
void RegionUS915SetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
int8_t phyTxPower = 0;
uint32_t frequency = Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_DEFAULT_MAX_ERP, 0 );
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
}
uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
{
int8_t datarate = DatarateOffsetsUS915[dr][drOffset];
if( datarate < 0 )
{
datarate = DR_0;
}
return datarate;
}

@ -0,0 +1,448 @@
/*!
* \file RegionUS915.h
*
* \brief Region definition for US915
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \defgroup REGIONUS915 Region US915
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
*/
#ifndef __REGION_US915_H__
#define __REGION_US915_H__
/*!
* LoRaMac maximum number of channels
*/
#define US915_MAX_NB_CHANNELS 72
/*!
* Minimal datarate that can be used by the node
*/
#define US915_TX_MIN_DATARATE DR_0
/*!
* Maximal datarate that can be used by the node
*/
#define US915_TX_MAX_DATARATE DR_4
/*!
* Minimal datarate that can be used by the node
*/
#define US915_RX_MIN_DATARATE DR_8
/*!
* Maximal datarate that can be used by the node
*/
#define US915_RX_MAX_DATARATE DR_13
/*!
* Default datarate used by the node
*/
#define US915_DEFAULT_DATARATE DR_0
/*!
* Minimal Rx1 receive datarate offset
*/
#define US915_MIN_RX1_DR_OFFSET 0
/*!
* Maximal Rx1 receive datarate offset
*/
#define US915_MAX_RX1_DR_OFFSET 3
/*!
* Default Rx1 receive datarate offset
*/
#define US915_DEFAULT_RX1_DR_OFFSET 0
/*!
* Minimal Tx output power that can be used by the node
*/
#define US915_MIN_TX_POWER TX_POWER_10
/*!
* Maximal Tx output power that can be used by the node
*/
#define US915_MAX_TX_POWER TX_POWER_0
/*!
* Default Tx output power used by the node
*/
#define US915_DEFAULT_TX_POWER TX_POWER_0
/*!
* Default Max ERP
*/
#define US915_DEFAULT_MAX_ERP 30.0f
/*!
* ADR Ack limit
*/
#define US915_ADR_ACK_LIMIT 64
/*!
* ADR Ack delay
*/
#define US915_ADR_ACK_DELAY 32
/*!
* Enabled or disabled the duty cycle
*/
#define US915_DUTY_CYCLE_ENABLED 0
/*!
* Maximum RX window duration
*/
#define US915_MAX_RX_WINDOW 3000
/*!
* Receive delay 1
*/
#define US915_RECEIVE_DELAY1 1000
/*!
* Receive delay 2
*/
#define US915_RECEIVE_DELAY2 2000
/*!
* Join accept delay 1
*/
#define US915_JOIN_ACCEPT_DELAY1 5000
/*!
* Join accept delay 2
*/
#define US915_JOIN_ACCEPT_DELAY2 6000
/*!
* Maximum frame counter gap
*/
#define US915_MAX_FCNT_GAP 16384
/*!
* Ack timeout
*/
#define US915_ACKTIMEOUT 2000
/*!
* Random ack timeout limits
*/
#define US915_ACK_TIMEOUT_RND 1000
/*!
* Second reception window channel frequency definition.
*/
#define US915_RX_WND_2_FREQ 923300000
/*!
* Second reception window channel datarate definition.
*/
#define US915_RX_WND_2_DR DR_8
/*!
* LoRaMac maximum number of bands
*/
#define US915_MAX_NB_BANDS 1
/*!
* Band 0 definition
* { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
*/
#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
*/
#define US915_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )
/*!
* Defines the last channel for RX window 1 for US band
*/
#define US915_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )
/*!
* Defines the step width of the channels for RX window 1
*/
#define US915_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )
/*!
* Data rates table definition
*/
static const uint8_t DataratesUS915[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
/*!
* Bandwidths table definition in Hz
*/
static const uint32_t BandwidthsUS915[] = { 125000, 125000, 125000, 125000, 500000, 0, 0, 0, 500000, 500000, 500000, 500000, 500000, 500000, 0, 0 };
/*!
* Up/Down link data rates offset definition
*/
static const int8_t DatarateOffsetsUS915[5][4] =
{
{ DR_10, DR_9 , DR_8 , DR_8 }, // DR_0
{ DR_11, DR_10, DR_9 , DR_8 }, // DR_1
{ DR_12, DR_11, DR_10, DR_9 }, // DR_2
{ DR_13, DR_12, DR_11, DR_10 }, // DR_3
{ DR_13, DR_13, DR_12, DR_11 }, // DR_4
};
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateUS915[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
static const uint8_t MaxPayloadOfDatarateRepeaterUS915[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
/*!
* \brief The function gets a value of a specific phy attribute.
*
* \param [IN] getPhy Pointer to the function parameters.
*
* \retval Returns a structure containing the PHY parameter.
*/
PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy );
/*!
* \brief Updates the last TX done parameters of the current channel.
*
* \param [IN] txDone Pointer to the function parameters.
*/
void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone );
/*!
* \brief Initializes the channels masks and the channels.
*
* \param [IN] type Sets the initialization type.
*/
void RegionUS915InitDefaults( InitType_t type );
/*!
* \brief Verifies a parameter.
*
* \param [IN] verify Pointer to the function parameters.
*
* \param [IN] type Sets the initialization type.
*
* \retval Returns true, if the parameter is valid.
*/
bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
/*!
* \brief The function parses the input buffer and sets up the channels of the
* CF list.
*
* \param [IN] applyCFList Pointer to the function parameters.
*/
void RegionUS915ApplyCFList( ApplyCFListParams_t* applyCFList );
/*!
* \brief Sets a channels mask.
*
* \param [IN] chanMaskSet Pointer to the function parameters.
*
* \retval Returns true, if the channels mask could be set.
*/
bool RegionUS915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
/*!
* \brief Calculates the next datarate to set, when ADR is on or off.
*
* \param [IN] adrNext Pointer to the function parameters.
*
* \param [OUT] drOut The calculated datarate for the next TX.
*
* \param [OUT] txPowOut The TX power for the next TX.
*
* \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
*
* \retval Returns true, if an ADR request should be performed.
*/
bool RegionUS915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
/*!
* Computes the Rx window timeout and offset.
*
* \param [IN] datarate Rx window datarate index to be used
*
* \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
*
* \param [IN] rxError System maximum timing error of the receiver. In milliseconds
* The receiver will turn on in a [-rxError : +rxError] ms
* interval around RxOffset
*
* \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
*/
void RegionUS915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
/*!
* \brief Configuration of the RX windows.
*
* \param [IN] rxConfig Pointer to the function parameters.
*
* \param [OUT] datarate The datarate index which was set.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
/*!
* \brief TX configuration.
*
* \param [IN] txConfig Pointer to the function parameters.
*
* \param [OUT] txPower The tx power index which was set.
*
* \param [OUT] txTimeOnAir The time-on-air of the frame.
*
* \retval Returns true, if the configuration was applied successfully.
*/
bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
/*!
* \brief The function processes a Link ADR Request.
*
* \param [IN] linkAdrReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
/*!
* \brief The function processes a RX Parameter Setup Request.
*
* \param [IN] rxParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
/*!
* \brief The function processes a Channel Request.
*
* \param [IN] newChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915NewChannelReq( NewChannelReqParams_t* newChannelReq );
/*!
* \brief The function processes a TX ParamSetup Request.
*
* \param [IN] txParamSetupReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
* Returns -1, if the functionality is not implemented. In this case, the end node
* shall not process the command.
*/
int8_t RegionUS915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
/*!
* \brief The function processes a DlChannel Request.
*
* \param [IN] dlChannelReq Pointer to the function parameters.
*
* \retval Returns the status of the operation, according to the LoRaMAC specification.
*/
uint8_t RegionUS915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
* \param [IN] alternateDr Pointer to the function parameters.
*
* \retval Datarate to apply.
*/
int8_t RegionUS915AlternateDr( AlternateDrParams_t* alternateDr );
/*!
* \brief Calculates the back-off time.
*
* \param [IN] calcBackOff Pointer to the function parameters.
*/
void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff );
/*!
* \brief Searches and set the next random available channel
*
* \param [OUT] channel Next channel to use for TX.
*
* \param [OUT] time Time to wait for the next transmission according to the duty
* cycle.
*
* \param [OUT] aggregatedTimeOff Updates the aggregated time off.
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
bool RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
*
* \param [IN] channelAdd Pointer to the function parameters.
*
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionUS915ChannelAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
*
* \param [IN] channelRemove Pointer to the function parameters.
*
* \retval Returns true, if the channel was removed successfully.
*/
bool RegionUS915ChannelsRemove( ChannelRemoveParams_t* channelRemove );
/*!
* \brief Sets the radio into continuous wave mode.
*
* \param [IN] continuousWave Pointer to the function parameters.
*/
void RegionUS915SetContinuousWave( ContinuousWaveParams_t* continuousWave );
/*!
* \brief Computes new datarate according to the given offset
*
* \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
*
* \param [IN] dr Current datarate
*
* \param [IN] drOffset Offset to be applied
*
* \retval newDr Computed datarate.
*/
uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
/*! \} defgroup REGIONUS915 */
#endif // __REGION_US915_H__

@ -0,0 +1,86 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Timer objects and scheduling management
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file timer.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief wrapper to timer server
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIMER_H__
#define __TIMER_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "timeServer.h"
/* Exported types ------------------------------------------------------------*/
/*!
* \brief Timer object description
*/
#ifdef __cplusplus
}
#endif
#endif /* __TIMER_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,350 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Generic radio driver definition
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
#ifndef __RADIO_H__
#define __RADIO_H__
/*!
* Radio driver supported modems
*/
typedef enum
{
MODEM_FSK = 0,
MODEM_LORA,
}RadioModems_t;
/*!
* Radio driver internal state machine states definition
*/
typedef enum
{
RF_IDLE = 0, //!< The radio is idle
RF_RX_RUNNING, //!< The radio is in reception state
RF_TX_RUNNING, //!< The radio is in transmission state
RF_CAD, //!< The radio is doing channel activity detection
}RadioState_t;
/*!
* \brief Radio driver callback functions
*/
typedef struct
{
/*!
* \brief Tx Done callback prototype.
*/
void ( *TxDone )( void );
/*!
* \brief Tx Timeout callback prototype.
*/
void ( *TxTimeout )( void );
/*!
* \brief Rx Done callback prototype.
*
* \param [IN] payload Received buffer pointer
* \param [IN] size Received buffer size
* \param [IN] rssi RSSI value computed while receiving the frame [dBm]
* \param [IN] snr Raw SNR value given by the radio hardware
* FSK : N/A ( set to 0 )
* LoRa: SNR value in dB
*/
void ( *RxDone )( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
/*!
* \brief Rx Timeout callback prototype.
*/
void ( *RxTimeout )( void );
/*!
* \brief Rx Error callback prototype.
*/
void ( *RxError )( void );
/*!
* \brief FHSS Change Channel callback prototype.
*
* \param [IN] currentChannel Index number of the current channel
*/
void ( *FhssChangeChannel )( uint8_t currentChannel );
/*!
* \brief CAD Done callback prototype.
*
* \param [IN] channelDetected Channel Activity detected during the CAD
*/
void ( *CadDone ) ( bool channelActivityDetected );
}RadioEvents_t;
/*!
* \brief Radio driver definition
*/
struct Radio_s
{
/*!
* \brief Initializes the io
*/
void ( *IoInit )( void );
/*!
* \brief Deinitializes the io
*/
void ( *IoDeInit )( void );
/*!
* \brief Initializes the radio
*
* \param [IN] events Structure containing the driver callback functions
* \param [OUT] returns radioWakeUpTime
*/
uint32_t ( *Init )( RadioEvents_t *events );
/*!
* Return current radio status
*
* \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING]
*/
RadioState_t ( *GetStatus )( void );
/*!
* \brief Configures the radio with the given modem
*
* \param [IN] modem Modem to be used [0: FSK, 1: LoRa]
*/
void ( *SetModem )( RadioModems_t modem );
/*!
* \brief Sets the channel frequency
*
* \param [IN] freq Channel RF frequency
*/
void ( *SetChannel )( uint32_t freq );
/*!
* \brief Checks if the channel is free for the given time
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] freq Channel RF frequency
* \param [IN] rssiThresh RSSI threshold
* \param [IN] maxCarrierSenseTime Max time while the RSSI is measured
*
* \retval isFree [true: Channel is free, false: Channel is not free]
*/
bool ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime );
/*!
* \brief Generates a 32 bits random value based on the RSSI readings
*
* \remark This function sets the radio in LoRa modem mode and disables
* all interrupts.
* After calling this function either Radio.SetRxConfig or
* Radio.SetTxConfig functions must be called.
*
* \retval randomValue 32 bits random value
*/
uint32_t ( *Random )( void );
/*!
* \brief Sets the reception parameters
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] bandwidth Sets the bandwidth
* FSK : >= 2600 and <= 250000 Hz
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only)
* FSK : >= 2600 and <= 250000 Hz
* LoRa: N/A ( set to 0 )
* \param [IN] preambleLen Sets the Preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] symbTimeout Sets the RxSingle timeout value
* FSK : timeout in number of bytes
* LoRa: timeout in symbols
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] payloadLen Sets payload length when fixed length is used
* \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
* \param [IN] freqHopOn Enables disables the intra-packet frequency hopping
* FSK : N/A ( set to 0 )
* LoRa: [0: OFF, 1: ON]
* \param [IN] hopPeriod Number of symbols between each hop
* FSK : N/A ( set to 0 )
* LoRa: Number of symbols
* \param [IN] iqInverted Inverts IQ signals (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [0: not inverted, 1: inverted]
* \param [IN] rxContinuous Sets the reception in continuous mode
* [false: single mode, true: continuous mode]
*/
void ( *SetRxConfig )( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint32_t bandwidthAfc, uint16_t preambleLen,
uint16_t symbTimeout, bool fixLen,
uint8_t payloadLen,
bool crcOn, bool freqHopOn, uint8_t hopPeriod,
bool iqInverted, bool rxContinuous );
/*!
* \brief Sets the transmission parameters
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] power Sets the output power [dBm]
* \param [IN] fdev Sets the frequency deviation (FSK only)
* FSK : [Hz]
* LoRa: 0
* \param [IN] bandwidth Sets the bandwidth (LoRa only)
* FSK : 0
* LoRa: [0: 125 kHz, 1: 250 kHz,
* 2: 500 kHz, 3: Reserved]
* \param [IN] datarate Sets the Datarate
* FSK : 600..300000 bits/s
* LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
* 10: 1024, 11: 2048, 12: 4096 chips]
* \param [IN] coderate Sets the coding rate (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
* \param [IN] preambleLen Sets the preamble length
* FSK : Number of bytes
* LoRa: Length in symbols (the hardware adds 4 more symbols)
* \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
* \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON]
* \param [IN] freqHopOn Enables disables the intra-packet frequency hopping
* FSK : N/A ( set to 0 )
* LoRa: [0: OFF, 1: ON]
* \param [IN] hopPeriod Number of symbols between each hop
* FSK : N/A ( set to 0 )
* LoRa: Number of symbols
* \param [IN] iqInverted Inverts IQ signals (LoRa only)
* FSK : N/A ( set to 0 )
* LoRa: [0: not inverted, 1: inverted]
* \param [IN] timeout Transmission timeout [ms]
*/
void ( *SetTxConfig )( RadioModems_t modem, int8_t power, uint32_t fdev,
uint32_t bandwidth, uint32_t datarate,
uint8_t coderate, uint16_t preambleLen,
bool fixLen, bool crcOn, bool freqHopOn,
uint8_t hopPeriod, bool iqInverted, uint32_t timeout );
/*!
* \brief Checks if the given RF frequency is supported by the hardware
*
* \param [IN] frequency RF frequency to be checked
* \retval isSupported [true: supported, false: unsupported]
*/
bool ( *CheckRfFrequency )( uint32_t frequency );
/*!
* \brief Computes the packet time on air in ms for the given payload
*
* \Remark Can only be called once SetRxConfig or SetTxConfig have been called
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] pktLen Packet payload length
*
* \retval airTime Computed airTime (ms) for the given packet payload length
*/
uint32_t ( *TimeOnAir )( RadioModems_t modem, uint8_t pktLen );
/*!
* \brief Sends the buffer of size. Prepares the packet to be sent and sets
* the radio in transmission
*
* \param [IN]: buffer Buffer pointer
* \param [IN]: size Buffer size
*/
void ( *Send )( uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the radio in sleep mode
*/
void ( *Sleep )( void );
/*!
* \brief Sets the radio in standby mode
*/
void ( *Standby )( void );
/*!
* \brief Sets the radio in reception mode for the given time
* \param [IN] timeout Reception timeout [ms]
* [0: continuous, others timeout]
*/
void ( *Rx )( uint32_t timeout );
/*!
* \brief Start a Channel Activity Detection
*/
void ( *StartCad )( void );
/*!
* \brief Sets the radio in continuous wave transmission mode
*
* \param [IN]: freq Channel RF frequency
* \param [IN]: power Sets the output power [dBm]
* \param [IN]: time Transmission mode timeout [s]
*/
void ( *SetTxContinuousWave )( uint32_t freq, int8_t power, uint16_t time );
/*!
* \brief Reads the current RSSI value
*
* \retval rssiValue Current RSSI value in [dBm]
*/
int16_t ( *Rssi )( RadioModems_t modem );
/*!
* \brief Writes the radio register at the specified address
*
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
void ( *Write )( uint8_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
*
* \param [IN]: addr Register address
* \retval data Register value
*/
uint8_t ( *Read )( uint8_t addr );
/*!
* \brief Writes multiple radio registers starting at address
*
* \param [IN] addr First Radio register address
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
void ( *WriteBuffer )( uint8_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
*
* \param [IN] addr First Radio register address
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
void ( *ReadBuffer )( uint8_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
*
* \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
* \param [IN] max Maximum payload length in bytes
*/
void ( *SetMaxPayloadLength )( RadioModems_t modem, uint8_t max );
/*!
* \brief Sets the network to public or private. Updates the sync byte.
*
* \remark Applies to LoRa modem only
*
* \param [IN] enable if true, it enables a public network
*/
void ( *SetPublicNetwork )( bool enable );
/*!
* \brief Service to get the radio wake-up time.
*
* \retval Value of the radio wake-up time.
*/
uint32_t ( *GetRadioWakeUpTime ) ( void );
};
/*!
* \brief Radio driver
*
* \remark This variable is defined and initialized in the specific radio
* board implementation
*/
extern const struct Radio_s Radio;
#endif // __RADIO_H__

@ -0,0 +1,77 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Delay functions implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file delay.c
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief Delay function
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "hw.h"
#include "timeServer.h"
void DelayMs( uint32_t ms )
{
HW_RTC_DelayMs( ms );
}
void Delay( float s )
{
DelayMs( (uint32_t) (s * 1000.0f) );
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,29 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Delay functions implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
#ifndef __DELAY_H__
#define __DELAY_H__
/*!
* Blocking delay of "s" seconds
*/
void Delay( float s );
/*!
* Blocking delay of "ms" milliseconds
*/
void DelayMs( uint32_t ms );
#endif // __DELAY_H__

@ -0,0 +1,149 @@
/*******************************************************************************
* @file low_power.c
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief driver for low power
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "hw.h"
#include "low_power.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/**
* \brief Flag to indicate if MCU can go to low power mode
* When 0, MCU is authorized to go in low power mode
*/
static uint32_t LowPower_State = 0;
/* Private function prototypes -----------------------------------------------*/
/* Exported functions ---------------------------------------------------------*/
/**
* \brief API to set flag allowing power mode
*
* \param [IN] enum e_LOW_POWER_State_Id_t
*/
void LowPower_Disable( e_LOW_POWER_State_Id_t state )
{
BACKUP_PRIMASK();
DISABLE_IRQ( );
LowPower_State |= state;
RESTORE_PRIMASK( );
}
/**
* \brief API to reset flag allowing power mode
*
* \param [IN] enum e_LOW_POWER_State_Id_t
*/
void LowPower_Enable( e_LOW_POWER_State_Id_t state )
{
BACKUP_PRIMASK();
DISABLE_IRQ( );
LowPower_State &= ~state;
RESTORE_PRIMASK( );
}
/**
* \brief API to get flag allowing power mode
* \note When flag is 0, low power mode is allowed
* \param [IN] state
* \retval flag state
*/
uint32_t LowPower_GetState( void )
{
return LowPower_State;
}
/**
* @brief Handle Low Power
* @param None
* @retval None
*/
void LowPower_Handler( void )
{
DBG_GPIO_RST(GPIOB, GPIO_PIN_15);
DBG_GPIO_RST(GPIOB, GPIO_PIN_14);
if ( LowPower_State == 0 )
{
DBG_PRINTF_CRITICAL("dz\n\r");
HW_EnterStopMode( );
/* mcu dependent. to be implemented by user*/
HW_ExitStopMode();
DBG_GPIO_SET(GPIOB, GPIO_PIN_15);
HW_RTC_setMcuWakeUpTime( );
}
else
{
DBG_PRINTF_CRITICAL("z\n\r");
HW_EnterSleepMode( );
DBG_GPIO_SET(GPIOB, GPIO_PIN_14);
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,98 @@
/******************************************************************************
* @file low_power.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief Header for driver low_power.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __LOW_POWER_H__
#define __LOW_POWER_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* @brief API to set flag allowing power mode
*
* @param [IN] enum e_LOW_POWER_State_Id_t
*/
void LowPower_Disable( e_LOW_POWER_State_Id_t state );
/*!
* @brief API to reset flag allowing power mode
*
* @param [IN] enum e_LOW_POWER_State_Id_t
*/
void LowPower_Enable( e_LOW_POWER_State_Id_t state );
/*!
* @brief API to get flag allowing power mode
* @note When flag is 0, low power mode is allowed
* @param [IN] non
* @retval flag state
*/
uint32_t LowPower_GetState( void );
/*!
* @brief Manages the entry into ARM cortex deep-sleep mode
* @param none
* @retval none
*/
void LowPower_Handler( void );
#ifdef __cplusplus
}
#endif
#endif /* __LOW_POWER_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,406 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Generic lora driver implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis, Gregory Cristian and Wael Guibene
*/
/******************************************************************************
* @file timeserver.c
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief Time server infrastructure
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <time.h>
#include "hw.h"
#include "timeServer.h"
//#include "low_power.h"
/*!
* safely execute call back
*/
#define exec_cb( _callback_ ) \
do { \
if( _callback_ == NULL ) \
{ \
while(1); \
} \
else \
{ \
_callback_( ); \
} \
} while(0);
/*!
* Timers list head pointer
*/
static TimerEvent_t *TimerListHead = NULL;
/*!
* \brief Adds or replace the head timer of the list.
*
* \remark The list is automatically sorted. The list head always contains the
* next timer to expire.
*
* \param [IN] obj Timer object to be become the new head
* \param [IN] remainingTime Remaining time of the previous head to be replaced
*/
static void TimerInsertNewHeadTimer( TimerEvent_t *obj );
/*!
* \brief Adds a timer to the list.
*
* \remark The list is automatically sorted. The list head always contains the
* next timer to expire.
*
* \param [IN] obj Timer object to be added to the list
* \param [IN] remainingTime Remaining time of the running head after which the object may be added
*/
static void TimerInsertTimer( TimerEvent_t *obj );
/*!
* \brief Sets a timeout with the duration "timestamp"
*
* \param [IN] timestamp Delay duration
*/
static void TimerSetTimeout( TimerEvent_t *obj );
/*!
* \brief Check if the Object to be added is not already in the list
*
* \param [IN] timestamp Delay duration
* \retval true (the object is already in the list) or false
*/
static bool TimerExists( TimerEvent_t *obj );
void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) )
{
obj->Timestamp = 0;
obj->ReloadValue = 0;
obj->IsRunning = false;
obj->Callback = callback;
obj->Next = NULL;
}
void TimerStart( TimerEvent_t *obj )
{
uint32_t elapsedTime = 0;
BACKUP_PRIMASK();
DISABLE_IRQ( );
if( ( obj == NULL ) || ( TimerExists( obj ) == true ) )
{
RESTORE_PRIMASK( );
return;
}
obj->Timestamp = obj->ReloadValue;
obj->IsRunning = false;
if( TimerListHead == NULL )
{
HW_RTC_SetTimerContext( );
TimerInsertNewHeadTimer( obj ); // insert a timeout at now+obj->Timestamp
}
else
{
elapsedTime = HW_RTC_GetTimerElapsedTime( );
obj->Timestamp += elapsedTime;
if( obj->Timestamp < TimerListHead->Timestamp )
{
TimerInsertNewHeadTimer( obj);
}
else
{
TimerInsertTimer( obj);
}
}
RESTORE_PRIMASK( );
}
static void TimerInsertTimer( TimerEvent_t *obj)
{
TimerEvent_t* cur = TimerListHead;
TimerEvent_t* next = TimerListHead->Next;
while (cur->Next != NULL )
{
if( obj->Timestamp > next->Timestamp )
{
cur = next;
next = next->Next;
}
else
{
cur->Next = obj;
obj->Next = next;
return;
}
}
cur->Next = obj;
obj->Next = NULL;
}
static void TimerInsertNewHeadTimer( TimerEvent_t *obj )
{
TimerEvent_t* cur = TimerListHead;
if( cur != NULL )
{
cur->IsRunning = false;
}
obj->Next = cur;
TimerListHead = obj;
TimerSetTimeout( TimerListHead );
}
void TimerIrqHandler( void )
{
TimerEvent_t* cur;
TimerEvent_t* next;
uint32_t old = HW_RTC_GetTimerContext( );
uint32_t now = HW_RTC_SetTimerContext( );
uint32_t DeltaContext = now - old; //intentionnal wrap around
/* update timeStamp based upon new Time Reference*/
/* beacuse delta context should never exceed 2^32*/
if ( TimerListHead != NULL )
{
for (cur=TimerListHead; cur->Next != NULL; cur= cur->Next)
{
next =cur->Next;
if (next->Timestamp > DeltaContext)
{
next->Timestamp -= DeltaContext;
}
else
{
next->Timestamp = 0 ;
}
}
}
/* execute imediately the alarm callback */
if ( TimerListHead != NULL )
{
cur = TimerListHead;
TimerListHead = TimerListHead->Next;
exec_cb( cur->Callback );
}
// remove all the expired object from the list
while( ( TimerListHead != NULL ) && ( TimerListHead->Timestamp < HW_RTC_GetTimerElapsedTime( ) ))
{
cur = TimerListHead;
TimerListHead = TimerListHead->Next;
exec_cb( cur->Callback );
}
/* start the next TimerListHead if it exists AND NOT running */
if(( TimerListHead != NULL ) && (TimerListHead->IsRunning == false))
{
TimerSetTimeout( TimerListHead );
}
}
void TimerStop( TimerEvent_t *obj )
{
BACKUP_PRIMASK();
DISABLE_IRQ( );
TimerEvent_t* prev = TimerListHead;
TimerEvent_t* cur = TimerListHead;
// List is empty or the Obj to stop does not exist
if( ( TimerListHead == NULL ) || ( obj == NULL ) )
{
RESTORE_PRIMASK( );
return;
}
if( TimerListHead == obj ) // Stop the Head
{
if( TimerListHead->IsRunning == true ) // The head is already running
{
if( TimerListHead->Next != NULL )
{
TimerListHead->IsRunning = false;
TimerListHead = TimerListHead->Next;
TimerSetTimeout( TimerListHead );
}
else
{
HW_RTC_StopAlarm( );
TimerListHead = NULL;
}
}
else // Stop the head before it is started
{
if( TimerListHead->Next != NULL )
{
TimerListHead = TimerListHead->Next;
}
else
{
TimerListHead = NULL;
}
}
}
else // Stop an object within the list
{
while( cur != NULL )
{
if( cur == obj )
{
if( cur->Next != NULL )
{
cur = cur->Next;
prev->Next = cur;
}
else
{
cur = NULL;
prev->Next = cur;
}
break;
}
else
{
prev = cur;
cur = cur->Next;
}
}
}
RESTORE_PRIMASK( );
}
static bool TimerExists( TimerEvent_t *obj )
{
TimerEvent_t* cur = TimerListHead;
while( cur != NULL )
{
if( cur == obj )
{
return true;
}
cur = cur->Next;
}
return false;
}
void TimerReset( TimerEvent_t *obj )
{
TimerStop( obj );
TimerStart( obj );
}
void TimerSetValue( TimerEvent_t *obj, uint32_t value )
{
uint32_t minValue = 0;
uint32_t ticks = HW_RTC_ms2Tick( value );
TimerStop( obj );
minValue = HW_RTC_GetMinimumTimeout( );
if( ticks < minValue )
{
ticks = minValue;
}
obj->Timestamp = ticks;
obj->ReloadValue = ticks;
}
TimerTime_t TimerGetCurrentTime( void )
{
uint32_t now = HW_RTC_GetTimerValue( );
return HW_RTC_Tick2ms(now);
}
TimerTime_t TimerGetElapsedTime( TimerTime_t past )
{
uint32_t nowInTicks = HW_RTC_GetTimerValue( );
uint32_t pastInTicks = HW_RTC_ms2Tick( past );
/* intentional wrap around. Works Ok if tick duation below 1ms */
return HW_RTC_Tick2ms( nowInTicks- pastInTicks );
}
static void TimerSetTimeout( TimerEvent_t *obj )
{
int32_t minTicks= HW_RTC_GetMinimumTimeout( );
obj->IsRunning = true;
//in case deadline too soon
if(obj->Timestamp < (HW_RTC_GetTimerElapsedTime( ) + minTicks) )
{
obj->Timestamp = HW_RTC_GetTimerElapsedTime( ) + minTicks;
}
HW_RTC_SetAlarm( obj->Timestamp );
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,164 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Timer objects and scheduling management
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file timeServer.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief is the timer server driver
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIMESERVER_H__
#define __TIMESERVER_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "utilities.h"
/* Exported types ------------------------------------------------------------*/
/*!
* \brief Timer object description
*/
typedef struct TimerEvent_s
{
uint32_t Timestamp; //! Expiring timer value in ticks from TimerContext
uint32_t ReloadValue; //! Reload Value when Timer is restarted
bool IsRunning; //! Is the timer currently running
void ( *Callback )( void ); //! Timer IRQ callback function
struct TimerEvent_s *Next; //! Pointer to the next Timer object.
} TimerEvent_t;
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/*!
* \brief Initializes the timer object
*
* \remark TimerSetValue function must be called before starting the timer.
* this function initializes timestamp and reload value at 0.
*
* \param [IN] obj Structure containing the timer object parameters
* \param [IN] callback Function callback called at the end of the timeout
*/
void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) );
/*!
* \brief Timer IRQ event handler
*
* \note Head Timer Object is automaitcally removed from the List
*
* \note e.g. it is snot needded to stop it
*/
void TimerIrqHandler( void );
/*!
* \brief Starts and adds the timer object to the list of timer events
*
* \param [IN] obj Structure containing the timer object parameters
*/
void TimerStart( TimerEvent_t *obj );
/*!
* \brief Stops and removes the timer object from the list of timer events
*
* \param [IN] obj Structure containing the timer object parameters
*/
void TimerStop( TimerEvent_t *obj );
/*!
* \brief Resets the timer object
*
* \param [IN] obj Structure containing the timer object parameters
*/
void TimerReset( TimerEvent_t *obj );
/*!
* \brief Set timer new timeout value
*
* \param [IN] obj Structure containing the timer object parameters
* \param [IN] value New timer timeout value
*/
void TimerSetValue( TimerEvent_t *obj, uint32_t value );
/*!
* \brief Read the current time
*
* \retval returns current time in ms
*/
TimerTime_t TimerGetCurrentTime( void );
/*!
* \brief Return the Time elapsed since a fix moment in Time
*
* \param [IN] savedTime fix moment in Time
* \retval time returns elapsed time in ms
*/
TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime );
#ifdef __cplusplus
}
#endif
#endif /* __TIMESERVER_H__*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@ -0,0 +1,85 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Helper functions implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "utilities.h"
/*!
* Redefinition of rand() and srand() standard C functions.
* These functions are redefined in order to get the same behavior across
* different compiler toolchains implementations.
*/
// Standard random functions redefinition start
#define RAND_LOCAL_MAX 2147483647L
static uint32_t next = 1;
int32_t rand1( void )
{
return ( ( next = next * 1103515245L + 12345L ) % RAND_LOCAL_MAX );
}
void srand1( uint32_t seed )
{
next = seed;
}
// Standard random functions redefinition end
int32_t randr( int32_t min, int32_t max )
{
return ( int32_t )rand1( ) % ( max - min + 1 ) + min;
}
void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size )
{
while( size-- )
{
*dst++ = *src++;
}
}
void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size )
{
dst = dst + ( size - 1 );
while( size-- )
{
*dst-- = *src++;
}
}
void memset1( uint8_t *dst, uint8_t value, uint16_t size )
{
while( size-- )
{
*dst++ = value;
}
}
int8_t Nibble2HexChar( uint8_t a )
{
if( a < 10 )
{
return '0' + a;
}
else if( a < 16 )
{
return 'A' + ( a - 10 );
}
else
{
return '?';
}
}

@ -0,0 +1,175 @@
/*
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
Description: Helper functions implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
*/
/******************************************************************************
* @file utilities.h
* @author MCD Application Team
* @version V1.1.2
* @date 08-September-2017
* @brief Header for driver utilities.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#ifndef __UTILITIES_H__
#define __UTILITIES_H__
#include "hw_conf.h"
/* BACKUP_PRIMASK MUST be implemented at the begining of the funtion
that implement a critical section
PRIMASK is saved on STACK and recovered at the end of the funtion
That way RESTORE_PRIMASK ensures that no irq would be triggered in case of
unbalanced enable/disable, reentrant code etc...*/
#define BACKUP_PRIMASK() uint32_t primask_bit= __get_PRIMASK()
#define DISABLE_IRQ() __disable_irq()
#define ENABLE_IRQ() __enable_irq()
#define RESTORE_PRIMASK() __set_PRIMASK(primask_bit)
/* prepocessor directive to align buffer*/
#define ALIGN(n) __attribute__((aligned(n)))
typedef uint32_t TimerTime_t;
/*!
* \brief Returns the minimum value between a and b
*
* \param [IN] a 1st value
* \param [IN] b 2nd value
* \retval minValue Minimum value
*/
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
/*!
* \brief Returns the maximum value between a and b
*
* \param [IN] a 1st value
* \param [IN] b 2nd value
* \retval maxValue Maximum value
*/
#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
/*!
* \brief Returns 2 raised to the power of n
*
* \param [IN] n power value
* \retval result of raising 2 to the power n
*/
#define POW2( n ) ( 1 << n )
/*!
* \brief Find First Set
* This function identifies the least significant index or position of the
* bits set to one in the word
*
* \param [in] value Value to find least significant index
* \retval bitIndex Index of least significat bit at one
*/
__STATIC_INLINE uint8_t __ffs( uint32_t value )
{
return( uint32_t )( 32 - __CLZ( value & ( -value ) ) );
}
/*!
* \brief Initializes the pseudo random generator initial value
*
* \param [IN] seed Pseudo random generator initial value
*/
void srand1( uint32_t seed );
/*!
* \brief Computes a random number between min and max
*
* \param [IN] min range minimum value
* \param [IN] max range maximum value
* \retval random random value in range min..max
*/
int32_t randr( int32_t min, int32_t max );
/*!
* \brief Copies size elements of src array to dst array
*
* \remark STM32 Standard memcpy function only works on pointers that are aligned
*
* \param [OUT] dst Destination array
* \param [IN] src Source array
* \param [IN] size Number of bytes to be copied
*/
void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size );
/*!
* \brief Copies size elements of src array to dst array reversing the byte order
*
* \param [OUT] dst Destination array
* \param [IN] src Source array
* \param [IN] size Number of bytes to be copied
*/
void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size );
/*!
* \brief Set size elements of dst array with value
*
* \remark STM32 Standard memset function only works on pointers that are aligned
*
* \param [OUT] dst Destination array
* \param [IN] value Default value
* \param [IN] size Number of bytes to be copied
*/
void memset1( uint8_t *dst, uint8_t value, uint16_t size );
/*!
* \brief Converts a nibble to an hexadecimal character
*
* \param [IN] a Nibble to be converted
* \retval hexChar Converted hexadecimal character
*/
int8_t Nibble2HexChar( uint8_t a );
#endif // __UTILITIES_H__

@ -0,0 +1,750 @@
/ _____) _ | |
( (____ _____ ____ _| |_ _____ ____| |__
\____ \| ___ | (_ _) ___ |/ ___) _ \
_____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
(C)2013 Semtech
LoRaWAN endpoint stack implementation and example projects.
=====================================
1. Introduction
----------------
The aim of this project is to show an example of the endpoint LoRaWAN stack implementation.
This LoRaWAN stack implements all regions defined in "LoRaWAN Regional Parameters v1.0.2rB" document. Class A and Class C endpoint implementation
is fully compatible with "LoRaWAN specification 1.0.2".
Each LoRaWAN application example includes the LoRaWAN certification protocol implementation.
SX1272/76 radio drivers are also provided.
In case only point to point links are required a Ping-Pong application is provided as example.
*The LoRaWAN stack API documentation can be found at: http://stackforce.github.io/LoRaMac-doc/*
**Note 1:**
*A port of this project can be found on [MBED Semtech Team page](http://developer.mbed.org/teams/Semtech/)*
*The example projects are:*
1. [LoRaWAN-demo-72](http://developer.mbed.org/teams/Semtech/code/LoRaWAN-demo-72/)
2. [LoRaWAN-demo-76](http://developer.mbed.org/teams/Semtech/code/LoRaWAN-demo-76/)
2. System schematic and definitions
------------------------------------
The available supported hardware platforms schematics can be found in the Doc directory.
3. Acknowledgments
-------------------
The mbed (https://mbed.org/) project was used at the beginning as source of
inspiration.
This program uses the AES algorithm implementation (http://www.gladman.me.uk/)
by Brian Gladman.
This program uses the CMAC algorithm implementation
(http://www.cse.chalmers.se/research/group/dcs/masters/contikisec/) by
Lander Casado, Philippas Tsigas.
4. Dependencies
----------------
This program depends on specific hardware platforms. Currently the supported
platforms are:
- LoRaMote
MCU : STM32L151CB - 128K FLASH, 10K RAM, Timers, SPI, I2C,
USART,
USB 2.0 full-speed device/host/OTG controller,
DAC, ADC, DMA
RADIO : SX1272
ANTENNA : Printed circuit antenna
BUTTONS : No
LEDS : 3
SENSORS : Proximity, Magnetic, 3 axis Accelerometer, Pressure,
Temperature
GPS : Yes, UP501 module
EXTENSION HEADER : Yes, 20 pins
REMARK : The MCU and Radio are on an IMST iM880A module
- MoteII
MCU : STM32L051C8 - 64K FLASH, 8K RAM, Timers, SPI, I2C,
USART,
USB 2.0 full-speed device/host/OTG controller (Not used),
DAC, ADC, DMA
RADIO : SX1272
ANTENNA : Printed circuit antenna
BUTTONS : 3
LEDS : 3
SENSORS : Magnetic, 3 axis Accelerometer, Pressure,
Temperature
GPS : Yes, PAM7Q module
Display : OLED
ST-Link : Yes, MBED like
EXTENSION HEADER : Yes, 20 pins
REMARK : The MCU and Radio are on an IMST iM881A module
- NAMote72
MCU : STM32L152RC - 256K FLASH, 32K RAM, Timers, SPI, I2C,
USART,
USB 2.0 full-speed device/host/OTG controller (Not used),
DAC, ADC, DMA
RADIO : SX1272
ANTENNA : Printed circuit antenna
BUTTONS : No
LEDS : 4
SENSORS : Magnetic, 3 axis Accelerometer, Pressure,
Temperature
GPS : Yes, SIM39EA module
Display : OLED
ST-Link : Yes, MBED like
EXTENSION HEADER : Yes, Arduino connectors
REMARK : None
- SensorNode
MCU : STM32L151CBU6 - 128K FLASH, 16K RAM, Timers, SPI, I2C,
USART,
USB 2.0 full-speed device/host/OTG controller,
DAC, ADC, DMA
RADIO : SX1276
ANTENNA : Printed circuit antenna
BUTTONS : Power ON/OFF, General purpose button
LEDS : 3
SENSORS : Proximity, Magnetic, 3 axis Accelerometer, Pressure,
Temperature
GPS : Yes, SIM39EA module
EXTENSION No
REMARK : The MCU and Radio are on an NYMTEK Cherry-LCC module
- SK-iM880A ( IMST starter kit )
MCU : STM32L151CB - 128K FLASH, 10K RAM, Timers, SPI, I2C,
USART,
USB 2.0 full-speed device/host/OTG controller,
DAC, ADC, DMA
RADIO : SX1272
ANTENNA : Connector for external antenna
BUTTONS : 1 Reset, 3 buttons + 2 DIP-Switch
LEDS : 3
SENSORS : Potentiometer
GPS : Possible through pin header GPS module connection
SDCARD : No
EXTENSION HEADER : Yes, all IMST iM880A module pins
REMARK : None
5. Usage
---------
Projects for CooCox-CoIDE and Keil Integrated Development Environments are available.
One project is available per application and for each hardware platform in each
development environment. Different targets/configurations have been created in
the different projects in order to select different options such as the usage or
not of a bootloader and the radio frequency band to be used.
6. Changelog
-------------
2017-09-08, V4.4.0
* General
1. First release based on "LoRaWAN specification 1.0.2" and "LoRaWAN Regional Parameters v1.0.2rB"
2. This version has passed the LoRa-Alliance compliance tests for the regions shown in the below table.
3. GitHub reported issues corrections.
4. Updated radio driver to perform the LBT carrier sense continuously for a given period of time.
* LoRaWAN
1. GitHub reported issues corrections.
2. Updated implementation to support 1.0.2 specification additions.
3. Added the support for all "LoRaWAN Regional Parameters v1.0.2rB" document defined regions.
**LoRaWAN certification results**
| Region | Verdict | # Test houses | Comments |
| ------------- |:-------------:|:-------------:|:--------------|
| EU868 | <font color='green'>PASS</font> | 2 | - |
| US915 | <font color='green'>PASS</font> | 2 | - |
| CN779 | <font color='orange'>Partial PASS</font> | 1 | No certification specification - tests based on EU868 certification - All tests PASS except 1. Join Accept Rx2 parameters not being applied (under investigation) |
| EU433 | <font color='green'>PASS</font> | 1 | No certification specification - tests based on EU868 certification |
| AU915 | <font color='orange'>Not tested yet</font> | 0 | No certification specification |
| CN470 | <font color='orange'>Not tested yet</font> | 0 | No certification specification |
| AS923 | <font color='green'>PASS</font> | 2 | - |
| KR920 | <font color='green'>PASS</font> | 1 | As of today only one test house has sent a report. We decided to perform the release anyway |
| IN865 | <font color='orange'>PASS</font> | 1 | No certification specification - tests based on EU868 certification |
2017-04-19, V4.3.2
* General (Last release based on LoRaWAN specification 1.0.1)
1. This version has passed EU868 and US915 LoRa-Alliance compliance tests.
2. GitHub reported issues corrections.
3. Added an algorithm to automatically compute the Rx windows parameters. (Window symbolTimeout and Offset from downlink expected time)
4. Added a workaround to reset the radio in case a TxTimeout occurs.
5. Modified FSK modem handling to use the provided symbolTimeout (1 symbol equals 1 byte) when in RxSingle mode.
6. Added newly defined TxCw(Tx Continuous Wave) certification protocol command.
7. Added a fix for an overflow issue that could happen with NmeaStringSize variable.
8. Improved GpioMcuInit function to first configure the output pin state before activating the pin.
* LoRaWAN
1. GitHub reported issues corrections.
2. Changed the AdrAckCounter handling as expected by the test houses.
3. Fix an issue where the node stopped transmitting.
4. Removed useless LoRaMacPayload buffer.
5. MAC layer indications handling simplification.
6. Relocate parameter settings from ResetMacParameters to the initialization.
2017-02-27, V4.3.1
* General
1. This version has passed EU868 and US915 LoRa-Alliance compliance tests.
2. Update the MAC layer in order to be LoRaWAN version 1.0.1 compliant (Mainly US915 bug fixes)
3. Removed api-v3 support from the project.
4. GitHub reported issues corrections.
5. Updated SensorNode projects according to the new MCU reference STM32L151CBU6. Bigger memories.
6. Addition of MoteII platform based on the IMST module iM881A (STM32L051C8)
7. Addition of NAMote72 platform
8. Correct compliance test protocol command 0x06 behaviour
9. Added TxCw (Tx continuous wave) LoRaWAN compliance protocol command.
10. Added TxContinuousWave support to the radio drivers.
11. Updated ST HAL drivers.
- STM32L1xx_HAL-Driver : V1.2.0
- STM32L0xx_HAL_Driver : V1.7.0
* LoRaWAN
1. US band corrections in order to pass the LoRaWAN certification.
2. GitHub reported issues corrections.
3. Add region CN470 support.
2016-06-22, V4.3.0
* General
1. This version has passed all LoRa-Alliance compliance tests.
2. Update the MAC layer in order to be LoRaWAN version 1.0.1 compliant
3. Applied to all application files the certification protocol change for LoRaWAN 1.0.1 compliance tests.
**REMARK**: api-v3 application files aren't updated.
4. Add radio RX_TIMEOUT irq clear into the irq handler.
5. Removed the end less loop from HAL_UART_ErrorCallback.
6. Update of the STM32L0 HAL to version 1.6.0
7. Consolidated the line endings across all project files.
Windows line endings has been choose for almost every file.
* LoRaWAN
1. Updated maximum payload size for US band.
2. Update datarate offset table for US band.
3. Make MAC commands sticky
4. Add retransmission back-off
5. Remove the TxPower limitation for US band on LoRaMacMibSetRequestConfirm function. The power will be limited anyway when the SendFrameOnChannel functions is called.
6. Issue(#81): Bug fix in function LoRaMacMlmeRequest case MLME_JOIN. Function will return LORAMAC_STATUS_BUSY in case the MAC is in status MAC_TX_DELAYED.
7. Add debug pin support to LoRaMote platform.
8. Updated and improved MPL3115 device driver.
9. Issue(#83): Bug fix in parameter validation
10. Issue(#84): Fix issue of CalibrateTimer function.
11. RTC driver major update
12. Applied pull request #87.
13. Add a function to verify the RX frequency of window 2 for US band.
14. Issue(#88): Bug fix in function PrepareFrame where repeated MAC commands were not handled correctly.
15. Bug fix in OnRadioRxDone. Node now drops frames on port 0 with fOpts > 0.
16. Bug fix in OnRadioRxDone. Node now receives frames with fOpts > 0 when no payload is present.
2016-05-13, V4.2.0
* General
1. This version has passed all LoRa-Alliance compliance tests.
2. Update STM32L1xx_HAL_Driver version to 1.5. Update related drivers and implementations accordingly.
**REMARK**: This change implies that the time base had to be changed from microseconds to milliseconds.
3. Corrected the frequency check condition for // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
4. Optimize radio drivers regarding FSK PER
5. Resolve issue when calling SX127xInit function more than once
6. Add a definition for the LoRaWAN device address. Add an IEEE_OUI for the LoRaWAN device EUI.
7. Add a definition for the default datarate.
8. Issue(#66) correction of functions SX1276SetOpMode and SX1272SetOpMode.
9. Issue(#68): Fix for low level RF switch control.
10. Increase RTC tick frequency for higher resolution.
11. Update the radio wake up time.
* LoRaWAN
1. Issue(#56) correction
2. Update channel mask handling for US915 hybrid mode to support any block in the channel mask.
3. Issue(#63) correct the maximum payload length in RX mode.
4. Fix Tx power setting loss for repeated join requests on US band.
5. Introduce individual MIN and MAX datarates for RX and TX.
6. Add the possibility to set and get the ChannelsDefaultDatarate.
7. Optimization of the RX symbol timeout.
8. Issue(#59): Add the possibility to set the uplink and downlink counter.
9. Replace definition LORAMAC_DEFAULT_DATARATE by ChannelsDefaultDatarate in LoRaMacChannelAdd.
10. Issue(#72): Fix of possible array overrun in LoRaMacChannelRemove.
11. Introduce a new status MAC_RX_ABORT. Reset MAC_TX_RUNNING only in OnMacStateCheckTimerEvent.
12. Accept MAC information of duplicated, confirmed downlinks.
13. Issue(#74): Drop frames with a downlink counter difference greater or equal to MAX_FCNT_GAP.
2016-03-10, V4.1.0
* General
1. This version has passed all mandatory LoRa-Alliance compliance tests.
*One of the optional tests is unsuccessful (FSK downlinks PER on Rx1 and Rx2 windows) and is currently under investigation.*
2. Removed support for Raisonance Ride7 IDE (Reduces the amount of work to be done at each new release)
3. Removed the Bleeper-72 and Bleeper-76 platforms support as these are now deprecated.
4. Application state machine. Relocate setting sleep state and update the duty cycle in compliance test mode.
5. Bug fix in TimerIrqHandler. Now, it is possible to insert timers in callback.
6. Changed TimerHwDelayMs function to be re-entrant.
7. Corrected FSK modem packets bigger than 64 bytes handling (Issue #36)
* LoRaWAN
1. Rename attribute nbRetries to NbTrials in structure McpsReqConfirmed_t. (Issue #37)
2. Updated implementation of SetNextChannel. Added enabling default channels in case of join request. (Issue #39)
3. Add missing documentation about MIB_REPEATER_SUPPORT. (Issue #42).
4. Add a new LoRaMacState to allow adding channels during TX procedure. (Issue #43)
5. Relocate the activation of LoRaMacFlags.Bits.McpsInd in OnRadioRxDone.
6. Add a new function PrepareRxDoneAbort to prepare a break-out of OnRadioRxDone in case of an error
7. Activate default channels in case all others are disabled. (Issue #39)
8. Bug fix in setting the default channel in case none is enabled.
9. SRV_MAC_NEW_CHANNEL_REQ MAC command added a fix to the macIndex variable on US915 band.
10. Start the MacStateCheckTimer in OnRxDone and related error cases with a short interval to handle events promptly. (Issue #44)
11. Reset status of NodeAckRequested if we received an ACK or in case of timeout.
12. Removed additional EU868 channels from the LoRaWAN implementation files. GitHub (Issue #49)
The creation of these additional channels has been moved to the application example.
13. Improved and corrected AdrNextDr function.
2015-12-18, V4.0.0
* General
1. STACKFORCE new API integration
2. Reverse the EUIs arrays in the MAC layer.
3. LoRaWAN certification protocol implementation
4. All reported issues and Pull requests have been addressed.
2015-10-06, V3.4.1
* General
1. Bug fixes
* LoRaWAN
1. Corrected downlink counter roll over management when several downlinks were missed.
2. Corrected the Radio maximum payload length management. Radio was filtering received frames with a length bigger than the transmitted one.
3. Applied Pull request #22 solution proposition.
2015-10-30, V3.4.0
* General
1. Changed all applications in order to have preprocessing definitions on top of the files and added relevant comments
2. Applications LED control is no more done into the timer callback functions but instead on the main while loop.
3. Added TimerStop function calls to each timer event callback.
4. Corrected timings comments. Timing values are most of the time us based.
5. Changed types names for stdint.h names. Helps on code portability
6. Renamed rand and srand to rand1 and srand1. Helps on code portability
7. Added some missing variables casts. Helps on code portability
8. Removed NULL definition from board.h
9. Added const variable attribute when necessary to functions prototypes
10. Moved ID1, ID2 and ID3 definition from board.h to board.c, usb-cdc-board.c and usb-dfu-board.c
11. Removed the definition of RAND_SEED. It has been replaced by a function named BoardGetRandomSeed
12. Renamed BoardMeasureBatterieLevel to BoardGetBatteryLevel
13. Added SetMaxPayloadLength API function to SX1272 and SX1276 radio drivers
14. Changed the name of Radio API Status function to GetStatus
15. AES/CMAC Changed types names for stdint.h names. Helps on code portability (Issue #20)
16. Moved __ffs function from utilities.h to spi-board.c. This function is only used there.
17. Utilities.c removed fputc function redefinition.
18. Replaced the usage of __IO attribute by volatile.
* LoRaWAN
1. Added support for the US915 band (Normal mode and hybrid mode. Hybrid mode is a temporary configuration up until servers support it automatically) (Issue #16)
2. Corrected and simplified the downlink sequence counter management.
3. Removed the usage of PACKED attribute for data structures.
4. Renamed LoRaMacEvent_t into LoRaMacCallbacks_t and added a function pointer for getting battery level status
5. Renamed LoRaMacSetDutyCycleOn into LoRaMacSetTestDutyCycleOn
6. Renamed LoRaMacSetMicTest into LoRaMacTestSetMic
7. Increased the PHY buffer size to 250
8. Removed IsChannelFree check on LoRaMacSetNextChannel function. LoRaWAN is an ALHOA protocol. (Pull request #8)
9. LoRaMacEventInfo.TxDatarate now returns LoRaWAN datarate (DR0 -> DR7) instead of (SF12 -> DF7)
10. Corrected channel mask management for EU868 band.
11. Corrected LoRaMacPrepareFrame behavior function when no applicative payload is present.
12. LoRaMac-board.h now implements the settings for the PHY layers specified by LoRaWAN 1.0 specification. ( EU433, CN780, EU868, US915 ) (Issue #19)
13. Added LORAMAC_MIN_RX1_DR_OFFSET and LORAMAC_MAX_RX1_DR_OFFSET definitions to LoRaMac-board.h. Can be different upon used PHY layer
14. Added the limitation of output power according to the number of enabled channels for US915 band.
15. Added the limitation of the applicative payload length according to the datarate. Does not yet take in account the MAC commands buffer. (Issue #15)
16. Corrected MacCommandBufferIndex management. (Issue #18)
2015-08-07, v3.3.0
* General
1. Added the support for LoRaWAN Class C devices.
2. Implemented the radios errata note workarounds. SX1276 errata 2.3 "Receiver Spurious Reception of a LoRa Signal" is not yet implemented.
3. Increased FSK SyncWord timeout value in order to listen for longer time if a down link is available or not. Makes FSK downlink more reliable.
4. Increased the UART USB FIFO buffer size in order to handle bigger chunks of data.
* LoRaWAN
1. Renamed data rates as per LoRaWAN specification.
2. Added the support for LoRaWAN Class C devices.
3. Handling of the MAC commands was done incorrectly the condition to verify the length of the buffer has changed from < to <=.
4. Added the possibility to change the channel mask and number of repetitions trough SRV_MAC_LINK_ADR_REQ command when ADR is disabled.
5. Corrected Rx1DrOffset management. In previous version DR1 was missing for all offsets.
6. Changed confirmed messages function to use default datarate when ADR control is off.
7. After a Join accept the node falls back to the default datarate. Enables the user to Join a network using a different datarate from its own default one.
8. Corrected default FSK channel frequency.
9. Solved a firmware freezing when one of the following situations arrived in OnRxDone callback: bad address, bad MIC, bad frame. (Pull request #10)
10. Moved the MAC commands processing to the right places. FOpts field before the Payload and Port 0 just after the decryption. (Pull request #9)
11. Weird conditions to check datarate on cmd mac SRV_MAC_NEW_CHANNEL_REQ (Pull request #7)
12. Ignore join accept message if already joined (Pull request #6)
13. Channel index verification should use OR on SRV_MAC_NEW_CHANNEL_REQ command (Pull request #5)
14. Corrected the CFList management on JoinAccept. The for loop indexes were wrong. (Pull request #4)
15. Correction of AES key size (Pull request #3)
2015-04-30, v3.2.0
* General
1. Updated LoRaMac implementation according to LoRaWAN R1.0 specification
2. General cosmetics corrections
3. Added the support of packed structures when using IAR tool chain
4. Timers: Added a function to get the time in us.
5. Timers: Added a typedef for time variables (TimerTime_t)
6. Radios: Changed the TimeOnAir radio function to return a uint32_t value instead of a double. The value is in us.
7. Radios: Corrected the 250 kHz bandwidth choice for the FSK modem
8. GPS: Added a function that returns if the GPS has a fix or not.
9. GPS: Changed the GetPosition functions to return a latitude and longitude of 0 and altitude of 65535 when no GPS fix.
* LoRaWAN
1. Removed support for previous LoRaMac/LoRaWAN specifications
2. Added missing MAC commands and updated others when necessary
* Corrected the Port 0 MAC commands decryption
* Changed the way the upper layer is notified. Now it is only notified
when all the operations are finished.
When a ClassA Tx cycle starts a timer is launched to check every second if everything is finished.
* Added a new parameter to LoRaMacEventFlags structure that indicates on which Rx window the data has been received.
* Added a new parameter to LoRaMacEventFlags structure that indicates if there is applicative data on the received payload.
* Corrected ADR MAC command behavior
* DutyCycle enforcement implementation (EU868 PHY only)
**REMARK 1** *The regulatory duty cycle enforcement is enabled by default
which means that for lower data rates the node may not transmit a new
frame as quickly as requested.
The formula used to compute the node idle time is*
*Toff = TimeOnAir / DutyCycle - TxTimeOnAir*
*Example:*
*A device just transmitted a 0.5 s long frame on one default channel.
This channel is in a sub-band allowing 1% duty-cycle. Therefore this
whole sub-band (868 MHz - 868.6 MHz) will be unavailable for 49.5 s.*
**REMARK 2** *The duty cycle enforcement can be disabled for test
purposes by calling the LoRaMacSetDutyCycleOn function with false
parameter.*
* Implemented aggregated duty cycle management
* Added a function to create new channels
* Implemented the missing features on the JoinAccept MAC command
* Updated LoRaMacJoinDecrypt function to handle the CFList field.
3. Due to duty cycle management the applicative API has changed.
All applications must be updated accordingly.
4. Added the possibility to chose to use either public or private networks
2015-01-30, v3.1.0
* General
1. Started to add support for CooCox CoIDE Integrated Development Environment.
Currently only LoRaMote and SensorNode platform projects are available.
2. Updated GCC compiler linker scripts.
3. Added the support of different tool chains for the HardFault_Handler function.
4. Corrected Radio drivers I&Q signals inversion to be possible in Rx and in Tx.
Added some missing radio state machine initialization.
5. Changed the RSSI values type from int8_t to int16_t. We can have RSSI values below -128 dBm.
6. Corrected SNR computation on RxDone interrupt.
7. Updated radio API to support FHSS and CAD handling.
8. Corrected in SetRxConfig function the FSK modem preamble register name.
9. Added an invalid bandwidth to the Bandwidths table in order to avoid an error
when selecting 250 kHz bandwidth when using FSK modem.
10. Corrected RTC alarm setup which could be set to an invalid date.
11. Added another timer in order increment the tick counter without blocking the normal timer count.
12. Added the possibility to switch between low power timers and normal timers on the fly.
13. I2C driver corrected the 2 bytes internal address management.
Corrected buffer read function when more that 1 byte was to be read.
Added a function to wait for the I2C bus to become IDLE.
14. Added an I2C EEPROM driver.
15. Corrected and improved USB Virtual COM Port management files.
Corrected the USB CDC and USB UART drivers.
16. Added the possibility to analyze a hard fault interrupt.
* LoRaMac
1. Corrected RxWindow2 Datarate management.
2. SrvAckRequested variable was never reset.
3. Corrected tstIndoor applications for LoRaMac R3.0 support.
4. LoRaMac added the possibility to configure almost all the MAC parameters.
5. Corrected the LoRaMacSetNextChannel function.
6. Corrected the port 0 MAC command decoding.
7. Changed all structures declarations to be packed.
8. Corrected the Acknowledgment retries management when only 1 trial is needed.
Before the device was issuing at least 2 trials.
9. Corrected server mac new channel req answer.
10. Added the functions to read the Up and Down Link sequence counters.
11. Corrected SRV_MAC_RX2_SETUP_REQ frequency handling. Added a 100 multiplication.
12. Corrected SRV_MAC_NEW_CHANNEL_REQ. Removed the DutyCycle parameter decoding.
13. Automatically activate the channel once it is created.
14. Corrected NbRepTimeoutTimer initial value. RxWindow2Delay already contains RxWindow1Delay in it.
2014-07-18, v3.0.0
* General
1. Added to Radio API the possibility to select the modem.
2. Corrected RSSI reading formulas as well as changed the RSSI and SNR values from double to int8_t type.
3. Changed radio callbacks events to timeout when it is a timeout event and error when it is a CRC error.
4. Radio API updated.
5. Updated ping-pong applications.
6. Updated tx-cw applications.
7. Updated LoRaMac applications in order to handle LoRaMac returned functions calls status.
8. Updated LoRaMac applications to toggle LED2 each time there is an application payload down link.
9. Updated tstIndoor application to handle correctly more than 6 channels.
10. Changed the MPL3115 altitude variable from unsigned to signed value.
11. Replaced the usage of pow(2, n) by defining POW2 functions. Saves ~2 KBytes of code.
12. Corrected an issue potentially arriving when LOW_POWER_MODE_ENABLE wasn't defined.
A timer interrupt could be generated while the TimerList could already be emptied.
* LoRaMac
1. Implemented LoRaMac specification R3.0 changes.
2. MAC commands implemented
* LinkCheckReq **YES**
* LinkCheckAns **YES**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DutyCycleReq **YES**
* DutyCycleAns **YES**
* Rx2SetupReq **YES**
* Rx2SetupAns **YES**
* DevStatusReq **YES**
* DevStatusAns **YES**
* JoinReq **YES**
* JoinAccept **YES**
* NewChannelReq **YES**
* NewChannelAns **YES**
3. Features implemented
* Possibility to shut-down the device **YES**
Possible by issuing DutyCycleReq MAC command.
* Duty cycle management enforcement **NO**
* Acknowledgments retries **YES**
* Unconfirmed messages retries **YES**
2014-07-10, v2.3.RC2
* General
1. Corrected all radios antenna switch low power mode handling.
2. SX1276: Corrected antenna switch control.
2014-06-06, v2.3.RC1
* General
1. Added the support for SX1276 radio.
2. Radio continuous reception mode correction.
3. Radio driver RxDone callback function API has changed ( size parameter is no more a pointer).
Previous function prototype:
void ( *RxDone )( uint8_t *payload, uint16_t *size, double rssi, double snr, uint8_t rawSnr );
New function prototype:
void ( *RxDone )( uint8_t *payload, uint16_t size, double rssi, double snr, uint8_t rawSnr );
4. Added Bleeper-76 and SensorNode platforms support.
5. Added to the radio drivers a function that generates a random value from
RSSI readings.
6. Added a project to transmit a continuous wave and a project to measure the
the radio sensitivity.
7. Added a bootloader project for the LoRaMote and SensorNode platforms.
8. The LoRaMac application for Bleeper platforms now sends the Selector and LED status plus the sensors values.
* The application payload for the Bleeper platforms is as follows:
LoRaMac port 1:
{ 0xX0/0xX1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
---------- ---------- ---------- ---------- ----
| | | | |
SELECTOR/LED PRESSURE TEMPERATURE ALTITUDE BATTERY
MSB nibble = SELECTOR (barometric)
LSB bit = LED
9. Redefined rand() and srand() standard C functions. These functions are
redefined in order to get the same behavior across different compiler
tool chains implementations.
10. GPS driver improvements. Made independent of the board platform.
11. Simplified the RTC management.
12. Added a function to the timer driver that checks if a timer is already in
the list or not.
13. Added the UART Overrun bit exception handling to the UART driver.
14. Removed dependency of spi-board files to the "__builtin_ffs" function.
This function is only available on GNU compiler tool suite. Removed --gnu
compiler option from Keil projects. Added own __ffs function
implementation to utilities.h file.
15. Removed obsolete class1 devices support.
16. Known bugs correction.
* LoRaMac
1. MAC commands implemented
* LinkCheckReq **YES**
* LinkCheckAns **YES**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DutyCycleReq **YES** (LoRaMac specification R2.2.1)
* DutyCycleAns **YES** (LoRaMac specification R2.2.1)
* Rx2SetupReq **YES** (LoRaMac specification R2.2.1)
* Rx2SetupAns **YES** (LoRaMac specification R2.2.1)
* DevStatusReq **YES**
* DevStatusAns **YES**
* JoinReq **YES**
* JoinAccept **YES** (LoRaMac specification R2.2.1)
* NewChannelReq **YES** (LoRaMac specification R2.2.1)
* NewChannelAns **YES** (LoRaMac specification R2.2.1)
2. Features implemented
* Possibility to shut-down the device **YES**
Possible by issuing DutyCycleReq MAC command.
* Duty cycle management enforcement **NO**
* Acknowledgments retries **WORK IN PROGRESS**
Not fully debugged. Disabled by default.
* Unconfirmed messages retries **WORK IN PROGRESS** (LoRaMac specification R2.2.1)
3. Implemented LoRaMac specification R2.2.1 changes.
4. Due to new specification the LoRaMacInitNwkIds LoRaMac API function had
to be modified.
Previous function prototype:
void LoRaMacInitNwkIds( uint32_t devAddr, uint8_t *nwkSKey, uint8_t *appSKey );
New function prototype:
void LoRaMacInitNwkIds( uint32_t netID, uint32_t devAddr, uint8_t *nwkSKey, uint8_t *appSKey );
5. Changed the LoRaMac channels management.
6. LoRaMac channels definition has been moved to LoRaMac-board.h file
located in each specific board directory.
2014-04-07, v2.2.0
* General
1. Added IMST SK-iM880A starter kit board support to the project.
* The application payload for the SK-iM880A platform is as follows:
LoRaMac port 3:
{ 0x00/0x01, 0x00, 0x00, 0x00 }
---------- ----- ----------
| | |
LED POTI VDD
2. Ping-Pong applications have been split per supported board.
3. Corrected the SX1272 output power management.
Added a variable to store the current Radio channel.
Added missing FSK bit definition.
4. Made fifo functions coding style coherent with the project.
5. UART driver is now independent of the used MCU
2014-03-28, v2.1.0
* General
1. The timers and RTC management has been rewritten.
2. Improved the UART and UP501 GPS drivers.
3. Corrected GPIO pin names management.
4. Corrected the antenna switch management in the SX1272 driver.
5. Added to the radio driver the possibility to choose the preamble length
and rxSingle symbol timeout in reception.
6. Added Hex coder selector driver for the Bleeper board.
7. Changed copyright Unicode character to (C) in all source files.
* LoRaMac
1. MAC commands implemented
* LinkCheckReq **YES**
* LinkCheckAns **YES**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DevStatusReq **YES**
* DevStatusAns **YES**
* JoinReq **YES**
* JoinAccept **YES**
2. Added acknowledgments retries management.
Split the LoRaMacSendOnChannel function in LoRaMacPrepareFrame and
LoRaMacSendFrameOnChannel. LoRaMacSendOnChannel now calls the 2 newly
defined functions.
**WARNING**: By default the acknowledgment retries specific code isn't
enabled. The current http://iot.semtech.com server version doesn't support
it.
3. Corrected issues on JoinRequest and JoinAccept MAC commands.
Added LORAMAC_EVENT_INFO_STATUS_MAC_ERROR event info status.
2014-02-21, v2.0.0
* General
1. The LoRaMac applications now sends the LED status plus the sensors values.
For the LoRaMote platform the application also sends the GPS coordinates.
* The application payload for the Bleeper platform is as follows:
LoRaMac port 1:
{ 0x00/0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
---------- ---------- ---------- ---------- ----
| | | | |
LED PRESSURE TEMPERATURE ALTITUDE BATTERY
(barometric)
* The application payload for the LoRaMote platform is as follows:
LoRaMac port 2:
{ 0x00/0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
---------- ---------- ---------- ---------- ---- ---------------- ---------------- ----------
| | | | | | | |
LED PRESSURE TEMPERATURE ALTITUDE BATTERY LATITUDE LONGITUDE ALTITUDE
(barometric) (gps)
2. Adapted applications to the new MAC layer API.
3. Added sensors drivers implementation.
4. Corrected new or known issues.
* LoRaMac
1. MAC commands implemented
* LinkCheckReq **YES**
* LinkCheckAns **YES**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DevStatusReq **YES**
* DevStatusAns **YES**
* JoinReq **YES (Not tested)**
* JoinAccept **YES (Not tested)**
2. New MAC layer application API implementation.
* Timers and RTC.
1. Still some issues. They will be corrected on next revisions of the firmware.
2014-01-24, v1.1.0
* LoRaMac
1. MAC commands implemented
* LinkCheckReq **NO**
* LinkCheckAns **NO**
* LinkADRReq **YES**
* LinkADRAns **YES**
* DevStatusReq **YES**
* DevStatusAns **YES**
2. Implemented an application LED control
If the server sends on port 1 an application payload of one byte with
the following contents:
0: LED off
1: LED on
The node transmits periodically on port 1 the LED status on 1st byte and
the message "Hello World!!!!" the array looks like:
{ 0, 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '!', '!', '!' }
* Timers and RTC.
1. Corrected issues existing in the previous version
2. Known bugs are:
* There is an issue when launching an asynchronous Timer. Will be solved
in a future version
2014-01-20, v1.1.RC1
* Added Doc directory. The directory contains:
1. LoRa MAC specification
2. Bleeper board schematic
* LoRaMac has been updated according to Release1 of the specification. Main changes are:
1. MAC API changed.
2. Frame format.
3. ClassA first ADR implementation.
4. MAC commands implemented
* LinkCheckReq **NO**
* LinkCheckAns **NO**
* LinkADRReq **YES**
* LinkADRAns **NO**
* DevStatusReq **NO**
* DevStatusAns **NO**
* Timers and RTC rewriting. Known bugs are:
1. The Radio wakeup time is taken in account for all timings.
2. When opening the second reception window the microcontroller sometimes doesn't enter in low power mode.
2013-11-28, v1.0.0
* Initial version of the LoRa MAC node firmware implementation.

@ -0,0 +1,182 @@
@verbatim
******************************************************************************
*
* Portions COPYRIGHT 2017 STMicroelectronics
*
* @file st_readme.txt
* @author MCD Application Team
* @brief This file lists the main modification done by STMicroelectronics on
* LoRa for integration with STM32Cube solution.
* For more details on LoRa implementation on STM32Cube, please refer
* to UM2073 "STM32 LORA01 software expansion for STM32Cube "
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
@endverbatim
### V1.1.2/08-September-2017 ###
===============================
+ Implements LoRa Mac 4.4.0 release from Semtech/StackForce
https://github.com/Lora-net/LoRaMac-node/tree/f42be67be402a40b3586724800771bfe13fb18e6
+ AckTimeoutRetriesCounter must be reset every time a new request (unconfirmed or confirmed) is performed.
+ Added verification for the power parameter in order to check that it is greater or equal to 0.
+ Enhancement for regions without FSK modulation support.
+ Bug fix for RX window 2 in class c mode.
+ AdrAckReq bit must be set to false as soon as we reach the lowest datarate.
+ MacCommandsBufferIndex must be reset when the mac commands are being sent on port 0.
+ Fixed RegionCommonSetBandTxDone in order to also update band->LastTxDoneTime when performing the Join procedure.
+ Added verification of payload size for Unconfirmed and Confirmed messages depending on Dwell time.
+ Added missing Rx1 timeout handling.
+ Updated all regions to use MAX output power by default.
+ Merge remote-tracking branch 'origin/develop' into develop
+ Bug fix in KR920 - update the maxEIRP calculation for continuous wave
+ Bug fix in IN865 - Update the band of the default channels
+ Bug fix in AS923 - for RX use always the payload limitation of dwell 0
+ Update function RegionCommonChanVerifyDr. Perform an 'AND' operation for security
+ Move the verification of ADR parameters into the common section. Update all regions with the related changes
+ Update comment for function RegionLinkAdrReq
+ Apply variables to data structure LinkAdrReqParams_t
+ Bug fix for KR920
+ Rename data structure LinkAdrParams_t
+ Issue(#238): Apply missing variable in sSetBandTxDoneParams
+ Bug fix in processing MAC commands for case SRV_MAC_TX_PARAM_SETUP_REQ.
+ Isse(#238): Apply missing variable in struct sBand
+ Update the MAC to enable the server to control the Channels Mask and the number of transmissions even ADR is off
+ Issue(#238): Update the backoff procedure for all regions. Move code parts into the common section
+ Update implementation to allow automatic MAC answers on port 0
+ Issue(#253): Delete all preconfigured channels when performing a join request
+ Initialize variable phyParam in functions RegionXXGetPhyParam
+ Remove assert_param from the radio drivers
+ Synchronize function RegionXXTxConfig
+ Update carrier sense functionality for LBT
+ Issue(#259): Update comment for variable HasLoopedThroughMain
+ Issue(#257): Fix typo in OnRxWindow2TimerEvent
+ Change scientific notation to numeric notation
+ Merge pull request #260 from clmklk/AU915
+ AU915: update Datarate limits according to LoRaWan 1.0.2rB
+ AU915: update Downstream datarate table according to LoRaWan 1.0.2rB
+ Merge pull request #225 from OpenChirp/patch_1
### V1.1.1/01-June-2017 ###
===============================
+ Implements LoRa Mac from Semtech/StackForce develop branch (30-May-2017 commits, 4.4.0 release candidate)
https://github.com/Lora-net/LoRaMac-node/tree/e2f35db75c1b449379d3b520c2d4e5922a9f5c81
+ Issue(235): Update functions RegionXXNextChannel.
+ Issue(238): Update initialization value of nextTxDelay.
+ Issue(234): Report back the aggregated time off.
+ Issue(232): Relocate function call to CalculateBackOff.
+ Issue(239): Update band TX power to the maximum.
+ Update LimitTxPower for US915.
+ Bug fix in function RegionCN470Verify.
+ Bug fix in function RegionAU915Verify.
+ Issue(229): Fix issue when receiving frames in second RX2 in Class C.
+ Add a ommand to get the next lower datarate.
+ Group initializations
+ Update regional definitions of KR920.
+ Update regional definitions of EU868.
+ Issue(239): Update regional definitions of AU915.
+ Update regional definitions of AU915.
+ Update regional definitions of AS923.
+ Update TX power computations.
+ Remove duplicated call to ApplyDrOffset in function RegionRxConfig.
+ Relocate the datarate, up- and downlink dwell time into a structure.
+ Change API of RegionGetPhyParam and the related functions.
+ Bug fix in function LoRaMacQueryTxPossible.
+ Apply patch for dwell time and minimum datarate.
+ Change the default datarate to DR_2 for AS923.
+ Take dwell time for ADR calculations and datarate settings into account.
+ Update LoRaMacQueryTxPossible to reset the MAC commands buffer.
+ Issue(#221): Add the dwell time in function ValidatePayloadLength.
+ Increase the transmission and reception timeout for KR920.
+ Bug fix in functions OnRxWindowXTimerEvent.
+ Remove datarate assignment.
+ Setup the downlink and uplink dwell time default value to 1.
+ Add frequency range check for AS923
+ Issue(#221): Bug fix in max payload size calculation.
+ GitHub reported issues corrections.
+ Changed the AdrAckCounter handling as expected by the test houses.
+ Fix an issue where the node stopped transmitting.
+ Removed useless LoRaMacPayload buffer.
+ MAC layer indications handling simplification.
+ Relocate parameter settings from ResetMacParameters to the initialization.
### V1.1.0/27-February-2017 ###
===============================
+ Implements LoRa Mac 4.4.0 from Semtech/StackForce from the develop branch
### V1.0.3/01-January-2017 ###
===============================
+ Read date between 2 successive read time to make sure date is ok
### V1.0.2/15-November-2016 ###
===============================
+ Corrected 1 bug in LoRaMac-board.h: RX_WND_2_CHANNEL for EU is now back at DR_0
+ Corrected 1 bug in LoRaMac.c for dataRate adaptation
### V1.0.1/15-September-2016 ###
===============================
+ Implements LoRa Mac 4.3.0 from Semtech/StackForce
### V1.0.0/01-July-2016 ###
===============================
+ First R1.0.0 customized version for STM32Cube solution.
+ Comissioning_template.h in /Conf contains all Lora Ids to connect on LoRa network
It is provided as a template. It must be moved to /Projects/inc/ as Comissioning.h
+ All files in Conf/src are provided as template and must be copied in /Projects/src.
+ All files in Conf/inc are provided as template and must be copied in /Projects/inc.
#if 0 and #endif must be removed to enable the template in the user directory
+ Implements LoRa Mac 4.2.0 from Semtech/StackForce
+ \Lora\Mac\LoRaMac.c : replace floating exponent e3 and e6 by int number
+ \Lora\Utilities\delay.c : cast uint32_t
+ Modified intensively timeServer.c
+ new low layer interfacing Cube HAL (hw_rtc.c, hw_gpio.c and hw_spi.c)
+ added lora.c as an interface layer to ease product integration
* <h3><center>&copy; COPYRIGHT STMicroelectronics</center></h3>
*/
Loading…
Cancel
Save