├── .cproject
├── .gitignore
├── .project
├── LICENSE
├── README.md
├── doc
├── LMiC-v1.5.pdf
├── README.txt
└── release-notes.txt
├── examples
├── beacon
│ └── main.c
├── hello
│ └── main.c
├── interrupt
│ ├── main.c
│ └── sensor.c
├── join
│ └── main.c
├── periodic
│ ├── main.c
│ └── sensor.c
├── ping
│ └── main.c
└── transmit
│ └── main.c
├── hal
├── debug.c
├── debug.h
└── hal.c
└── lmic
├── aes.c
├── hal.h
├── lmic.c
├── lmic.h
├── lorabase.h
├── oslmic.c
├── oslmic.h
└── radio.c
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows image file caches
2 | Thumbs.db
3 | ehthumbs.db
4 |
5 | # Folder config file
6 | Desktop.ini
7 |
8 | # Recycle Bin used on file shares
9 | $RECYCLE.BIN/
10 |
11 | # Windows Installer files
12 | *.cab
13 | *.msi
14 | *.msm
15 | *.msp
16 |
17 | # Windows shortcuts
18 | *.lnk
19 |
20 | # =========================
21 | # Operating System Files
22 | # =========================
23 |
24 | # OSX
25 | # =========================
26 |
27 | .DS_Store
28 | .AppleDouble
29 | .LSOverride
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | # Files that might appear on external disk
35 | .Spotlight-V100
36 | .Trashes
37 |
38 | # Directories potentially created on remote AFP share
39 | .AppleDB
40 | .AppleDesktop
41 | Network Trash Folder
42 | Temporary Items
43 | .apdisk
44 |
45 |
46 |
47 |
48 |
49 | # Compiled binaries
50 | *.bin
51 | *.elf
52 | *.hex
53 | *.map
54 |
55 | # Trash
56 | *.bak
57 |
58 | # IAR project "Debug" directory
59 | Debug/
60 |
61 | # IAR project "Release" directory
62 | Release/
63 |
64 | # IAR project settings directory
65 | settings/
66 |
67 | # IAR backup files
68 | Backup*
69 |
70 | # IAR .dep files
71 | *.dep
72 |
73 | Exe/
74 | List/
75 | Obj/
76 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | lmic
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 |
16 | org.eclipse.cdt.core.cnature
17 | com.silabs.ide.project.core.SLSProjectNature
18 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
19 |
20 |
21 |
22 | emlib/em_acmp.c
23 | 1
24 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_acmp.c
25 |
26 |
27 | emlib/em_adc.c
28 | 1
29 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_adc.c
30 |
31 |
32 | emlib/em_aes.c
33 | 1
34 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_aes.c
35 |
36 |
37 | emlib/em_assert.c
38 | 1
39 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_assert.c
40 |
41 |
42 | emlib/em_burtc.c
43 | 1
44 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_burtc.c
45 |
46 |
47 | emlib/em_cmu.c
48 | 1
49 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_cmu.c
50 |
51 |
52 | emlib/em_dac.c
53 | 1
54 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_dac.c
55 |
56 |
57 | emlib/em_dbg.c
58 | 1
59 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_dbg.c
60 |
61 |
62 | emlib/em_dma.c
63 | 1
64 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_dma.c
65 |
66 |
67 | emlib/em_ebi.c
68 | 1
69 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_ebi.c
70 |
71 |
72 | emlib/em_emu.c
73 | 1
74 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_emu.c
75 |
76 |
77 | emlib/em_gpio.c
78 | 1
79 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_gpio.c
80 |
81 |
82 | emlib/em_i2c.c
83 | 1
84 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_i2c.c
85 |
86 |
87 | emlib/em_idac.c
88 | 1
89 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_idac.c
90 |
91 |
92 | emlib/em_int.c
93 | 1
94 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_int.c
95 |
96 |
97 | emlib/em_lcd.c
98 | 1
99 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_lcd.c
100 |
101 |
102 | emlib/em_lesense.c
103 | 1
104 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_lesense.c
105 |
106 |
107 | emlib/em_letimer.c
108 | 1
109 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_letimer.c
110 |
111 |
112 | emlib/em_leuart.c
113 | 1
114 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_leuart.c
115 |
116 |
117 | emlib/em_mpu.c
118 | 1
119 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_mpu.c
120 |
121 |
122 | emlib/em_msc.c
123 | 1
124 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_msc.c
125 |
126 |
127 | emlib/em_opamp.c
128 | 1
129 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_opamp.c
130 |
131 |
132 | emlib/em_pcnt.c
133 | 1
134 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_pcnt.c
135 |
136 |
137 | emlib/em_prs.c
138 | 1
139 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_prs.c
140 |
141 |
142 | emlib/em_rmu.c
143 | 1
144 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_rmu.c
145 |
146 |
147 | emlib/em_rtc.c
148 | 1
149 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_rtc.c
150 |
151 |
152 | emlib/em_system.c
153 | 1
154 | STUDIO_SDK_LOC/emlib/src/em_system.c
155 |
156 |
157 | emlib/em_timer.c
158 | 1
159 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_timer.c
160 |
161 |
162 | emlib/em_usart.c
163 | 1
164 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_usart.c
165 |
166 |
167 | emlib/em_vcmp.c
168 | 1
169 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_vcmp.c
170 |
171 |
172 | emlib/em_wdog.c
173 | 1
174 | PARENT-5-PROJECT_LOC/SiliconLabs/SimplicityStudio/v3/developer/sdks/efm32/v2/emlib/src/em_wdog.c
175 |
176 |
177 | CMSIS/efm32g/startup_gcc_efm32g.s
178 | 1
179 | STUDIO_SDK_LOC/Device/SiliconLabs/EFM32G/Source/GCC/startup_efm32g.S
180 |
181 |
182 | CMSIS/efm32g/system_efm32g.c
183 | 1
184 | STUDIO_SDK_LOC/Device/SiliconLabs/EFM32G/Source/system_efm32g.c
185 |
186 |
187 |
188 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Eclipse Public License - v 1.0
2 |
3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6 |
7 | 1. DEFINITIONS
8 |
9 | "Contribution" means:
10 |
11 | a) in the case of the initial Contributor, the initial code and documentation
12 | distributed under this Agreement, and
13 | b) in the case of each subsequent Contributor:
14 | i) changes to the Program, and
15 | ii) additions to the Program;
16 |
17 | where such changes and/or additions to the Program originate from and are
18 | distributed by that particular Contributor. A Contribution 'originates'
19 | from a Contributor if it was added to the Program by such Contributor
20 | itself or anyone acting on such Contributor's behalf. Contributions do not
21 | include additions to the Program which: (i) are separate modules of
22 | software distributed in conjunction with the Program under their own
23 | license agreement, and (ii) are not derivative works of the Program.
24 |
25 | "Contributor" means any person or entity that distributes the Program.
26 |
27 | "Licensed Patents" mean patent claims licensable by a Contributor which are
28 | necessarily infringed by the use or sale of its Contribution alone or when
29 | combined with the Program.
30 |
31 | "Program" means the Contributions distributed in accordance with this
32 | Agreement.
33 |
34 | "Recipient" means anyone who receives the Program under this Agreement,
35 | including all Contributors.
36 |
37 | 2. GRANT OF RIGHTS
38 | a) Subject to the terms of this Agreement, each Contributor hereby grants
39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
40 | reproduce, prepare derivative works of, publicly display, publicly
41 | perform, distribute and sublicense the Contribution of such Contributor,
42 | if any, and such derivative works, in source code and object code form.
43 | b) Subject to the terms of this Agreement, each Contributor hereby grants
44 | Recipient a non-exclusive, worldwide, royalty-free patent license under
45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
46 | transfer the Contribution of such Contributor, if any, in source code and
47 | object code form. This patent license shall apply to the combination of
48 | the Contribution and the Program if, at the time the Contribution is
49 | added by the Contributor, such addition of the Contribution causes such
50 | combination to be covered by the Licensed Patents. The patent license
51 | shall not apply to any other combinations which include the Contribution.
52 | No hardware per se is licensed hereunder.
53 | c) Recipient understands that although each Contributor grants the licenses
54 | to its Contributions set forth herein, no assurances are provided by any
55 | Contributor that the Program does not infringe the patent or other
56 | intellectual property rights of any other entity. Each Contributor
57 | disclaims any liability to Recipient for claims brought by any other
58 | entity based on infringement of intellectual property rights or
59 | otherwise. As a condition to exercising the rights and licenses granted
60 | hereunder, each Recipient hereby assumes sole responsibility to secure
61 | any other intellectual property rights needed, if any. For example, if a
62 | third party patent license is required to allow Recipient to distribute
63 | the Program, it is Recipient's responsibility to acquire that license
64 | before distributing the Program.
65 | d) Each Contributor represents that to its knowledge it has sufficient
66 | copyright rights in its Contribution, if any, to grant the copyright
67 | license set forth in this Agreement.
68 |
69 | 3. REQUIREMENTS
70 |
71 | A Contributor may choose to distribute the Program in object code form under
72 | its own license agreement, provided that:
73 |
74 | a) it complies with the terms and conditions of this Agreement; and
75 | b) its license agreement:
76 | i) effectively disclaims on behalf of all Contributors all warranties
77 | and conditions, express and implied, including warranties or
78 | conditions of title and non-infringement, and implied warranties or
79 | conditions of merchantability and fitness for a particular purpose;
80 | ii) effectively excludes on behalf of all Contributors all liability for
81 | damages, including direct, indirect, special, incidental and
82 | consequential damages, such as lost profits;
83 | iii) states that any provisions which differ from this Agreement are
84 | offered by that Contributor alone and not by any other party; and
85 | iv) states that source code for the Program is available from such
86 | Contributor, and informs licensees how to obtain it in a reasonable
87 | manner on or through a medium customarily used for software exchange.
88 |
89 | When the Program is made available in source code form:
90 |
91 | a) it must be made available under this Agreement; and
92 | b) a copy of this Agreement must be included with each copy of the Program.
93 | Contributors may not remove or alter any copyright notices contained
94 | within the Program.
95 |
96 | Each Contributor must identify itself as the originator of its Contribution,
97 | if
98 | any, in a manner that reasonably allows subsequent Recipients to identify the
99 | originator of the Contribution.
100 |
101 | 4. COMMERCIAL DISTRIBUTION
102 |
103 | Commercial distributors of software may accept certain responsibilities with
104 | respect to end users, business partners and the like. While this license is
105 | intended to facilitate the commercial use of the Program, the Contributor who
106 | includes the Program in a commercial product offering should do so in a manner
107 | which does not create potential liability for other Contributors. Therefore,
108 | if a Contributor includes the Program in a commercial product offering, such
109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
110 | every other Contributor ("Indemnified Contributor") against any losses,
111 | damages and costs (collectively "Losses") arising from claims, lawsuits and
112 | other legal actions brought by a third party against the Indemnified
113 | Contributor to the extent caused by the acts or omissions of such Commercial
114 | Contributor in connection with its distribution of the Program in a commercial
115 | product offering. The obligations in this section do not apply to any claims
116 | or Losses relating to any actual or alleged intellectual property
117 | infringement. In order to qualify, an Indemnified Contributor must:
118 | a) promptly notify the Commercial Contributor in writing of such claim, and
119 | b) allow the Commercial Contributor to control, and cooperate with the
120 | Commercial Contributor in, the defense and any related settlement
121 | negotiations. The Indemnified Contributor may participate in any such claim at
122 | its own expense.
123 |
124 | For example, a Contributor might include the Program in a commercial product
125 | offering, Product X. That Contributor is then a Commercial Contributor. If
126 | that Commercial Contributor then makes performance claims, or offers
127 | warranties related to Product X, those performance claims and warranties are
128 | such Commercial Contributor's responsibility alone. Under this section, the
129 | Commercial Contributor would have to defend claims against the other
130 | Contributors related to those performance claims and warranties, and if a
131 | court requires any other Contributor to pay any damages as a result, the
132 | Commercial Contributor must pay those damages.
133 |
134 | 5. NO WARRANTY
135 |
136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
140 | Recipient is solely responsible for determining the appropriateness of using
141 | and distributing the Program and assumes all risks associated with its
142 | exercise of rights under this Agreement , including but not limited to the
143 | risks and costs of program errors, compliance with applicable laws, damage to
144 | or loss of data, programs or equipment, and unavailability or interruption of
145 | operations.
146 |
147 | 6. DISCLAIMER OF LIABILITY
148 |
149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
156 | OF SUCH DAMAGES.
157 |
158 | 7. GENERAL
159 |
160 | If any provision of this Agreement is invalid or unenforceable under
161 | applicable law, it shall not affect the validity or enforceability of the
162 | remainder of the terms of this Agreement, and without further action by the
163 | parties hereto, such provision shall be reformed to the minimum extent
164 | necessary to make such provision valid and enforceable.
165 |
166 | If Recipient institutes patent litigation against any entity (including a
167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
168 | (excluding combinations of the Program with other software or hardware)
169 | infringes such Recipient's patent(s), then such Recipient's rights granted
170 | under Section 2(b) shall terminate as of the date such litigation is filed.
171 |
172 | All Recipient's rights under this Agreement shall terminate if it fails to
173 | comply with any of the material terms or conditions of this Agreement and does
174 | not cure such failure in a reasonable period of time after becoming aware of
175 | such noncompliance. If all Recipient's rights under this Agreement terminate,
176 | Recipient agrees to cease use and distribution of the Program as soon as
177 | reasonably practicable. However, Recipient's obligations under this Agreement
178 | and any licenses granted by Recipient relating to the Program shall continue
179 | and survive.
180 |
181 | Everyone is permitted to copy and distribute copies of this Agreement, but in
182 | order to avoid inconsistency the Agreement is copyrighted and may only be
183 | modified in the following manner. The Agreement Steward reserves the right to
184 | publish new versions (including revisions) of this Agreement from time to
185 | time. No one other than the Agreement Steward has the right to modify this
186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The
187 | Eclipse Foundation may assign the responsibility to serve as the Agreement
188 | Steward to a suitable separate entity. Each new version of the Agreement will
189 | be given a distinguishing version number. The Program (including
190 | Contributions) may always be distributed subject to the version of the
191 | Agreement under which it was received. In addition, after a new version of the
192 | Agreement is published, Contributor may elect to distribute the Program
193 | (including its Contributions) under the new version. Except as expressly
194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
195 | licenses to the intellectual property of any Contributor under this Agreement,
196 | whether expressly, by implication, estoppel or otherwise. All rights in the
197 | Program not expressly granted under this Agreement are reserved.
198 |
199 | This Agreement is governed by the laws of the State of New York and the
200 | intellectual property laws of the United States of America. No party to this
201 | Agreement will bring a legal action under this Agreement more than one year
202 | after the cause of action arose. Each party waives its rights to a jury trial in
203 | any resulting litigation.
204 |
205 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Attention
2 | This is a port of the original lmic HAL for STM32 microcontroller to EFM32.
3 |
4 | Original IAR projects are also ported to Eclipse + GNU compiler.
5 |
6 | # lmic
7 | IBM “LoRa WAN in C” is the LoRa WAN implementation of choice, and a perfect match to the IBM LRSC on the end device. It is provided as open source under the Eclipse Public License (EPL).
8 | http://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html
9 |
--------------------------------------------------------------------------------
/doc/LMiC-v1.5.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mirakonta/lmic/cc9b4134379b056f03fe7629756e4c2adbe0453a/doc/LMiC-v1.5.pdf
--------------------------------------------------------------------------------
/doc/README.txt:
--------------------------------------------------------------------------------
1 | DISCLAIMER:
2 | Please note that the software is provided AS IS and we cannot
3 | provide support for optimizations, adaptations, integration,
4 | ports to other platforms or device drivers!
5 |
--------------------------------------------------------------------------------
/doc/release-notes.txt:
--------------------------------------------------------------------------------
1 | ==============================================================================
2 | LMIC VERSION 1.4 (17-Mar-2015)
3 | -------------------------------
4 |
5 | - changed API: inverted port indicator flag in LMIC.txrxFlags
6 | (now TXRX_PORT, previously TXRX_NOPORT)
7 |
8 | - fixed offset OFF_CFLIST constant
9 |
10 | - changed CRC-16 algorithm for beacons to CCITT(XMODEM) polynomial
11 |
12 | - fixed radio driver (low data rate optimization for SF11+SF12 only for BW125)
13 |
14 | - fixed timer rollover handling in job queue
15 |
16 | ==============================================================================
17 | LMIC VERSION 1.5 (8-May-2015)
18 | ------------------------------
19 |
20 | - fixed condition in convFreq()
21 |
22 | - fixed freq*100 bug and freq==0 bug for CFList
23 |
24 | - fixed TX scheduling bug
25 |
26 | - better support for GNU compiler toolchain
27 |
28 | ==============================================================================
29 |
--------------------------------------------------------------------------------
/examples/beacon/main.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "../../lmic/lmic.h"
13 | #include "../../hal/debug.h"
14 |
15 | //////////////////////////////////////////////////
16 | // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
17 | //////////////////////////////////////////////////
18 |
19 | // application router ID (LSBF)
20 | static const u1_t APPEUI[8] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xFF, 0xC0 };
21 |
22 | // unique device ID (LSBF)
23 | static const u1_t DEVEUI[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
24 |
25 | // device-specific AES key (derived from device EUI)
26 | static const u1_t DEVKEY[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
27 |
28 | static const u1_t nwkKey[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
29 |
30 | static const u1_t artKey[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
31 |
32 |
33 | //////////////////////////////////////////////////
34 | // APPLICATION CALLBACKS
35 | //////////////////////////////////////////////////
36 |
37 | // provide application router ID (8 bytes, LSBF)
38 | void os_getArtEui (u1_t* buf) {
39 | memcpy(buf, APPEUI, 8);
40 | }
41 |
42 | // provide device ID (8 bytes, LSBF)
43 | void os_getDevEui (u1_t* buf) {
44 | memcpy(buf, DEVEUI, 8);
45 | }
46 |
47 | // provide device key (16 bytes)
48 | void os_getDevKey (u1_t* buf) {
49 | memcpy(buf, DEVKEY, 16);
50 | }
51 |
52 |
53 | //////////////////////////////////////////////////
54 | // MAIN - INITIALIZATION AND STARTUP
55 | //////////////////////////////////////////////////
56 |
57 | // initial job
58 | static void initfunc (osjob_t* j) {
59 | // reset MAC state
60 | LMIC_reset();
61 | // start joining
62 | LMIC_setSession(0x12345678, 0xB710566C, nwkKey, artKey);
63 | // enable tracking mode, start scanning...
64 | LMIC_enableTracking(0);
65 | debug_str("SCANNING...\r\n");
66 |
67 | //LMIC_startJoining();
68 | // init done - onEvent() callback will be invoked...
69 | }
70 |
71 |
72 | // application entry point
73 | int main () {
74 | osjob_t initjob;
75 |
76 | // initialize runtime env
77 | os_init();
78 | // initialize debug library
79 | debug_init();
80 | // setup initial job
81 | os_setCallback(&initjob, initfunc);
82 | // execute scheduled jobs and events
83 | os_runloop();
84 | // (not reached)
85 | return 0;
86 | }
87 |
88 |
89 | //////////////////////////////////////////////////
90 | // LMIC EVENT CALLBACK
91 | //////////////////////////////////////////////////
92 |
93 | void onEvent (ev_t ev) {
94 | debug_event(ev);
95 |
96 | switch(ev) {
97 |
98 | // network joined, session established
99 | case EV_JOINED:
100 | // enable tracking mode, start scanning...
101 | LMIC_enableTracking(0);
102 | debug_str("SCANNING...\r\n");
103 | break;
104 |
105 | // beacon found by scanning
106 | case EV_BEACON_FOUND:
107 | // switch LEN on
108 | debug_led(1);
109 | break;
110 |
111 | // beacon tracked at expected time
112 | case EV_BEACON_TRACKED:
113 | debug_val("GPS time = ", LMIC.bcninfo.time);
114 | // switch LEN on
115 | debug_led(1);
116 | break;
117 |
118 | // beacon missed at expected time
119 | case EV_BEACON_MISSED:
120 | // switch LEN off
121 | debug_led(0);
122 | break;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/examples/hello/main.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "../../lmic/lmic.h"
13 | #include "../../hal/debug.h"
14 |
15 | // LMIC application callbacks not used in his example
16 | void os_getArtEui (u1_t* buf) {
17 | }
18 |
19 | void os_getDevEui (u1_t* buf) {
20 | }
21 |
22 | void os_getDevKey (u1_t* buf) {
23 | }
24 |
25 | void onEvent (ev_t ev) {
26 | }
27 |
28 | // counter
29 | static int cnt = 0;
30 |
31 | // log text to USART and toggle LED
32 | static void initfunc (osjob_t* job) {
33 | // say hello
34 | debug_str("Hello World!\r\n");
35 | // log counter
36 | debug_val("cnt = ", cnt);
37 | // toggle LED
38 | debug_led(++cnt & 1);
39 | // reschedule job every second
40 | os_setTimedCallback(job, os_getTime()+sec2osticks(1), initfunc);
41 | }
42 |
43 | // application entry point
44 | int main ()
45 | {
46 | osjob_t initjob;
47 | u4_t time;
48 |
49 | debug_init(); // initialize debug library
50 |
51 | /*hal_init();
52 | while(1)
53 | {
54 | debug_str("\r\nT=");
55 | time = hal_ticks();
56 | debug_hex(time>>24);
57 | debug_hex(time>>16);
58 | debug_hex(time>>8);
59 | debug_hex(time>>0);
60 | }*/
61 |
62 | os_init(); // initialize runtime env
63 |
64 | os_setCallback(&initjob, initfunc); // setup initial job
65 |
66 | os_runloop(); // execute scheduled jobs and events
67 |
68 |
69 | return 0; // (not reached)
70 | }
71 |
--------------------------------------------------------------------------------
/examples/interrupt/main.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "../../lmic/lmic.h"
13 | #include "../../hal/debug.h"
14 |
15 | // sensor functions
16 | extern void initsensor(osjobcb_t callback);
17 | extern u2_t readsensor(void);
18 |
19 |
20 | //////////////////////////////////////////////////
21 | // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
22 | //////////////////////////////////////////////////
23 |
24 | // application router ID (LSBF)
25 | static const u1_t APPEUI[8] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xFF, 0xC0 };
26 |
27 | // unique device ID (LSBF)
28 | static const u1_t DEVEUI[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
29 |
30 | // device-specific AES key (derived from device EUI)
31 | static const u1_t DEVKEY[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
32 |
33 | static const u1_t nwkKey[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
34 |
35 | static const u1_t artKey[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
36 |
37 |
38 | //////////////////////////////////////////////////
39 | // APPLICATION CALLBACKS
40 | //////////////////////////////////////////////////
41 |
42 | // provide application router ID (8 bytes, LSBF)
43 | void os_getArtEui (u1_t* buf) {
44 | memcpy(buf, APPEUI, 8);
45 | }
46 |
47 | // provide device ID (8 bytes, LSBF)
48 | void os_getDevEui (u1_t* buf) {
49 | memcpy(buf, DEVEUI, 8);
50 | }
51 |
52 | // provide device key (16 bytes)
53 | void os_getDevKey (u1_t* buf) {
54 | memcpy(buf, DEVKEY, 16);
55 | }
56 |
57 |
58 | //////////////////////////////////////////////////
59 | // SENSOR CALLBACK (run by sensor IRQ job)
60 | //////////////////////////////////////////////////
61 |
62 | // report sensor value when change was detected
63 | static void sensorfunc (osjob_t* j) {
64 | // read sensor
65 | u2_t val = readsensor();
66 | debug_val("val = ", val);
67 | // prepare and schedule data for transmission
68 | LMIC.frame[0] = val << 8;
69 | LMIC.frame[1] = val;
70 | LMIC_setTxData2(1, LMIC.frame, 2, 0); // (port 1, 2 bytes, unconfirmed)
71 | }
72 |
73 |
74 | //////////////////////////////////////////////////
75 | // MAIN - INITIALIZATION AND STARTUP
76 | //////////////////////////////////////////////////
77 |
78 | // initial job
79 | static void initfunc (osjob_t* j) {
80 | // intialize sensor hardware
81 | initsensor(sensorfunc);
82 | // reset MAC state
83 | LMIC_reset();
84 | // start joining
85 | LMIC_startJoining();
86 | // init done - onEvent() callback will be invoked...
87 | }
88 |
89 |
90 | // application entry point
91 | int main () {
92 | osjob_t initjob;
93 |
94 | // initialize runtime env
95 | os_init();
96 | // initialize debug library
97 | debug_init();
98 | // setup initial job
99 | os_setCallback(&initjob, initfunc);
100 | // execute scheduled jobs and events
101 | os_runloop();
102 | // (not reached)
103 | return 0;
104 | }
105 |
106 |
107 | //////////////////////////////////////////////////
108 | // LMIC EVENT CALLBACK
109 | //////////////////////////////////////////////////
110 |
111 | void onEvent (ev_t ev) {
112 | debug_event(ev);
113 |
114 | switch(ev) {
115 |
116 | // network joined, session established
117 | case EV_JOINED:
118 | // switch on LED
119 | debug_led(1);
120 | // (further actions will be interrupt-driven)
121 | break;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/examples/interrupt/sensor.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "../../lmic/lmic.h"
13 |
14 | // use PB12 (DIP switch 1)
15 | #define INP_PORT 1
16 | #define INP_PIN 12
17 |
18 | static osjob_t irqjob;
19 |
20 | // use DIP1 as sensor value
21 | void initsensor (osjobcb_t callback) {
22 | // configure input
23 | //RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // clock enable port B
24 | //hw_cfg_pin(GPIOx(INP_PORT), INP_PIN, GPIOCFG_MODE_INP | GPIOCFG_OSPEED_40MHz | GPIOCFG_OTYPE_OPEN);
25 | //hw_cfg_extirq(INP_PORT, INP_PIN, GPIO_IRQ_CHANGE);
26 | // save application callback
27 | irqjob.func = callback;
28 | }
29 |
30 | // read PB12
31 | u2_t readsensor ()
32 | {
33 | return 0;
34 | // return ((GPIOB->IDR & (1 << INP_PIN)) != 0);
35 | }
36 |
37 | // called by EXTI_IRQHandler
38 | // (set preprocessor option CFG_EXTI_IRQ_HANDLER=sensorirq)
39 | void sensorirq ()
40 | {
41 | // if((EXTI->PR & (1<PR = (1<AHBENR |= RCC_AHBENR_GPIOBEN; // clock enable port B
19 | // hw_cfg_pin(GPIOB, 12, GPIOCFG_MODE_INP | GPIOCFG_OSPEED_40MHz | GPIOCFG_OTYPE_OPEN); // PB12
20 | }
21 |
22 | // read PB12
23 | u2_t readsensor ()
24 | {
25 | return 0;
26 | // return ((GPIOB->IDR & (1 << 12)) != 0);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/ping/main.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "../../lmic/lmic.h"
13 | #include "../../hal/debug.h"
14 |
15 | //////////////////////////////////////////////////
16 | // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
17 | //////////////////////////////////////////////////
18 |
19 | // application router ID (LSBF)
20 | static const u1_t APPEUI[8] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xFF, 0xC0 };
21 |
22 | // unique device ID (LSBF)
23 | static const u1_t DEVEUI[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
24 |
25 | // device-specific AES key (derived from device EUI)
26 | static const u1_t DEVKEY[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
27 |
28 | static const u1_t nwkKey[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
29 |
30 | static const u1_t artKey[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
31 |
32 |
33 | //////////////////////////////////////////////////
34 | // APPLICATION CALLBACKS
35 | //////////////////////////////////////////////////
36 |
37 | // provide application router ID (8 bytes, LSBF)
38 | void os_getArtEui (u1_t* buf) {
39 | memcpy(buf, APPEUI, 8);
40 | }
41 |
42 | // provide device ID (8 bytes, LSBF)
43 | void os_getDevEui (u1_t* buf) {
44 | memcpy(buf, DEVEUI, 8);
45 | }
46 |
47 | // provide device key (16 bytes)
48 | void os_getDevKey (u1_t* buf) {
49 | memcpy(buf, DEVKEY, 16);
50 | }
51 |
52 |
53 | //////////////////////////////////////////////////
54 | // MAIN - INITIALIZATION AND STARTUP
55 | //////////////////////////////////////////////////
56 |
57 | // initial job
58 | static void initfunc (osjob_t* j) {
59 | // reset MAC state
60 | LMIC_reset();
61 | // start joining
62 | LMIC_setSession(0x12345678, 0xB710566C, nwkKey, artKey);
63 | // enable pinging mode, start scanning...
64 | // (set local ping interval configuration to 2^1 == 2 sec)
65 | LMIC_setPingable(1);
66 | debug_str("SCANNING...\r\n");
67 |
68 | LMIC_sendAlive();
69 | //LMIC_startJoining();
70 | // init done - onEvent() callback will be invoked...
71 | }
72 |
73 |
74 | // application entry point
75 | int main () {
76 | osjob_t initjob;
77 |
78 | // initialize runtime env
79 | os_init();
80 | // initialize debug library
81 | debug_init();
82 | // setup initial job
83 | os_setCallback(&initjob, initfunc);
84 | // execute scheduled jobs and events
85 | os_runloop();
86 | // (not reached)
87 | return 0;
88 | }
89 |
90 |
91 | //////////////////////////////////////////////////
92 | // LMIC EVENT CALLBACK
93 | //////////////////////////////////////////////////
94 |
95 | void onEvent (ev_t ev) {
96 | debug_event(ev);
97 |
98 | switch(ev) {
99 |
100 | // network joined, session established
101 | case EV_JOINED:
102 | // enable pinging mode, start scanning...
103 | // (set local ping interval configuration to 2^1 == 2 sec)
104 | LMIC_setPingable(1);
105 | debug_str("SCANNING...\r\n");
106 | break;
107 |
108 | // beacon found by scanning
109 | case EV_BEACON_FOUND:
110 | // send empty frame up to notify server of ping mode and interval!
111 | LMIC_sendAlive();
112 | break;
113 |
114 | // data frame received in ping slot
115 | case EV_RXCOMPLETE:
116 | // log frame data
117 | debug_buf(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
118 | if(LMIC.dataLen == 1) {
119 | // set LED state if exactly one byte is received
120 | debug_led(LMIC.frame[LMIC.dataBeg] & 0x01);
121 | }
122 | break;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/examples/transmit/main.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "../../lmic/lmic.h"
13 | #include "../../hal/debug.h"
14 |
15 | //////////////////////////////////////////////////
16 | // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
17 | //////////////////////////////////////////////////
18 |
19 | // application router ID (LSBF)
20 | static const u1_t APPEUI[8] = { 0xBE, 0x7A, 0x00, 0x0B, 0xE7, 0xA0, 0x00, 0x40 };//0x02, 0x00, 0x00, 0x00, 0x00, 0xEE, 0xFF, 0xC0 };
21 |
22 | // unique device ID (LSBF)
23 | static const u1_t DEVEUI[8] = { 0xBE, 0x7A, 0x00, 0x0B, 0xE7, 0xA0, 0x00, 0x45 };//0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
24 |
25 | // device-specific AES key (derived from device EUI)
26 | static const u1_t DEVKEY[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
27 |
28 | static const u1_t nwkKey[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
29 |
30 | static const u1_t artKey[16] = { 0xE7, 0x63, 0x2E, 0x1C, 0xF3, 0x61, 0x7E, 0xAD, 0xF5, 0xC0, 0xBC, 0x7E, 0x38, 0xEA, 0x09, 0xA8 };
31 |
32 | //////////////////////////////////////////////////
33 | // APPLICATION CALLBACKS
34 | //////////////////////////////////////////////////
35 |
36 | // provide application router ID (8 bytes, LSBF)
37 | void os_getArtEui (u1_t* buf) {
38 | memcpy(buf, APPEUI, 8);
39 | }
40 |
41 | // provide device ID (8 bytes, LSBF)
42 | void os_getDevEui (u1_t* buf) {
43 | memcpy(buf, DEVEUI, 8);
44 | }
45 |
46 | // provide device key (16 bytes)
47 | void os_getDevKey (u1_t* buf) {
48 | memcpy(buf, DEVKEY, 16);
49 | }
50 |
51 |
52 | //////////////////////////////////////////////////
53 | // MAIN - INITIALIZATION AND STARTUP
54 | //////////////////////////////////////////////////
55 |
56 | // initial job
57 | static void initfunc (osjob_t* j) {
58 |
59 | LMIC_reset(); // reset MAC state
60 |
61 | LMIC_setSession(0x12345678, 0xB710566C, nwkKey, artKey);
62 |
63 | //LMIC_startJoining(); // start joining
64 | // init done - onEvent() callback will be invoked...
65 |
66 | /*void LMIC_setSession (u4_t netid, devaddr_t(u4_t) devaddr, xref2u1_t nwkKey, xref2u1_t artKey) {
67 | LMIC.netid = netid;
68 | LMIC.devaddr = devaddr;
69 | if( nwkKey != (xref2u1_t)0 )
70 | os_copyMem(LMIC.nwkKey, nwkKey, 16);
71 | if( artKey != (xref2u1_t)0 )
72 | os_copyMem(LMIC.artKey, artKey, 16);*/
73 |
74 | debug_str("\r\nSending");
75 | // immediately prepare next transmission
76 | LMIC.frame[0] = LMIC.snr;
77 | // schedule transmission (port 1, datalen 1, no ack requested)
78 | LMIC_setTxData2(1, LMIC.frame, 1, 0);
79 | // (will be sent as soon as duty cycle permits)
80 |
81 | LMIC_sendAlive();
82 | }
83 |
84 |
85 | // application entry point
86 | int main () {
87 | osjob_t initjob;
88 |
89 | // initialize runtime env
90 | os_init();
91 | // initialize debug library
92 | debug_init();
93 | // setup initial job
94 | os_setCallback(&initjob, initfunc);
95 | // execute scheduled jobs and events
96 | os_runloop();
97 | // (not reached)
98 | return 0;
99 | }
100 |
101 |
102 | //////////////////////////////////////////////////
103 | // LMIC EVENT CALLBACK
104 | //////////////////////////////////////////////////
105 |
106 | void onEvent (ev_t ev)
107 | {
108 | debug_event(ev);
109 |
110 | switch(ev)
111 | {
112 |
113 | // network joined, session established
114 | case EV_JOINED:
115 | debug_val("\r\nnetid = ", LMIC.netid);
116 |
117 | // immediately prepare next transmission
118 | debug_str("\r\nSending");
119 | LMIC.frame[0] = LMIC.snr;
120 | LMIC_setTxData2(1, LMIC.frame, 1, 0); // schedule transmission (port 1, datalen 1, no ack requested)
121 | break;
122 |
123 | // scheduled data sent (optionally data received)
124 | case EV_TXCOMPLETE:
125 | if(LMIC.dataLen) { // data received in rx slot after tx
126 | debug_str("\r\nReceived:");
127 | debug_buf(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
128 | }
129 | // immediately prepare next transmission
130 | LMIC.frame[0] = LMIC.snr;
131 | debug_val("\r\nSending:", LMIC.frame[0]);
132 | // schedule transmission (port 1, datalen 1, no ack requested)
133 | LMIC_setTxData2(1, LMIC.frame, 1, 0);
134 | break;
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/hal/debug.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 |
13 | #include "debug.h"
14 | #include "../lmic/lmic.h"
15 | #include "em_gpio.h"
16 | #include "em_cmu.h"
17 | #include "em_leuart.h"
18 |
19 | #if defined PA52
20 | #define PORT_TXD gpioPortD //TXD = PD4
21 | #define PIN_TXD 4U
22 | #define PORT_RXD gpioPortD //RXD = PD5
23 | #define PIN_RXD 5U
24 |
25 | #define PORT_SPK gpioPortC //REED3 = PC15 TILT = SPK
26 | #define PIN_SPK 15U
27 | #elif defined PA53
28 | #define PORT_TXD gpioPortD //TXD = PD4
29 | #define PIN_TXD 4U
30 | #define PORT_RXD gpioPortD //RXD = PD5
31 | #define PIN_RXD 5U
32 |
33 | #define PORT_SPK gpioPortC //REED3 = PC15 TILT = SPK
34 | #define PIN_SPK 15U
35 | #endif
36 |
37 | void debug_init ()
38 | {
39 | GPIO_PinModeSet(PORT_SPK, PIN_SPK, gpioModePushPull, 0);
40 |
41 | LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT;
42 |
43 | CMU_ClockEnable(cmuClock_HFPER, true);
44 | CMU_ClockEnable(cmuClock_GPIO, true);
45 |
46 | CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);
47 | CMU_ClockDivSet(cmuClock_LEUART0, cmuClkDiv_1);
48 | CMU_ClockEnable(cmuClock_LEUART0, true);
49 |
50 | init.refFreq = 0; //14MHz / 2 pre-scaled by 4 = 1750000;
51 | init.enable = leuartDisable;
52 | init.baudrate = 9600;
53 | init.databits = leuartDatabits8;
54 | init.parity = leuartNoParity;
55 | init.stopbits = leuartStopbits1;
56 |
57 | // Reseting and initializing LEUART0
58 | LEUART_Reset(LEUART0);
59 | LEUART_Init(LEUART0, &init);
60 |
61 | GPIO_PinModeSet(PORT_TXD, PIN_TXD, gpioModePushPull, 1);
62 | GPIO_PinModeSet(PORT_RXD, PIN_RXD, gpioModeInput, 0);
63 |
64 | LEUART0->ROUTE = LEUART_ROUTE_TXPEN | LEUART_ROUTE_RXPEN | LEUART_ROUTE_LOCATION_LOC0;
65 | LEUART0->CMD = LEUART_CMD_TXDIS | LEUART_CMD_RXDIS | LEUART_CMD_CLEARTX | LEUART_CMD_CLEARRX;
66 | LEUART0->CMD = LEUART_CMD_TXEN | LEUART_CMD_RXEN;
67 |
68 | // Eventually enable UART
69 | LEUART_Enable(LEUART0, leuartEnable);
70 |
71 | // print banner
72 | debug_str("\r\n============= DEBUG STARTED =============\r\n");
73 | }
74 |
75 | void debug_led (u1_t val)
76 | {
77 | if (val)
78 | GPIO_PinOutSet(PORT_SPK, PIN_SPK);
79 | else
80 | GPIO_PinOutClear(PORT_SPK, PIN_SPK);
81 | }
82 |
83 | void debug_char (u1_t c)
84 | {
85 | LEUART_Tx(LEUART0, c);
86 | }
87 |
88 | void debug_hex (u1_t b) {
89 | debug_char("0123456789ABCDEF"[b>>4]);
90 | debug_char("0123456789ABCDEF"[b&0xF]);
91 | }
92 |
93 | void debug_buf (const u1_t* buf, u2_t len) {
94 | while(len--) {
95 | debug_hex(*buf++);
96 | debug_char(' ');
97 | }
98 | debug_char('\r');
99 | debug_char('\n');
100 | }
101 |
102 | void debug_uint (u4_t v) {
103 | for(s1_t n=24; n>=0; n-=8) {
104 | debug_hex(v>>n);
105 | }
106 | }
107 |
108 | void debug_str (const u1_t* str) {
109 | while(*str) {
110 | debug_char(*str++);
111 | }
112 | }
113 |
114 | void debug_val (const u1_t* label, u4_t val) {
115 | debug_str(label);
116 | debug_uint(val);
117 | debug_char('\r');
118 | debug_char('\n');
119 | }
120 |
121 | void debug_event (int ev) {
122 | static const u1_t* evnames[] = {
123 | [EV_SCAN_TIMEOUT] = "SCAN_TIMEOUT",
124 | [EV_BEACON_FOUND] = "BEACON_FOUND",
125 | [EV_BEACON_MISSED] = "BEACON_MISSED",
126 | [EV_BEACON_TRACKED] = "BEACON_TRACKED",
127 | [EV_JOINING] = "JOINING",
128 | [EV_JOINED] = "JOINED",
129 | [EV_RFU1] = "RFU1",
130 | [EV_JOIN_FAILED] = "JOIN_FAILED",
131 | [EV_REJOIN_FAILED] = "REJOIN_FAILED",
132 | [EV_TXCOMPLETE] = "TXCOMPLETE",
133 | [EV_LOST_TSYNC] = "LOST_TSYNC",
134 | [EV_RESET] = "RESET",
135 | [EV_RXCOMPLETE] = "RXCOMPLETE",
136 | [EV_LINK_DEAD] = "LINK_DEAD",
137 | [EV_LINK_ALIVE] = "LINK_ALIVE",
138 | };
139 | debug_str(evnames[ev]);
140 | debug_char('\r');
141 | debug_char('\n');
142 | }
143 |
--------------------------------------------------------------------------------
/hal/debug.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 | #include "../lmic/oslmic.h"
12 |
13 | // intialize debug library
14 | void debug_init (void);
15 |
16 | // set LED state
17 | void debug_led (u1_t val);
18 |
19 | // write character to USART
20 | void debug_char (u1_t c);
21 |
22 | // write byte as two hex digits to USART
23 | void debug_hex (u1_t b);
24 |
25 | // write buffer as hex dump to USART
26 | void debug_buf (const u1_t* buf, u2_t len);
27 |
28 | // write 32-bit integer as eight hex digits to USART
29 | void debug_uint (u4_t v);
30 |
31 | // write nul-terminated string to USART
32 | void debug_str (const u1_t* str);
33 |
34 | // write LMiC event name to USART
35 | void debug_event (int ev);
36 |
37 | // write label and 32-bit value as hex to USART
38 | void debug_val (const u1_t* label, u4_t val);
39 |
--------------------------------------------------------------------------------
/hal/hal.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "../lmic/lmic.h"
13 |
14 | #include "em_chip.h"
15 | #include "em_device.h"
16 | #include "em_cmu.h"
17 | #include "em_gpio.h"
18 | #include "em_int.h"
19 | #include "em_emu.h"
20 | #include "em_rtc.h"
21 | #include "em_usart.h"
22 |
23 | // -----------------------------------------------------------------------------
24 | // I/O
25 | #if defined PA52
26 | #define PORT_DIO0 gpioPortB //DIO0 = PB11
27 | #define PIN_DIO0 11
28 | #define PORT_DIO1 gpioPortC //DIO1 = PC1
29 | #define PIN_DIO1 1
30 | #define PORT_DIO2 gpioPortC //DIO2 = PC0
31 | #define PIN_DIO2 0
32 | #define PORT_DIO3 gpioPortA //DIO3 = PA2
33 | #define PIN_DIO3 2
34 | #define PORT_DIO4 gpioPortA //DIO4 = PA1
35 | #define PIN_DIO4 1
36 | #define PORT_DIO5 gpioPortA //DIO5 = PA0
37 | #define PIN_DIO5 0
38 | #define USART_USED USART0
39 | #define USART_LOCATION USART_ROUTE_LOCATION_LOC0
40 | #define USART_CLK cmuClock_USART0
41 | #define PIN_SPI_TX 10 //MOSI = PE10
42 | #define PORT_SPI_TX gpioPortE
43 | #define PIN_SPI_RX 11 //MISO = PE11
44 | #define PORT_SPI_RX gpioPortE
45 | #define PIN_SPI_CLK 12 //SCK = PE12
46 | #define PORT_SPI_CLK gpioPortE
47 | #define PIN_SPI_CS 13 //CSN = PE13
48 | #define PORT_SPI_CS gpioPortE
49 | #elif defined PA53
50 | #define PORT_DIO0 gpioPortC //DIO0 = PC1
51 | #define PIN_DIO0 1U
52 | #define PORT_DIO1 gpioPortC //DIO1 = PC0
53 | #define PIN_DIO1 0U
54 | #define PORT_DIO2 gpioPortA //DIO2 = PA2
55 | #define PIN_DIO2 2U
56 | #define PORT_DIO4 gpioPortA //DIO4 = PA1
57 | #define PIN_DIO4 1U
58 | #define PORT_DIO5 gpioPortA //DIO5 = PA0
59 | #define PIN_DIO5 0U
60 | #define USART_USED USART0
61 | #define USART_LOCATION USART_ROUTE_LOCATION_LOC0
62 | #define USART_CLK cmuClock_USART0
63 | #define PIN_SPI_TX 10 //MOSI = PE10
64 | #define PORT_SPI_TX gpioPortE
65 | #define PIN_SPI_RX 11 //MISO = PE11
66 | #define PORT_SPI_RX gpioPortE
67 | #define PIN_SPI_CLK 12 //SCK = PE12
68 | #define PORT_SPI_CLK gpioPortE
69 | #define PIN_SPI_CS 13 //CSN = PE13
70 | #define PORT_SPI_CS gpioPortE
71 | #else
72 | #error Missing board!
73 | #endif
74 |
75 | // HAL state
76 | static struct
77 | {
78 | //int irqlevel;
79 | u4_t ticks;
80 | } HAL;
81 |
82 | // -----------------------------------------------------------------------------
83 | // I/O
84 |
85 | static void hal_io_init ()
86 | {
87 | //Enable module clocks
88 | CMU_ClockEnable(cmuClock_HFPER, true);
89 | CMU_ClockEnable(cmuClock_GPIO, true);
90 |
91 | GPIO_PinModeSet(PORT_DIO0, PIN_DIO0, gpioModeInputPull, 0); //DIO0=PayLoadReady
92 | GPIO_PinModeSet(PORT_DIO1, PIN_DIO1, gpioModeInputPull, 0); //DIO1=FifoLevel
93 | GPIO_PinModeSet(PORT_DIO2, PIN_DIO2, gpioModeInputPull, 0); //DIO2=SyncAddr
94 | #if !defined PA53
95 | GPIO_PinModeSet(PORT_DIO3, PIN_DIO3, gpioModeInputPull, 0); //DIO3=FifoEmpty
96 | #endif
97 | GPIO_PinModeSet(PORT_DIO4, PIN_DIO4, gpioModeInputPull, 0); //DIO4=PreambleDetect/RSSI
98 | GPIO_PinModeSet(PORT_DIO5, PIN_DIO5, gpioModeInputPull, 0); //DIO5=ModeReady
99 |
100 | GPIO_IntConfig(PORT_DIO0, PIN_DIO0, true, false, true);
101 | GPIO_IntConfig(PORT_DIO1, PIN_DIO1, true, false, true);
102 | GPIO_IntConfig(PORT_DIO2, PIN_DIO2, true, false, true);
103 | NVIC_EnableIRQ(GPIO_ODD_IRQn);
104 | NVIC_EnableIRQ(GPIO_EVEN_IRQn);
105 | }
106 |
107 | // val ==1 => tx 1, rx 0 ; val == 0 => tx 0, rx 1
108 | void hal_pin_rxtx (u1_t val)
109 | {
110 | //not used in PA52 nor PA53
111 | }
112 |
113 |
114 | // set radio NSS pin to given value
115 | void hal_pin_nss (u1_t val)
116 | {
117 | if (val)
118 | GPIO_PinOutSet(PORT_SPI_CS, PIN_SPI_CS); // SPI Disable
119 | else
120 | GPIO_PinOutClear(PORT_SPI_CS, PIN_SPI_CS); // SPI Enable (Active Low)
121 | }
122 |
123 | // set radio RST pin to given value (or keep floating!)
124 | void hal_pin_rst (u1_t val)
125 | {
126 | #if defined PA52
127 | //not used in PA52
128 | #elif defined PA53
129 | if(val == 0 || val == 1) { // drive pin
130 | hw_cfg_pin(GPIOx(RST_PORT), RST_PIN, GPIOCFG_MODE_OUT | GPIOCFG_OSPEED_40MHz | GPIOCFG_OTYPE_PUPD | GPIOCFG_PUPD_PUP);
131 | hw_set_pin(GPIOx(RST_PORT), RST_PIN, val);
132 | } else { // keep pin floating
133 | hw_cfg_pin(GPIOx(RST_PORT), RST_PIN, GPIOCFG_MODE_INP | GPIOCFG_OSPEED_40MHz | GPIOCFG_OTYPE_OPEN);
134 | }
135 | #endif
136 | }
137 |
138 | extern void radio_irq_handler(u1_t dio);
139 |
140 | void GPIO_ODD_IRQHandler(void) //impar
141 | {
142 | u4_t i = GPIO_IntGet();
143 | if (i & 1<ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN | USART_LOCATION;
186 | }
187 |
188 | // perform SPI transaction with radio
189 | u1_t hal_spi (u1_t out)
190 | {
191 | /* For every byte sent, one is received */
192 | USART_Tx(USART_USED, out);
193 | return USART_Rx(USART_USED);
194 | }
195 |
196 |
197 | // -----------------------------------------------------------------------------
198 | // TIME
199 | static uint8_t rtcInitialized = 0; /**< 1 if rtc is initialized */
200 | static uint32_t rtcFreq; /**< RTC Frequence. 32.768 kHz */
201 |
202 | /***************************************************************************//**
203 | * @brief RTC Interrupt Handler, invoke callback function if defined.
204 | ******************************************************************************/
205 | void RTC_IRQHandler(void)
206 | {
207 | if (RTC_IntGet() & RTC_IF_OF)
208 | {
209 | HAL.ticks ++;
210 | }
211 |
212 | if(RTC_IntGet() & RTC_IF_COMP0) // expired
213 | {
214 | // do nothing, only wake up cpu
215 | }
216 | RTC_IntClear(_RTC_IF_MASK); // clear IRQ flags
217 | }
218 |
219 |
220 | static void hal_time_init ()
221 | {
222 | RTC_Init_TypeDef init;
223 |
224 | rtcInitialized = 1;
225 |
226 | /* Ensure LE modules are accessible */
227 | CMU_ClockEnable(cmuClock_CORELE, true);
228 |
229 | /* Enable LFACLK in CMU (will also enable oscillator if not enabled) */
230 | CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO);
231 |
232 | /* Use the prescaler to reduce power consumption. */
233 | CMU_ClockDivSet(cmuClock_RTC, cmuClkDiv_1);
234 |
235 | rtcFreq = CMU_ClockFreqGet(cmuClock_RTC);
236 |
237 | /* Enable clock to RTC module */
238 | CMU_ClockEnable(cmuClock_RTC, true);
239 |
240 | init.enable = false;
241 | init.debugRun = false;
242 | init.comp0Top = false;
243 | //init.comp0Top = true; /* Count to max before wrapping */
244 | RTC_Init(&init);
245 |
246 | /* Disable interrupt generation from RTC0 */
247 | RTC_IntDisable(_RTC_IF_MASK);
248 |
249 | /* Enable interrupts */
250 | NVIC_ClearPendingIRQ(RTC_IRQn);
251 | NVIC_EnableIRQ(RTC_IRQn);
252 |
253 | /* Enable RTC */
254 | RTC_Enable(true);
255 |
256 | RTC_IntEnable(RTC_IF_OF); //Enable interrupt on overflow
257 | }
258 |
259 | u4_t hal_ticks ()
260 | {
261 | hal_disableIRQs();
262 | u4_t t = HAL.ticks;
263 | u4_t cnt = RTC_CounterGet();
264 | if (RTC_IntGet() & RTC_IF_OF) // Overflow before we read CNT?
265 | {
266 | cnt = RTC_CounterGet();
267 | t ++; // Include overflow in evaluation but leave update of state to ISR once interrupts enabled again
268 | }
269 | hal_enableIRQs();
270 | return (t<<24)|cnt;
271 | }
272 |
273 | // return modified delta ticks from now to specified ticktime (0 for past, FFFF for far future)
274 | static u2_t deltaticks (u4_t time)
275 | {
276 | u4_t t = hal_ticks();
277 | s4_t d = time - t;
278 | if( d<=0 ) return 0; // in the past
279 | if( (d>>16)!=0 ) return 0xFFFF; // far ahead
280 | return (u2_t)d;
281 | }
282 |
283 | void hal_waitUntil (u4_t time)
284 | {
285 | while( deltaticks(time) != 0 ); // busy wait until timestamp is reached
286 | }
287 |
288 | // check and rewind for target time
289 | u1_t hal_checkTimer (u4_t time)
290 | {
291 | u2_t dt;
292 | RTC_IntClear(RTC_IF_COMP0); //clear any pending interrupts
293 | if((dt = deltaticks(time)) < 5) // event is now (a few ticks ahead)
294 | {
295 | RTC_IntDisable(RTC_IF_COMP0); // disable IE
296 | return 1;
297 | }
298 | else // rewind timer (fully or to exact time))
299 | {
300 | RTC_CompareSet(0, RTC_CounterGet() + dt); // set comparator
301 | RTC_IntEnable(RTC_IF_COMP0); // enable IE
302 | return 0;
303 | }
304 | }
305 |
306 |
307 |
308 | // -----------------------------------------------------------------------------
309 | // IRQ
310 |
311 | void hal_disableIRQs ()
312 | {
313 | INT_Disable();
314 | }
315 |
316 | void hal_enableIRQs ()
317 | {
318 | INT_Enable();
319 | }
320 |
321 | void hal_sleep ()
322 | {
323 | EMU_EnterEM2(false);
324 | }
325 |
326 | // -----------------------------------------------------------------------------
327 |
328 | void hal_init ()
329 | {
330 | CHIP_Init();
331 |
332 | memset(&HAL, 0x00, sizeof(HAL));
333 | hal_disableIRQs();
334 |
335 | hal_io_init(); // configure radio I/O and interrupt handler
336 |
337 | hal_spi_init(); // configure radio SPI
338 |
339 | hal_time_init(); // configure timer and interrupt handler
340 |
341 | hal_enableIRQs();
342 | }
343 |
344 | void hal_failed ()
345 | {
346 | debug_led(1);
347 | // HALT...
348 | hal_disableIRQs();
349 | hal_sleep();
350 | while(1);
351 | }
352 |
353 |
--------------------------------------------------------------------------------
/lmic/aes.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "oslmic.h"
13 |
14 | #define AES_MICSUB 0x30 // internal use only
15 |
16 | static const u4_t AES_RCON[10] = {
17 | 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
18 | 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000
19 | };
20 |
21 | static const u1_t AES_S[256] = {
22 | 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
23 | 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
24 | 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
25 | 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
26 | 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
27 | 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
28 | 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
29 | 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
30 | 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
31 | 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
32 | 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
33 | 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
34 | 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
35 | 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
36 | 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
37 | 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
38 | };
39 |
40 | static const u4_t AES_E1[256] = {
41 | 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, 0xDE6F6FB1, 0x91C5C554,
42 | 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A,
43 | 0x8FCACA45, 0x1F82829D, 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B,
44 | 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, 0xE4727296, 0x9BC0C05B,
45 | 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F,
46 | 0x6834345C, 0x51A5A5F4, 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F,
47 | 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, 0x0A05050F, 0x2F9A9AB5,
48 | 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F,
49 | 0x1209091B, 0x1D83839E, 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB,
50 | 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, 0x5E2F2F71, 0x13848497,
51 | 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED,
52 | 0xD46A6ABE, 0x8DCBCB46, 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A,
53 | 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, 0x66333355, 0x11858594,
54 | 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3,
55 | 0xA25151F3, 0x5DA3A3FE, 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504,
56 | 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A, 0xFDF3F30E, 0xBFD2D26D,
57 | 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739,
58 | 0x93C4C457, 0x55A7A7F2, 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395,
59 | 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, 0x3B9090AB, 0x0B888883,
60 | 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76,
61 | 0xDBE0E03B, 0x64323256, 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4,
62 | 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, 0xD3E4E437, 0xF279798B,
63 | 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0,
64 | 0xD86C6CB4, 0xAC5656FA, 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818,
65 | 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, 0x73B4B4C7, 0x97C6C651,
66 | 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85,
67 | 0xE0707090, 0x7C3E3E42, 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12,
68 | 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, 0x3A1D1D27, 0x279E9EB9,
69 | 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7,
70 | 0x2D9B9BB6, 0x3C1E1E22, 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A,
71 | 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631, 0x844242C6, 0xD06868B8,
72 | 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A,
73 | };
74 |
75 | static const u4_t AES_E2[256] = {
76 | 0xA5C66363, 0x84F87C7C, 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5,
77 | 0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7, 0xE64DABAB, 0x9AEC7676,
78 | 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D, 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0,
79 | 0xEC41ADAD, 0x67B3D4D4, 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0,
80 | 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, 0x5A6C3636, 0x417E3F3F, 0x02F5F7F7, 0x4F83CCCC,
81 | 0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1, 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515,
82 | 0x0C080404, 0x5295C7C7, 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A,
83 | 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, 0x26CDEBEB, 0x694E2727, 0xCD7FB2B2, 0x9FEA7575,
84 | 0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0,
85 | 0xF6A45252, 0x4D763B3B, 0x61B7D6D6, 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484,
86 | 0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, 0x60402020, 0x1FE3FCFC, 0xC879B1B1, 0xEDB65B5B,
87 | 0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF,
88 | 0x6BBBD0D0, 0x2AC5EFEF, 0xE54FAAAA, 0x16EDFBFB, 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585,
89 | 0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C, 0xBA259F9F, 0xE34BA8A8,
90 | 0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F, 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5,
91 | 0xDF63BCBC, 0xC177B6B6, 0x75AFDADA, 0x63422121, 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2,
92 | 0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797, 0xCC884444, 0x392E1717,
93 | 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D, 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373,
94 | 0xA0C06060, 0x98198181, 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888,
95 | 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E, 0x1D160B0B, 0x76ADDBDB,
96 | 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A, 0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C,
97 | 0x5D9FC2C2, 0x6EBDD3D3, 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979,
98 | 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, 0x8C018D8D, 0x64B1D5D5, 0xD29C4E4E, 0xE049A9A9,
99 | 0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808,
100 | 0xD56FBABA, 0x88F07878, 0x6F4A2525, 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6,
101 | 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B, 0xDC61BDBD, 0x860D8B8B, 0x850F8A8A,
102 | 0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E,
103 | 0xA3C26161, 0x5F6A3535, 0xF9AE5757, 0xD069B9B9, 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E,
104 | 0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9, 0x89078E8E, 0xA7339494,
105 | 0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9, 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF,
106 | 0x8F038C8C, 0xF859A1A1, 0x80098989, 0x171A0D0D, 0xDA65BFBF, 0x31D7E6E6, 0xC6844242, 0xB8D06868,
107 | 0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454, 0xD66DBBBB, 0x3A2C1616,
108 | };
109 |
110 | static const u4_t AES_E3[256] = {
111 | 0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5,
112 | 0x30506030, 0x01030201, 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76,
113 | 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, 0xFA15EFFA, 0x59EBB259, 0x47C98E47, 0xF00BFBF0,
114 | 0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0,
115 | 0xB7C275B7, 0xFD1CE1FD, 0x93AE3D93, 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC,
116 | 0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, 0xD873ABD8, 0x31536231, 0x153F2A15,
117 | 0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A,
118 | 0x07090E07, 0x12362412, 0x809B1B80, 0xE23DDFE2, 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75,
119 | 0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E, 0x5AEEB45A, 0xA0FB5BA0,
120 | 0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384,
121 | 0x53F5A653, 0xD168B9D1, 0x00000000, 0xED2CC1ED, 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B,
122 | 0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C, 0x58E8B058, 0xCF4A85CF,
123 | 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB, 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185,
124 | 0x45CF8A45, 0xF910E9F9, 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8,
125 | 0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, 0x92AD3F92, 0x9DBC219D, 0x38487038, 0xF504F1F5,
126 | 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221, 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2,
127 | 0xCD4C81CD, 0x0C14180C, 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17,
128 | 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, 0x64ACC864, 0x5DE7BA5D, 0x192B3219, 0x7395E673,
129 | 0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88,
130 | 0x46CA8C46, 0xEE29C7EE, 0xB8D36BB8, 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB,
131 | 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, 0x49DB9249, 0x060A0C06, 0x246C4824, 0x5CE4B85C,
132 | 0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279,
133 | 0xE732D5E7, 0xC8438BC8, 0x37596E37, 0x6DB7DA6D, 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9,
134 | 0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A, 0xAEE947AE, 0x08181008,
135 | 0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E, 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6,
136 | 0xE823CBE8, 0xDD7CA1DD, 0x749CE874, 0x1F213E1F, 0x4BDD964B, 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A,
137 | 0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603, 0xF601F7F6, 0x0E121C0E,
138 | 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9, 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E,
139 | 0xE138D9E1, 0xF813EBF8, 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394,
140 | 0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, 0xCE4987CE, 0x55FFAA55, 0x28785028, 0xDF7AA5DF,
141 | 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D, 0xBFDA65BF, 0xE631D7E6, 0x42C68442, 0x68B8D068,
142 | 0x41C38241, 0x99B02999, 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16,
143 | };
144 |
145 | static const u4_t AES_E4[256] = {
146 | 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
147 | 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
148 | 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
149 | 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
150 | 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
151 | 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
152 | 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
153 | 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
154 | 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
155 | 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
156 | 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
157 | 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
158 | 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
159 | 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
160 | 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
161 | 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
162 | 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
163 | 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
164 | 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
165 | 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
166 | 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
167 | 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
168 | 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
169 | 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
170 | 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
171 | 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
172 | 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
173 | 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
174 | 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
175 | 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
176 | 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
177 | 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C,
178 | };
179 |
180 | #define msbf4_read(p) ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3])
181 | #define msbf4_write(p,v) (p)[0]=(v)>>24,(p)[1]=(v)>>16,(p)[2]=(v)>>8,(p)[3]=(v)
182 | #define swapmsbf(x) ( (x&0xFF)<<24 | (x&0xFF00)<<8 | (x&0xFF0000)>>8 | (x>>24) )
183 |
184 | #define u1(v) ((u1_t)(v))
185 |
186 | #define AES_key4(r1,r2,r3,r0,i) r1 = ki[i+1]; \
187 | r2 = ki[i+2]; \
188 | r3 = ki[i+3]; \
189 | r0 = ki[i]
190 |
191 | #define AES_expr4(r1,r2,r3,r0,i) r1 ^= AES_E4[u1(i)]; \
192 | r2 ^= AES_E3[u1(i>>8)]; \
193 | r3 ^= AES_E2[u1(i>>16)]; \
194 | r0 ^= AES_E1[ (i>>24)]
195 |
196 | #define AES_expr(a,r0,r1,r2,r3,i) a = ki[i]; \
197 | a ^= (AES_S[ r0>>24 ]<<24); \
198 | a ^= (AES_S[u1(r1>>16)]<<16); \
199 | a ^= (AES_S[u1(r2>> 8)]<< 8); \
200 | a ^= AES_S[u1(r3) ]
201 |
202 | // global area for passing parameters (aux, key) and for storing round keys
203 | u4_t AESAUX[16/sizeof(u4_t)];
204 | u4_t AESKEY[11*16/sizeof(u4_t)];
205 |
206 | // generate 1+10 roundkeys for encryption with 128-bit key
207 | // read 128-bit key from AESKEY in MSBF, generate roundkey words in place
208 | static void aesroundkeys () {
209 | int i;
210 | u4_t b;
211 |
212 | for( i=0; i<4; i++) {
213 | AESKEY[i] = swapmsbf(AESKEY[i]);
214 | }
215 |
216 | b = AESKEY[3];
217 | for( ; i<44; i++ ) {
218 | if( i%4==0 ) {
219 | // b = SubWord(RotWord(b)) xor Rcon[i/4]
220 | b = (AES_S[u1(b >> 16)] << 24) ^
221 | (AES_S[u1(b >> 8)] << 16) ^
222 | (AES_S[u1(b) ] << 8) ^
223 | (AES_S[ b >> 24 ] ) ^
224 | AES_RCON[(i-4)/4];
225 | }
226 | AESKEY[i] = b ^= AESKEY[i-4];
227 | }
228 | }
229 |
230 | u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len) {
231 |
232 | aesroundkeys();
233 |
234 | if( mode & AES_MICNOAUX ) {
235 | AESAUX[0] = AESAUX[1] = AESAUX[2] = AESAUX[3] = 0;
236 | } else {
237 | AESAUX[0] = swapmsbf(AESAUX[0]);
238 | AESAUX[1] = swapmsbf(AESAUX[1]);
239 | AESAUX[2] = swapmsbf(AESAUX[2]);
240 | AESAUX[3] = swapmsbf(AESAUX[3]);
241 | }
242 |
243 | while( (signed char)len > 0 ) {
244 | u4_t a0, a1, a2, a3;
245 | u4_t t0, t1, t2, t3;
246 | u4_t *ki, *ke;
247 |
248 | // load input block
249 | if( (mode & AES_CTR) || ((mode & AES_MIC) && (mode & AES_MICNOAUX)==0) ) { // load CTR block or first MIC block
250 | a0 = AESAUX[0];
251 | a1 = AESAUX[1];
252 | a2 = AESAUX[2];
253 | a3 = AESAUX[3];
254 | }
255 | else if( (mode & AES_MIC) && len <= 16 ) { // last MIC block
256 | a0 = a1 = a2 = a3 = 0; // load null block
257 | mode |= ((len == 16) ? 1 : 2) << 4; // set MICSUB: CMAC subkey K1 or K2
258 | } else
259 | LOADDATA: { // load data block (partially)
260 | for(t0=0; t0<16; t0++) {
261 | t1 = (t1<<8) | ((t0> 4) != 0 ) { // last block
312 | do {
313 | // compute CMAC subkey K1 and K2
314 | t0 = a0 >> 31; // save MSB
315 | a0 = (a0 << 1) | (a1 >> 31);
316 | a1 = (a1 << 1) | (a2 >> 31);
317 | a2 = (a2 << 1) | (a3 >> 31);
318 | a3 = (a3 << 1);
319 | if( t0 ) a3 ^= 0x87;
320 | } while( --t1 );
321 |
322 | AESAUX[0] ^= a0;
323 | AESAUX[1] ^= a1;
324 | AESAUX[2] ^= a2;
325 | AESAUX[3] ^= a3;
326 | mode &= ~AES_MICSUB;
327 | goto LOADDATA;
328 | } else {
329 | // save cipher block as new iv
330 | AESAUX[0] = a0;
331 | AESAUX[1] = a1;
332 | AESAUX[2] = a2;
333 | AESAUX[3] = a3;
334 | }
335 | } else { // CIPHER
336 | if( mode & AES_CTR ) { // xor block (partially)
337 | t0 = (len > 16) ? 16: len;
338 | for(t1=0; t1>24);
340 | a0 <<= 8;
341 | if((t1&3)==3) {
342 | a0 = a1;
343 | a1 = a2;
344 | a2 = a3;
345 | }
346 | }
347 | // update counter
348 | AESAUX[3]++;
349 | } else { // ECB
350 | // store block
351 | msbf4_write(buf+0, a0);
352 | msbf4_write(buf+4, a1);
353 | msbf4_write(buf+8, a2);
354 | msbf4_write(buf+12, a3);
355 | }
356 | }
357 |
358 | // update block state
359 | if( (mode & AES_MIC)==0 || (mode & AES_MICNOAUX) ) {
360 | buf += 16;
361 | len -= 16;
362 | }
363 | mode |= AES_MICNOAUX;
364 | }
365 | return AESAUX[0];
366 | }
367 |
368 |
--------------------------------------------------------------------------------
/lmic/hal.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #ifndef _hal_hpp_
13 | #define _hal_hpp_
14 |
15 | /*
16 | * initialize hardware (IO, SPI, TIMER, IRQ).
17 | */
18 | void hal_init (void);
19 |
20 | /*
21 | * drive radio NSS pin (0=low, 1=high).
22 | */
23 | void hal_pin_nss (u1_t val);
24 |
25 | /*
26 | * drive radio RX/TX pins (0=rx, 1=tx).
27 | */
28 | void hal_pin_rxtx (u1_t val);
29 |
30 | /*
31 | * control radio RST pin (0=low, 1=high, 2=floating)
32 | */
33 | void hal_pin_rst (u1_t val);
34 |
35 | /*
36 | * perform 8-bit SPI transaction with radio.
37 | * - write given byte 'outval'
38 | * - read byte and return value
39 | */
40 | u1_t hal_spi (u1_t outval);
41 |
42 | /*
43 | * disable all CPU interrupts.
44 | * - might be invoked nested
45 | * - will be followed by matching call to hal_enableIRQs()
46 | */
47 | void hal_disableIRQs (void);
48 |
49 | /*
50 | * enable CPU interrupts.
51 | */
52 | void hal_enableIRQs (void);
53 |
54 | /*
55 | * put system and CPU in low-power mode, sleep until interrupt.
56 | */
57 | void hal_sleep (void);
58 |
59 | /*
60 | * return 32-bit system time in ticks.
61 | */
62 | u4_t hal_ticks (void);
63 |
64 | /*
65 | * busy-wait until specified timestamp (in ticks) is reached.
66 | */
67 | void hal_waitUntil (u4_t time);
68 |
69 | /*
70 | * check and rewind timer for target time.
71 | * - return 1 if target time is close
72 | * - otherwise rewind timer for target time or full period and return 0
73 | */
74 | u1_t hal_checkTimer (u4_t targettime);
75 |
76 | /*
77 | * perform fatal failure action.
78 | * - called by assertions
79 | * - action could be HALT or reboot
80 | */
81 | void hal_failed (void);
82 |
83 | #endif // _hal_hpp_
84 |
--------------------------------------------------------------------------------
/lmic/lmic.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | //! @file
13 | //! @brief LMIC API
14 |
15 | #ifndef _lmic_h_
16 | #define _lmic_h_
17 |
18 | #include "oslmic.h"
19 | #include "lorabase.h"
20 |
21 | // LMIC version
22 | #define LMIC_VERSION_MAJOR 1
23 | #define LMIC_VERSION_MINOR 5
24 | #define LMIC_VERSION_BUILD 1431528305
25 |
26 | enum { MAX_FRAME_LEN = 64 }; //!< Library cap on max frame length
27 | enum { TXCONF_ATTEMPTS = 8 }; //!< Transmit attempts for confirmed frames
28 | enum { MAX_MISSED_BCNS = 20 }; // threshold for triggering rejoin requests
29 | enum { MAX_RXSYMS = 100 }; // stop tracking beacon beyond this
30 |
31 | enum { LINK_CHECK_CONT = 12 , // continue with this after reported dead link
32 | LINK_CHECK_DEAD = 24 , // after this UP frames and no response from NWK assume link is dead
33 | LINK_CHECK_INIT = -12 , // UP frame count until we inc datarate
34 | LINK_CHECK_OFF =-128 }; // link check disabled
35 |
36 | enum { TIME_RESYNC = 6*128 }; // secs
37 | enum { TXRX_GUARD_ms = 6000 }; // msecs - don't start TX-RX transaction before beacon
38 | enum { JOIN_GUARD_ms = 9000 }; // msecs - don't start Join Req/Acc transaction before beacon
39 | enum { TXRX_BCNEXT_secs = 2 }; // secs - earliest start after beacon time
40 | enum { RETRY_PERIOD_secs = 3 }; // secs - random period for retrying a confirmed send
41 |
42 | #if defined(CFG_eu868) // EU868 spectrum ====================================================
43 |
44 | enum { MAX_CHANNELS = 16 }; //!< Max supported channels
45 | enum { MAX_BANDS = 4 };
46 |
47 | enum { LIMIT_CHANNELS = (1<<4) }; // EU868 will never have more channels
48 | //! \internal
49 | struct band_t {
50 | u2_t txcap; // duty cycle limitation: 1/txcap
51 | s1_t txpow; // maximum TX power
52 | u1_t lastchnl; // last used channel
53 | ostime_t avail; // channel is blocked until this time
54 | };
55 | TYPEDEF_xref2band_t; //!< \internal
56 |
57 | #elif defined(CFG_us915) // US915 spectrum =================================================
58 |
59 | enum { MAX_XCHANNELS = 2 }; // extra channels in RAM, channels 0-71 are immutable
60 | enum { MAX_TXPOW_125kHz = 30 };
61 |
62 | #endif // ==========================================================================
63 |
64 | // Keep in sync with evdefs.hpp::drChange
65 | enum { DRCHG_SET, DRCHG_NOJACC, DRCHG_NOACK, DRCHG_NOADRACK, DRCHG_NWKCMD };
66 | enum { KEEP_TXPOW = -128 };
67 |
68 |
69 | //! \internal
70 | struct rxsched_t {
71 | u1_t dr;
72 | u1_t intvExp; // 0..7
73 | u1_t slot; // runs from 0 to 128
74 | u1_t rxsyms;
75 | ostime_t rxbase;
76 | ostime_t rxtime; // start of next spot
77 | u4_t freq;
78 | };
79 | TYPEDEF_xref2rxsched_t; //!< \internal
80 |
81 |
82 | //! Parsing and tracking states of beacons.
83 | enum { BCN_NONE = 0x00, //!< No beacon received
84 | BCN_PARTIAL = 0x01, //!< Only first (common) part could be decoded (info,lat,lon invalid/previous)
85 | BCN_FULL = 0x02, //!< Full beacon decoded
86 | BCN_NODRIFT = 0x04, //!< No drift value measured yet
87 | BCN_NODDIFF = 0x08 }; //!< No differential drift measured yet
88 | //! Information about the last and previous beacons.
89 | struct bcninfo_t {
90 | ostime_t txtime; //!< Time when the beacon was sent
91 | s1_t rssi; //!< Adjusted RSSI value of last received beacon
92 | s1_t snr; //!< Scaled SNR value of last received beacon
93 | u1_t flags; //!< Last beacon reception and tracking states. See BCN_* values.
94 | u4_t time; //!< GPS time in seconds of last beacon (received or surrogate)
95 | //
96 | u1_t info; //!< Info field of last beacon (valid only if BCN_FULL set)
97 | s4_t lat; //!< Lat field of last beacon (valid only if BCN_FULL set)
98 | s4_t lon; //!< Lon field of last beacon (valid only if BCN_FULL set)
99 | };
100 |
101 | // purpose of receive window - lmic_t.rxState
102 | enum { RADIO_RST=0, RADIO_TX=1, RADIO_RX=2, RADIO_RXON=3 };
103 | // Netid values / lmic_t.netid
104 | enum { NETID_NONE=(int)~0U, NETID_MASK=(int)0xFFFFFF };
105 | // MAC operation modes (lmic_t.opmode).
106 | enum { OP_NONE = 0x0000,
107 | OP_SCAN = 0x0001, // radio scan to find a beacon
108 | OP_TRACK = 0x0002, // track my networks beacon (netid)
109 | OP_JOINING = 0x0004, // device joining in progress (blocks other activities)
110 | OP_TXDATA = 0x0008, // TX user data (buffered in pendTxData)
111 | OP_POLL = 0x0010, // send empty UP frame to ACK confirmed DN/fetch more DN data
112 | OP_REJOIN = 0x0020, // occasionally send JOIN REQUEST
113 | OP_SHUTDOWN = 0x0040, // prevent MAC from doing anything
114 | OP_TXRXPEND = 0x0080, // TX/RX transaction pending
115 | OP_RNDTX = 0x0100, // prevent TX lining up after a beacon
116 | OP_PINGINI = 0x0200, // pingable is initialized and scheduling active
117 | OP_PINGABLE = 0x0400, // we're pingable
118 | OP_NEXTCHNL = 0x0800, // find a new channel
119 | OP_LINKDEAD = 0x1000, // link was reported as dead
120 | OP_TESTMODE = 0x2000, // developer test mode
121 | };
122 | // TX-RX transaction flags - report back to user
123 | enum { TXRX_ACK = 0x80, // confirmed UP frame was acked
124 | TXRX_NACK = 0x40, // confirmed UP frame was not acked
125 | TXRX_NOPORT = 0x20, // set if a frame with a port was RXed, clr if no frame/no port
126 | TXRX_PORT = 0x10, // set if a frame with a port was RXed, LMIC.frame[LMIC.dataBeg-1] => port
127 | TXRX_DNW1 = 0x01, // received in 1st DN slot
128 | TXRX_DNW2 = 0x02, // received in 2dn DN slot
129 | TXRX_PING = 0x04 }; // received in a scheduled RX slot
130 | // Event types for event callback
131 | enum _ev_t { EV_SCAN_TIMEOUT=1, EV_BEACON_FOUND,
132 | EV_BEACON_MISSED, EV_BEACON_TRACKED, EV_JOINING,
133 | EV_JOINED, EV_RFU1, EV_JOIN_FAILED, EV_REJOIN_FAILED,
134 | EV_TXCOMPLETE, EV_LOST_TSYNC, EV_RESET,
135 | EV_RXCOMPLETE, EV_LINK_DEAD, EV_LINK_ALIVE };
136 | typedef enum _ev_t ev_t;
137 |
138 |
139 | struct lmic_t {
140 | // Radio settings TX/RX (also accessed by HAL)
141 | ostime_t txend;
142 | ostime_t rxtime;
143 | u4_t freq;
144 | s1_t rssi;
145 | s1_t snr;
146 | rps_t rps;
147 | u1_t rxsyms;
148 | u1_t dndr;
149 | s1_t txpow; // dBm
150 |
151 | osjob_t osjob;
152 |
153 | // Channel scheduling
154 | #if defined(CFG_eu868)
155 | band_t bands[MAX_BANDS];
156 | u4_t channelFreq[MAX_CHANNELS];
157 | u2_t channelDrMap[MAX_CHANNELS];
158 | u2_t channelMap;
159 | #elif defined(CFG_us915)
160 | u4_t xchFreq[MAX_XCHANNELS]; // extra channel frequencies (if device is behind a repeater)
161 | u2_t xchDrMap[MAX_XCHANNELS]; // extra channel datarate ranges ---XXX: ditto
162 | u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits
163 | u2_t chRnd; // channel randomizer
164 | #endif
165 | u1_t txChnl; // channel for next TX
166 | u1_t globalDutyRate; // max rate: 1/2^k
167 | ostime_t globalDutyAvail; // time device can send again
168 |
169 | u4_t netid; // current network id (~0 - none)
170 | u2_t opmode;
171 | u1_t upRepeat; // configured up repeat
172 | s1_t adrTxPow; // ADR adjusted TX power
173 | u1_t datarate; // current data rate
174 | u1_t errcr; // error coding rate (used for TX only)
175 | u1_t rejoinCnt; // adjustment for rejoin datarate
176 | s2_t drift; // last measured drift
177 | s2_t lastDriftDiff;
178 | s2_t maxDriftDiff;
179 |
180 | u1_t pendTxPort;
181 | u1_t pendTxConf; // confirmed data
182 | u1_t pendTxLen; // +0x80 = confirmed
183 | u1_t pendTxData[MAX_LEN_PAYLOAD];
184 |
185 | u2_t devNonce; // last generated nonce
186 | u1_t nwkKey[16]; // network session key
187 | u1_t artKey[16]; // application router session key
188 | devaddr_t devaddr;
189 | u4_t seqnoDn; // device level down stream seqno
190 | u4_t seqnoUp;
191 |
192 | u1_t dnConf; // dn frame confirm pending: LORA::FCT_ACK or 0
193 | s1_t adrAckReq; // counter until we reset data rate (0=off)
194 | u1_t adrChanged;
195 |
196 | u1_t margin;
197 | bit_t ladrAns; // link adr adapt answer pending
198 | bit_t devsAns; // device status answer pending
199 | u1_t adrEnabled;
200 | u1_t moreData; // NWK has more data pending
201 | bit_t dutyCapAns; // have to ACK duty cycle settings
202 | u1_t snchAns; // answer set new channel
203 | // 2nd RX window (after up stream)
204 | u1_t dn2Dr;
205 | u4_t dn2Freq;
206 | u1_t dn2Ans; // 0=no answer pend, 0x80+ACKs
207 | #if defined CLASS_B
208 | // Class B state
209 | u1_t missedBcns; // unable to track last N beacons
210 | u1_t bcninfoTries; // how often to try (scan mode only)
211 | u1_t pingSetAns; // answer set cmd and ACK bits
212 | rxsched_t ping; // pingable setup
213 | #endif
214 | // Public part of MAC state
215 | u1_t txCnt;
216 | u1_t txrxFlags; // transaction flags (TX-RX combo)
217 | u1_t dataBeg; // 0 or start of data (dataBeg-1 is port)
218 | u1_t dataLen; // 0 no data or zero length data, >0 byte count of data
219 | u1_t frame[MAX_LEN_FRAME];
220 |
221 | u1_t bcnChnl;
222 | u1_t bcnRxsyms; //
223 | ostime_t bcnRxtime;
224 | bcninfo_t bcninfo; // Last received beacon info
225 | };
226 | //! \var struct lmic_t LMIC
227 | //! The state of LMIC MAC layer is encapsulated in this variable.
228 | DECLARE_LMIC; //!< \internal
229 |
230 | //! Construct a bit map of allowed datarates from drlo to drhi (both included).
231 | #define DR_RANGE_MAP(drlo,drhi) (((u2_t)0xFFFF<<(drlo)) & ((u2_t)0xFFFF>>(15-(drhi))))
232 | #if defined(CFG_eu868)
233 | enum { BAND_MILLI=0, BAND_CENTI=1, BAND_DECI=2, BAND_AUX=3 };
234 | bit_t LMIC_setupBand (u1_t bandidx, s1_t txpow, u2_t txcap);
235 | #endif
236 | bit_t LMIC_setupChannel (u1_t channel, u4_t freq, u2_t drmap, s1_t band);
237 | void LMIC_disableChannel (u1_t channel);
238 |
239 | void LMIC_setDrTxpow (dr_t dr, s1_t txpow); // set default/start DR/txpow
240 | void LMIC_setAdrMode (bit_t enabled); // set ADR mode (if mobile turn off)
241 | bit_t LMIC_startJoining (void);
242 |
243 | void LMIC_shutdown (void);
244 | void LMIC_init (void);
245 | void LMIC_reset (void);
246 | void LMIC_restart (void); //restart after a LMIC_shutdown without reset
247 | void LMIC_clrTxData (void);
248 | void LMIC_setTxData (void);
249 | int LMIC_setTxData2 (u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed);
250 | void LMIC_sendAlive (void);
251 |
252 | bit_t LMIC_enableTracking (u1_t tryBcnInfo);
253 | void LMIC_disableTracking (void);
254 |
255 | void LMIC_stopPingable (void);
256 | void LMIC_setPingable (u1_t intvExp);
257 | void LMIC_tryRejoin (void);
258 |
259 | void LMIC_setSession (u4_t netid, devaddr_t devaddr, xref2u1_t nwkKey, xref2u1_t artKey);
260 | void LMIC_setLinkCheckMode (bit_t enabled);
261 |
262 | // Special APIs - for development or testing
263 | // !!!See implementation for caveats!!!
264 |
265 | #endif // _lmic_h_
266 |
--------------------------------------------------------------------------------
/lmic/lorabase.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #ifndef _lorabase_h_
13 | #define _lorabase_h_
14 |
15 | // ================================================================================
16 | // BEG: Keep in sync with lorabase.hpp
17 | //
18 |
19 | enum _cr_t { CR_4_5=0, CR_4_6, CR_4_7, CR_4_8 };
20 | enum _sf_t { FSK=0, SF7, SF8, SF9, SF10, SF11, SF12, SFrfu };
21 | enum _bw_t { BW125=0, BW250, BW500, BWrfu };
22 | typedef u1_t cr_t;
23 | typedef u1_t sf_t;
24 | typedef u1_t bw_t;
25 | typedef u1_t dr_t;
26 | // Radio parameter set (encodes SF/BW/CR/IH/NOCRC)
27 | typedef u2_t rps_t;
28 | TYPEDEF_xref2rps_t;
29 |
30 | enum { ILLEGAL_RPS = 0xFF };
31 | enum { DR_PAGE_EU868 = 0x00 };
32 | enum { DR_PAGE_US915 = 0x10 };
33 |
34 | // Global maximum frame length
35 | enum { STD_PREAMBLE_LEN = 8 };
36 | enum { MAX_LEN_FRAME = 64 };
37 | enum { LEN_DEVNONCE = 2 };
38 | enum { LEN_ARTNONCE = 3 };
39 | enum { LEN_NETID = 3 };
40 | enum { DELAY_JACC1 = 5 }; // in secs
41 | enum { DELAY_DNW1 = 1 }; // in secs down window #1
42 | enum { DELAY_EXTDNW2 = 1 }; // in secs
43 | enum { DELAY_JACC2 = DELAY_JACC1+(int)DELAY_EXTDNW2 }; // in secs
44 | enum { DELAY_DNW2 = DELAY_DNW1 +(int)DELAY_EXTDNW2 }; // in secs down window #1
45 | enum { BCN_INTV_exp = 7 };
46 | enum { BCN_INTV_sec = 1<> 3) & 0x3); }
346 | inline rps_t setBw (rps_t params, bw_t cr) { return (rps_t)((params & ~0x18) | (cr<<3)); }
347 | inline cr_t getCr (rps_t params) { return (cr_t)((params >> 5) & 0x3); }
348 | inline rps_t setCr (rps_t params, cr_t cr) { return (rps_t)((params & ~0x60) | (cr<<5)); }
349 | inline int getNocrc(rps_t params) { return ((params >> 7) & 0x1); }
350 | inline rps_t setNocrc(rps_t params, int nocrc) { return (rps_t)((params & ~0x80) | (nocrc<<7)); }
351 | inline int getIh (rps_t params) { return ((params >> 8) & 0xFF); }
352 | inline rps_t setIh (rps_t params, int ih) { return (rps_t)((params & ~0xFF00) | (ih<<8)); }
353 | inline rps_t makeRps (sf_t sf, bw_t bw, cr_t cr, int ih, int nocrc) {
354 | return sf | (bw<<3) | (cr<<5) | (nocrc?(1<<7):0) | ((ih&0xFF)<<8);
355 | }
356 | #define MAKERPS(sf,bw,cr,ih,nocrc) ((rps_t)((sf) | ((bw)<<3) | ((cr)<<5) | ((nocrc)?(1<<7):0) | ((ih&0xFF)<<8)))
357 | // Two frames with params r1/r2 would interfere on air: same SFx + BWx
358 | inline int sameSfBw(rps_t r1, rps_t r2) { return ((r1^r2)&0x1F) == 0; }
359 |
360 | extern const u1_t _DR2RPS_CRC[];
361 | inline rps_t updr2rps (dr_t dr) { return (rps_t)_DR2RPS_CRC[dr+1]; }
362 | inline rps_t dndr2rps (dr_t dr) { return setNocrc(updr2rps(dr),1); }
363 | inline int isFasterDR (dr_t dr1, dr_t dr2) { return dr1 > dr2; }
364 | inline int isSlowerDR (dr_t dr1, dr_t dr2) { return dr1 < dr2; }
365 | inline dr_t incDR (dr_t dr) { return _DR2RPS_CRC[dr+2]==ILLEGAL_RPS ? dr : (dr_t)(dr+1); } // increase data rate
366 | inline dr_t decDR (dr_t dr) { return _DR2RPS_CRC[dr ]==ILLEGAL_RPS ? dr : (dr_t)(dr-1); } // decrease data rate
367 | inline dr_t assertDR (dr_t dr) { return _DR2RPS_CRC[dr+1]==ILLEGAL_RPS ? DR_DFLTMIN : dr; } // force into a valid DR
368 | inline bit_t validDR (dr_t dr) { return _DR2RPS_CRC[dr+1]!=ILLEGAL_RPS; } // in range
369 | inline dr_t lowerDR (dr_t dr, u1_t n) { while(n--){dr=decDR(dr);} return dr; } // decrease data rate by n steps
370 |
371 | //
372 | // BEG: Keep in sync with lorabase.hpp
373 | // ================================================================================
374 |
375 |
376 | // Convert between dBm values and power codes (MCMD_LADR_XdBm)
377 | s1_t pow2dBm (u1_t mcmd_ladr_p1);
378 | // Calculate airtime
379 | ostime_t calcAirTime (rps_t rps, u1_t plen);
380 | // Sensitivity at given SF/BW
381 | int getSensitivity (rps_t rps);
382 |
383 |
384 | #endif // _lorabase_h_
385 |
--------------------------------------------------------------------------------
/lmic/oslmic.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "lmic.h"
13 |
14 | // RUNTIME STATE
15 | static struct {
16 | osjob_t* scheduledjobs;
17 | osjob_t* runnablejobs;
18 | } OS;
19 |
20 | void os_init () {
21 | memset(&OS, 0x00, sizeof(OS));
22 | hal_init();
23 | radio_init();
24 | LMIC_init();
25 | }
26 |
27 | ostime_t os_getTime () {
28 | return hal_ticks();
29 | }
30 |
31 | static u1_t unlinkjob (osjob_t** pnext, osjob_t* job) {
32 | for( ; *pnext; pnext = &((*pnext)->next)) {
33 | if(*pnext == job) { // unlink
34 | *pnext = job->next;
35 | return 1;
36 | }
37 | }
38 | return 0;
39 | }
40 |
41 | // clear scheduled job
42 | void os_clearCallback (osjob_t* job) {
43 | hal_disableIRQs();
44 | unlinkjob(&OS.scheduledjobs, job) || unlinkjob(&OS.runnablejobs, job);
45 | hal_enableIRQs();
46 | }
47 |
48 | // schedule immediately runnable job
49 | void os_setCallback (osjob_t* job, osjobcb_t cb) {
50 | osjob_t** pnext;
51 | hal_disableIRQs();
52 | // remove if job was already queued
53 | os_clearCallback(job);
54 | // fill-in job
55 | job->func = cb;
56 | job->next = NULL;
57 | // add to end of run queue
58 | for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next));
59 | *pnext = job;
60 | hal_enableIRQs();
61 | }
62 |
63 | // schedule timed job
64 | void os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) {
65 | osjob_t** pnext;
66 | hal_disableIRQs();
67 | // remove if job was already queued
68 | os_clearCallback(job);
69 | // fill-in job
70 | job->deadline = time;
71 | job->func = cb;
72 | job->next = NULL;
73 | // insert into schedule
74 | for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) {
75 | if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!)
76 | // enqueue before next element and stop
77 | job->next = *pnext;
78 | break;
79 | }
80 | }
81 | *pnext = job;
82 | hal_enableIRQs();
83 | }
84 |
85 | // execute jobs from timer and from run queue
86 | void os_runloop () {
87 | while(1) {
88 | osjob_t* j = NULL;
89 | hal_disableIRQs();
90 | // check for runnable jobs
91 | if(OS.runnablejobs) {
92 | j = OS.runnablejobs;
93 | OS.runnablejobs = j->next;
94 | } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs
95 | j = OS.scheduledjobs;
96 | OS.scheduledjobs = j->next;
97 | } else { // nothing pending
98 | hal_sleep(); // wake by irq (timer already restarted)
99 | }
100 | hal_enableIRQs();
101 | if(j) { // run job callback
102 | j->func(j);
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/lmic/oslmic.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | //! \file
13 | #ifndef _oslmic_h_
14 | #define _oslmic_h_
15 |
16 | // Dependencies required for the LoRa MAC in C to run.
17 | // These settings can be adapted to the underlying system.
18 | // You should not, however, change the lmic.[hc]
19 |
20 |
21 |
22 | //================================================================================
23 | //================================================================================
24 | // Target platform as C library
25 | typedef unsigned char bit_t;
26 | typedef unsigned char u1_t;
27 | typedef signed char s1_t;
28 | typedef unsigned short u2_t;
29 | typedef short s2_t;
30 | typedef unsigned int u4_t;
31 | typedef int s4_t;
32 | typedef unsigned long long u8_t;
33 | typedef long long s8_t;
34 | typedef unsigned int uint;
35 | typedef const char* str_t;
36 |
37 | #include
38 | #include "hal.h"
39 | #define EV(a,b,c) /**/
40 | #define DO_DEVDB(field1,field2) /**/
41 | #if !defined(CFG_noassert)
42 | #define ASSERT(cond) if(!(cond)) hal_failed()
43 | #else
44 | #define ASSERT(cond) /**/
45 | #endif
46 |
47 | #define os_clearMem(a,b) memset(a,0,b)
48 | #define os_copyMem(a,b,c) memcpy(a,b,c)
49 |
50 | typedef struct osjob_t osjob_t;
51 | typedef struct band_t band_t;
52 | typedef struct chnldef_t chnldef_t;
53 | typedef struct rxsched_t rxsched_t;
54 | typedef struct bcninfo_t bcninfo_t;
55 | typedef const u1_t* xref2cu1_t;
56 | typedef u1_t* xref2u1_t;
57 | #define TYPEDEF_xref2rps_t typedef rps_t* xref2rps_t
58 | #define TYPEDEF_xref2rxsched_t typedef rxsched_t* xref2rxsched_t
59 | #define TYPEDEF_xref2chnldef_t typedef chnldef_t* xref2chnldef_t
60 | #define TYPEDEF_xref2band_t typedef band_t* xref2band_t
61 | #define TYPEDEF_xref2osjob_t typedef osjob_t* xref2osjob_t
62 |
63 | #define SIZEOFEXPR(x) sizeof(x)
64 |
65 | #define ON_LMIC_EVENT(ev) onEvent(ev)
66 | #define DECL_ON_LMIC_EVENT void onEvent(ev_t e)
67 |
68 | extern u4_t AESAUX[];
69 | extern u4_t AESKEY[];
70 | #define AESkey ((u1_t*)AESKEY)
71 | #define AESaux ((u1_t*)AESAUX)
72 | #define FUNC_ADDR(func) (&(func))
73 |
74 | u1_t radio_rand1 (void);
75 | #define os_getRndU1() radio_rand1()
76 |
77 | #define DEFINE_LMIC struct lmic_t LMIC
78 | #define DECLARE_LMIC extern struct lmic_t LMIC
79 |
80 | void radio_init (void);
81 | void radio_irq_handler (u1_t dio);
82 | void os_init (void);
83 | void os_runloop (void);
84 |
85 | //================================================================================
86 |
87 |
88 | #ifndef RX_RAMPUP
89 | #define RX_RAMPUP (us2osticks(2000))
90 | #endif
91 | #ifndef TX_RAMPUP
92 | #define TX_RAMPUP (us2osticks(2000))
93 | #endif
94 |
95 | #ifndef OSTICKS_PER_SEC
96 | #define OSTICKS_PER_SEC 32768
97 | #elif OSTICKS_PER_SEC < 10000 || OSTICKS_PER_SEC > 64516
98 | #error Illegal OSTICKS_PER_SEC - must be in range [10000:64516]. One tick must be 15.5us .. 100us long.
99 | #endif
100 |
101 | typedef s4_t ostime_t;
102 |
103 | #if !HAS_ostick_conv
104 | #define us2osticks(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC) / 1000000))
105 | #define ms2osticks(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC) / 1000))
106 | #define sec2osticks(sec) ((ostime_t)( (s8_t)(sec) * OSTICKS_PER_SEC))
107 | #define osticks2ms(os) ((s4_t)(((os)*(s8_t)1000 ) / OSTICKS_PER_SEC))
108 | #define osticks2us(os) ((s4_t)(((os)*(s8_t)1000000 ) / OSTICKS_PER_SEC))
109 | // Special versions
110 | #define us2osticksCeil(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC + 999999) / 1000000))
111 | #define us2osticksRound(us) ((ostime_t)( ((s8_t)(us) * OSTICKS_PER_SEC + 500000) / 1000000))
112 | #define ms2osticksCeil(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC + 999) / 1000))
113 | #define ms2osticksRound(ms) ((ostime_t)( ((s8_t)(ms) * OSTICKS_PER_SEC + 500) / 1000))
114 | #endif
115 |
116 |
117 | struct osjob_t; // fwd decl.
118 | typedef void (*osjobcb_t) (struct osjob_t*);
119 | struct osjob_t {
120 | struct osjob_t* next;
121 | ostime_t deadline;
122 | osjobcb_t func;
123 | };
124 | TYPEDEF_xref2osjob_t;
125 |
126 |
127 | #ifndef HAS_os_calls
128 |
129 | #ifndef os_getDevKey
130 | void os_getDevKey (xref2u1_t buf);
131 | #endif
132 | #ifndef os_getArtEui
133 | void os_getArtEui (xref2u1_t buf);
134 | #endif
135 | #ifndef os_getDevEui
136 | void os_getDevEui (xref2u1_t buf);
137 | #endif
138 | #ifndef os_setCallback
139 | void os_setCallback (xref2osjob_t job, osjobcb_t cb);
140 | #endif
141 | #ifndef os_setTimedCallback
142 | void os_setTimedCallback (xref2osjob_t job, ostime_t time, osjobcb_t cb);
143 | #endif
144 | #ifndef os_clearCallback
145 | void os_clearCallback (xref2osjob_t job);
146 | #endif
147 | #ifndef os_getTime
148 | ostime_t os_getTime (void);
149 | #endif
150 | #ifndef os_getTimeSecs
151 | uint os_getTimeSecs (void);
152 | #endif
153 | #ifndef os_radio
154 | void os_radio (u1_t mode);
155 | #endif
156 | #ifndef os_getBattLevel
157 | u1_t os_getBattLevel (void);
158 | #endif
159 |
160 | #ifndef os_rlsbf4
161 | //! Read 32-bit quantity from given pointer in little endian byte order.
162 | u4_t os_rlsbf4 (xref2cu1_t buf);
163 | #endif
164 | #ifndef os_wlsbf4
165 | //! Write 32-bit quntity into buffer in little endian byte order.
166 | void os_wlsbf4 (xref2u1_t buf, u4_t value);
167 | #endif
168 | #ifndef os_rmsbf4
169 | //! Read 32-bit quantity from given pointer in big endian byte order.
170 | u4_t os_rmsbf4 (xref2cu1_t buf);
171 | #endif
172 | #ifndef os_wmsbf4
173 | //! Write 32-bit quntity into buffer in big endian byte order.
174 | void os_wmsbf4 (xref2u1_t buf, u4_t value);
175 | #endif
176 | #ifndef os_rlsbf2
177 | //! Read 16-bit quantity from given pointer in little endian byte order.
178 | u2_t os_rlsbf2 (xref2cu1_t buf);
179 | #endif
180 | #ifndef os_wlsbf2
181 | //! Write 16-bit quntity into buffer in little endian byte order.
182 | void os_wlsbf2 (xref2u1_t buf, u2_t value);
183 | #endif
184 |
185 | //! Get random number (default impl for u2_t).
186 | #ifndef os_getRndU2
187 | #define os_getRndU2() ((u2_t)((os_getRndU1()<<8)|os_getRndU1()))
188 | #endif
189 | #ifndef os_crc16
190 | u2_t os_crc16 (xref2u1_t d, uint len);
191 | #endif
192 |
193 | #endif // !HAS_os_calls
194 |
195 | // ======================================================================
196 | // AES support
197 | // !!Keep in sync with lorabase.hpp!!
198 |
199 | #ifndef AES_ENC // if AES_ENC is defined as macro all other values must be too
200 | #define AES_ENC 0x00
201 | #define AES_DEC 0x01
202 | #define AES_MIC 0x02
203 | #define AES_CTR 0x04
204 | #define AES_MICNOAUX 0x08
205 | #endif
206 | #ifndef AESkey // if AESkey is defined as macro all other values must be too
207 | extern xref2u1_t AESkey;
208 | extern xref2u1_t AESaux;
209 | #endif
210 | #ifndef os_aes
211 | u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len);
212 | #endif
213 |
214 |
215 |
216 | #endif // _oslmic_h_
217 |
--------------------------------------------------------------------------------
/lmic/radio.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014-2015 IBM Corporation.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/epl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Zurich Research Lab - initial API, implementation and documentation
10 | *******************************************************************************/
11 |
12 | #include "lmic.h"
13 |
14 | // ----------------------------------------
15 | // Registers Mapping
16 | #define RegFifo 0x00 // common
17 | #define RegOpMode 0x01 // common
18 | #define FSKRegBitrateMsb 0x02
19 | #define FSKRegBitrateLsb 0x03
20 | #define FSKRegFdevMsb 0x04
21 | #define FSKRegFdevLsb 0x05
22 | #define RegFrfMsb 0x06 // common
23 | #define RegFrfMid 0x07 // common
24 | #define RegFrfLsb 0x08 // common
25 | #define RegPaConfig 0x09 // common
26 | #define RegPaRamp 0x0A // common
27 | #define RegOcp 0x0B // common
28 | #define RegLna 0x0C // common
29 | #define FSKRegRxConfig 0x0D
30 | #define LORARegFifoAddrPtr 0x0D
31 | #define FSKRegRssiConfig 0x0E
32 | #define LORARegFifoTxBaseAddr 0x0E
33 | #define FSKRegRssiCollision 0x0F
34 | #define LORARegFifoRxBaseAddr 0x0F
35 | #define FSKRegRssiThresh 0x10
36 | #define LORARegFifoRxCurrentAddr 0x10
37 | #define FSKRegRssiValue 0x11
38 | #define LORARegIrqFlagsMask 0x11
39 | #define FSKRegRxBw 0x12
40 | #define LORARegIrqFlags 0x12
41 | #define FSKRegAfcBw 0x13
42 | #define LORARegRxNbBytes 0x13
43 | #define FSKRegOokPeak 0x14
44 | #define LORARegRxHeaderCntValueMsb 0x14
45 | #define FSKRegOokFix 0x15
46 | #define LORARegRxHeaderCntValueLsb 0x15
47 | #define FSKRegOokAvg 0x16
48 | #define LORARegRxPacketCntValueMsb 0x16
49 | #define LORARegRxpacketCntValueLsb 0x17
50 | #define LORARegModemStat 0x18
51 | #define LORARegPktSnrValue 0x19
52 | #define FSKRegAfcFei 0x1A
53 | #define LORARegPktRssiValue 0x1A
54 | #define FSKRegAfcMsb 0x1B
55 | #define LORARegRssiValue 0x1B
56 | #define FSKRegAfcLsb 0x1C
57 | #define LORARegHopChannel 0x1C
58 | #define FSKRegFeiMsb 0x1D
59 | #define LORARegModemConfig1 0x1D
60 | #define FSKRegFeiLsb 0x1E
61 | #define LORARegModemConfig2 0x1E
62 | #define FSKRegPreambleDetect 0x1F
63 | #define LORARegSymbTimeoutLsb 0x1F
64 | #define FSKRegRxTimeout1 0x20
65 | #define LORARegPreambleMsb 0x20
66 | #define FSKRegRxTimeout2 0x21
67 | #define LORARegPreambleLsb 0x21
68 | #define FSKRegRxTimeout3 0x22
69 | #define LORARegPayloadLength 0x22
70 | #define FSKRegRxDelay 0x23
71 | #define LORARegPayloadMaxLength 0x23
72 | #define FSKRegOsc 0x24
73 | #define LORARegHopPeriod 0x24
74 | #define FSKRegPreambleMsb 0x25
75 | #define LORARegFifoRxByteAddr 0x25
76 | #define LORARegModemConfig3 0x26
77 | #define FSKRegPreambleLsb 0x26
78 | #define FSKRegSyncConfig 0x27
79 | #define LORARegFeiMsb 0x28
80 | #define FSKRegSyncValue1 0x28
81 | #define LORAFeiMib 0x29
82 | #define FSKRegSyncValue2 0x29
83 | #define LORARegFeiLsb 0x2A
84 | #define FSKRegSyncValue3 0x2A
85 | #define FSKRegSyncValue4 0x2B
86 | #define LORARegRssiWideband 0x2C
87 | #define FSKRegSyncValue5 0x2C
88 | #define FSKRegSyncValue6 0x2D
89 | #define FSKRegSyncValue7 0x2E
90 | #define FSKRegSyncValue8 0x2F
91 | #define FSKRegPacketConfig1 0x30
92 | #define FSKRegPacketConfig2 0x31
93 | #define LORARegDetectOptimize 0x31
94 | #define FSKRegPayloadLength 0x32
95 | #define FSKRegNodeAdrs 0x33
96 | #define LORARegInvertIQ 0x33
97 | #define FSKRegBroadcastAdrs 0x34
98 | #define FSKRegFifoThresh 0x35
99 | #define FSKRegSeqConfig1 0x36
100 | #define FSKRegSeqConfig2 0x37
101 | #define LORARegDetectionThreshold 0x37
102 | #define FSKRegTimerResol 0x38
103 | #define FSKRegTimer1Coef 0x39
104 | #define LORARegSyncWord 0x39
105 | #define FSKRegTimer2Coef 0x3A
106 | #define FSKRegImageCal 0x3B
107 | #define FSKRegTemp 0x3C
108 | #define FSKRegLowBat 0x3D
109 | #define FSKRegIrqFlags1 0x3E
110 | #define FSKRegIrqFlags2 0x3F
111 | #define RegDioMapping1 0x40 // common
112 | #define RegDioMapping2 0x41 // common
113 | #define RegVersion 0x42 // common
114 | // #define RegAgcRef 0x43 // common
115 | // #define RegAgcThresh1 0x44 // common
116 | // #define RegAgcThresh2 0x45 // common
117 | // #define RegAgcThresh3 0x46 // common
118 | // #define RegPllHop 0x4B // common
119 | // #define RegTcxo 0x58 // common
120 | #define RegPaDac 0x5A // common
121 | // #define RegPll 0x5C // common
122 | // #define RegPllLowPn 0x5E // common
123 | // #define RegFormerTemp 0x6C // common
124 | // #define RegBitRateFrac 0x70 // common
125 |
126 | // ----------------------------------------
127 | // spread factors and mode for RegModemConfig2
128 | #define SX1272_MC2_FSK 0x00
129 | #define SX1272_MC2_SF7 0x70
130 | #define SX1272_MC2_SF8 0x80
131 | #define SX1272_MC2_SF9 0x90
132 | #define SX1272_MC2_SF10 0xA0
133 | #define SX1272_MC2_SF11 0xB0
134 | #define SX1272_MC2_SF12 0xC0
135 | // bandwidth for RegModemConfig1
136 | #define SX1272_MC1_BW_125 0x00
137 | #define SX1272_MC1_BW_250 0x40
138 | #define SX1272_MC1_BW_500 0x80
139 | // coding rate for RegModemConfig1
140 | #define SX1272_MC1_CR_4_5 0x08
141 | #define SX1272_MC1_CR_4_6 0x10
142 | #define SX1272_MC1_CR_4_7 0x18
143 | #define SX1272_MC1_CR_4_8 0x20
144 | #define SX1272_MC1_IMPLICIT_HEADER_MODE_ON 0x04 // required for receive
145 | #define SX1272_MC1_RX_PAYLOAD_CRCON 0x02
146 | #define SX1272_MC1_LOW_DATA_RATE_OPTIMIZE 0x01 // mandated for SF11 and SF12
147 | // transmit power configuration for RegPaConfig
148 | #define SX1272_PAC_PA_SELECT_PA_BOOST 0x80
149 | #define SX1272_PAC_PA_SELECT_RFIO_PIN 0x00
150 |
151 |
152 | // sx1276 RegModemConfig1
153 | #define SX1276_MC1_BW_125 0x70
154 | #define SX1276_MC1_BW_250 0x80
155 | #define SX1276_MC1_BW_500 0x90
156 | #define SX1276_MC1_CR_4_5 0x02
157 | #define SX1276_MC1_CR_4_6 0x04
158 | #define SX1276_MC1_CR_4_7 0x06
159 | #define SX1276_MC1_CR_4_8 0x08
160 |
161 | #define SX1276_MC1_IMPLICIT_HEADER_MODE_ON 0x01
162 |
163 | // sx1276 RegModemConfig2
164 | #define SX1276_MC2_RX_PAYLOAD_CRCON 0x04
165 |
166 | // sx1276 RegModemConfig3
167 | #define SX1276_MC3_LOW_DATA_RATE_OPTIMIZE 0x08
168 | #define SX1276_MC3_AGCAUTO 0x04
169 |
170 | // preamble for lora networks (nibbles swapped)
171 | #define LORA_MAC_PREAMBLE 0x34
172 |
173 | #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1 0x0A
174 | #ifdef CFG_sx1276_radio
175 | #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x70
176 | #elif CFG_sx1272_radio
177 | #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74
178 | #endif
179 |
180 |
181 |
182 | // ----------------------------------------
183 | // Constants for radio registers
184 | #define OPMODE_LORA 0x80
185 | #define OPMODE_MASK 0x07
186 | #define OPMODE_SLEEP 0x00
187 | #define OPMODE_STANDBY 0x01
188 | #define OPMODE_FSTX 0x02
189 | #define OPMODE_TX 0x03
190 | #define OPMODE_FSRX 0x04
191 | #define OPMODE_RX 0x05
192 | #define OPMODE_RX_SINGLE 0x06
193 | #define OPMODE_CAD 0x07
194 |
195 | // ----------------------------------------
196 | // Bits masking the corresponding IRQs from the radio
197 | #define IRQ_LORA_RXTOUT_MASK 0x80
198 | #define IRQ_LORA_RXDONE_MASK 0x40
199 | #define IRQ_LORA_CRCERR_MASK 0x20
200 | #define IRQ_LORA_HEADER_MASK 0x10
201 | #define IRQ_LORA_TXDONE_MASK 0x08
202 | #define IRQ_LORA_CDDONE_MASK 0x04
203 | #define IRQ_LORA_FHSSCH_MASK 0x02
204 | #define IRQ_LORA_CDDETD_MASK 0x01
205 |
206 | #define IRQ_FSK1_MODEREADY_MASK 0x80
207 | #define IRQ_FSK1_RXREADY_MASK 0x40
208 | #define IRQ_FSK1_TXREADY_MASK 0x20
209 | #define IRQ_FSK1_PLLLOCK_MASK 0x10
210 | #define IRQ_FSK1_RSSI_MASK 0x08
211 | #define IRQ_FSK1_TIMEOUT_MASK 0x04
212 | #define IRQ_FSK1_PREAMBLEDETECT_MASK 0x02
213 | #define IRQ_FSK1_SYNCADDRESSMATCH_MASK 0x01
214 | #define IRQ_FSK2_FIFOFULL_MASK 0x80
215 | #define IRQ_FSK2_FIFOEMPTY_MASK 0x40
216 | #define IRQ_FSK2_FIFOLEVEL_MASK 0x20
217 | #define IRQ_FSK2_FIFOOVERRUN_MASK 0x10
218 | #define IRQ_FSK2_PACKETSENT_MASK 0x08
219 | #define IRQ_FSK2_PAYLOADREADY_MASK 0x04
220 | #define IRQ_FSK2_CRCOK_MASK 0x02
221 | #define IRQ_FSK2_LOWBAT_MASK 0x01
222 |
223 | // ----------------------------------------
224 | // DIO function mappings D0D1D2D3
225 | #define MAP_DIO0_LORA_RXDONE 0x00 // 00------
226 | #define MAP_DIO0_LORA_TXDONE 0x40 // 01------
227 | #define MAP_DIO1_LORA_RXTOUT 0x00 // --00----
228 | #define MAP_DIO1_LORA_NOP 0x30 // --11----
229 | #define MAP_DIO2_LORA_NOP 0xC0 // ----11--
230 |
231 | #define MAP_DIO0_FSK_READY 0x00 // 00------ (packet sent / payload ready)
232 | #define MAP_DIO1_FSK_NOP 0x30 // --11----
233 | #define MAP_DIO2_FSK_TXNOP 0x04 // ----01--
234 | #define MAP_DIO2_FSK_TIMEOUT 0x08 // ----10--
235 |
236 |
237 | // FSK IMAGECAL defines
238 | #define RF_IMAGECAL_AUTOIMAGECAL_MASK 0x7F
239 | #define RF_IMAGECAL_AUTOIMAGECAL_ON 0x80
240 | #define RF_IMAGECAL_AUTOIMAGECAL_OFF 0x00 // Default
241 |
242 | #define RF_IMAGECAL_IMAGECAL_MASK 0xBF
243 | #define RF_IMAGECAL_IMAGECAL_START 0x40
244 |
245 | #define RF_IMAGECAL_IMAGECAL_RUNNING 0x20
246 | #define RF_IMAGECAL_IMAGECAL_DONE 0x00 // Default
247 |
248 |
249 | // RADIO STATE
250 | // (initialized by radio_init(), used by radio_rand1())
251 | static u1_t randbuf[16];
252 |
253 |
254 | #ifdef CFG_sx1276_radio
255 | #define LNA_RX_GAIN (0x20|0x1)
256 | #elif CFG_sx1272_radio
257 | #define LNA_RX_GAIN (0x20|0x03)
258 | #else
259 | #error Missing CFG_sx1272_radio/CFG_sx1276_radio
260 | #endif
261 |
262 |
263 | static void writeReg (u1_t addr, u1_t data ) {
264 | hal_pin_nss(0);
265 | hal_spi(addr | 0x80);
266 | hal_spi(data);
267 | hal_pin_nss(1);
268 | }
269 |
270 | static u1_t readReg (u1_t addr) {
271 | hal_pin_nss(0);
272 | hal_spi(addr & 0x7F);
273 | u1_t val = hal_spi(0x00);
274 | hal_pin_nss(1);
275 | return val;
276 | }
277 |
278 | static void writeBuf (u1_t addr, xref2u1_t buf, u1_t len) {
279 | hal_pin_nss(0);
280 | hal_spi(addr | 0x80);
281 | for (u1_t i=0; i>16));
393 | writeReg(RegFrfMid, (u1_t)(frf>> 8));
394 | writeReg(RegFrfLsb, (u1_t)(frf>> 0));
395 | }
396 |
397 |
398 |
399 | static void configPower () {
400 | #ifdef CFG_sx1276_radio
401 | // no boost used for now
402 | s1_t pw = (s1_t)LMIC.txpow;
403 | if(pw >= 17) {
404 | pw = 15;
405 | } else if(pw < 2) {
406 | pw = 2;
407 | }
408 | // check board type for BOOST pin
409 | writeReg(RegPaConfig, (u1_t)(0x80|(pw&0xf)));
410 | writeReg(RegPaDac, readReg(RegPaDac)|0x4);
411 |
412 | #elif CFG_sx1272_radio
413 | // set PA config (2-17 dBm using PA_BOOST)
414 | s1_t pw = (s1_t)LMIC.txpow;
415 | if(pw > 17) {
416 | pw = 17;
417 | } else if(pw < 2) {
418 | pw = 2;
419 | }
420 | writeReg(RegPaConfig, (u1_t)(0x80|(pw-2)));
421 | #else
422 | #error Missing CFG_sx1272_radio/CFG_sx1276_radio
423 | #endif /* CFG_sx1272_radio */
424 | }
425 |
426 | static void txfsk () {
427 | // select FSK modem (from sleep mode)
428 | writeReg(RegOpMode, 0x10); // FSK, BT=0.5
429 | ASSERT(readReg(RegOpMode) == 0x10);
430 | // enter standby mode (required for FIFO loading))
431 | opmode(OPMODE_STANDBY);
432 | // set bitrate
433 | writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
434 | writeReg(FSKRegBitrateLsb, 0x80);
435 | // set frequency deviation
436 | writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
437 | writeReg(FSKRegFdevLsb, 0x99);
438 | // frame and packet handler settings
439 | writeReg(FSKRegPreambleMsb, 0x00);
440 | writeReg(FSKRegPreambleLsb, 0x05);
441 | writeReg(FSKRegSyncConfig, 0x12);
442 | writeReg(FSKRegPacketConfig1, 0xD0);
443 | writeReg(FSKRegPacketConfig2, 0x40);
444 | writeReg(FSKRegSyncValue1, 0xC1);
445 | writeReg(FSKRegSyncValue2, 0x94);
446 | writeReg(FSKRegSyncValue3, 0xC1);
447 | // configure frequency
448 | configChannel();
449 | // configure output power
450 | configPower();
451 |
452 | // set the IRQ mapping DIO0=PacketSent DIO1=NOP DIO2=NOP
453 | writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TXNOP);
454 |
455 | // initialize the payload size and address pointers
456 | writeReg(FSKRegPayloadLength, LMIC.dataLen+1); // (insert length byte into payload))
457 |
458 | // download length byte and buffer to the radio FIFO
459 | writeReg(RegFifo, LMIC.dataLen);
460 | writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
461 |
462 | // enable antenna switch for TX
463 | hal_pin_rxtx(1);
464 |
465 | // now we actually start the transmission
466 | opmode(OPMODE_TX);
467 | }
468 |
469 | static void txlora () {
470 | // select LoRa modem (from sleep mode)
471 | //writeReg(RegOpMode, OPMODE_LORA);
472 | opmodeLora();
473 | ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
474 |
475 | // enter standby mode (required for FIFO loading))
476 | opmode(OPMODE_STANDBY);
477 | // configure LoRa modem (cfg1, cfg2)
478 | configLoraModem();
479 | // configure frequency
480 | configChannel();
481 | // configure output power
482 | writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec
483 | configPower();
484 | // set sync word
485 | writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
486 |
487 | // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
488 | writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP);
489 | // clear all radio IRQ flags
490 | writeReg(LORARegIrqFlags, 0xFF);
491 | // mask all IRQs but TxDone
492 | writeReg(LORARegIrqFlagsMask, ~IRQ_LORA_TXDONE_MASK);
493 |
494 | // initialize the payload size and address pointers
495 | writeReg(LORARegFifoTxBaseAddr, 0x00);
496 | writeReg(LORARegFifoAddrPtr, 0x00);
497 | writeReg(LORARegPayloadLength, LMIC.dataLen);
498 |
499 | // download buffer to the radio FIFO
500 | writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
501 |
502 | // enable antenna switch for TX
503 | hal_pin_rxtx(1);
504 |
505 | // now we actually start the transmission
506 | opmode(OPMODE_TX);
507 | }
508 |
509 | // start transmitter (buf=LMIC.frame, len=LMIC.dataLen)
510 | static void starttx () {
511 | ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
512 | if(getSf(LMIC.rps) == FSK) { // FSK modem
513 | txfsk();
514 | } else { // LoRa modem
515 | txlora();
516 | }
517 | // the radio will go back to STANDBY mode as soon as the TX is finished
518 | // the corresponding IRQ will inform us about completion.
519 | }
520 |
521 | enum { RXMODE_SINGLE, RXMODE_SCAN, RXMODE_RSSI };
522 |
523 | static const u1_t rxlorairqmask[] = {
524 | [RXMODE_SINGLE] = IRQ_LORA_RXDONE_MASK|IRQ_LORA_RXTOUT_MASK,
525 | [RXMODE_SCAN] = IRQ_LORA_RXDONE_MASK,
526 | [RXMODE_RSSI] = 0x00,
527 | };
528 |
529 | // start LoRa receiver (time=LMIC.rxtime, timeout=LMIC.rxsyms, result=LMIC.frame[LMIC.dataLen])
530 | static void rxlora (u1_t rxmode) {
531 | // select LoRa modem (from sleep mode)
532 | opmodeLora();
533 | ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
534 | // enter standby mode (warm up))
535 | opmode(OPMODE_STANDBY);
536 | // don't use MAC settings at startup
537 | if(rxmode == RXMODE_RSSI) { // use fixed settings for rssi scan
538 | writeReg(LORARegModemConfig1, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1);
539 | writeReg(LORARegModemConfig2, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2);
540 | } else { // single or continuous rx mode
541 | // configure LoRa modem (cfg1, cfg2)
542 | configLoraModem();
543 | // configure frequency
544 | configChannel();
545 | }
546 | // set LNA gain
547 | writeReg(RegLna, LNA_RX_GAIN);
548 | // set max payload size
549 | writeReg(LORARegPayloadMaxLength, 64);
550 | // use inverted I/Q signal (prevent mote-to-mote communication)
551 | writeReg(LORARegInvertIQ, readReg(LORARegInvertIQ)|(1<<6));
552 | // set symbol timeout (for single rx)
553 | writeReg(LORARegSymbTimeoutLsb, LMIC.rxsyms);
554 | // set sync word
555 | writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
556 |
557 | // configure DIO mapping DIO0=RxDone DIO1=RxTout DIO2=NOP
558 | writeReg(RegDioMapping1, MAP_DIO0_LORA_RXDONE|MAP_DIO1_LORA_RXTOUT|MAP_DIO2_LORA_NOP);
559 | // clear all radio IRQ flags
560 | writeReg(LORARegIrqFlags, 0xFF);
561 | // enable required radio IRQs
562 | writeReg(LORARegIrqFlagsMask, ~rxlorairqmask[rxmode]);
563 |
564 | // enable antenna switch for RX
565 | hal_pin_rxtx(0);
566 |
567 | // now instruct the radio to receive
568 | if (rxmode == RXMODE_SINGLE) { // single rx
569 | hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
570 | opmode(OPMODE_RX_SINGLE);
571 | } else { // continous rx (scan or rssi)
572 | opmode(OPMODE_RX);
573 | }
574 | }
575 |
576 | static void rxfsk (u1_t rxmode) {
577 | // only single rx (no continuous scanning, no noise sampling)
578 | ASSERT( rxmode == RXMODE_SINGLE );
579 | // select FSK modem (from sleep mode)
580 | //writeReg(RegOpMode, 0x00); // (not LoRa)
581 | opmodeFSK();
582 | ASSERT((readReg(RegOpMode) & OPMODE_LORA) == 0);
583 | // enter standby mode (warm up))
584 | opmode(OPMODE_STANDBY);
585 | // configure frequency
586 | configChannel();
587 | // set LNA gain
588 | //writeReg(RegLna, 0x20|0x03); // max gain, boost enable
589 | writeReg(RegLna, LNA_RX_GAIN);
590 | // configure receiver
591 | writeReg(FSKRegRxConfig, 0x1E); // AFC auto, AGC, trigger on preamble?!?
592 | // set receiver bandwidth
593 | writeReg(FSKRegRxBw, 0x0B); // 50kHz SSb
594 | // set AFC bandwidth
595 | writeReg(FSKRegAfcBw, 0x12); // 83.3kHz SSB
596 | // set preamble detection
597 | writeReg(FSKRegPreambleDetect, 0xAA); // enable, 2 bytes, 10 chip errors
598 | // set sync config
599 | writeReg(FSKRegSyncConfig, 0x12); // no auto restart, preamble 0xAA, enable, fill FIFO, 3 bytes sync
600 | // set packet config
601 | writeReg(FSKRegPacketConfig1, 0xD8); // var-length, whitening, crc, no auto-clear, no adr filter
602 | writeReg(FSKRegPacketConfig2, 0x40); // packet mode
603 | // set sync value
604 | writeReg(FSKRegSyncValue1, 0xC1);
605 | writeReg(FSKRegSyncValue2, 0x94);
606 | writeReg(FSKRegSyncValue3, 0xC1);
607 | // set preamble timeout
608 | writeReg(FSKRegRxTimeout2, 0xFF);//(LMIC.rxsyms+1)/2);
609 | // set bitrate
610 | writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
611 | writeReg(FSKRegBitrateLsb, 0x80);
612 | // set frequency deviation
613 | writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
614 | writeReg(FSKRegFdevLsb, 0x99);
615 |
616 | // configure DIO mapping DIO0=PayloadReady DIO1=NOP DIO2=TimeOut
617 | writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TIMEOUT);
618 |
619 | // enable antenna switch for RX
620 | hal_pin_rxtx(0);
621 |
622 | // now instruct the radio to receive
623 | hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
624 | opmode(OPMODE_RX); // no single rx mode available in FSK
625 | }
626 |
627 | static void startrx (u1_t rxmode) {
628 | ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
629 | if(getSf(LMIC.rps) == FSK) { // FSK modem
630 | rxfsk(rxmode);
631 | } else { // LoRa modem
632 | rxlora(rxmode);
633 | }
634 | // the radio will go back to STANDBY mode as soon as the RX is finished
635 | // or timed out, and the corresponding IRQ will inform us about completion.
636 | }
637 |
638 | // get random seed from wideband noise rssi
639 | void radio_init () {
640 | hal_disableIRQs();
641 |
642 | // manually reset radio
643 | #ifdef CFG_sx1276_radio
644 | hal_pin_rst(0); // drive RST pin low
645 | #else
646 | hal_pin_rst(1); // drive RST pin high
647 | #endif
648 | hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us
649 | hal_pin_rst(2); // configure RST pin floating!
650 | hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms
651 |
652 | opmode(OPMODE_SLEEP);
653 |
654 | // some sanity checks, e.g., read version number
655 | u1_t v = readReg(RegVersion);
656 | #ifdef CFG_sx1276_radio
657 | ASSERT(v == 0x12 );
658 | #elif CFG_sx1272_radio
659 | ASSERT(v == 0x22);
660 | #else
661 | #error Missing CFG_sx1272_radio/CFG_sx1276_radio
662 | #endif
663 | // seed 15-byte randomness via noise rssi
664 | rxlora(RXMODE_RSSI);
665 | while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx
666 | for(int i=1; i<16; i++) {
667 | for(int j=0; j<8; j++) {
668 | u1_t b; // wait for two non-identical subsequent least-significant bits
669 | while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) );
670 | randbuf[i] = (randbuf[i] << 1) | b;
671 | }
672 | }
673 | randbuf[0] = 16; // set initial index
674 |
675 | #ifdef CFG_sx1276_radio //CFG_sx1276mb1_board
676 | // chain calibration
677 | writeReg(RegPaConfig, 0);
678 |
679 | // Launch Rx chain calibration for LF band
680 | writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
681 | while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; }
682 |
683 | // Sets a Frequency in HF band
684 | u4_t frf = 868000000;
685 | writeReg(RegFrfMsb, (u1_t)(frf>>16));
686 | writeReg(RegFrfMid, (u1_t)(frf>> 8));
687 | writeReg(RegFrfLsb, (u1_t)(frf>> 0));
688 |
689 | // Launch Rx chain calibration for HF band
690 | writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
691 | while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; }
692 | #endif /* CFG_sx1276_radio //CFG_sx1276mb1_board */
693 |
694 | opmode(OPMODE_SLEEP);
695 |
696 | hal_enableIRQs();
697 | }
698 |
699 | // return next random byte derived from seed buffer
700 | // (buf[0] holds index of next byte to be returned)
701 | u1_t radio_rand1 () {
702 | u1_t i = randbuf[0];
703 | ASSERT( i != 0 );
704 | if( i==16 ) {
705 | os_aes(AES_ENC, randbuf, 16); // encrypt seed with any key
706 | i = 0;
707 | }
708 | u1_t v = randbuf[i++];
709 | randbuf[0] = i;
710 | return v;
711 | }
712 |
713 | u1_t radio_rssi () {
714 | hal_disableIRQs();
715 | u1_t r = readReg(LORARegRssiValue);
716 | hal_enableIRQs();
717 | return r;
718 | }
719 |
720 | static const u2_t LORA_RXDONE_FIXUP[] = {
721 | [FSK] = us2osticks(0), // ( 0 ticks)
722 | [SF7] = us2osticks(0), // ( 0 ticks)
723 | [SF8] = us2osticks(1648), // ( 54 ticks)
724 | [SF9] = us2osticks(3265), // ( 107 ticks)
725 | [SF10] = us2osticks(7049), // ( 231 ticks)
726 | [SF11] = us2osticks(13641), // ( 447 ticks)
727 | [SF12] = us2osticks(31189), // (1022 ticks)
728 | };
729 |
730 | // called by hal ext IRQ handler
731 | // (radio goes to stanby mode after tx/rx operations)
732 | void radio_irq_handler (u1_t dio) {
733 | ostime_t now = os_getTime();
734 | if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem
735 | u1_t flags = readReg(LORARegIrqFlags);
736 | if( flags & IRQ_LORA_TXDONE_MASK ) {
737 | // save exact tx time
738 | LMIC.txend = now - us2osticks(43); // TXDONE FIXUP
739 | } else if( flags & IRQ_LORA_RXDONE_MASK ) {
740 | // save exact rx time
741 | if(getBw(LMIC.rps) == BW125) {
742 | now -= LORA_RXDONE_FIXUP[getSf(LMIC.rps)];
743 | }
744 | LMIC.rxtime = now;
745 | // read the PDU and inform the MAC that we received something
746 | LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ?
747 | readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes);
748 | // set FIFO read address pointer
749 | writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr));
750 | // now read the FIFO
751 | readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
752 | // read rx quality parameters
753 | LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4
754 | LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
755 | } else if( flags & IRQ_LORA_RXTOUT_MASK ) {
756 | // indicate timeout
757 | LMIC.dataLen = 0;
758 | }
759 | // mask all radio IRQs
760 | writeReg(LORARegIrqFlagsMask, 0xFF);
761 | // clear radio IRQ flags
762 | writeReg(LORARegIrqFlags, 0xFF);
763 | } else { // FSK modem
764 | u1_t flags1 = readReg(FSKRegIrqFlags1);
765 | u1_t flags2 = readReg(FSKRegIrqFlags2);
766 | if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) {
767 | // save exact tx time
768 | LMIC.txend = now;
769 | } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) {
770 | // save exact rx time
771 | LMIC.rxtime = now;
772 | // read the PDU and inform the MAC that we received something
773 | LMIC.dataLen = readReg(FSKRegPayloadLength);
774 | // now read the FIFO
775 | readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
776 | // read rx quality parameters
777 | LMIC.snr = 0; // determine snr
778 | LMIC.rssi = 0; // determine rssi
779 | } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) {
780 | // indicate timeout
781 | LMIC.dataLen = 0;
782 | } else {
783 | while(1);
784 | }
785 | }
786 | // go from stanby to sleep
787 | opmode(OPMODE_SLEEP);
788 | // run os job (use preset func ptr)
789 | os_setCallback(&LMIC.osjob, LMIC.osjob.func);
790 | }
791 |
792 | void os_radio (u1_t mode) {
793 | hal_disableIRQs();
794 | switch (mode) {
795 | case RADIO_RST:
796 | // put radio to sleep
797 | opmode(OPMODE_SLEEP);
798 | break;
799 |
800 | case RADIO_TX:
801 | // transmit frame now
802 | starttx(); // buf=LMIC.frame, len=LMIC.dataLen
803 | break;
804 |
805 | case RADIO_RX:
806 | // receive frame now (exactly at rxtime)
807 | startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms
808 | break;
809 |
810 | case RADIO_RXON:
811 | // start scanning for beacon now
812 | startrx(RXMODE_SCAN); // buf=LMIC.frame
813 | break;
814 | }
815 | hal_enableIRQs();
816 | }
817 |
--------------------------------------------------------------------------------