diff --git a/firmware/application/apps/ui_weatherstation.cpp b/firmware/application/apps/ui_weatherstation.cpp index c030c358d..c7c51310d 100644 --- a/firmware/application/apps/ui_weatherstation.cpp +++ b/firmware/application/apps/ui_weatherstation.cpp @@ -197,6 +197,10 @@ WeatherView::~WeatherView() { baseband::shutdown(); } +uint16_t WeatherView::bcd_decode_short(uint32_t data) { + return (data & 0xF) * 10 + ((data >> 4) & 0xF); +} + const char* WeatherView::getWeatherSensorTypeName(FPROTO_WEATHER_SENSOR type) { switch (type) { case FPW_NexusTH: @@ -225,6 +229,8 @@ const char* WeatherView::getWeatherSensorTypeName(FPROTO_WEATHER_SENSOR type) { return "LaCrosse TX141THBv2"; case FPW_OREGON2: return "Oregon2"; + case FPW_OREGON2B: + return "Oregon2B"; case FPW_OREGON3: return "Oregon3"; case FPW_OREGONv1: @@ -299,7 +305,9 @@ WeatherRecentEntry WeatherView::process_data(const WeatherDataMessage* data) { WeatherRecentEntry ret = {}; ret.sensorType = data->sensorType; int16_t i16 = 0; + int32_t i32 = 0; uint16_t u16 = 0; + uint64_t u64 = 0; uint8_t u8 = 0; uint8_t channel_3021[] = {3, 0, 2, 1}; @@ -442,12 +450,34 @@ WeatherRecentEntry WeatherView::process_data(const WeatherDataMessage* data) { ret.humidity = (data->decode_data >> 8) & 0xFF; break; case FPW_OREGON2: - i16 = ((data->decode_data >> 4) & 0xF) * 10 + (((data->decode_data >> 4) >> 4) & 0xF); - i16 *= 10; - i16 += (data->decode_data >> 12) & 0xF; - if (data->decode_data & 0xF) i16 = -i16; - ret.temp = (float)i16 / 10.0; - // todo fix missing parts. + i32 = bcd_decode_short(data->decode_data >> 4); + i32 *= 10; + i32 += (data->decode_data >> 12) & 0xf; + if (data->decode_data & 0xF) i32 = -i32; + ret.temp = (float)i32 / 10.0; + ret.battery_low = ((data->decode_data >> 32) & 0x4) ? 1 : 0; + u8 = (data->decode_data >> 44) & 0xF; + ret.channel = 1; + while (u8 > 1) { + ret.channel++; + u8 >>= 1; + } + break; + case FPW_OREGON2B: + ret.humidity = bcd_decode_short(data->decode_data); + u64 = data->decode_data >> 8; + i32 = bcd_decode_short(u64 >> 4); + i32 *= 10; + i32 += (u64 >> 12) & 0xf; + if (u64 & 0xF) i32 = -i32; + ret.temp = (float)i32 / 10.0; + ret.battery_low = ((data->decode_data >> 32) & 0x4) ? 1 : 0; + u8 = (data->decode_data >> 44) & 0xF; + ret.channel = 1; + while (u8 > 1) { + ret.channel++; + u8 >>= 1; + } break; case FPW_OREGON3: // todo check diff --git a/firmware/application/apps/ui_weatherstation.hpp b/firmware/application/apps/ui_weatherstation.hpp index 2c992bbbd..30e20ed2b 100644 --- a/firmware/application/apps/ui_weatherstation.hpp +++ b/firmware/application/apps/ui_weatherstation.hpp @@ -114,6 +114,7 @@ class WeatherView : public View { private: void on_tick_second(); + uint16_t bcd_decode_short(uint32_t data); void on_data(const WeatherDataMessage* data); WeatherRecentEntry process_data(const WeatherDataMessage* data); NavigationView& nav_; diff --git a/firmware/baseband/fprotos/w-oregon2.hpp b/firmware/baseband/fprotos/w-oregon2.hpp index 9d00a6f9f..3140f5b9a 100644 --- a/firmware/baseband/fprotos/w-oregon2.hpp +++ b/firmware/baseband/fprotos/w-oregon2.hpp @@ -132,15 +132,14 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase { // waiting for variable (sensor-specific data) if (decode_count_bit == (uint32_t)var_bits + OREGON2_CHECKSUM_BITS) { var_data = decode_data & 0xFFFFFFFF; - // reverse nibbles in var data var_data = (var_data & 0x55555555) << 1 | (var_data & 0xAAAAAAAA) >> 1; var_data = (var_data & 0x33333333) << 2 | (var_data & 0xCCCCCCCC) >> 2; - decode_data = var_data; + decode_data = var_data >> OREGON2_CHECKSUM_BITS; + decode_data |= (data << 32); // unique to portapack, i sent the upper part too, so we have all the data in one place // ws_oregon2_decode_var_data(OREGON2_SENSOR_ID(data), var_data >> OREGON2_CHECKSUM_BITS); //a bit stepback, but will work - parser_step = Oregon2DecoderStepReset; if (callback) callback(this); } @@ -195,8 +194,10 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase { case ID_RTHN129_3: case ID_RTHN129_4: case ID_RTHN129_5: + sensorType = FPW_OREGON2; return 16; case ID_THGR122N: + sensorType = FPW_OREGON2B; return 24; default: return 0; diff --git a/firmware/baseband/fprotos/w-oregon3.hpp b/firmware/baseband/fprotos/w-oregon3.hpp index c0654972b..34c3823dd 100644 --- a/firmware/baseband/fprotos/w-oregon3.hpp +++ b/firmware/baseband/fprotos/w-oregon3.hpp @@ -96,7 +96,7 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase { (var_data & 0xAAAAAAAAAAAAAAAA) >> 1; var_data = (var_data & 0x3333333333333333) << 2 | (var_data & 0xCCCCCCCCCCCCCCCC) >> 2; - decode_data = var_data; + decode_data = var_data >> OREGON3_CHECKSUM_BITS; // ws_oregon3_decode_var_data(OREGON3_SENSOR_ID(data), var_data >> OREGON3_CHECKSUM_BITS); parser_step = Oregon3DecoderStepReset; if (callback) callback(this); diff --git a/firmware/baseband/fprotos/weatherprotos.hpp b/firmware/baseband/fprotos/weatherprotos.hpp index efcb4220c..98dec833e 100644 --- a/firmware/baseband/fprotos/weatherprotos.hpp +++ b/firmware/baseband/fprotos/weatherprotos.hpp @@ -71,6 +71,7 @@ class WeatherProtos : public FProtoListGeneral { protos[FPW_Bresser3CH] = new FProtoWeatheBresser3CH(); protos[FPW_Bresser3CH_V1] = nullptr; // done by FProtoWeatheBresser3CH protos[FPW_Vauno_EN8822] = new FProtoWeatherVaunoEN8822(); + protos[FPW_OREGON2B] = nullptr; // done by FProtoWeatherOregon2 // set callback for them for (uint8_t i = 0; i < FPW_COUNT; ++i) { diff --git a/firmware/baseband/fprotos/weathertypes.hpp b/firmware/baseband/fprotos/weathertypes.hpp index fd6d043be..cc185fe55 100644 --- a/firmware/baseband/fprotos/weathertypes.hpp +++ b/firmware/baseband/fprotos/weathertypes.hpp @@ -42,6 +42,7 @@ enum FPROTO_WEATHER_SENSOR { FPW_Bresser3CH = 24, FPW_Bresser3CH_V1 = 25, FPW_Vauno_EN8822 = 26, + FPW_OREGON2B = 27, FPW_COUNT // this must be the last };