Erriez Oregon THN128 433MHz temperature sensor library for Arduino 1.1.1
This is an Oregon THN128 433MHz temperature sensor transmit/receive library for Arduino.
Loading...
Searching...
No Matches
ErriezOregonTHN128Receive.c
Go to the documentation of this file.
1/*
2 * MIT License
3 *
4 * Copyright (c) 2020-2026 Erriez
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
33#include <Arduino.h>
34
35#if defined(ARDUINO_ARCH_AVR)
36#include <avr/interrupt.h>
37#endif
38
40
51
52/* Static variables */
53static uint8_t _rxPin;
54static uint32_t _tPulseBegin;
55static uint16_t _tPinHigh;
56static uint16_t _tPinLow;
57static int8_t _rxBit;
58static volatile uint32_t _rxData;
59static volatile RxState_t _rxState = StateSearchSync;
60
61/* Pin functions */
62#if defined(ARDUINO_ARCH_AVR)
63static uint8_t _rxPinPort;
64static uint8_t _rxPinBit;
65
72#define RF_RX_PIN_INIT(rfRxPin) { \
73 /* Save interrupt number of the RF pin */ \
74 _rxPin = digitalPinToInterrupt(extIntPin); \
75 /* Save pin port and bit */ \
76 _rxPinPort = digitalPinToPort(extIntPin); \
77 _rxPinBit = digitalPinToBitMask(extIntPin); \
78}
79
85#define RF_RX_PIN_READ() (*portInputRegister(_rxPinPort) & _rxPinBit)
86
87#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
88
95#define RF_RX_PIN_INIT(rfRxPin) { _rxPin = rfRxPin; }
96
102#define RF_RX_PIN_READ() (digitalRead(_rxPin) ? HIGH : LOW)
103
104#else
105#error "May work, but not tested on this target"
106#endif
107
108/* Forward declaration */
109void rfPinChange(void);
110
111
115static void rxEnable()
116{
117 /* Enable INTx change interrupt */
118 attachInterrupt(_rxPin, rfPinChange, CHANGE);
119
120 /* Initialize with search for sync state */
121 _rxState = StateSearchSync;
122}
123
127static void rxDisable()
128{
129 /* Disable INTx change interrupt */
130 detachInterrupt(_rxPin);
131}
132
146static bool isPulseInRange(uint16_t tPulse, uint16_t tMin, uint16_t tMax)
147{
148 /* Check is pulse length between min and max time */
149 if ((tPulse >= tMin) && (tPulse <= tMax)) {
150 return true;
151 } else {
152 return false;
153 }
154}
155
163static bool findSync()
164{
165 /* Read sync pulse */
166 if (isPulseInRange(_tPinHigh, T_SYNC_H_MIN, T_SYNC_H_MAX)) {
167 if (isPulseInRange(_tPinLow, T_SYNC_L_MIN_0, T_SYNC_L_MAX_0)) {
168 _rxData = 0;
169 _rxState = StateMid1;
170 _rxBit = 1;
171 return true;
172 } else if (isPulseInRange(_tPinLow, T_SYNC_L_MIN_1, T_SYNC_L_MAX_1)) {
173 _rxData = 0;
174 _rxState = StateEnd;
175 _rxBit = 0;
176 return true;
177 }
178 }
179
180 return false;
181}
182
189static void storeBit(bool one)
190{
191 /* Store received bit */
192 if (one) {
193 _rxData |= (1UL << _rxBit);
194 }
195
196 /* Check if all 32 data bits are received */
197 _rxBit++;
198 if (_rxBit >= 32) {
199 if (OregonTHN128_CheckCRC(_rxData)) {
200 _rxState = StateRxComplete;
201 /* Disable receive */
202 rxDisable();
203 } else {
204 _rxState = StateSearchSync;
205 }
206 }
207}
208
212static void handlePulse()
213{
214 if (isPulseInRange(_tPinHigh, T_BIT_SHORT_MIN, T_BIT_SHORT_MAX)) {
215 if (_rxState == StateEnd) {
216 _rxState = StateMid0;
217 storeBit(1);
218 } else if (_rxState == StateMid1) {
219 _rxState = StateEnd;
220 } else {
221 _rxState = StateSearchSync;
222 }
223 } else if (isPulseInRange(_tPinHigh, T_BIT_LONG_MIN, T_BIT_LONG_MAX)) {
224 if (_rxState == StateMid1) {
225 _rxState = StateMid0;
226 storeBit(1);
227 } else {
228 _rxState = StateSearchSync;
229 }
230 } else {
231 _rxState = StateSearchSync;
232 }
233}
234
238static void handleSpace()
239{
240 /* State machine */
241 if (isPulseInRange(_tPinLow, T_BIT_SHORT_MIN, T_BIT_SHORT_MAX)) {
242 if (_rxState == StateEnd) {
243 _rxState = StateMid1;
244 storeBit(0);
245 } else if (_rxState == StateMid0) {
246 _rxState = StateEnd;
247 } else {
248 _rxState = StateSearchSync;
249 }
250 } else if (isPulseInRange(_tPinLow, T_BIT_LONG_MIN, T_BIT_LONG_MAX)) {
251 if (_rxState == StateMid0) {
252 _rxState = StateMid1;
253 storeBit(0);
254 } else {
255 _rxState = StateSearchSync;
256 }
257 } else {
258 _rxState = StateSearchSync;
259 }
260}
261
265void IRAM_ATTR rfPinChange(void)
266{
267 uint32_t tNow;
268 uint16_t _tPulseLength;
269 uint8_t rfPinHigh;
270
271 /* Return when previous completed receive is not read */
272 if (_rxState == StateRxComplete) {
273 return;
274 }
275
276 /* Read absolute pulse time in us for sync */
277 tNow = micros();
278 if (tNow > _tPulseBegin) {
279 _tPulseLength = tNow - _tPulseBegin;
280 } else {
281 _tPulseLength = _tPulseBegin - tNow;
282 }
283
284 /* Ignore short pulses */
285 if (_tPulseLength < T_RX_TOLERANCE_US) {
286 return;
287 }
288 _tPulseBegin = tNow;
289
290 /* Get RF pin state */
291 rfPinHigh = RF_RX_PIN_READ();
292
293 /* Store pulse (high) or space (low) length */
294 if (rfPinHigh) {
295 _tPinLow = _tPulseLength;
296 } else {
297 _tPinHigh = _tPulseLength;
298 }
299
300 /* Always search for sync */
301 if (findSync()) {
302 return;
303 }
304
305 /* Handle received pulse */
306 if (_rxState != StateSearchSync) {
307 if (rfPinHigh) {
308 handleSpace();
309 } else {
310 handlePulse();
311 }
312 }
313}
314
315/*------------------------------------------------------------------------------------------------*/
316/* Public functions */
317/*------------------------------------------------------------------------------------------------*/
324void OregonTHN128_RxBegin(uint8_t extIntPin)
325{
326 /* Initialize RF RX pin */
327 RF_RX_PIN_INIT(extIntPin);
328
329 /* Enable receive */
330 rxEnable();
331}
332
337{
338 /* Enable receive */
339 rxEnable();
340}
341
346{
347 /* Disable receive */
348 rxDisable();
349}
350
359{
360 /* Return receive complete */
361 return (_rxState == StateRxComplete) ? true : false;
362}
363
374{
376 /* Convert raw 32-bit data to data structure */
377 OregonTHN128_RawToData(_rxData, data);
378 return true;
379 } else {
380 return false;
381 }
382}
bool OregonTHN128_RawToData(uint32_t rawData, OregonTHN128Data_t *data)
Cnonvert 32-bit raw data to OregonTHN128Data_t structure.
bool OregonTHN128_CheckCRC(uint32_t rawData)
Verify checksum.
void rfPinChange(void)
RF pin level change.
bool OregonTHN128_Read(OregonTHN128Data_t *data)
Read data.
RxState_t
Receive state.
void OregonTHN128_RxEnable()
Receive enable.
void OregonTHN128_RxBegin(uint8_t extIntPin)
Initialize receiver pin.
void OregonTHN128_RxDisable()
Receive disable.
bool OregonTHN128_Available()
Check if data received.
Oregon THN128 433MHz temperature receive library for Arduino.