mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-14 10:39:30 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e6afd7744d | |||
| 76763b9bab | |||
| 02b75f567a | |||
| a2c4fefe34 | |||
| 121352b149 | |||
| 0ae7768f20 | |||
| 1a0555f9eb |
@@ -1,6 +1,7 @@
|
||||
> [!WARNING]
|
||||
> __IF YOU'VE PAID FOR MAYHEM OR ANY PREPACKAGED PACKAGES, YOU'RE BEING SCAMMED.__
|
||||
> The only legitimate link leading to our repositories is the organization [portapack-mayhem](https://github.com/portapack-mayhem/mayhem-firmware).
|
||||
> __IF YOU'VE PAID FOR MAYHEM OR ANY PREPACKAGED VERSIONS, YOU'RE BEING SCAMMED.__
|
||||
>
|
||||
> The only legitimate link to our repositories is the [portapack-mayhem](https://github.com/portapack-mayhem/mayhem-firmware) organization on GitHub.
|
||||
|
||||
# PortaPack Mayhem
|
||||
|
||||
@@ -16,9 +17,9 @@ This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmw
|
||||
|
||||
If you are new to *HackRF+PortaPack+Mayhem*, check these:
|
||||
|
||||
[<img alt="What is the HackRF One Portapack H2+?" src="https://img.youtube.com/vi/alrFbY5vxt4/maxresdefault.jpg" width="512">](https://grabify.link/9UZGEW)
|
||||
[<img alt="It’s TOO Easy to Accidentally Do Illegal Stuff with This" src="https://img.youtube.com/vi/OPckpjBSAOw/maxresdefault.jpg" width="700">](https://grabify.link/X4D5TF)
|
||||
|
||||
[<img alt="Beginner's Guide To The HackRF & Portapak With Mayhem" src="https://img.youtube.com/vi/H-bqdWfbhpg/maxresdefault.jpg" width="254">](https://grabify.link/5MU2VH) [<img alt="HackRF 101 : Everything You Need to Know to Get Started!" src="https://img.youtube.com/vi/xGR_PMD9LeU/maxresdefault.jpg" width="254">](https://grabify.link/C0J6ZR)
|
||||
[<img alt="What is the HackRF One Portapack H2+?" src="https://img.youtube.com/vi/alrFbY5vxt4/maxresdefault.jpg" width="230">](https://grabify.link/9UZGEW) [<img alt="Beginner's Guide To The HackRF & Portapak With Mayhem" src="https://img.youtube.com/vi/H-bqdWfbhpg/maxresdefault.jpg" width="230">](https://grabify.link/5MU2VH) [<img alt="HackRF 101 : Everything You Need to Know to Get Started!" src="https://img.youtube.com/vi/xGR_PMD9LeU/maxresdefault.jpg" width="230">](https://grabify.link/C0J6ZR)
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
@@ -54,13 +55,7 @@ Consider that the hardware and firmware has been created and maintain by a [lot]
|
||||
To support the people behind the hardware, please buy a genuine [HackRF](https://greatscottgadgets.com/hackrf/) and [PortaPack](https://store.sharebrained.com/products/portapack-for-hackrf-one-kit).
|
||||
|
||||
## What if I really want something specific?
|
||||
If what you need can be relevant in general, you can [request a feature](https://github.com/portapack-mayhem/mayhem-firmware/issues/new?labels=enhancement&template=feature_request.md).
|
||||
|
||||
<del>You can create a bounty and invite people to your own bounty. This will incentivize coders to work on a new feature, solving a bug or even writting documentation. Start a bounty by [creating](https://github.com/portapack-mayhem/mayhem-firmware/issues/new/choose) or [choosing](https://github.com/portapack-mayhem/mayhem-firmware/issues/) an existing issue. Then, go to [Bountysource](https://www.bountysource.com/) and post a bounty using the link to that specific [issue](https://www.bountysource.com/teams/portapack-mayhem/issues).</del>
|
||||
|
||||
<del>Promote your bounty over our Discord by clicking the chat badge on [top](#portapack-mayhem).</del>
|
||||
|
||||
Bountysource has not been reliable lately, so until this changes, please **DO NOT** post a bounty there. Go to our Discord by clicking the chat badge on [top](#portapack-mayhem) and discuss there.
|
||||
If what you need can be relevant in general, you can [request a feature](https://github.com/portapack-mayhem/mayhem-firmware/issues/new?labels=enhancement&template=feature_request.md). Alternatively, go to our Discord by clicking the chat badge on [top](#portapack-mayhem) and discuss there.
|
||||
|
||||
## What if I need help?
|
||||
First, check the [documentation](https://github.com/portapack-mayhem/mayhem-firmware/wiki). If you find a bug or you think the problem is related to the current repository, please open an [issue](https://github.com/portapack-mayhem/mayhem-firmware/issues/new/choose).
|
||||
|
||||
@@ -435,4 +435,7 @@ void AnalogAudioView::handle_coded_squelch(uint32_t value) {
|
||||
text_ctcss.set(tone_key_string_by_value(value, text_ctcss.parent_rect().width() / 8));
|
||||
}
|
||||
|
||||
void AnalogAudioView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -247,12 +247,21 @@ class AnalogAudioView : public View {
|
||||
|
||||
void handle_coded_squelch(uint32_t value);
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
|
||||
MessageHandlerRegistration message_handler_coded_squelch{
|
||||
Message::ID::CodedSquelch,
|
||||
[this](const Message* p) {
|
||||
const auto message = *reinterpret_cast<const CodedSquelchMessage*>(p);
|
||||
this->handle_coded_squelch(message.value);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -428,6 +428,7 @@ BLERxView::BLERxView(NavigationView& nav)
|
||||
&text_found_count,
|
||||
&check_serial_log,
|
||||
&button_filter,
|
||||
&options_filter,
|
||||
&button_save_list,
|
||||
&button_clear_list,
|
||||
&button_switch,
|
||||
@@ -499,6 +500,7 @@ BLERxView::BLERxView(NavigationView& nav)
|
||||
|
||||
check_name.on_select = [this](Checkbox&, bool v) {
|
||||
name_enable = v;
|
||||
// update the include_name instance variable value of each entry in recent entries
|
||||
setAllMembersToValue(recent, &BleRecentEntry::include_name, v);
|
||||
recent_entries_view.set_dirty();
|
||||
};
|
||||
@@ -525,8 +527,14 @@ BLERxView::BLERxView(NavigationView& nav)
|
||||
handle_entries_sort(v);
|
||||
};
|
||||
|
||||
options_filter.on_change = [this](size_t index, int32_t v) {
|
||||
filter_index = (uint8_t)index;
|
||||
handle_filter_options(v);
|
||||
};
|
||||
|
||||
options_channel.set_selected_index(channel_index, true);
|
||||
options_sort.set_selected_index(sort_index, true);
|
||||
options_filter.set_selected_index(filter_index, true);
|
||||
|
||||
button_find.on_select = [this](Button&) {
|
||||
auto open_view = nav_.push<FileLoadView>(".TXT");
|
||||
@@ -716,10 +724,11 @@ void BLERxView::on_data(BlePacketData* packet) {
|
||||
updateEntry(packet, entry, (ADV_PDU_TYPE)packet->type);
|
||||
|
||||
// Add entries if they meet the criteria.
|
||||
auto value = filter;
|
||||
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||
return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||
});
|
||||
// auto value = filter;
|
||||
// resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||
// return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||
// });
|
||||
handle_filter_options(options_filter.selected_index());
|
||||
|
||||
handle_entries_sort(options_sort.selected_index());
|
||||
|
||||
@@ -756,12 +765,13 @@ void BLERxView::on_data(BlePacketData* packet) {
|
||||
void BLERxView::on_filter_change(std::string value) {
|
||||
// New filter? Reset list from recent entries.
|
||||
if (filter != value) {
|
||||
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||
return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||
});
|
||||
// resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||
// // return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||
// return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos) && (to_string_mac_address(entry.packetData.macAddress, 6, false).find(value) == std::string::npos);
|
||||
// });
|
||||
filter = value;
|
||||
handle_filter_options(options_filter.selected_index());
|
||||
}
|
||||
|
||||
filter = value;
|
||||
}
|
||||
|
||||
void BLERxView::on_file_changed(const std::filesystem::path& new_file_path) {
|
||||
@@ -852,6 +862,24 @@ void BLERxView::handle_entries_sort(uint8_t index) {
|
||||
recent_entries_view.set_dirty();
|
||||
}
|
||||
|
||||
void BLERxView::handle_filter_options(uint8_t index) {
|
||||
auto value = filter;
|
||||
switch (index) {
|
||||
case 0: // filter by Data
|
||||
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||
return (entry.dataString.find(value) == std::string::npos) && (entry.nameString.find(value) == std::string::npos);
|
||||
});
|
||||
break;
|
||||
case 1: // filter by MAC address (All caps: e.g. AA:BB:CC:DD:EE:FF)
|
||||
resetFilteredEntries(recent, [&value](const BleRecentEntry& entry) {
|
||||
return (to_string_mac_address(entry.packetData.macAddress, 6, false).find(value) == std::string::npos);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BLERxView::set_parent_rect(const Rect new_parent_rect) {
|
||||
View::set_parent_rect(new_parent_rect);
|
||||
const Rect content_rect{0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height - switch_button_height};
|
||||
@@ -914,6 +942,7 @@ void BLERxView::updateEntry(const BlePacketData* packet, BleRecentEntry& entry,
|
||||
|
||||
// Subtract 1 because type is part of the length.
|
||||
for (int i = 0; i < length - 1; i++) {
|
||||
// parse the name of bluetooth device: 0x08->Shortened Local Name; 0x09->Complete Local Name
|
||||
if (type == 0x08 || type == 0x09) {
|
||||
decoded_data += (char)advertiseData->Data[currentByte];
|
||||
}
|
||||
|
||||
@@ -203,6 +203,7 @@ class BLERxView : public View {
|
||||
void file_error();
|
||||
void on_timer();
|
||||
void handle_entries_sort(uint8_t index);
|
||||
void handle_filter_options(uint8_t index);
|
||||
void updateEntry(const BlePacketData* packet, BleRecentEntry& entry, ADV_PDU_TYPE pdu_type);
|
||||
|
||||
NavigationView& nav_;
|
||||
@@ -214,6 +215,7 @@ class BLERxView : public View {
|
||||
|
||||
uint8_t channel_index{0};
|
||||
uint8_t sort_index{0};
|
||||
uint8_t filter_index{0};
|
||||
std::string filter{};
|
||||
bool logging{false};
|
||||
bool serial_logging{false};
|
||||
@@ -227,6 +229,7 @@ class BLERxView : public View {
|
||||
{"sort_index"sv, &sort_index},
|
||||
{"filter"sv, &filter},
|
||||
{"log"sv, &logging},
|
||||
{"filter_index"sv, &filter_index},
|
||||
// disabled to always start without USB serial activated until we can make it non blocking if not connected
|
||||
// {"serial_log"sv, &serial_logging},
|
||||
{"name"sv, &name_enable},
|
||||
@@ -255,13 +258,13 @@ class BLERxView : public View {
|
||||
std::filesystem::path log_packets_path{blerx_dir / u"Logs/????.TXT"};
|
||||
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
|
||||
|
||||
static constexpr auto header_height = 4 * 16;
|
||||
static constexpr auto header_height = 9 * 8;
|
||||
static constexpr auto switch_button_height = 3 * 16;
|
||||
|
||||
OptionsField options_channel{
|
||||
{0 * 8, 0 * 8},
|
||||
5,
|
||||
{{"Ch.37 ", 37},
|
||||
{{"Ch.37", 37},
|
||||
{"Ch.38", 38},
|
||||
{"Ch.39", 39},
|
||||
{"Auto", 40}}};
|
||||
@@ -286,10 +289,10 @@ class BLERxView : public View {
|
||||
{24 * 8, 5, 6 * 8, 4}};
|
||||
|
||||
Labels label_sort{
|
||||
{{0 * 8, 3 * 8}, "Sort:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{0 * 8, 2 * 8}, "Sort:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
OptionsField options_sort{
|
||||
{5 * 8, 3 * 8},
|
||||
{5 * 8, 2 * 8},
|
||||
4,
|
||||
{{"MAC", 0},
|
||||
{"Hits", 1},
|
||||
@@ -298,40 +301,46 @@ class BLERxView : public View {
|
||||
{"Name", 4}}};
|
||||
|
||||
Button button_filter{
|
||||
{11 * 8, 3 * 8, 4 * 8, 16},
|
||||
"Filter"};
|
||||
{11 * 8, 2 * 8, 7 * 8, 16},
|
||||
"Filter:"};
|
||||
|
||||
OptionsField options_filter{
|
||||
{18 * 8 + 2, 2 * 8},
|
||||
4,
|
||||
{{"Data", 0},
|
||||
{"MAC", 1}}};
|
||||
|
||||
Checkbox check_log{
|
||||
{17 * 8, 3 * 8},
|
||||
{10 * 8, 4 * 8 + 2},
|
||||
3,
|
||||
"Log",
|
||||
true};
|
||||
|
||||
Checkbox check_name{
|
||||
{23 * 8, 3 * 8},
|
||||
{0 * 8, 4 * 8 + 2},
|
||||
3,
|
||||
"Name",
|
||||
true};
|
||||
|
||||
Button button_find{
|
||||
{0 * 8, 6 * 8, 4 * 8, 16},
|
||||
{0 * 8, 7 * 8 - 2, 4 * 8, 16},
|
||||
"Find"};
|
||||
|
||||
Labels label_found{
|
||||
{{5 * 8, 6 * 8}, "Found:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{5 * 8, 7 * 8 - 2}, "Found:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_found_count{
|
||||
{11 * 8, 3 * 16, 20 * 8, 16},
|
||||
{11 * 8, 7 * 8 - 2, 20 * 8, 16},
|
||||
"0/0"};
|
||||
|
||||
Checkbox check_serial_log{
|
||||
{17 * 8, 3 * 16 - 2},
|
||||
{18 * 8 + 2, 4 * 8 + 2},
|
||||
7,
|
||||
"USB Log",
|
||||
true};
|
||||
|
||||
Console console{
|
||||
{0, 4 * 16, 240, 240}};
|
||||
// Console console{
|
||||
// {0, 10 * 8, 240, 240}};
|
||||
|
||||
Button button_clear_list{
|
||||
{2 * 8, 320 - (16 + 32), 7 * 8, 32},
|
||||
@@ -371,7 +380,7 @@ class BLERxView : public View {
|
||||
[this](const Message* const) {
|
||||
this->on_timer();
|
||||
}};
|
||||
};
|
||||
}; /* BLERxView */
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
|
||||
@@ -128,4 +128,8 @@ void CaptureAppView::focus() {
|
||||
record_view.focus();
|
||||
}
|
||||
|
||||
void CaptureAppView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -108,6 +108,15 @@ class CaptureAppView : public View {
|
||||
3};
|
||||
|
||||
spectrum::WaterfallView waterfall{};
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -178,4 +178,8 @@ void ERTAppView::on_show_list() {
|
||||
recent_entries_view.focus();
|
||||
}
|
||||
|
||||
void ERTAppView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -176,6 +176,14 @@ class ERTAppView : public View {
|
||||
this->on_packet(packet);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
void on_packet(const ert::Packet& packet);
|
||||
void on_show_list();
|
||||
};
|
||||
|
||||
@@ -321,6 +321,10 @@ void POCSAGAppView::on_stats(const POCSAGStatsMessage* stats) {
|
||||
widget_frames.set_sync(stats->has_sync);
|
||||
}
|
||||
|
||||
void POCSAGAppView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
void BaudIndicator::paint(Painter& painter) {
|
||||
auto p = screen_pos();
|
||||
char top = '-';
|
||||
|
||||
@@ -292,6 +292,15 @@ class POCSAGAppView : public View {
|
||||
Console console{
|
||||
{0, 2 * 16 + 6, screen_width, screen_height - 54}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_packet{
|
||||
Message::ID::POCSAGPacket,
|
||||
[this](Message* const p) {
|
||||
|
||||
@@ -122,6 +122,10 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect)
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
void APRSRxView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
void APRSRxView::on_packet(const APRSPacketMessage* message) {
|
||||
std::string str_console = "\x1B";
|
||||
|
||||
|
||||
@@ -185,6 +185,7 @@ class APRSRxView : public View {
|
||||
|
||||
std::string title() const override { return "APRS RX"; };
|
||||
void on_packet(const APRSPacketMessage* message);
|
||||
void on_freqchg(int64_t freq);
|
||||
|
||||
private:
|
||||
void on_data(uint32_t value, bool is_data);
|
||||
@@ -271,6 +272,13 @@ class APRSRXView : public View {
|
||||
this->view_stream.on_packet(message);
|
||||
this->view_table.on_pkt(message);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->view_stream.on_freqchg(message->freq);
|
||||
}};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -49,6 +49,7 @@ void BattinfoView::update_result() {
|
||||
text_voltage.set("UNKNOWN");
|
||||
text_current.set("-");
|
||||
text_charge.set("-");
|
||||
text_method.set("-");
|
||||
return;
|
||||
}
|
||||
bool uichg = false;
|
||||
@@ -78,6 +79,13 @@ void BattinfoView::update_result() {
|
||||
text_current.hidden(true);
|
||||
text_charge.hidden(true);
|
||||
}
|
||||
if ((valid_mask & battery::BatteryManagement::BATT_VALID_PERCENT) == battery::BatteryManagement::BATT_VALID_PERCENT) {
|
||||
text_method.set("IC");
|
||||
button_mode.set_text("Volt");
|
||||
} else {
|
||||
text_method.set("Voltage");
|
||||
button_mode.set_text("IC");
|
||||
}
|
||||
if (uichg) set_dirty();
|
||||
// to update status bar too, send message in behalf of batt manager
|
||||
BatteryStateMessage msg{valid_mask, percent, current >= 0, voltage};
|
||||
@@ -92,12 +100,24 @@ BattinfoView::BattinfoView(NavigationView& nav)
|
||||
&text_voltage,
|
||||
&text_current,
|
||||
&text_charge,
|
||||
&text_method,
|
||||
&button_mode,
|
||||
&button_exit});
|
||||
|
||||
button_exit.on_select = [this, &nav](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
button_mode.on_select = [this, &nav](Button&) {
|
||||
if (button_mode.text() == "IC") {
|
||||
battery::BatteryManagement::set_calc_override(false);
|
||||
persistent_memory::set_ui_override_batt_calc(false);
|
||||
button_mode.set_text("Volt");
|
||||
} else {
|
||||
battery::BatteryManagement::set_calc_override(true);
|
||||
persistent_memory::set_ui_override_batt_calc(true);
|
||||
button_mode.set_text("IC");
|
||||
}
|
||||
};
|
||||
update_result();
|
||||
if (thread == nullptr) thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, BattinfoView::static_fn, this);
|
||||
}
|
||||
|
||||
@@ -53,11 +53,14 @@ class BattinfoView : public View {
|
||||
|
||||
Labels labels{
|
||||
{{2 * 8, 1 * 16}, "Percent:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 2 * 16}, "Voltage:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{2 * 8, 2 * 16}, "Voltage:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 3 * 16}, "Method:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 7 * 16}, "Change method:", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
Labels labels_opt{
|
||||
{{2 * 8, 3 * 16}, "Current:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 4 * 16}, "Charge:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{2 * 8, 4 * 16}, "Current:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 5 * 16}, "Charge:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_percent{
|
||||
{13 * 8, 1 * 16, 10 * 16, 16},
|
||||
@@ -65,12 +68,19 @@ class BattinfoView : public View {
|
||||
Text text_voltage{
|
||||
{13 * 8, 2 * 16, 10 * 16, 16},
|
||||
"-"};
|
||||
Text text_current{
|
||||
Text text_method{
|
||||
{13 * 8, 3 * 16, 10 * 16, 16},
|
||||
"-"};
|
||||
Text text_charge{
|
||||
Text text_current{
|
||||
{13 * 8, 4 * 16, 10 * 16, 16},
|
||||
"-"};
|
||||
Text text_charge{
|
||||
{13 * 8, 5 * 16, 10 * 16, 16},
|
||||
"-"};
|
||||
|
||||
Button button_mode{
|
||||
{2 * 8, 8 * 16 + 5, 5 * 16, 32},
|
||||
"Volt"};
|
||||
|
||||
Button button_exit{
|
||||
{72, 17 * 16, 96, 32},
|
||||
|
||||
@@ -323,4 +323,9 @@ void LevelView::handle_coded_squelch(const uint32_t value) {
|
||||
text_ctcss.set(" ");
|
||||
}
|
||||
|
||||
void LevelView::on_freqchg(int64_t freq) {
|
||||
receiver_model.set_target_frequency(freq);
|
||||
button_frequency.set_text("<" + to_string_short_freq(freq) + " MHz>");
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -188,6 +188,15 @@ class LevelView : public View {
|
||||
|
||||
void handle_coded_squelch(const uint32_t value);
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_coded_squelch{
|
||||
Message::ID::CodedSquelch,
|
||||
[this](const Message* const p) {
|
||||
|
||||
@@ -948,6 +948,32 @@ void SetThemeView::focus() {
|
||||
options.focus();
|
||||
}
|
||||
|
||||
/* SetBatteryView ************************************/
|
||||
|
||||
SetBatteryView::SetBatteryView(NavigationView& nav) {
|
||||
add_children({&labels,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
&checkbox_overridebatt});
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
pmem::set_ui_override_batt_calc(checkbox_overridebatt.value());
|
||||
battery::BatteryManagement::set_calc_override(checkbox_overridebatt.value());
|
||||
send_system_refresh();
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
checkbox_overridebatt.set_value(pmem::ui_override_batt_calc());
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
}
|
||||
|
||||
void SetBatteryView::focus() {
|
||||
button_cancel.focus();
|
||||
}
|
||||
|
||||
/* SettingsMenuView **************************************/
|
||||
|
||||
SettingsMenuView::SettingsMenuView(NavigationView& nav)
|
||||
@@ -978,6 +1004,7 @@ void SettingsMenuView::on_populate() {
|
||||
{"Theme", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetThemeView>(); }},
|
||||
{"Autostart", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetAutostartView>(); }},
|
||||
});
|
||||
if (battery::BatteryManagement::isDetected()) add_item({"Battery", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetBatteryView>(); }});
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -888,6 +888,35 @@ class SetThemeView : public View {
|
||||
};
|
||||
};
|
||||
|
||||
class SetBatteryView : public View {
|
||||
public:
|
||||
SetBatteryView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Battery"; };
|
||||
|
||||
private:
|
||||
int32_t selected = 0;
|
||||
Labels labels{
|
||||
{{1 * 8, 1 * 16}, "Override batt calculation", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 2 * 16}, "method to voltage based", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
Checkbox checkbox_overridebatt{
|
||||
{2 * 8, 6 * 16},
|
||||
23,
|
||||
"Override"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
||||
class SettingsMenuView : public BtnGridView {
|
||||
public:
|
||||
SettingsMenuView(NavigationView& nav);
|
||||
|
||||
@@ -187,4 +187,8 @@ void SondeView::on_packet(const sonde::Packet& packet) {
|
||||
}
|
||||
}
|
||||
|
||||
void SondeView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -195,6 +195,14 @@ class SondeView : public View {
|
||||
const auto message = static_cast<const OrientationDataMessage*>(p);
|
||||
this->on_orientation(message);
|
||||
}};
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
|
||||
void on_gps(const GPSPosDataMessage* msg);
|
||||
void on_orientation(const OrientationDataMessage* msg);
|
||||
|
||||
@@ -212,7 +212,10 @@ const char* SubGhzDView::getSensorTypeName(FPROTO_SUBGHZD_SENSOR type) {
|
||||
return "Somify Keytis";
|
||||
case FPS_SOMIFY_TELIS:
|
||||
return "Somify Telis";
|
||||
|
||||
case FPS_GANGQI:
|
||||
return "GangQi";
|
||||
case FPS_MARANTEC24:
|
||||
return "Marantec24";
|
||||
case FPS_Invalid:
|
||||
default:
|
||||
return "Unknown";
|
||||
@@ -224,6 +227,10 @@ std::string SubGhzDView::pad_string_with_spaces(int snakes) {
|
||||
return paddedStr;
|
||||
}
|
||||
|
||||
void SubGhzDView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
template <>
|
||||
void RecentEntriesTable<ui::SubGhzDRecentEntries>::draw(
|
||||
const Entry& entry,
|
||||
@@ -713,5 +720,18 @@ void SubGhzDRecentEntryDetailView::parseProtocol() {
|
||||
serial = dataa & 0xFFFFFF; // address}
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry_.sensorType == FPS_GANGQI) {
|
||||
btn = 0; // parser needs some time i think in flipper side.
|
||||
cnt = (uint8_t)(entry_.data >> 32);
|
||||
serial = (entry_.data & 0xFFFFFFFF);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry_.sensorType == FPS_MARANTEC24) {
|
||||
serial = (entry_.data >> 4);
|
||||
btn = entry_.data & 0xf;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} // namespace ui
|
||||
@@ -127,6 +127,14 @@ class SubGhzDView : public View {
|
||||
}};
|
||||
SubGhzDRecentEntriesView recent_entries_view{columns, recent};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_packet{
|
||||
Message::ID::SubGhzDData,
|
||||
[this](Message* const p) {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "baseband_api.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "../baseband/fprotos/fprotogeneral.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
using namespace ui;
|
||||
@@ -138,7 +139,8 @@ void WeatherView::on_tick_second() {
|
||||
}
|
||||
|
||||
void WeatherView::on_data(const WeatherDataMessage* data) {
|
||||
WeatherRecentEntry key{data->sensorType, data->id, data->temp, data->humidity, data->channel, data->battery_low};
|
||||
WeatherRecentEntry key = process_data(data);
|
||||
// WeatherRecentEntry key{data->sensorType, data->id, data->temp, data->humidity, data->channel, data->battery_low};
|
||||
auto matching_recent = find(recent, key.key());
|
||||
if (matching_recent != std::end(recent)) {
|
||||
// Found within. Move to front of list, increment counter.
|
||||
@@ -209,6 +211,8 @@ const char* WeatherView::getWeatherSensorTypeName(FPROTO_WEATHER_SENSOR type) {
|
||||
return "Acurite5in1";
|
||||
case FPW_EmosE601x:
|
||||
return "EmosE601x";
|
||||
case FPW_SolightTE44:
|
||||
return "SolightTE44";
|
||||
case FPW_Invalid:
|
||||
default:
|
||||
return "Unknown";
|
||||
@@ -220,6 +224,10 @@ std::string WeatherView::pad_string_with_spaces(int snakes) {
|
||||
return paddedStr;
|
||||
}
|
||||
|
||||
void WeatherView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
template <>
|
||||
void RecentEntriesTable<ui::WeatherRecentEntries>::draw(
|
||||
const Entry& entry,
|
||||
@@ -250,4 +258,287 @@ void RecentEntriesTable<ui::WeatherRecentEntries>::draw(
|
||||
painter.draw_string(target_rect.location(), style, line);
|
||||
}
|
||||
|
||||
#define LACROSSE_TX_MSG_TYPE_TEMP 0x00
|
||||
#define LACROSSE_TX_MSG_TYPE_HUM 0x0E
|
||||
|
||||
WeatherRecentEntry WeatherView::process_data(const WeatherDataMessage* data) {
|
||||
WeatherRecentEntry ret = {};
|
||||
ret.sensorType = data->sensorType;
|
||||
int16_t i16 = 0;
|
||||
uint16_t u16 = 0;
|
||||
uint64_t u64 = 0;
|
||||
uint8_t u8 = 0;
|
||||
uint8_t channel_3021[] = {3, 0, 2, 1};
|
||||
float flo = 0.0;
|
||||
switch (data->sensorType) {
|
||||
case FPW_NexusTH:
|
||||
ret.id = (data->decode_data >> 28) & 0xFF;
|
||||
ret.battery_low = !((data->decode_data >> 27) & 1);
|
||||
ret.channel = ((data->decode_data >> 24) & 0x03) + 1;
|
||||
if (!((data->decode_data >> 23) & 1)) {
|
||||
ret.temp = (float)((data->decode_data >> 12) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
ret.temp = (float)((~(data->decode_data >> 12) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
ret.humidity = data->decode_data & 0xFF;
|
||||
if (ret.humidity > 95)
|
||||
ret.humidity = 95;
|
||||
else if (ret.humidity < 20)
|
||||
ret.humidity = 20;
|
||||
break;
|
||||
case FPW_Acurite592TXR:
|
||||
|
||||
u8 = ((data->decode_data >> 54) & 0x03);
|
||||
ret.channel = channel_3021[u8];
|
||||
ret.id = (data->decode_data >> 40) & 0x3FFF;
|
||||
ret.battery_low = !((data->decode_data >> 38) & 1);
|
||||
ret.humidity = (data->decode_data >> 24) & 0x7F;
|
||||
u16 = ((data->decode_data >> 9) & 0xF80) | ((data->decode_data >> 8) & 0x7F);
|
||||
ret.temp = ((float)(u16)-1000) / 10.0f;
|
||||
break;
|
||||
case FPW_Acurite606TX:
|
||||
ret.id = (data->decode_data >> 24) & 0xFF;
|
||||
ret.battery_low = (data->decode_data >> 23) & 1;
|
||||
if (!((data->decode_data >> 19) & 1)) {
|
||||
ret.temp = (float)((data->decode_data >> 8) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
ret.temp = (float)((~(data->decode_data >> 8) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
break;
|
||||
case FPW_Acurite609TX:
|
||||
ret.id = (data->decode_data >> 32) & 0xFF;
|
||||
ret.battery_low = (data->decode_data >> 31) & 1;
|
||||
ret.channel = WS_NO_CHANNEL;
|
||||
// Temperature in Celsius is encoded as a 12 bit integer value
|
||||
// multiplied by 10 using the 4th - 6th nybbles (bytes 1 & 2)
|
||||
// negative values are recovered by sign extend from int16_t.
|
||||
i16 = (int16_t)(((data->decode_data >> 12) & 0xf000) | ((data->decode_data >> 16) << 4));
|
||||
ret.temp = (i16 >> 4) * 0.1f;
|
||||
ret.humidity = (data->decode_data >> 8) & 0xff;
|
||||
break;
|
||||
case FPW_Ambient:
|
||||
id = (data->decode_data >> 32) & 0xFF;
|
||||
ret.battery_low = (data->decode_data >> 31) & 1;
|
||||
ret.channel = ((data->decode_data >> 28) & 0x07) + 1;
|
||||
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data->decode_data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
|
||||
ret.humidity = (data->decode_data >> 8) & 0xFF;
|
||||
break;
|
||||
case FPW_AuriolAhfl:
|
||||
ret.id = data->decode_data >> 34;
|
||||
ret.battery_low = (data->decode_data >> 33) & 1;
|
||||
// btn = (data >> 32) & 1;
|
||||
ret.channel = ((data->decode_data >> 30) & 0x3) + 1;
|
||||
if (!((data->decode_data >> 29) & 1)) {
|
||||
ret.temp = (float)((data->decode_data >> 18) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
ret.temp = (float)((~(data->decode_data >> 18) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
ret.humidity = (data->decode_data >> 11) & 0x7F;
|
||||
break;
|
||||
case FPW_AuriolTH:
|
||||
ret.id = (data->decode_data >> 31) & 0xFF;
|
||||
ret.battery_low = ((data->decode_data >> 30) & 1);
|
||||
ret.channel = ((data->decode_data >> 25) & 0x03) + 1;
|
||||
if (!((data->decode_data >> 23) & 1)) {
|
||||
ret.temp = (float)((data->decode_data >> 13) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
ret.temp = (float)((~(data->decode_data >> 13) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
ret.humidity = (data->decode_data >> 1) & 0x7F;
|
||||
break;
|
||||
case FPW_GTWT02:
|
||||
ret.id = (data->decode_data >> 29) & 0xFF;
|
||||
ret.battery_low = (data->decode_data >> 28) & 1;
|
||||
// btn = (data->decode_data >> 27) & 1;
|
||||
ret.channel = ((data->decode_data >> 25) & 0x3) + 1;
|
||||
|
||||
if (!((data->decode_data >> 24) & 1)) {
|
||||
ret.temp = (float)((data->decode_data >> 13) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
ret.temp = (float)((~(data->decode_data >> 13) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
ret.humidity = (data->decode_data >> 6) & 0x7F;
|
||||
if (ret.humidity <= 10) // actually the sensors sends 10 below working range of 20%
|
||||
ret.humidity = 0;
|
||||
else if (ret.humidity > 90) // actually the sensors sends 110 above working range of 90%
|
||||
ret.humidity = 100;
|
||||
break;
|
||||
case FPW_GTWT03:
|
||||
ret.id = data->decode_data >> 33;
|
||||
ret.humidity = (data->decode_data >> 25) & 0xFF;
|
||||
if (ret.humidity <= 10) { // actually the sensors sends 10 below working range of 20%
|
||||
ret.humidity = 0;
|
||||
} else if (ret.humidity > 95) { // actually the sensors sends 110 above working range of 90%
|
||||
ret.humidity = 100;
|
||||
}
|
||||
ret.battery_low = (data->decode_data >> 24) & 1;
|
||||
// (data->decode_data >> 23) & 1;
|
||||
ret.channel = ((data->decode_data >> 21) & 0x03) + 1;
|
||||
if (!((data->decode_data >> 20) & 1)) {
|
||||
ret.temp = (float)((data->decode_data >> 9) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
ret.temp = (float)((~(data->decode_data >> 9) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
break;
|
||||
case FPW_INFACTORY:
|
||||
ret.id = data->decode_data >> 32;
|
||||
ret.battery_low = (data->decode_data >> 26) & 1;
|
||||
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data->decode_data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
|
||||
ret.humidity = (((data->decode_data >> 8) & 0x0F) * 10) + ((data->decode_data >> 4) & 0x0F); // BCD, 'A0'=100%rH
|
||||
ret.channel = data->decode_data & 0x03;
|
||||
break;
|
||||
case FPW_LACROSSETX:
|
||||
u8 = (data->decode_data >> 32) & 0x0F;
|
||||
ret.id = (((data->decode_data >> 28) & 0x0F) << 3) | (((data->decode_data >> 24) & 0x0F) >> 1);
|
||||
flo = (float)((data->decode_data >> 20) & 0x0F) * 10.0f + (float)((data->decode_data >> 16) & 0x0F) + (float)((data->decode_data >> 12) & 0x0F) * 0.1f;
|
||||
if (u8 == LACROSSE_TX_MSG_TYPE_TEMP) { //-V1051
|
||||
ret.temp = flo - 50.0f;
|
||||
ret.humidity = WS_NO_HUMIDITY;
|
||||
} else if (u8 == LACROSSE_TX_MSG_TYPE_HUM) {
|
||||
// ToDo for verification, records are needed with sensors maintaining temperature and temperature for this standard
|
||||
ret.humidity = (uint8_t)flo;
|
||||
}
|
||||
break;
|
||||
case FPW_LACROSSETX141thbv2:
|
||||
ret.id = data->decode_data >> 32;
|
||||
ret.battery_low = (data->decode_data >> 31) & 1;
|
||||
// btn = (data->decode_data >> 30) & 1;
|
||||
ret.channel = ((data->decode_data >> 28) & 0x03) + 1;
|
||||
ret.temp = ((float)((data->decode_data >> 16) & 0x0FFF) - 500.0f) / 10.0f;
|
||||
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.
|
||||
break;
|
||||
case FPW_OREGON3:
|
||||
// todo check
|
||||
ret.humidity = ((data->decode_data >> 4) & 0xF) * 10 + (((data->decode_data >> 4) >> 4) & 0xF);
|
||||
i16 = (((data->decode_data >> 12) >> 4) & 0xF) * 10 + ((((data->decode_data >> 12) >> 4) >> 4) & 0xF); // ws_oregon3_bcd_decode_short((data->decode_data >> 12) >> 4);
|
||||
i16 *= 10;
|
||||
i16 += ((data->decode_data >> 12) >> 12) & 0xF;
|
||||
if ((data->decode_data >> 12) & 0xF) i16 = -i16;
|
||||
ret.temp = (float)i16 / 10.0;
|
||||
break;
|
||||
case FPW_OREGONv1:
|
||||
u64 = FProtoGeneral::subghz_protocol_blocks_reverse_key(data->decode_data, 32);
|
||||
id = u64 & 0xFF;
|
||||
ret.channel = ((u64 >> 6) & 0x03) + 1;
|
||||
ret.temp = ((u64 >> 8) & 0x0F) * 0.1f + ((u64 >> 12) & 0x0F) + ((u64 >> 16) & 0x0F) * 10.0f;
|
||||
if (!((u64 >> 21) & 1)) {
|
||||
ret.temp = ret.temp;
|
||||
} else {
|
||||
ret.temp = -ret.temp;
|
||||
}
|
||||
ret.battery_low = !((u64 >> 23) & 1ULL);
|
||||
break;
|
||||
case FPW_THERMOPROTX4:
|
||||
ret.id = (data->decode_data >> 25) & 0xFF;
|
||||
ret.battery_low = (data->decode_data >> 24) & 1;
|
||||
// btn = (data->decode_data >> 23) & 1;
|
||||
ret.channel = ((data->decode_data >> 21) & 0x03) + 1;
|
||||
if (!((data->decode_data >> 20) & 1)) {
|
||||
ret.temp = (float)((data->decode_data >> 9) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
ret.temp = (float)((~(data->decode_data >> 9) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
ret.humidity = (data->decode_data >> 1) & 0xFF;
|
||||
break;
|
||||
case FPW_TX_8300:
|
||||
ret.humidity = (((data->decode_data >> 28) & 0x0F) * 10) + ((data->decode_data >> 24) & 0x0F);
|
||||
if (!((data->decode_data >> 22) & 0x03))
|
||||
ret.battery_low = 0;
|
||||
else
|
||||
ret.battery_low = 1;
|
||||
ret.channel = (data->decode_data >> 20) & 0x03;
|
||||
ret.id = (data->decode_data >> 12) & 0x7F;
|
||||
ret.temp = ((data->decode_data >> 8) & 0x0F) * 10.0f + ((data->decode_data >> 4) & 0x0F) +
|
||||
(data->decode_data & 0x0F) * 0.1f;
|
||||
if (!((data->decode_data >> 19) & 1)) {
|
||||
ret.temp = ret.temp;
|
||||
} else {
|
||||
ret.temp = -ret.temp;
|
||||
}
|
||||
break;
|
||||
case FPW_WENDOX_W6726:
|
||||
ret.id = (data->decode_data >> 24) & 0xFF;
|
||||
ret.battery_low = (data->decode_data >> 6) & 1;
|
||||
if (((data->decode_data >> 23) & 1)) {
|
||||
ret.temp = (float)(((data->decode_data >> 14) & 0x1FF) + 12) / 10.0f;
|
||||
} else {
|
||||
ret.temp = (float)((~(data->decode_data >> 14) & 0x1FF) + 1 - 12) / -10.0f;
|
||||
}
|
||||
if (ret.temp < -50.0f) {
|
||||
ret.temp = -50.0f;
|
||||
} else if (ret.temp > 70.0f) {
|
||||
ret.temp = 70.0f;
|
||||
}
|
||||
break;
|
||||
case FPW_Acurite986:
|
||||
ret.id = FProtoGeneral::subghz_protocol_blocks_reverse_key(data->decode_data >> 24, 8);
|
||||
ret.id = (id << 8) | FProtoGeneral::subghz_protocol_blocks_reverse_key(data->decode_data >> 16, 8);
|
||||
ret.battery_low = (data->decode_data >> 14) & 1;
|
||||
ret.channel = ((data->decode_data >> 15) & 1) + 1;
|
||||
i16 = FProtoGeneral::subghz_protocol_blocks_reverse_key(data->decode_data >> 32, 8);
|
||||
if (i16 & 0x80) {
|
||||
i16 = -(i16 & 0x7F);
|
||||
}
|
||||
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius((float)i16);
|
||||
break;
|
||||
case FPW_KEDSUM:
|
||||
ret.id = data->decode_data >> 32;
|
||||
if ((data->decode_data >> 30) & 0x3) {
|
||||
ret.battery_low = 0;
|
||||
} else {
|
||||
ret.battery_low = 1;
|
||||
}
|
||||
ret.channel = ((data->decode_data >> 28) & 0x3) + 1;
|
||||
u16 = ((data->decode_data >> 16) & 0x0f) << 8 | ((data->decode_data >> 20) & 0x0f) << 4 | ((data->decode_data >> 24) & 0x0f);
|
||||
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)u16 - 900.0f) / 10.0f);
|
||||
ret.humidity = ((data->decode_data >> 8) & 0x0f) << 4 | ((data->decode_data >> 12) & 0x0f);
|
||||
break;
|
||||
case FPW_Acurite5in1:
|
||||
u8 = ((data->decode_data >> 62) & 0x03);
|
||||
ret.channel = channel_3021[u8];
|
||||
ret.id = (data->decode_data >> 48) & 0x3FFF;
|
||||
ret.battery_low = !((data->decode_data >> 46) & 1);
|
||||
ret.humidity = (data->decode_data >> 8) & 0x7F;
|
||||
u16 = ((data->decode_data >> (24 - 7)) & 0x780) | ((data->decode_data >> 16) & 0x7F);
|
||||
ret.temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)(u16)-400) / 10.0f);
|
||||
break;
|
||||
case FPW_EmosE601x:
|
||||
ret.id = 0xffff; //(upper_decode_data >> 24) & 0xff; //todo maybe with oregon, and +64bit usage/message
|
||||
ret.battery_low = (data->decode_data >> 10) & 1;
|
||||
i16 = (data->decode_data >> 40) & 0xfff;
|
||||
/* Handle signed data */
|
||||
if (i16 & 0x800) {
|
||||
i16 |= 0xf000;
|
||||
}
|
||||
ret.temp = (float)i16 / 10.0;
|
||||
ret.humidity = (data->decode_data >> 32) & 0xff;
|
||||
ret.channel = (data->decode_data >> 52) & 0x03;
|
||||
break;
|
||||
case FPW_SolightTE44:
|
||||
ret.id = (data->decode_data >> 28) & 0xff;
|
||||
ret.battery_low = !(data->decode_data >> 27) & 0x01;
|
||||
ret.channel = ((data->decode_data >> 24) & 0x03) + 1;
|
||||
i16 = (data->decode_data >> 12) & 0x0fff;
|
||||
/* Handle signed data */
|
||||
if (i16 & 0x0800) {
|
||||
i16 |= 0xf000;
|
||||
}
|
||||
ret.temp = (float)i16 / 10.0;
|
||||
break;
|
||||
case FPW_Invalid:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
||||
@@ -96,7 +96,7 @@ class WeatherView : public View {
|
||||
private:
|
||||
void on_tick_second();
|
||||
void on_data(const WeatherDataMessage* data);
|
||||
|
||||
WeatherRecentEntry process_data(const WeatherDataMessage* data);
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{
|
||||
433'920'000 /* frequency */,
|
||||
@@ -151,6 +151,14 @@ class WeatherView : public View {
|
||||
}};
|
||||
WeatherRecentEntriesView recent_entries_view{columns, recent};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_packet{
|
||||
Message::ID::WeatherData,
|
||||
[this](Message* const p) {
|
||||
|
||||
@@ -143,6 +143,10 @@ void AFSKRxView::on_data(uint32_t value, bool is_data) {
|
||||
}
|
||||
}
|
||||
|
||||
void AFSKRxView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
AFSKRxView::~AFSKRxView() {
|
||||
audio::output::stop();
|
||||
receiver_model.disable();
|
||||
|
||||
@@ -117,6 +117,15 @@ class AFSKRxView : public View {
|
||||
const auto message = static_cast<const AFSKDataMessage*>(p);
|
||||
this->on_data(message->value, message->is_data);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::afsk_rx
|
||||
|
||||
@@ -202,4 +202,8 @@ void AnalogTvView::update_modulation(const ReceiverModel::Mode modulation) {
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
void AnalogTvView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::analogtv
|
||||
|
||||
@@ -108,6 +108,15 @@ class AnalogTvView : public View {
|
||||
void set_options_widget(std::unique_ptr<Widget> new_widget);
|
||||
|
||||
void update_modulation(const ReceiverModel::Mode modulation);
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::analogtv
|
||||
|
||||
@@ -103,4 +103,8 @@ void FoxhuntRxView::on_orientation(const OrientationDataMessage* msg) {
|
||||
geomap.update_my_orientation(msg->angle, true);
|
||||
}
|
||||
|
||||
void FoxhuntRxView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::foxhunt_rx
|
||||
|
||||
@@ -103,6 +103,14 @@ class FoxhuntRxView : public View {
|
||||
[this](const Message* const p) {
|
||||
this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
|
||||
}};
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
|
||||
float my_lat = 200;
|
||||
float my_lon = 200;
|
||||
|
||||
@@ -125,6 +125,10 @@ void NRFRxView::on_data(uint32_t value, bool is_data) {
|
||||
}
|
||||
}
|
||||
|
||||
void NRFRxView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
NRFRxView::~NRFRxView() {
|
||||
audio::output::stop();
|
||||
receiver_model.disable();
|
||||
|
||||
@@ -89,6 +89,15 @@ class NRFRxView : public View {
|
||||
const auto message = static_cast<const AFSKDataMessage*>(p);
|
||||
this->on_data(message->value, message->is_data);
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
};
|
||||
|
||||
} /* namespace ui::external_app::nrf_rx */
|
||||
|
||||
@@ -186,6 +186,10 @@ void ProtoView::on_data(const ProtoViewDataMessage* message) {
|
||||
draw2();
|
||||
}
|
||||
|
||||
void ProtoView::on_freqchg(int64_t freq) {
|
||||
field_frequency.set_value(freq);
|
||||
}
|
||||
|
||||
ProtoView::~ProtoView() {
|
||||
audio::output::stop();
|
||||
receiver_model.disable();
|
||||
|
||||
@@ -157,6 +157,15 @@ class ProtoView : public View {
|
||||
[this](const Message* const) {
|
||||
this->on_timer();
|
||||
}};
|
||||
|
||||
MessageHandlerRegistration message_handler_freqchg{
|
||||
Message::ID::FreqChangeCommand,
|
||||
[this](Message* const p) {
|
||||
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
|
||||
this->on_freqchg(message->freq);
|
||||
}};
|
||||
|
||||
void on_freqchg(int64_t freq);
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::protoview
|
||||
|
||||
@@ -586,7 +586,7 @@ init_status_t init() {
|
||||
chThdSleepMilliseconds(10);
|
||||
|
||||
audio::init(portapack_audio_codec());
|
||||
battery::BatteryManagement::init();
|
||||
battery::BatteryManagement::init(persistent_memory::ui_override_batt_calc());
|
||||
|
||||
if (lcd_fast_setup)
|
||||
draw_splash_screen_icon(4, ui::bitmap_icon_speaker);
|
||||
|
||||
@@ -1147,6 +1147,23 @@ static void cmd_asyncmsg(BaseSequentialStream* chp, int argc, char* argv[]) {
|
||||
chprintf(chp, usage);
|
||||
}
|
||||
}
|
||||
static void cmd_setfreq(BaseSequentialStream* chp, int argc, char* argv[]) {
|
||||
const char* usage = "usage: setfreq freq_in_hz\r\n";
|
||||
if (argc != 1) {
|
||||
chprintf(chp, usage);
|
||||
return;
|
||||
}
|
||||
int64_t freq = atol(argv[0]);
|
||||
|
||||
if (freq <= 0) {
|
||||
chprintf(chp, usage);
|
||||
return;
|
||||
}
|
||||
// radio::set_tuning_frequency(freq); // sadly this doesn't update any widget, just change the frequency.
|
||||
FreqChangeCommandMessage message{freq};
|
||||
EventDispatcher::send_message(message);
|
||||
chprintf(chp, "ok\r\n");
|
||||
}
|
||||
|
||||
static const ShellCommand commands[] = {
|
||||
{"reboot", cmd_reboot},
|
||||
@@ -1180,6 +1197,7 @@ static const ShellCommand commands[] = {
|
||||
{"settingsreset", cmd_settingsreset},
|
||||
{"sendpocsag", cmd_sendpocsag},
|
||||
{"asyncmsg", cmd_asyncmsg},
|
||||
{"setfreq", cmd_setfreq},
|
||||
{NULL, NULL}};
|
||||
|
||||
static const ShellConfig shell_cfg1 = {
|
||||
|
||||
@@ -36,7 +36,6 @@ class FProtoSubGhzDBett : public FProtoSubGhzDBase {
|
||||
(te_delta * 15)) {
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// dip decoder needed
|
||||
if (callback) callback(this);
|
||||
|
||||
@@ -53,7 +53,6 @@ class FProtoSubGhzDCame : public FProtoSubGhzDBase {
|
||||
parser_step = CameDecoderStepFoundStartBit;
|
||||
if ((decode_count_bit == min_count_bit_for_found) || (decode_count_bit == AIRFORCE_COUNT_BIT) ||
|
||||
(decode_count_bit == PRASTEL_COUNT_BIT) || (decode_count_bit == CAME_24_COUNT_BIT)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// if flippa hacky, i hacky
|
||||
sensorType = FPS_CAME;
|
||||
|
||||
@@ -43,7 +43,6 @@ class FProtoSubGhzDCameAtomo : public FProtoSubGhzDBase {
|
||||
duration >= ((uint32_t)te_long * 2 + te_delta)) {
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ class FProtoSubGhzDCameTwee : public FProtoSubGhzDBase {
|
||||
} else if (
|
||||
duration >= ((uint32_t)te_long * 2 + te_delta)) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ class FProtoSubGhzDChambCode : public FProtoSubGhzDBase {
|
||||
if (duration > te_short * 5) {
|
||||
if (decode_count_bit >= min_count_bit_for_found) {
|
||||
if (subghz_protocol_decoder_chamb_code_check_mask_and_parse()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@ class FProtoSubGhzDClemsa : public FProtoSubGhzDBase {
|
||||
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ class FProtoSubGhzDDoitrand : public FProtoSubGhzDBase {
|
||||
if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
|
||||
parser_step = DoitrandDecoderStepFoundStartBit;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,6 @@ class FProtoSubGhzDDooya : public FProtoSubGhzDBase {
|
||||
parser_step = DooyaDecoderStepFoundStartBit;
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ class FProtoSubGhzDFaac : public FProtoSubGhzDBase {
|
||||
if (duration >= ((uint32_t)te_short * 3 + te_delta)) {
|
||||
parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// remark controller skipped
|
||||
if (callback) callback(this);
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
#ifndef __FPROTO_GANGQI_H__
|
||||
#define __FPROTO_GANGQI_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
GangQiDecoderStepReset = 0,
|
||||
GangQiDecoderStepSaveDuration,
|
||||
GangQiDecoderStepCheckDuration,
|
||||
} GangQiDecoderStep;
|
||||
|
||||
class FProtoSubGhzDGangqi : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDGangqi() {
|
||||
sensorType = FPS_GANGQI;
|
||||
te_short = 500;
|
||||
te_long = 1200;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 34;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
switch (parser_step) {
|
||||
case GangQiDecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 2) < te_delta * 3)) {
|
||||
// Found GAP
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = GangQiDecoderStepSaveDuration;
|
||||
}
|
||||
break;
|
||||
case GangQiDecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = GangQiDecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = GangQiDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case GangQiDecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
// Bit 0 is short and long timing
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = GangQiDecoderStepSaveDuration;
|
||||
// Bit 1 is long and short timing
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = GangQiDecoderStepSaveDuration;
|
||||
} else if (
|
||||
// End of the key
|
||||
DURATION_DIFF(duration, te_short * 4) <
|
||||
te_delta) {
|
||||
// Found next GAP and add bit 0 or 1 (only bit 0 was found on the remotes)
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short * 4) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
}
|
||||
if ((DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short * 4) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
}
|
||||
// If got 34 bits key reading is finished
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = GangQiDecoderStepReset;
|
||||
} else {
|
||||
parser_step = GangQiDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = GangQiDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -44,7 +44,6 @@ class FProtoSubGhzDGateTx : public FProtoSubGhzDBase {
|
||||
if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
|
||||
parser_step = GateTXDecoderStepFoundStartBit;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ class FProtoSubGhzDHoltek : public FProtoSubGhzDBase {
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
if ((decode_data & HOLTEK_HEADER_MASK) == HOLTEK_HEADER) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -44,11 +44,8 @@ class FProtoSubGhzDHoltekHt12x : public FProtoSubGhzDBase {
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_short * 10 + te_delta)) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
if (data != decode_data) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
|
||||
@@ -71,7 +71,6 @@ class FProtoSubGhzDHoneywell : public FProtoSubGhzDBase {
|
||||
uint16_t crc = decode_data & 0xFFFF;
|
||||
if (crc == crc_calc) {
|
||||
// the data is good. process it.
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit; // maybe set it to 64, and hack the first 2 bits to 1! will see if replay needs it
|
||||
if (callback) callback(this);
|
||||
decode_data = 0;
|
||||
|
||||
@@ -36,7 +36,6 @@ class FProtoSubGhzDHoneywellWdb : public FProtoSubGhzDBase {
|
||||
if (DURATION_DIFF(duration, te_short * 3) < te_delta) {
|
||||
if ((decode_count_bit == min_count_bit_for_found) &&
|
||||
((decode_data & 0x01) == FProtoGeneral::subghz_protocol_blocks_get_parity(decode_data >> 1, min_count_bit_for_found - 1))) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
// controller has too much, should be done on ui side
|
||||
if (callback) callback(this);
|
||||
|
||||
@@ -47,7 +47,6 @@ class FProtoSubGhzDHormann : public FProtoSubGhzDBase {
|
||||
parser_step = HormannDecoderStepFoundStartBit;
|
||||
if (decode_count_bit >=
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ class FProtoSubGhzDHormannBiSecure : public FProtoSubGhzDBase {
|
||||
|
||||
void subghz_protocol_decoder_hormann_bisecur_reset() {
|
||||
parser_step = HormannBiSecurDecoderStepReset;
|
||||
data = 0;
|
||||
for (uint8_t i = 0; i < 22; ++i) dataa[i] = 0;
|
||||
data_count_bit = 0;
|
||||
manchester_saved_state = ManchesterStateStart1;
|
||||
|
||||
@@ -44,7 +44,6 @@ class FProtoSubGhzDIdo : public FProtoSubGhzDBase {
|
||||
parser_step = IDoDecoderStepFoundPreambula;
|
||||
if (decode_count_bit >=
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ class FProtoSubGhzDIntertechnoV3 : public FProtoSubGhzDBase {
|
||||
parser_step = IntertechnoV3DecoderStepStartSync;
|
||||
if ((decode_count_bit == min_count_bit_for_found) ||
|
||||
(decode_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -57,11 +57,8 @@ class FProtoSubGhzDKeeLoq : public FProtoSubGhzDBase {
|
||||
parser_step = KeeloqDecoderStepReset;
|
||||
if ((decode_count_bit >= min_count_bit_for_found) &&
|
||||
(decode_count_bit <= min_count_bit_for_found + 2)) {
|
||||
if (data != decode_data) {
|
||||
data = decode_data;
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
if (callback) callback(this);
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
header_count = 0;
|
||||
@@ -96,6 +93,8 @@ class FProtoSubGhzDKeeLoq : public FProtoSubGhzDBase {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t header_count = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -50,7 +50,8 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
|
||||
DURATION_DIFF(duration, te_short * 2) < te_delta * 2) {
|
||||
parser_step = KingGates_stylo_4kDecoderStepSaveDuration;
|
||||
decode_data = 0;
|
||||
data_2 = 0;
|
||||
// data_2 = 0;
|
||||
// data = 0;
|
||||
decode_count_bit = 0;
|
||||
header_count = 0;
|
||||
}
|
||||
@@ -58,17 +59,17 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
|
||||
case KingGates_stylo_4kDecoderStepSaveDuration:
|
||||
if (!level) {
|
||||
if (duration >= ((uint32_t)te_long * 3)) {
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = data_2;
|
||||
data_2 = decode_data; // TODO DATA2
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
// data = data_2;
|
||||
// data_2 = decode_data; // TODO DATA2
|
||||
data_count_bit = decode_count_bit;
|
||||
// decode_data = data;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
parser_step = KingGates_stylo_4kDecoderStepReset;
|
||||
decode_data = 0;
|
||||
data_2 = 0;
|
||||
// data_2 = 0;
|
||||
decode_count_bit = 0;
|
||||
header_count = 0;
|
||||
break;
|
||||
@@ -101,7 +102,7 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
|
||||
header_count = 0;
|
||||
}
|
||||
if (decode_count_bit == 53) {
|
||||
data_2 = decode_data;
|
||||
// data_2 = decode_data;
|
||||
decode_data = 0;
|
||||
}
|
||||
} else {
|
||||
@@ -113,7 +114,9 @@ class FProtoSubGhzDKinggatesStylo4K : public FProtoSubGhzDBase {
|
||||
}
|
||||
|
||||
protected:
|
||||
uint64_t data_2 = 0;
|
||||
// uint64_t data_2 = 0;
|
||||
// uint64_t data = 0;
|
||||
uint16_t header_count = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -79,23 +79,17 @@ class FProtoSubGhzDLegrand : public FProtoSubGhzDBase {
|
||||
if (found) {
|
||||
te += duration;
|
||||
|
||||
if (decode_count_bit <
|
||||
min_count_bit_for_found) {
|
||||
if (decode_count_bit < min_count_bit_for_found) {
|
||||
parser_step = LegrandDecoderStepSaveDuration;
|
||||
break;
|
||||
}
|
||||
|
||||
// enough bits for a packet found, save it only if there was a previous packet
|
||||
// with the same data
|
||||
if (data && (data != decode_data)) {
|
||||
te /= decode_count_bit * 4;
|
||||
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) {
|
||||
callback(this);
|
||||
}
|
||||
te /= decode_count_bit * 4;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) {
|
||||
callback(this);
|
||||
}
|
||||
// fallthrough to reset, the next bit is expected to be a sync
|
||||
// it also takes care of resetting the decoder state
|
||||
|
||||
@@ -54,7 +54,6 @@ class FProtoSubGhzDLinear : public FProtoSubGhzDBase {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
}
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -49,11 +49,8 @@ class FProtoSubGhzDLinearDelta3 : public FProtoSubGhzDBase {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
}
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
if ((data == decode_data) && data) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
parser_step = LinearD3DecoderStepSaveDuration;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -90,7 +90,6 @@ class FProtoSubGhzDMagellan : public FProtoSubGhzDBase {
|
||||
// Found stop bit
|
||||
if ((decode_count_bit == min_count_bit_for_found) &&
|
||||
subghz_protocol_magellan_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
@@ -129,6 +128,7 @@ class FProtoSubGhzDMagellan : public FProtoSubGhzDBase {
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
uint16_t header_count = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -43,7 +43,6 @@ class FProtoSubGhzDMarantec : public FProtoSubGhzDBase {
|
||||
} else if (
|
||||
duration >= ((uint32_t)te_long * 2 + te_delta)) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
|
||||
#ifndef __FPROTO_MARANTEC24_H__
|
||||
#define __FPROTO_MARANTEC24_H__
|
||||
|
||||
#include "subghzdbase.hpp"
|
||||
|
||||
typedef enum {
|
||||
Marantec24DecoderStepReset = 0,
|
||||
Marantec24DecoderStepSaveDuration,
|
||||
Marantec24DecoderStepCheckDuration,
|
||||
} Marantec24DecoderStep;
|
||||
|
||||
class FProtoSubGhzDMarantec24 : public FProtoSubGhzDBase {
|
||||
public:
|
||||
FProtoSubGhzDMarantec24() {
|
||||
sensorType = FPS_MARANTEC24;
|
||||
te_short = 800;
|
||||
te_long = 1600;
|
||||
te_delta = 200;
|
||||
min_count_bit_for_found = 24;
|
||||
}
|
||||
|
||||
void feed(bool level, uint32_t duration) {
|
||||
// Key samples
|
||||
// 101011000000010111001000 = AC05C8
|
||||
// 101011000000010111000100 = AC05C4
|
||||
// 101011000000010111001100 = AC05CC
|
||||
// 101011000000010111000000 = AC05C0
|
||||
|
||||
switch (parser_step) {
|
||||
case Marantec24DecoderStepReset:
|
||||
if ((!level) && (DURATION_DIFF(duration, te_long * 9) < te_delta * 4)) {
|
||||
// Found GAP
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = Marantec24DecoderStepSaveDuration;
|
||||
}
|
||||
break;
|
||||
case Marantec24DecoderStepSaveDuration:
|
||||
if (level) {
|
||||
te_last = duration;
|
||||
parser_step = Marantec24DecoderStepCheckDuration;
|
||||
} else {
|
||||
parser_step = Marantec24DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case Marantec24DecoderStepCheckDuration:
|
||||
if (!level) {
|
||||
// Bit 0 is long and short x2 timing = 1600us HIGH (te_last) and 2400us LOW
|
||||
if ((DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_short * 3) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
parser_step = Marantec24DecoderStepSaveDuration;
|
||||
// Bit 1 is short and long x2 timing = 800us HIGH (te_last) and 3200us LOW
|
||||
} else if (
|
||||
(DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long * 2) < te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
parser_step = Marantec24DecoderStepSaveDuration;
|
||||
} else if (
|
||||
// End of the key
|
||||
DURATION_DIFF(duration, te_long * 9) < te_delta * 4) {
|
||||
// Found next GAP and add bit 0 or 1 (only bit 0 was found on the remotes)
|
||||
if ((DURATION_DIFF(te_last, te_long) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long * 9) < te_delta * 4)) {
|
||||
subghz_protocol_blocks_add_bit(0);
|
||||
}
|
||||
if ((DURATION_DIFF(te_last, te_short) < te_delta) &&
|
||||
(DURATION_DIFF(duration, te_long * 9) < te_delta * 4)) {
|
||||
subghz_protocol_blocks_add_bit(1);
|
||||
}
|
||||
// If got 24 bits key reading is finished
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
parser_step = Marantec24DecoderStepReset;
|
||||
} else {
|
||||
parser_step = Marantec24DecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
parser_step = Marantec24DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -61,7 +61,6 @@ class FProtoSubGhzDMastercode : public FProtoSubGhzDBase {
|
||||
}
|
||||
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
|
||||
@@ -48,7 +48,6 @@ class FProtoSubGhzDMegacode : public FProtoSubGhzDBase {
|
||||
parser_step = MegaCodeDecoderStepReset;
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
|
||||
@@ -67,7 +67,6 @@ class FProtoSubGhzDNeroSketch : public FProtoSubGhzDBase {
|
||||
// Found stop bit
|
||||
parser_step = NeroSketchDecoderStepReset;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
@@ -103,6 +102,7 @@ class FProtoSubGhzDNeroSketch : public FProtoSubGhzDBase {
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint16_t header_count = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -82,7 +82,6 @@ class FProtoSubGhzDNeroRadio : public FProtoSubGhzDBase {
|
||||
parser_step = NeroRadioDecoderStepReset;
|
||||
if ((decode_count_bit == min_count_bit_for_found) ||
|
||||
(decode_count_bit == min_count_bit_for_found + 1)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
@@ -110,6 +109,7 @@ class FProtoSubGhzDNeroRadio : public FProtoSubGhzDBase {
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint16_t header_count = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,6 @@ class FProtoSubGhzDNiceflo : public FProtoSubGhzDBase {
|
||||
if (duration >= (te_short * 4)) {
|
||||
parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
if (decode_count_bit >= min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -56,10 +56,9 @@ class FProtoSubGhzDNiceflors : public FProtoSubGhzDBase {
|
||||
// Found STOP bit
|
||||
parser_step = NiceFlorSDecoderStepReset;
|
||||
if ((decode_count_bit == min_count_bit_for_found) || (decode_count_bit == NICE_ONE_COUNT_BIT)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
decode_data = 0;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
@@ -86,8 +85,8 @@ class FProtoSubGhzDNiceflors : public FProtoSubGhzDBase {
|
||||
parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
decode_data = 0;
|
||||
// data = decode_data;
|
||||
// decode_data = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ class FProtoSubGhzDPhoenixV2 : public FProtoSubGhzDBase {
|
||||
parser_step = Phoenix_V2DecoderStepFoundStartBit;
|
||||
if (decode_count_bit ==
|
||||
min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ class FProtoSubGhzDPowerSmart : public FProtoSubGhzDBase {
|
||||
}
|
||||
if ((decode_data & POWER_SMART_PACKET_HEADER_MASK) == POWER_SMART_PACKET_HEADER) {
|
||||
if (subghz_protocol_power_smart_chek_valid(decode_data)) {
|
||||
data = decode_data;
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
|
||||
if (callback) callback(this);
|
||||
|
||||
@@ -42,7 +42,6 @@ class FProtoSubGhzDPrinceton : public FProtoSubGhzDBase {
|
||||
if (duration >= ((uint32_t)te_long * 2)) {
|
||||
parser_step = PrincetonDecoderStepSaveDuration;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ class FProtoSubGhzDSecPlusV2 : public FProtoSubGhzDBase {
|
||||
} else if (
|
||||
duration >= (te_long * 2UL + te_delta)) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (subghz_protocol_secplus_v2_check_packet()) {
|
||||
// controller too big
|
||||
|
||||
@@ -42,7 +42,6 @@ class FProtoSubGhzDSmc5326 : public FProtoSubGhzDBase {
|
||||
if (duration >= ((uint32_t)te_long * 2)) {
|
||||
parser_step = SMC5326DecoderStepSaveDuration;
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
|
||||
@@ -68,11 +68,9 @@ class FProtoSubGhzDSomifyKeytis : public FProtoSubGhzDBase {
|
||||
duration >= (te_long + te_delta)) {
|
||||
if (decode_count_bit == min_count_bit_for_found) {
|
||||
// check crc
|
||||
uint64_t data_tmp = data ^ (data >> 8);
|
||||
uint64_t data_tmp = decode_data ^ (decode_data >> 8);
|
||||
if (((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_keytis_crc(data_tmp)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
}
|
||||
}
|
||||
@@ -124,6 +122,8 @@ class FProtoSubGhzDSomifyKeytis : public FProtoSubGhzDBase {
|
||||
}
|
||||
return crc & 0xf;
|
||||
}
|
||||
|
||||
uint16_t header_count = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,7 +71,6 @@ class FProtoSubGhzDSomifyTelis : public FProtoSubGhzDBase {
|
||||
// check crc
|
||||
uint64_t data_tmp = decode_data ^ (decode_data >> 8);
|
||||
if (((data_tmp >> 40) & 0xF) == subghz_protocol_somfy_telis_crc(data_tmp)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
@@ -118,6 +117,7 @@ class FProtoSubGhzDSomifyTelis : public FProtoSubGhzDBase {
|
||||
}
|
||||
return crc & 0xf;
|
||||
}
|
||||
uint16_t header_count = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -53,11 +53,8 @@ class FProtoSubGhzDStarLine : public FProtoSubGhzDBase {
|
||||
parser_step = StarLineDecoderStepReset;
|
||||
if ((decode_count_bit >= min_count_bit_for_found) &&
|
||||
(decode_count_bit <= min_count_bit_for_found + 2)) {
|
||||
if (data != decode_data) {
|
||||
data = decode_data;
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
@@ -101,6 +98,7 @@ class FProtoSubGhzDStarLine : public FProtoSubGhzDBase {
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint16_t header_count = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,6 @@ class FProtoSubGhzDX10 : public FProtoSubGhzDBase {
|
||||
if (decode_count_bit >= min_count_bit_for_found &&
|
||||
((((decode_data >> 24) ^ (decode_data >> 16)) & 0xFF) == 0xFF) &&
|
||||
((((decode_data >> 8) ^ (decode_data)) & 0xFF) == 0xFF)) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
|
||||
if (callback) callback(this);
|
||||
|
||||
@@ -26,7 +26,7 @@ class FProtoSubGhzDBase {
|
||||
// General data holder, these will be passed
|
||||
uint8_t sensorType = FPS_Invalid;
|
||||
uint16_t data_count_bit = 0;
|
||||
uint64_t data = 0;
|
||||
uint64_t decode_data = 0;
|
||||
|
||||
protected:
|
||||
// Helper functions to keep it as compatible with flipper as we can, so adding new protos will be easy.
|
||||
@@ -42,11 +42,11 @@ class FProtoSubGhzDBase {
|
||||
uint32_t min_count_bit_for_found = UINT32_MAX;
|
||||
|
||||
SubGhzDProtocolDecoderBaseRxCallback callback = NULL;
|
||||
uint16_t header_count = 0;
|
||||
|
||||
uint8_t parser_step = 0;
|
||||
uint32_t te_last = 0;
|
||||
uint32_t decode_count_bit = 0;
|
||||
uint64_t decode_data = 0;
|
||||
|
||||
//
|
||||
};
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ So include here the .hpp, and add a new element to the protos vector in the cons
|
||||
#include "s-legrand.hpp"
|
||||
#include "s-somify_keytis.hpp"
|
||||
#include "s-somify_telis.hpp"
|
||||
|
||||
#include "s-gangqi.hpp"
|
||||
#include "s-marantec24.hpp"
|
||||
// GENIE FROM PR
|
||||
|
||||
#ifndef __FPROTO_PROTOLISTSGZ_H__
|
||||
@@ -104,6 +105,8 @@ class SubGhzDProtos : public FProtoListGeneral {
|
||||
protos[FPS_X10] = new FProtoSubGhzDX10();
|
||||
// protos[FPS_HORMANNBISECURE] = new FProtoSubGhzDHormannBiSecure(); //fm
|
||||
protos[FPS_LEGRAND] = new FProtoSubGhzDLegrand();
|
||||
protos[FPS_GANGQI] = new FProtoSubGhzDGangqi();
|
||||
protos[FPS_MARANTEC24] = new FProtoSubGhzDMarantec24();
|
||||
|
||||
for (uint8_t i = 0; i < FPS_COUNT; ++i) {
|
||||
if (protos[i] != NULL) protos[i]->setCallback(callbackTarget);
|
||||
@@ -120,7 +123,7 @@ class SubGhzDProtos : public FProtoListGeneral {
|
||||
};
|
||||
|
||||
static void callbackTarget(FProtoSubGhzDBase* instance) {
|
||||
SubGhzDDataMessage packet_message{instance->sensorType, instance->data_count_bit, instance->data};
|
||||
SubGhzDDataMessage packet_message{instance->sensorType, instance->data_count_bit, instance->decode_data};
|
||||
shared_memory.application_queue.push(packet_message);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ enum FPROTO_SUBGHZD_SENSOR : uint8_t {
|
||||
FPS_X10,
|
||||
FPS_SOMIFY_KEYTIS,
|
||||
FPS_SOMIFY_TELIS,
|
||||
FPS_GANGQI,
|
||||
FPS_MARANTEC24,
|
||||
FPS_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -80,9 +80,6 @@ class FProtoWeatherAcurite592TXR : public FProtoWeatherBase {
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
ws_protocol_acurite_592txr_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_acurite_592txr_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -138,17 +135,6 @@ class FProtoWeatherAcurite592TXR : public FProtoWeatherBase {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ws_protocol_acurite_592txr_remote_controller() {
|
||||
uint8_t channel_[] = {3, 0, 2, 1};
|
||||
uint8_t channel_raw = ((data >> 54) & 0x03);
|
||||
channel = channel_[channel_raw];
|
||||
id = (data >> 40) & 0x3FFF;
|
||||
battery_low = !((data >> 38) & 1);
|
||||
humidity = (data >> 24) & 0x7F;
|
||||
uint16_t temp_raw = ((data >> 9) & 0xF80) | ((data >> 8) & 0x7F);
|
||||
temp = ((float)(temp_raw)-1000) / 10.0f;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -73,9 +73,6 @@ class FProtoWeatherAcurite5in1 : public FProtoWeatherBase {
|
||||
if ((decode_count_bit == min_count_bit_for_found) &&
|
||||
ws_protocol_acurite_5n1_check_crc() &&
|
||||
ws_protocol_acurite_5n1_check_message_type()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_acurite_5n1_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -133,17 +130,6 @@ class FProtoWeatherAcurite5in1 : public FProtoWeatherBase {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ws_protocol_acurite_5n1_remote_controller() {
|
||||
uint8_t channell[] = {3, 0, 2, 1};
|
||||
uint8_t channel_raw = ((data >> 62) & 0x03);
|
||||
channel = channell[channel_raw];
|
||||
id = (data >> 48) & 0x3FFF;
|
||||
battery_low = !((data >> 46) & 1);
|
||||
humidity = (data >> 8) & 0x7F;
|
||||
uint16_t temp_raw = ((data >> (24 - 7)) & 0x780) | ((data >> 16) & 0x7F);
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)(temp_raw)-400) / 10.0f);
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,9 +48,6 @@ class FProtoWeatherAcurite606TX : public FProtoWeatherBase {
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
ws_protocol_acurite_606tx_check()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_acurite_606tx_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -83,17 +80,6 @@ class FProtoWeatherAcurite606TX : public FProtoWeatherBase {
|
||||
uint32_t te_delta = 150;
|
||||
uint32_t min_count_bit_for_found = 32;
|
||||
|
||||
void ws_protocol_acurite_606tx_remote_controller() {
|
||||
id = (data >> 24) & 0xFF;
|
||||
battery_low = (data >> 23) & 1;
|
||||
channel = WS_NO_CHANNEL;
|
||||
if (!((data >> 19) & 1)) {
|
||||
temp = (float)((data >> 8) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
temp = (float)((~(data >> 8) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
humidity = WS_NO_HUMIDITY;
|
||||
}
|
||||
bool ws_protocol_acurite_606tx_check() {
|
||||
if (!decode_data) return false;
|
||||
uint8_t msg[] = {
|
||||
|
||||
@@ -44,9 +44,6 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
|
||||
// Found syncPostfix
|
||||
parser_step = Acurite_609TXCDecoderStepReset;
|
||||
if ((decode_count_bit == min_count_bit_for_found) && ws_protocol_acurite_609txc_check()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_acurite_609txc_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -76,19 +73,6 @@ class FProtoWeatherAcurite609TX : public FProtoWeatherBase {
|
||||
uint32_t te_delta = 150;
|
||||
uint32_t min_count_bit_for_found = 32;
|
||||
|
||||
void ws_protocol_acurite_609txc_remote_controller() {
|
||||
id = (data >> 32) & 0xFF;
|
||||
battery_low = (data >> 31) & 1;
|
||||
channel = WS_NO_CHANNEL;
|
||||
|
||||
// Temperature in Celsius is encoded as a 12 bit integer value
|
||||
// multiplied by 10 using the 4th - 6th nybbles (bytes 1 & 2)
|
||||
// negative values are recovered by sign extend from int16_t.
|
||||
int16_t temp_raw =
|
||||
(int16_t)(((data >> 12) & 0xf000) | ((data >> 16) << 4));
|
||||
temp = (temp_raw >> 4) * 0.1f;
|
||||
humidity = (data >> 8) & 0xff;
|
||||
}
|
||||
bool ws_protocol_acurite_609txc_check() {
|
||||
if (!decode_data) return false;
|
||||
uint8_t crc = (uint8_t)(decode_data >> 32) +
|
||||
|
||||
@@ -84,9 +84,6 @@ class FProtoWeatherAcurite986 : public FProtoWeatherBase {
|
||||
// Found syncPostfix
|
||||
parser_step = Acurite_986DecoderStepReset;
|
||||
if ((decode_count_bit == min_count_bit_for_found) && ws_protocol_acurite_986_check()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_acurite_986_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -105,22 +102,6 @@ class FProtoWeatherAcurite986 : public FProtoWeatherBase {
|
||||
uint32_t te_delta = 50;
|
||||
uint32_t min_count_bit_for_found = 40;
|
||||
|
||||
void ws_protocol_acurite_986_remote_controller() {
|
||||
int temp;
|
||||
|
||||
id = FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 24, 8);
|
||||
id = (id << 8) | FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 16, 8);
|
||||
battery_low = (data >> 14) & 1;
|
||||
channel = ((data >> 15) & 1) + 1;
|
||||
|
||||
temp = FProtoGeneral::subghz_protocol_blocks_reverse_key(data >> 32, 8);
|
||||
if (temp & 0x80) {
|
||||
temp = -(temp & 0x7F);
|
||||
}
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius((float)temp);
|
||||
humidity = WS_NO_HUMIDITY;
|
||||
}
|
||||
|
||||
bool ws_protocol_acurite_986_check() {
|
||||
if (!decode_data) return false;
|
||||
uint8_t msg[] = {
|
||||
|
||||
@@ -42,9 +42,6 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
|
||||
if (((decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == AMBIENT_WEATHER_PACKET_HEADER_1) ||
|
||||
((decode_data & AMBIENT_WEATHER_PACKET_HEADER_MASK) == AMBIENT_WEATHER_PACKET_HEADER_2)) {
|
||||
if (ws_protocol_ambient_weather_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = min_count_bit_for_found;
|
||||
ws_protocol_ambient_weather_remote_controller();
|
||||
if (callback) callback(this);
|
||||
decode_data = 0;
|
||||
decode_count_bit = 0;
|
||||
@@ -74,14 +71,6 @@ class FProtoWeatherAmbient : public FProtoWeatherBase {
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8(msg, 5, 0x98, 0x3e) ^ 0x64;
|
||||
return (crc == (uint8_t)(decode_data & 0xFF));
|
||||
}
|
||||
|
||||
void ws_protocol_ambient_weather_remote_controller() {
|
||||
id = (data >> 32) & 0xFF;
|
||||
battery_low = (data >> 31) & 1;
|
||||
channel = ((data >> 28) & 0x07) + 1;
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 16) & 0x0FFF) - 400.0f) / 10.0f);
|
||||
humidity = (data >> 8) & 0xFF;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,9 +48,6 @@ class FProtoWeatherAuriolAhfl : public FProtoWeatherBase {
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
ws_protocol_auriol_ahfl_check()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_auriol_ahfl_remote_controller();
|
||||
if (callback) {
|
||||
callback(this);
|
||||
}
|
||||
@@ -88,19 +85,6 @@ class FProtoWeatherAuriolAhfl : public FProtoWeatherBase {
|
||||
uint32_t te_delta = 150;
|
||||
uint32_t min_count_bit_for_found = 42;
|
||||
|
||||
void ws_protocol_auriol_ahfl_remote_controller() {
|
||||
id = data >> 34;
|
||||
battery_low = (data >> 33) & 1;
|
||||
// btn = (data >> 32) & 1;
|
||||
channel = ((data >> 30) & 0x3) + 1;
|
||||
if (!((data >> 29) & 1)) {
|
||||
temp = (float)((data >> 18) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
temp = (float)((~(data >> 18) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
humidity = (data >> 11) & 0x7F;
|
||||
}
|
||||
|
||||
bool ws_protocol_auriol_ahfl_check() {
|
||||
uint8_t type = (decode_data >> 6) & 0x0F;
|
||||
if (type != AURIOL_AHFL_CONST_DATA) {
|
||||
|
||||
@@ -47,9 +47,6 @@ class FProtoWeatherAuriolTh : public FProtoWeatherBase {
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
ws_protocol_auriol_th_check()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_auriol_th_remote_controller();
|
||||
if (callback) callback(this);
|
||||
parser_step = auriol_THDecoderStepCheckDuration;
|
||||
}
|
||||
@@ -87,18 +84,6 @@ class FProtoWeatherAuriolTh : public FProtoWeatherBase {
|
||||
uint32_t te_delta = 150;
|
||||
uint32_t min_count_bit_for_found = 37;
|
||||
|
||||
void ws_protocol_auriol_th_remote_controller() {
|
||||
id = (data >> 31) & 0xFF;
|
||||
battery_low = ((data >> 30) & 1);
|
||||
channel = ((data >> 25) & 0x03) + 1;
|
||||
if (!((data >> 23) & 1)) {
|
||||
temp = (float)((data >> 13) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
temp = (float)((~(data >> 13) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
|
||||
humidity = (data >> 1) & 0x7F;
|
||||
}
|
||||
bool ws_protocol_auriol_th_check() {
|
||||
uint8_t type = (decode_data >> 8) & 0x0F;
|
||||
|
||||
|
||||
@@ -81,9 +81,7 @@ class FProtoWeatherEmosE601x : public FProtoWeatherBase {
|
||||
}
|
||||
|
||||
if (decode_count_bit == 120) {
|
||||
data_count_bit = decode_count_bit;
|
||||
if (ws_protocol_emose601x_check()) {
|
||||
ws_protocol_emose601x_extract_data();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
break;
|
||||
@@ -127,20 +125,6 @@ class FProtoWeatherEmosE601x : public FProtoWeatherBase {
|
||||
uint8_t sum = FProtoGeneral::subghz_protocol_blocks_add_bytes(msg, 13);
|
||||
return (sum == ((decode_data >> 8) & 0xff));
|
||||
}
|
||||
|
||||
void ws_protocol_emose601x_extract_data() {
|
||||
id = (upper_decode_data >> 24) & 0xff;
|
||||
battery_low = (decode_data >> 10) & 1;
|
||||
int16_t temp = (decode_data >> 40) & 0xfff;
|
||||
/* Handle signed data */
|
||||
if (temp & 0x800) {
|
||||
temp |= 0xf000;
|
||||
}
|
||||
temp = (float)temp / 10.0;
|
||||
humidity = (decode_data >> 32) & 0xff;
|
||||
channel = (decode_data >> 52) & 0x03;
|
||||
data = (decode_data >> 16);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -50,9 +50,6 @@ class FProtoWeatherGTWT02 : public FProtoWeatherBase {
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
ws_protocol_gt_wt_02_check()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_gt_wt_02_remote_controller();
|
||||
if (callback) callback(this);
|
||||
} else if (decode_count_bit == 1) {
|
||||
parser_step = GT_WT02DecoderStepSaveDuration;
|
||||
@@ -88,25 +85,6 @@ class FProtoWeatherGTWT02 : public FProtoWeatherBase {
|
||||
uint32_t te_delta = 150;
|
||||
uint32_t min_count_bit_for_found = 37;
|
||||
|
||||
void ws_protocol_gt_wt_02_remote_controller() {
|
||||
id = (data >> 29) & 0xFF;
|
||||
battery_low = (data >> 28) & 1;
|
||||
// btn = (data >> 27) & 1;
|
||||
channel = ((data >> 25) & 0x3) + 1;
|
||||
|
||||
if (!((data >> 24) & 1)) {
|
||||
temp = (float)((data >> 13) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
temp = (float)((~(data >> 13) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
|
||||
humidity = (data >> 6) & 0x7F;
|
||||
if (humidity <= 10) // actually the sensors sends 10 below working range of 20%
|
||||
humidity = 0;
|
||||
else if (humidity > 90) // actually the sensors sends 110 above working range of 90%
|
||||
humidity = 100;
|
||||
}
|
||||
|
||||
bool ws_protocol_gt_wt_02_check() {
|
||||
if (!decode_data) return false;
|
||||
uint8_t sum = (decode_data >> 5) & 0xe;
|
||||
|
||||
@@ -77,9 +77,6 @@ class FProtoWeatherGTWT03 : public FProtoWeatherBase {
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
ws_protocol_gt_wt_03_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_gt_wt_03_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -113,27 +110,6 @@ class FProtoWeatherGTWT03 : public FProtoWeatherBase {
|
||||
uint32_t te_delta = 120;
|
||||
uint32_t min_count_bit_for_found = 41;
|
||||
|
||||
void ws_protocol_gt_wt_03_remote_controller() {
|
||||
id = data >> 33;
|
||||
humidity = (data >> 25) & 0xFF;
|
||||
|
||||
if (humidity <= 10) { // actually the sensors sends 10 below working range of 20%
|
||||
humidity = 0;
|
||||
} else if (humidity > 95) { // actually the sensors sends 110 above working range of 90%
|
||||
humidity = 100;
|
||||
}
|
||||
|
||||
battery_low = (data >> 24) & 1;
|
||||
// (data >> 23) & 1;
|
||||
channel = ((data >> 21) & 0x03) + 1;
|
||||
|
||||
if (!((data >> 20) & 1)) {
|
||||
temp = (float)((data >> 9) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
temp = (float)((~(data >> 9) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
}
|
||||
|
||||
bool ws_protocol_gt_wt_03_check_crc() {
|
||||
uint8_t msg[] = {
|
||||
static_cast<uint8_t>(decode_data >> 33),
|
||||
|
||||
@@ -71,9 +71,6 @@ class FProtoWeatherInfactory : public FProtoWeatherBase {
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
ws_protocol_infactory_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_infactory_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -122,13 +119,6 @@ class FProtoWeatherInfactory : public FProtoWeatherBase {
|
||||
crc ^= msg[4] >> 4; // last nibble is only XORed
|
||||
return (crc == ((decode_data >> 28) & 0x0F));
|
||||
}
|
||||
void ws_protocol_infactory_remote_controller() {
|
||||
id = data >> 32;
|
||||
battery_low = (data >> 26) & 1;
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)((data >> 12) & 0x0FFF) - 900.0f) / 10.0f);
|
||||
humidity = (((data >> 8) & 0x0F) * 10) + ((data >> 4) & 0x0F); // BCD, 'A0'=100%rH
|
||||
channel = data & 0x03;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -78,9 +78,6 @@ class FProtoWeatherKedsum : public FProtoWeatherBase {
|
||||
if ((decode_count_bit ==
|
||||
min_count_bit_for_found) &&
|
||||
ws_protocol_kedsum_th_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_kedsum_th_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -127,20 +124,6 @@ class FProtoWeatherKedsum : public FProtoWeatherBase {
|
||||
crc ^= msg[4] >> 4; // last nibble is only XORed
|
||||
return (crc == (msg[4] & 0x0F));
|
||||
}
|
||||
|
||||
void ws_protocol_kedsum_th_remote_controller() {
|
||||
id = data >> 32;
|
||||
if ((data >> 30) & 0x3) {
|
||||
battery_low = 0;
|
||||
} else {
|
||||
battery_low = 1;
|
||||
}
|
||||
channel = ((data >> 28) & 0x3) + 1;
|
||||
uint16_t temp_raw = ((data >> 16) & 0x0f) << 8 |
|
||||
((data >> 20) & 0x0f) << 4 | ((data >> 24) & 0x0f);
|
||||
temp = FProtoGeneral::locale_fahrenheit_to_celsius(((float)temp_raw - 900.0f) / 10.0f);
|
||||
humidity = ((data >> 8) & 0x0f) << 4 | ((data >> 12) & 0x0f);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -79,9 +79,6 @@ class FProtoWeatherLaCrosseTx : public FProtoWeatherBase {
|
||||
if ((decode_data & LACROSSE_TX_SUNC_MASK) ==
|
||||
LACROSSE_TX_SUNC_PATTERN) {
|
||||
if (ws_protocol_lacrosse_tx_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = LACROSSE_TX_BIT_SIZE;
|
||||
ws_protocol_lacrosse_tx_remote_controller();
|
||||
if (callback) callback(this);
|
||||
}
|
||||
}
|
||||
@@ -119,28 +116,6 @@ class FProtoWeatherLaCrosseTx : public FProtoWeatherBase {
|
||||
uint32_t te_delta = 120;
|
||||
uint32_t min_count_bit_for_found = 40;
|
||||
|
||||
void ws_protocol_lacrosse_tx_remote_controller() {
|
||||
uint8_t msg_type = (data >> 32) & 0x0F;
|
||||
id = (((data >> 28) & 0x0F) << 3) | (((data >> 24) & 0x0F) >> 1);
|
||||
|
||||
float msg_value = (float)((data >> 20) & 0x0F) * 10.0f +
|
||||
(float)((data >> 16) & 0x0F) +
|
||||
(float)((data >> 12) & 0x0F) * 0.1f;
|
||||
|
||||
if (msg_type == LACROSSE_TX_MSG_TYPE_TEMP) { //-V1051
|
||||
temp = msg_value - 50.0f;
|
||||
humidity = WS_NO_HUMIDITY;
|
||||
} else if (msg_type == LACROSSE_TX_MSG_TYPE_HUM) {
|
||||
// ToDo for verification, records are needed with sensors maintaining temperature and temperature for this standard
|
||||
humidity = (uint8_t)msg_value;
|
||||
} else {
|
||||
// furi_crash("WS: WSProtocolLaCrosse_TX incorrect msg_type.");
|
||||
}
|
||||
|
||||
battery_low = WS_NO_BATT;
|
||||
channel = WS_NO_CHANNEL;
|
||||
}
|
||||
|
||||
bool ws_protocol_lacrosse_tx_check_crc() {
|
||||
if (!decode_data) return false;
|
||||
uint8_t msg[] = {
|
||||
|
||||
@@ -67,9 +67,9 @@ class FProtoWeatherLaCrosseTx141thbv2 : public FProtoWeatherBase {
|
||||
if ((decode_count_bit == min_count_bit_for_found) ||
|
||||
(decode_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT)) {
|
||||
if (ws_protocol_lacrosse_tx141thbv2_check_crc()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_lacrosse_tx141thbv2_remote_controller();
|
||||
if (decode_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT) {
|
||||
decode_data >>= 1;
|
||||
}
|
||||
if (callback) callback(this);
|
||||
}
|
||||
decode_data = 0;
|
||||
@@ -107,17 +107,7 @@ class FProtoWeatherLaCrosseTx141thbv2 : public FProtoWeatherBase {
|
||||
uint8_t crc = FProtoGeneral::subghz_protocol_blocks_lfsr_digest8_reflect(msg, 4, 0x31, 0xF4);
|
||||
return (crc == (data & 0xFF));
|
||||
}
|
||||
void ws_protocol_lacrosse_tx141thbv2_remote_controller() {
|
||||
if (data_count_bit == LACROSSE_TX141TH_BV2_BIT_COUNT) {
|
||||
data >>= 1;
|
||||
}
|
||||
id = data >> 32;
|
||||
battery_low = (data >> 31) & 1;
|
||||
// btn = (data >> 30) & 1;
|
||||
channel = ((data >> 28) & 0x03) + 1;
|
||||
temp = ((float)((data >> 16) & 0x0FFF) - 500.0f) / 10.0f;
|
||||
humidity = (data >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
bool ws_protocol_decoder_lacrosse_tx141thbv2_add_bit(uint32_t te_last, uint32_t te_current) {
|
||||
bool ret = false;
|
||||
if (DURATION_DIFF(te_last + te_current, te_short + te_long) < te_delta * 2) {
|
||||
|
||||
@@ -51,9 +51,6 @@ class FProtoWeatherNexusTH : public FProtoWeatherBase {
|
||||
parser_step = Nexus_THDecoderStepReset;
|
||||
if ((decode_count_bit == min_count_bit_for_found) &&
|
||||
ws_protocol_nexus_th_check()) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
ws_protocol_nexus_th_remote_controller();
|
||||
if (callback) callback((FProtoWeatherBase*)this);
|
||||
parser_step = Nexus_THDecoderStepCheckDuration;
|
||||
}
|
||||
@@ -98,23 +95,6 @@ class FProtoWeatherNexusTH : public FProtoWeatherBase {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// fill the base class's variables before calling the callback
|
||||
void ws_protocol_nexus_th_remote_controller() {
|
||||
id = (data >> 28) & 0xFF;
|
||||
battery_low = !((data >> 27) & 1);
|
||||
channel = ((data >> 24) & 0x03) + 1;
|
||||
if (!((data >> 23) & 1)) {
|
||||
temp = (float)((data >> 12) & 0x07FF) / 10.0f;
|
||||
} else {
|
||||
temp = (float)((~(data >> 12) & 0x07FF) + 1) / -10.0f;
|
||||
}
|
||||
humidity = data & 0xFF;
|
||||
if (humidity > 95)
|
||||
humidity = 95;
|
||||
else if (humidity < 20)
|
||||
humidity = 20;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -107,7 +107,6 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
||||
// waiting for fixed oregon2 data
|
||||
if (decode_count_bit == 32) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
decode_data = 0UL;
|
||||
decode_count_bit = 0;
|
||||
|
||||
@@ -117,13 +116,13 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
||||
data = (data & 0x33333333) << 2 |
|
||||
(data & 0xCCCCCCCC) >> 2;
|
||||
|
||||
ws_oregon2_decode_const_data();
|
||||
// ws_oregon2_decode_const_data();
|
||||
var_bits = oregon2_sensor_id_var_bits(OREGON2_SENSOR_ID(data));
|
||||
|
||||
if (!var_bits) {
|
||||
// sensor is not supported, stop decoding, but showing the decoded fixed part
|
||||
// sensor is not supported, stop decoding, so won't showing the decoded fixed part
|
||||
parser_step = Oregon2DecoderStepReset;
|
||||
if (callback) callback(this);
|
||||
// if (callback) callback(this);
|
||||
} else {
|
||||
parser_step = Oregon2DecoderStepVarData;
|
||||
}
|
||||
@@ -139,8 +138,8 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
||||
(var_data & 0xAAAAAAAA) >> 1;
|
||||
var_data = (var_data & 0x33333333) << 2 |
|
||||
(var_data & 0xCCCCCCCC) >> 2;
|
||||
|
||||
ws_oregon2_decode_var_data(OREGON2_SENSOR_ID(data), var_data >> OREGON2_CHECKSUM_BITS);
|
||||
decode_data = var_data;
|
||||
// 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);
|
||||
@@ -155,6 +154,7 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
||||
uint32_t te_long = 1000;
|
||||
uint32_t te_delta = 200;
|
||||
uint32_t min_count_bit_for_found = 32;
|
||||
uint64_t data = 0;
|
||||
|
||||
bool have_bit = false;
|
||||
bool prev_bit = 0;
|
||||
@@ -202,19 +202,21 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void ws_oregon2_decode_const_data() {
|
||||
id = OREGON2_SENSOR_ID(data);
|
||||
uint8_t ch_bits = (data >> 12) & 0xF;
|
||||
channel = 1;
|
||||
while (ch_bits > 1) {
|
||||
channel++;
|
||||
ch_bits >>= 1;
|
||||
}
|
||||
battery_low = (data & OREGON2_FLAG_BAT_LOW) ? 1 : 0;
|
||||
}
|
||||
/* void ws_oregon2_decode_const_data() {
|
||||
id = OREGON2_SENSOR_ID(data);
|
||||
uint8_t ch_bits = (data >> 12) & 0xF;
|
||||
channel = 1;
|
||||
while (ch_bits > 1) {
|
||||
channel++;
|
||||
ch_bits >>= 1;
|
||||
}
|
||||
battery_low = (data & OREGON2_FLAG_BAT_LOW) ? 1 : 0;
|
||||
}
|
||||
|
||||
uint16_t bcd_decode_short(uint32_t data) {
|
||||
return (data & 0xF) * 10 + ((data >> 4) & 0xF);
|
||||
}
|
||||
|
||||
float ws_oregon2_decode_temp(uint32_t data) {
|
||||
int32_t temp_val;
|
||||
temp_val = bcd_decode_short(data >> 4);
|
||||
@@ -241,7 +243,7 @@ class FProtoWeatherOregon2 : public FProtoWeatherBase {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,6 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
|
||||
// waiting for fixed oregon3 data
|
||||
if (decode_count_bit == OREGON3_FIXED_PART_BITS) {
|
||||
data = decode_data;
|
||||
data_count_bit = decode_count_bit;
|
||||
decode_data = 0UL;
|
||||
decode_count_bit = 0;
|
||||
|
||||
@@ -76,9 +75,8 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
|
||||
data = (data & 0x33333333) << 2 |
|
||||
(data & 0xCCCCCCCC) >> 2;
|
||||
|
||||
ws_oregon3_decode_const_data();
|
||||
var_bits =
|
||||
oregon3_sensor_id_var_bits(OREGON3_SENSOR_ID(data));
|
||||
// ws_oregon3_decode_const_data(); //todo fix somehow in the future
|
||||
var_bits = oregon3_sensor_id_var_bits(OREGON3_SENSOR_ID(data));
|
||||
|
||||
if (!var_bits) {
|
||||
// sensor is not supported, stop decoding
|
||||
@@ -98,8 +96,8 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
|
||||
(var_data & 0xAAAAAAAAAAAAAAAA) >> 1;
|
||||
var_data = (var_data & 0x3333333333333333) << 2 |
|
||||
(var_data & 0xCCCCCCCCCCCCCCCC) >> 2;
|
||||
|
||||
ws_oregon3_decode_var_data(OREGON3_SENSOR_ID(data), var_data >> OREGON3_CHECKSUM_BITS);
|
||||
decode_data = var_data;
|
||||
// ws_oregon3_decode_var_data(OREGON3_SENSOR_ID(data), var_data >> OREGON3_CHECKSUM_BITS);
|
||||
parser_step = Oregon3DecoderStepReset;
|
||||
if (callback) callback(this);
|
||||
}
|
||||
@@ -113,6 +111,7 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
|
||||
uint32_t te_long = 1100;
|
||||
uint32_t te_delta = 300;
|
||||
uint32_t min_count_bit_for_found = 32;
|
||||
uint64_t data = 0;
|
||||
|
||||
bool prev_bit = false;
|
||||
uint8_t var_bits{0};
|
||||
@@ -143,31 +142,31 @@ class FProtoWeatherOregon3 : public FProtoWeatherBase {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void ws_oregon3_decode_const_data() {
|
||||
id = OREGON3_SENSOR_ID(data);
|
||||
channel = (data >> 12) & 0xF;
|
||||
battery_low = (data & OREGON3_FLAG_BAT_LOW) ? 1 : 0;
|
||||
}
|
||||
uint16_t ws_oregon3_bcd_decode_short(uint32_t data) {
|
||||
return (data & 0xF) * 10 + ((data >> 4) & 0xF);
|
||||
}
|
||||
float ws_oregon3_decode_temp(uint32_t data) {
|
||||
int32_t temp_val;
|
||||
temp_val = ws_oregon3_bcd_decode_short(data >> 4);
|
||||
temp_val *= 10;
|
||||
temp_val += (data >> 12) & 0xF;
|
||||
if (data & 0xF) temp_val = -temp_val;
|
||||
return (float)temp_val / 10.0;
|
||||
}
|
||||
void ws_oregon3_decode_var_data(uint16_t sensor_id, uint32_t data) {
|
||||
switch (sensor_id) {
|
||||
case ID_THGR221:
|
||||
default:
|
||||
humidity = ws_oregon3_bcd_decode_short(data >> 4);
|
||||
temp = ws_oregon3_decode_temp(data >> 12);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* void ws_oregon3_decode_const_data() {
|
||||
id = OREGON3_SENSOR_ID(data);
|
||||
channel = (data >> 12) & 0xF;
|
||||
battery_low = (data & OREGON3_FLAG_BAT_LOW) ? 1 : 0;
|
||||
}
|
||||
uint16_t ws_oregon3_bcd_decode_short(uint32_t data) {
|
||||
return (data & 0xF) * 10 + ((data >> 4) & 0xF);
|
||||
}
|
||||
float ws_oregon3_decode_temp(uint32_t data) {
|
||||
int32_t temp_val;
|
||||
temp_val = ws_oregon3_bcd_decode_short(data >> 4);
|
||||
temp_val *= 10;
|
||||
temp_val += (data >> 12) & 0xF;
|
||||
if (data & 0xF) temp_val = -temp_val;
|
||||
return (float)temp_val / 10.0;
|
||||
}
|
||||
void ws_oregon3_decode_var_data(uint16_t sensor_id, uint32_t data) {
|
||||
switch (sensor_id) {
|
||||
case ID_THGR221:
|
||||
default:
|
||||
humidity = ws_oregon3_bcd_decode_short(data >> 4);
|
||||
temp = ws_oregon3_decode_temp(data >> 12);
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user