Erriez Oregon THN128 433MHz temperature sensor library for Arduino  1.1.0
This is an Oregon THN128 433MHz temperature sensor transmit/receive library for Arduino.
ErriezOregonTHN128Receive.c
Go to the documentation of this file.
1 /*
2  * MIT License
3  *
4  * Copyright (c) 2020-2022 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 
44 typedef enum {
46  StateMid0 = 1,
47  StateMid1 = 2,
48  StateEnd = 3,
49  StateRxComplete = 4
51 
52 /* Static variables */
53 static uint8_t _rxPin;
54 static uint32_t _tPulseBegin;
55 static uint16_t _tPinHigh;
56 static uint16_t _tPinLow;
57 static int8_t _rxBit;
58 static volatile uint32_t _rxData;
59 static volatile RxState_t _rxState = StateSearchSync;
60 
61 /* Pin functions */
62 #if defined(ARDUINO_ARCH_AVR)
63 static uint8_t _rxPinPort;
64 static 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 */
109 void rfPinChange(void);
110 
111 
115 static 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 
127 static void rxDisable()
128 {
129  /* Disable INTx change interrupt */
130  detachInterrupt(_rxPin);
131 }
132 
146 static 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 
163 static 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 
189 static 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 
212 static 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 
238 static 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 
265 void 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 /*------------------------------------------------------------------------------------------------*/
324 void 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 {
375  if (OregonTHN128_Available()) {
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.