diff --git a/firmware/application/Makefile b/firmware/application/Makefile index f3e7941a..aeb55a32 100755 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -126,6 +126,7 @@ CPPSRC = main.cpp \ hackrf_hal.cpp \ portapack.cpp \ portapack_shared_memory.cpp \ + portapack_persistent_memory.cpp \ portapack_io.cpp \ i2c_pp.cpp \ spi_pp.cpp \ diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp index 0a15dcc3..d1e47739 100755 --- a/firmware/application/main.cpp +++ b/firmware/application/main.cpp @@ -482,7 +482,6 @@ int main(void) { } init_message_queues(); - shared_memory.correction_ppm = 0; portapack::io.init(); ui::Context context; diff --git a/firmware/application/radio.cpp b/firmware/application/radio.cpp index f404f76a..6073ca10 100644 --- a/firmware/application/radio.cpp +++ b/firmware/application/radio.cpp @@ -37,6 +37,7 @@ using namespace hackrf::one; #include "portapack.hpp" +#include "portapack_persistent_memory.hpp" namespace radio { @@ -117,7 +118,8 @@ void set_direction(const rf::Direction new_direction) { } bool set_tuning_frequency(const rf::Frequency frequency) { - rf::Frequency corrected_frequency = frequency * (1000000 + shared_memory.correction_ppm) / 1000000; + const int32_t frequency_correction = frequency * portapack::persistent_memory::correction_ppb() / 1000000000; + rf::Frequency corrected_frequency = frequency + frequency_correction; const auto tuning_config = tuning::config::create(corrected_frequency); if( tuning_config.is_valid() ) { first_if.disable(); diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 51e8c27e..387fa82b 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -22,6 +22,7 @@ #include "receiver_model.hpp" #include "portapack_shared_memory.hpp" +#include "portapack_persistent_memory.hpp" #include "portapack.hpp" using namespace portapack; @@ -43,11 +44,11 @@ void ReceiverModel::set_frequency_step(rf::Frequency f) { } int32_t ReceiverModel::reference_ppm_correction() const { - return shared_memory.correction_ppm; + return persistent_memory::correction_ppb() / 1000; } void ReceiverModel::set_reference_ppm_correction(int32_t v) { - shared_memory.correction_ppm = v; + persistent_memory::set_correction_ppb(v * 1000); update_tuning_frequency(); } diff --git a/firmware/application/ui_setup.cpp b/firmware/application/ui_setup.cpp index d4be6bb6..fd7aa4db 100644 --- a/firmware/application/ui_setup.cpp +++ b/firmware/application/ui_setup.cpp @@ -21,7 +21,7 @@ #include "ui_setup.hpp" -#include "portapack_shared_memory.hpp" +#include "portapack_persistent_memory.hpp" #include "lpc43xx_cpp.hpp" using namespace lpc43xx; @@ -104,7 +104,7 @@ SetFrequencyCorrectionView::SetFrequencyCorrectionView( ) { button_ok.on_select = [&nav, this](Button&){ const auto model = this->form_collect(); - shared_memory.correction_ppm = model.ppm; + portapack::persistent_memory::set_correction_ppb(model.ppm * 1000); nav.pop(); }, @@ -121,7 +121,7 @@ SetFrequencyCorrectionView::SetFrequencyCorrectionView( } }); SetFrequencyCorrectionModel model { - shared_memory.correction_ppm + portapack::persistent_memory::correction_ppb() / 1000 }; form_init(model); diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp new file mode 100644 index 00000000..43626d71 --- /dev/null +++ b/firmware/common/portapack_persistent_memory.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "portapack_persistent_memory.hpp" + +#include "hal.h" + +#include +#include + +namespace portapack { +namespace persistent_memory { + +/* TODO: This is widely applicable. Factor this to somewhere useful. */ +template +struct range_t { + const T minimum; + const T maximum; + + const T& clip(const T& value) const { + return std::max(std::min(value, maximum), minimum); + } + + void reset_if_outside(T& value, const T& reset_value) const { + if( (value < minimum ) || + (value > maximum ) ) { + value = reset_value; + } + } +}; + +using ppb_range_t = range_t; +constexpr ppb_range_t ppb_range { -99000, 99000 }; + +/* struct must pack the same way on M4 and M0 cores. */ +struct data_t { + ppb_t correction_ppb; +}; + +static_assert(sizeof(data_t) <= 0x100, "Persistent memory structure too large for VBAT-maintained region"); + +static data_t* const data = reinterpret_cast(LPC_BACKUP_REG_BASE); + +ppb_t correction_ppb() { + ppb_range.reset_if_outside(data->correction_ppb, 0); + return data->correction_ppb; +} + +void set_correction_ppb(ppb_t new_value) { + data->correction_ppb = ppb_range.clip(new_value); +} + +} /* namespace persistent_memory */ +} /* namespace portapack */ diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp new file mode 100644 index 00000000..db229bdb --- /dev/null +++ b/firmware/common/portapack_persistent_memory.hpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PORTAPACK_PERSISTENT_MEMORY_H__ +#define __PORTAPACK_PERSISTENT_MEMORY_H__ + +#include + +namespace portapack { +namespace persistent_memory { + +using ppb_t = int32_t; + +ppb_t correction_ppb(); +void set_correction_ppb(ppb_t new_value); + +} /* namespace persistent_memory */ +} /* namespace portapack */ + +#endif/*__PORTAPACK_PERSISTENT_MEMORY_H__*/ diff --git a/firmware/common/portapack_shared_memory.hpp b/firmware/common/portapack_shared_memory.hpp index 53097f82..c4ae6aab 100644 --- a/firmware/common/portapack_shared_memory.hpp +++ b/firmware/common/portapack_shared_memory.hpp @@ -38,7 +38,6 @@ struct SharedMemory { // TODO: M0 should directly configure and control DMA channel that is // acquiring ADC samples. TouchADCFrame touch_adc_frame; - int8_t correction_ppm; }; extern SharedMemory& shared_memory;