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.
ErriezOregonTHN128.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 <string.h>
34 #include <stdio.h>
35 #include "ErriezOregonTHN128.h"
36 
42 #define SET_ROL_ADDR(x) (((x) & 0x07) << 0)
44 #define GET_ROL_ADDR(x) (((x) & 0x07) << 0)
45 
47 #define SET_CHANNEL(x) ((((x) - 1) & 0x03) << 6)
49 #define GET_CHANNEL(x) ((((x) >> 6) & 0x03) + 1)
50 
52 #define SET_TEMP(x) ((((((uint32_t)(x) / 100) % 10)) << 16) | \
53  ((((uint32_t)(x) / 10) % 10) << 12) | \
54  (((x) % 10) << 8))
56 #define GET_TEMP(x) (((((x) >> 16) & 0x0f) * 100) + \
57  ((((x) >> 12) & 0x0f) * 10) + \
58  (((x) >> 8) & 0x0f))
59 
61 #define SIGN_BIT (1UL << 21)
62 
64 #define LOW_BAT_BIT (1UL << 23)
65 
67 #define SET_CRC(x) ((uint32_t)(x) << 24)
69 #define GET_CRC(x) ((x) >> 24)
70 
81 static uint8_t calcCrc(uint32_t rawData)
82 {
83  uint16_t crc;
84 
85  /* Add Bytes 0, 1 and 2 */
86  crc = ((rawData >> 16) & 0xff) + ((rawData >> 8) & 0xff) + ((rawData >> 0) & 0xff);
87  /* Add most significant Byte of the CRC to the final CRC */
88  crc = (crc >> 8) + (crc & 0xff);
89 
90  /* Return 8-bit CRC */
91  return (uint8_t)crc;
92 }
93 
101 bool OregonTHN128_CheckCRC(uint32_t rawData)
102 {
103  return calcCrc(rawData) == GET_CRC(rawData);
104 }
105 
106 /*------------------------------------------------------------------------------------------------*/
107 /* Public functions */
108 /*------------------------------------------------------------------------------------------------*/
118 void OregonTHN128_TempToString(char *temperatureStr, uint8_t temperatureStrLen, int16_t temperature)
119 {
120  bool tempNegative = false;
121  int tempAbs;
122 
123  /* Convert temperature without using float to string */
124  tempAbs = temperature;
125  if (temperature < 0) {
126  tempNegative = true;
127  tempAbs *= -1;
128  }
129 
130  snprintf(temperatureStr, temperatureStrLen, "%s%d.%d",
131  tempNegative ? "-" : "", (tempAbs / 10), tempAbs % 10);
132 }
133 
142 {
143  uint32_t rawData;
144 
145  /* Rolling address 0..7 */
146  rawData = SET_ROL_ADDR(data->rollingAddress);
147 
148  /* Set channel 1..3 */
149  rawData |= SET_CHANNEL(data->channel);
150 
151  /* Set temperature -999..999 */
152  if (data->temperature < 0) {
153  rawData |= SIGN_BIT;
154  rawData |= SET_TEMP(data->temperature * -1);
155  } else {
156  rawData |= SET_TEMP(data->temperature);
157  }
158 
159  /* Low battery bit */
160  if (data->lowBattery) {
161  rawData |= LOW_BAT_BIT;
162  }
163 
164  /* Calculate CRC */
165  rawData |= SET_CRC(calcCrc(rawData));
166 
167  /* Return 32-bit raw data */
168  return rawData;
169 }
170 
180 bool OregonTHN128_RawToData(uint32_t rawData, OregonTHN128Data_t *data)
181 {
182  memset(data, 0, sizeof(OregonTHN128Data_t));
183 
184  /* Set data structure */
185  data->rawData = rawData;
186  data->rollingAddress = GET_ROL_ADDR(rawData);
187  data->channel = GET_CHANNEL(rawData);
188  data->temperature = GET_TEMP(rawData);
189  if (rawData & SIGN_BIT) {
190  data->temperature *= -1;
191  }
192  data->lowBattery = (rawData & LOW_BAT_BIT) ? true : false;
193 
194  /* Return CRC success or failure */
195  return calcCrc(rawData) == GET_CRC(rawData);
196 }
uint32_t OregonTHN128_DataToRaw(OregonTHN128Data_t *data)
Convert data structure to 32-bit raw data.
bool OregonTHN128_RawToData(uint32_t rawData, OregonTHN128Data_t *data)
Cnonvert 32-bit raw data to OregonTHN128Data_t structure.
void OregonTHN128_TempToString(char *temperatureStr, uint8_t temperatureStrLen, int16_t temperature)
Convert temperature to string.
bool OregonTHN128_CheckCRC(uint32_t rawData)
Verify checksum.
#define SET_CRC(x)
#define GET_TEMP(x)
#define SET_ROL_ADDR(x)
#define SIGN_BIT
#define GET_CRC(x)
#define SET_TEMP(x)
#define LOW_BAT_BIT
#define SET_CHANNEL(x)
#define GET_CHANNEL(x)
#define GET_ROL_ADDR(x)