oregon2.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #include "oregon2.h"
  2. #include <lib/subghz/blocks/const.h>
  3. #include <lib/subghz/blocks/decoder.h>
  4. #include <lib/subghz/blocks/encoder.h>
  5. #include <lib/subghz/blocks/math.h>
  6. #include "ws_generic.h"
  7. #include <lib/toolbox/manchester_decoder.h>
  8. #include <lib/flipper_format/flipper_format_i.h>
  9. #define TAG "WSProtocolOregon2"
  10. static const SubGhzBlockConst ws_oregon2_const = {
  11. .te_long = 1000,
  12. .te_short = 500,
  13. .te_delta = 200,
  14. .min_count_bit_for_found = 32,
  15. };
  16. #define OREGON2_PREAMBLE_BITS 19
  17. #define OREGON2_PREAMBLE_MASK 0b1111111111111111111
  18. #define OREGON2_SENSOR_ID(d) (((d) >> 16) & 0xFFFF)
  19. #define OREGON2_CHECKSUM_BITS 8
  20. // 15 ones + 0101 (inverted A)
  21. #define OREGON2_PREAMBLE 0b1111111111111110101
  22. // bit indicating the low battery
  23. #define OREGON2_FLAG_BAT_LOW 0x4
  24. struct WSProtocolDecoderOregon2 {
  25. SubGhzProtocolDecoderBase base;
  26. SubGhzBlockDecoder decoder;
  27. WSBlockGeneric generic;
  28. ManchesterState manchester_state;
  29. bool prev_bit;
  30. bool have_bit;
  31. uint8_t var_bits;
  32. uint32_t var_data;
  33. };
  34. typedef struct WSProtocolDecoderOregon2 WSProtocolDecoderOregon2;
  35. typedef enum {
  36. Oregon2DecoderStepReset = 0,
  37. Oregon2DecoderStepFoundPreamble,
  38. Oregon2DecoderStepVarData,
  39. } Oregon2DecoderStep;
  40. void* ws_protocol_decoder_oregon2_alloc(SubGhzEnvironment* environment) {
  41. UNUSED(environment);
  42. WSProtocolDecoderOregon2* instance = malloc(sizeof(WSProtocolDecoderOregon2));
  43. instance->base.protocol = &ws_protocol_oregon2;
  44. instance->generic.protocol_name = instance->base.protocol->name;
  45. instance->generic.humidity = WS_NO_HUMIDITY;
  46. instance->generic.temp = WS_NO_TEMPERATURE;
  47. instance->generic.btn = WS_NO_BTN;
  48. instance->generic.channel = WS_NO_CHANNEL;
  49. instance->generic.battery_low = WS_NO_BATT;
  50. instance->generic.id = WS_NO_ID;
  51. return instance;
  52. }
  53. void ws_protocol_decoder_oregon2_free(void* context) {
  54. furi_assert(context);
  55. WSProtocolDecoderOregon2* instance = context;
  56. free(instance);
  57. }
  58. void ws_protocol_decoder_oregon2_reset(void* context) {
  59. furi_assert(context);
  60. WSProtocolDecoderOregon2* instance = context;
  61. instance->decoder.parser_step = Oregon2DecoderStepReset;
  62. instance->decoder.decode_data = 0UL;
  63. instance->decoder.decode_count_bit = 0;
  64. manchester_advance(
  65. instance->manchester_state, ManchesterEventReset, &instance->manchester_state, NULL);
  66. instance->have_bit = false;
  67. instance->var_data = 0;
  68. instance->var_bits = 0;
  69. }
  70. static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration) {
  71. bool is_long = false;
  72. if(DURATION_DIFF(duration, ws_oregon2_const.te_long) < ws_oregon2_const.te_delta) {
  73. is_long = true;
  74. } else if(DURATION_DIFF(duration, ws_oregon2_const.te_short) < ws_oregon2_const.te_delta) {
  75. is_long = false;
  76. } else {
  77. return ManchesterEventReset;
  78. }
  79. if(level)
  80. return is_long ? ManchesterEventLongHigh : ManchesterEventShortHigh;
  81. else
  82. return is_long ? ManchesterEventLongLow : ManchesterEventShortLow;
  83. }
  84. // From sensor id code return amount of bits in variable section
  85. static uint8_t oregon2_sensor_id_var_bits(uint16_t sensor_id) {
  86. if(sensor_id == 0xEC40) return 16;
  87. if(sensor_id == 0x1D20) return 24;
  88. return 0;
  89. }
  90. static void ws_oregon2_decode_const_data(WSBlockGeneric* ws_block) {
  91. ws_block->id = OREGON2_SENSOR_ID(ws_block->data);
  92. uint8_t ch_bits = (ws_block->data >> 12) & 0xF;
  93. ws_block->channel = 1;
  94. while(ch_bits > 1) {
  95. ws_block->channel++;
  96. ch_bits >>= 1;
  97. }
  98. ws_block->battery_low = (ws_block->data & OREGON2_FLAG_BAT_LOW) ? 1 : 0;
  99. }
  100. uint16_t bcd_decode_short(uint32_t data) {
  101. return (data & 0xF) * 10 + ((data >> 4) & 0xF);
  102. }
  103. static float ws_oregon2_decode_temp(uint32_t data) {
  104. int32_t temp_val;
  105. temp_val = bcd_decode_short(data >> 4);
  106. temp_val *= 10;
  107. temp_val += (data >> 12) & 0xF;
  108. if(data & 0xF) temp_val = -temp_val;
  109. return (float)temp_val / 10.0;
  110. }
  111. static void ws_oregon2_decode_var_data(WSBlockGeneric* ws_b, uint16_t sensor_id, uint32_t data) {
  112. switch(sensor_id) {
  113. case 0xEC40:
  114. ws_b->temp = ws_oregon2_decode_temp(data);
  115. ws_b->humidity = WS_NO_HUMIDITY;
  116. break;
  117. case 0x1D20:
  118. ws_b->humidity = bcd_decode_short(data);
  119. ws_b->temp = ws_oregon2_decode_temp(data >> 8);
  120. break;
  121. }
  122. }
  123. void ws_protocol_decoder_oregon2_feed(void* context, bool level, uint32_t duration) {
  124. furi_assert(context);
  125. WSProtocolDecoderOregon2* instance = context;
  126. // oregon v2.1 signal is inverted
  127. ManchesterEvent event = level_and_duration_to_event(!level, duration);
  128. bool data;
  129. // low-level bit sequence decoding
  130. if(event == ManchesterEventReset) {
  131. instance->decoder.parser_step = Oregon2DecoderStepReset;
  132. instance->have_bit = false;
  133. instance->decoder.decode_data = 0UL;
  134. instance->decoder.decode_count_bit = 0;
  135. }
  136. if(manchester_advance(instance->manchester_state, event, &instance->manchester_state, &data)) {
  137. if(instance->have_bit) {
  138. if(!instance->prev_bit && data) {
  139. subghz_protocol_blocks_add_bit(&instance->decoder, 1);
  140. } else if(instance->prev_bit && !data) {
  141. subghz_protocol_blocks_add_bit(&instance->decoder, 0);
  142. } else {
  143. ws_protocol_decoder_oregon2_reset(context);
  144. }
  145. instance->have_bit = false;
  146. } else {
  147. instance->prev_bit = data;
  148. instance->have_bit = true;
  149. }
  150. }
  151. switch(instance->decoder.parser_step) {
  152. case Oregon2DecoderStepReset:
  153. // waiting for fixed oregon2 preamble
  154. if(instance->decoder.decode_count_bit >= OREGON2_PREAMBLE_BITS &&
  155. ((instance->decoder.decode_data & OREGON2_PREAMBLE_MASK) == OREGON2_PREAMBLE)) {
  156. instance->decoder.parser_step = Oregon2DecoderStepFoundPreamble;
  157. instance->decoder.decode_count_bit = 0;
  158. instance->decoder.decode_data = 0UL;
  159. }
  160. break;
  161. case Oregon2DecoderStepFoundPreamble:
  162. // waiting for fixed oregon2 data
  163. if(instance->decoder.decode_count_bit == 32) {
  164. instance->generic.data = instance->decoder.decode_data;
  165. instance->generic.data_count_bit = instance->decoder.decode_count_bit;
  166. instance->decoder.decode_data = 0UL;
  167. instance->decoder.decode_count_bit = 0;
  168. // reverse nibbles in decoded data
  169. instance->generic.data = (instance->generic.data & 0x55555555) << 1 |
  170. (instance->generic.data & 0xAAAAAAAA) >> 1;
  171. instance->generic.data = (instance->generic.data & 0x33333333) << 2 |
  172. (instance->generic.data & 0xCCCCCCCC) >> 2;
  173. ws_oregon2_decode_const_data(&instance->generic);
  174. instance->var_bits =
  175. oregon2_sensor_id_var_bits(OREGON2_SENSOR_ID(instance->generic.data));
  176. if(!instance->var_bits) {
  177. // sensor is not supported, stop decoding, but showing the decoded fixed part
  178. instance->decoder.parser_step = Oregon2DecoderStepReset;
  179. if(instance->base.callback)
  180. instance->base.callback(&instance->base, instance->base.context);
  181. } else {
  182. instance->decoder.parser_step = Oregon2DecoderStepVarData;
  183. }
  184. }
  185. break;
  186. case Oregon2DecoderStepVarData:
  187. // waiting for variable (sensor-specific data)
  188. if(instance->decoder.decode_count_bit == instance->var_bits + OREGON2_CHECKSUM_BITS) {
  189. instance->var_data = instance->decoder.decode_data & 0xFFFFFFFF;
  190. // reverse nibbles in var data
  191. instance->var_data = (instance->var_data & 0x55555555) << 1 |
  192. (instance->var_data & 0xAAAAAAAA) >> 1;
  193. instance->var_data = (instance->var_data & 0x33333333) << 2 |
  194. (instance->var_data & 0xCCCCCCCC) >> 2;
  195. ws_oregon2_decode_var_data(
  196. &instance->generic,
  197. OREGON2_SENSOR_ID(instance->generic.data),
  198. instance->var_data >> OREGON2_CHECKSUM_BITS);
  199. instance->decoder.parser_step = Oregon2DecoderStepReset;
  200. if(instance->base.callback)
  201. instance->base.callback(&instance->base, instance->base.context);
  202. }
  203. break;
  204. }
  205. }
  206. uint8_t ws_protocol_decoder_oregon2_get_hash_data(void* context) {
  207. furi_assert(context);
  208. WSProtocolDecoderOregon2* instance = context;
  209. return subghz_protocol_blocks_get_hash_data(
  210. &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
  211. }
  212. bool ws_protocol_decoder_oregon2_serialize(
  213. void* context,
  214. FlipperFormat* flipper_format,
  215. SubGhzRadioPreset* preset) {
  216. furi_assert(context);
  217. WSProtocolDecoderOregon2* instance = context;
  218. if(!ws_block_generic_serialize(&instance->generic, flipper_format, preset)) return false;
  219. uint32_t temp = instance->var_bits;
  220. if(!flipper_format_write_uint32(flipper_format, "VarBits", &temp, 1)) {
  221. FURI_LOG_E(TAG, "Error adding VarBits");
  222. return false;
  223. }
  224. if(!flipper_format_write_hex(
  225. flipper_format,
  226. "VarData",
  227. (const uint8_t*)&instance->var_data,
  228. sizeof(instance->var_data))) {
  229. FURI_LOG_E(TAG, "Error adding VarData");
  230. return false;
  231. }
  232. return true;
  233. }
  234. bool ws_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipper_format) {
  235. furi_assert(context);
  236. WSProtocolDecoderOregon2* instance = context;
  237. bool ret = false;
  238. uint32_t temp_data;
  239. do {
  240. if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
  241. break;
  242. }
  243. if(!flipper_format_read_uint32(flipper_format, "VarBits", &temp_data, 1)) {
  244. FURI_LOG_E(TAG, "Missing VarLen");
  245. break;
  246. }
  247. instance->var_bits = (uint8_t)temp_data;
  248. if(!flipper_format_read_hex(
  249. flipper_format,
  250. "VarData",
  251. (uint8_t*)&instance->var_data,
  252. sizeof(instance->var_data))) {
  253. FURI_LOG_E(TAG, "Missing VarData");
  254. break;
  255. }
  256. if(instance->generic.data_count_bit != ws_oregon2_const.min_count_bit_for_found) {
  257. FURI_LOG_E(TAG, "Wrong number of bits in key: %d", instance->generic.data_count_bit);
  258. break;
  259. }
  260. ret = true;
  261. } while(false);
  262. return ret;
  263. }
  264. static void oregon2_append_check_sum(uint32_t fix_data, uint32_t var_data, FuriString* output) {
  265. uint8_t sum = fix_data & 0xF;
  266. uint8_t ref_sum = var_data & 0xFF;
  267. var_data >>= 8;
  268. for(uint8_t i = 1; i < 8; i++) {
  269. fix_data >>= 4;
  270. var_data >>= 4;
  271. sum += (fix_data & 0xF) + (var_data & 0xF);
  272. }
  273. // swap calculated sum nibbles
  274. sum = (((sum >> 4) & 0xF) | (sum << 4)) & 0xFF;
  275. if(sum == ref_sum)
  276. furi_string_cat_printf(output, "Sum ok: 0x%hhX", ref_sum);
  277. else
  278. furi_string_cat_printf(output, "Sum err: 0x%hhX vs 0x%hhX", ref_sum, sum);
  279. }
  280. void ws_protocol_decoder_oregon2_get_string(void* context, FuriString* output) {
  281. furi_assert(context);
  282. WSProtocolDecoderOregon2* instance = context;
  283. furi_string_cat_printf(
  284. output,
  285. "%s\r\n"
  286. "ID: 0x%04lX, ch: %d, bat: %d, rc: 0x%02lX\r\n",
  287. instance->generic.protocol_name,
  288. instance->generic.id,
  289. instance->generic.channel,
  290. instance->generic.battery_low,
  291. (uint32_t)(instance->generic.data >> 4) & 0xFF);
  292. if(instance->var_bits > 0) {
  293. furi_string_cat_printf(
  294. output,
  295. "Temp:%d.%d C Hum:%d%%",
  296. (int16_t)instance->generic.temp,
  297. abs(
  298. ((int16_t)(instance->generic.temp * 10) -
  299. (((int16_t)instance->generic.temp) * 10))),
  300. instance->generic.humidity);
  301. oregon2_append_check_sum((uint32_t)instance->generic.data, instance->var_data, output);
  302. }
  303. }
  304. const SubGhzProtocolDecoder ws_protocol_oregon2_decoder = {
  305. .alloc = ws_protocol_decoder_oregon2_alloc,
  306. .free = ws_protocol_decoder_oregon2_free,
  307. .feed = ws_protocol_decoder_oregon2_feed,
  308. .reset = ws_protocol_decoder_oregon2_reset,
  309. .get_hash_data = ws_protocol_decoder_oregon2_get_hash_data,
  310. .serialize = ws_protocol_decoder_oregon2_serialize,
  311. .deserialize = ws_protocol_decoder_oregon2_deserialize,
  312. .get_string = ws_protocol_decoder_oregon2_get_string,
  313. };
  314. const SubGhzProtocol ws_protocol_oregon2 = {
  315. .name = WS_PROTOCOL_OREGON2_NAME,
  316. .type = SubGhzProtocolWeatherStation,
  317. .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable,
  318. .decoder = &ws_protocol_oregon2_decoder,
  319. };