Quick and dirty temperature logger, debug view of temp vs. time.

This commit is contained in:
Jared Boone 2015-12-16 22:36:51 -08:00
parent 750506b33e
commit 86edf01def
8 changed files with 206 additions and 3 deletions

View File

@ -180,6 +180,7 @@ CPPSRC = main.cpp \
log_file.cpp \
manchester.cpp \
string_format.cpp \
temperature_logger.cpp \
../common/utility.cpp \
../common/chibios_cpp.cpp \
../common/debug.cpp \

View File

@ -129,6 +129,8 @@ private:
void handle_rtc_tick() {
sd_card::poll_inserted();
portapack::temperature_logger.second_tick();
}
static ui::Widget* touch_widget(ui::Widget* const w, ui::TouchEvent event) {

View File

@ -65,6 +65,8 @@ ReceiverModel receiver_model {
clock_manager
};
TemperatureLogger temperature_logger;
class Power {
public:
void init() {

View File

@ -29,6 +29,7 @@
#include "lcd_ili9341.hpp"
#include "radio.hpp"
#include "temperature_logger.hpp"
namespace portapack {
@ -45,6 +46,8 @@ extern si5351::Si5351 clock_generator;
extern ReceiverModel receiver_model;
extern TemperatureLogger temperature_logger;
void init();
void shutdown();

View File

@ -0,0 +1,65 @@
/*
* 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 "temperature_logger.hpp"
#include "radio.hpp"
#include <algorithm>
void TemperatureLogger::second_tick() {
sample_phase++;
if( sample_phase >= sample_interval ) {
push_sample(read_sample());
}
}
size_t TemperatureLogger::size() const {
return std::min(samples.size(), samples_count);
}
std::vector<TemperatureLogger::sample_t> TemperatureLogger::history() const {
std::vector<sample_t> result;
const auto n = size();
result.resize(n);
// Copy the last N samples from the buffer, since new samples are added at the end.
std::copy(samples.cend() - n, samples.cend(), result.data());
return result;
}
TemperatureLogger::sample_t TemperatureLogger::read_sample() {
// MAX2837 does not return a valid temperature if in "shutdown" mode.
return radio::second_if.temp_sense() & 0x1f;
}
void TemperatureLogger::push_sample(const TemperatureLogger::sample_t sample) {
// Started out building a pseudo-FIFO, then got lazy.
// Shift samples: samples[1:] -> samples[0:-1]
// New sample goes into samples[-1]
std::copy(samples.cbegin() + 1, samples.cend(), samples.begin());
samples.back() = sample;
samples_count++;
sample_phase = 0;
}

View File

@ -0,0 +1,51 @@
/*
* 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 __TEMPERATURE_LOGGER_H__
#define __TEMPERATURE_LOGGER_H__
#include <cstddef>
#include <cstdint>
#include <array>
#include <vector>
class TemperatureLogger {
public:
using sample_t = uint8_t;
void second_tick();
size_t size() const;
std::vector<sample_t> history() const;
private:
std::array<sample_t, 128> samples;
static constexpr size_t sample_interval = 5;
size_t sample_phase = 0;
size_t samples_count = 0;
sample_t read_sample();
void push_sample(const sample_t sample);
};
#endif/*__TEMPERATURE_LOGGER_H__*/

View File

@ -57,6 +57,50 @@ void DebugMemoryView::focus() {
button_done.focus();
}
/* TemperatureWidget *****************************************************/
void TemperatureWidget::paint(Painter& painter) {
const auto history = portapack::temperature_logger.history();
const auto rect = screen_rect();
for(size_t i=0; i<history.size(); i++) {
const auto sample = history[i];
const Dim bar_height = sample * 4;
const Rect bar_rect {
static_cast<Coord>(rect.right() - (history.size() - i) * 1),
static_cast<Coord>(rect.bottom() - bar_height),
1, bar_height
};
painter.fill_rectangle(bar_rect, Color::green());
}
if( !history.empty() ) {
const int32_t temp = -45 + history.back() * 5;
const size_t temp_len = 3;
painter.draw_string(
{ static_cast<Coord>(rect.right() - (temp_len * 8)), rect.top() },
style(),
to_string_dec_int(temp, temp_len)
);
}
}
/* TemperatureView *******************************************************/
TemperatureView::TemperatureView(NavigationView& nav) {
add_children({ {
&temperature_widget,
&button_done,
} });
button_done.on_select = [&nav](Button&){ nav.pop(); };
}
void TemperatureView::focus() {
button_done.focus();
}
/* RegistersWidget *******************************************************/
RegistersWidget::RegistersWidget(
@ -80,6 +124,8 @@ void RegistersWidget::paint(Painter& painter) {
}
void RegistersWidget::draw_legend(const Coord left, Painter& painter) {
const auto pos = screen_pos();
for(size_t i=0; i<config.registers_count; i+=config.registers_per_row) {
const Point offset {
left, static_cast<Coord>((i / config.registers_per_row) * row_height)
@ -87,7 +133,7 @@ void RegistersWidget::draw_legend(const Coord left, Painter& painter) {
const auto text = to_string_hex(i, config.legend_length);
painter.draw_string(
screen_pos() + offset,
pos + offset,
style().invert(),
text
);
@ -98,6 +144,8 @@ void RegistersWidget::draw_values(
const Coord left,
Painter& painter
) {
const auto pos = screen_pos();
for(size_t i=0; i<config.registers_count; i++) {
const Point offset = {
static_cast<Coord>(left + config.legend_width() + 8 + (i % config.registers_per_row) * (config.value_width() + 8)),
@ -108,7 +156,7 @@ void RegistersWidget::draw_values(
const auto text = to_string_hex(value, config.value_length);
painter.draw_string(
screen_pos() + offset,
pos + offset,
style(),
text
);
@ -152,7 +200,7 @@ void RegistersView::focus() {
/* DebugMenuView *********************************************************/
DebugMenuView::DebugMenuView(NavigationView& nav) {
add_items<7>({ {
add_items<8>({ {
{ "Memory", [&nav](){ nav.push<DebugMemoryView>(); } },
{ "Radio State", [&nav](){ nav.push<NotImplementedView>(); } },
{ "SD Card", [&nav](){ nav.push<NotImplementedView>(); } },
@ -172,6 +220,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
"WM8731", RegistersWidgetConfig { wolfson::wm8731::reg_count, 1, 3, 4 },
[](const size_t register_number) { return portapack::audio_codec.read(register_number); }
); } },
{ "Temperature", [&nav](){ nav.push<TemperatureView>(); } },
} });
on_left = [&nav](){ nav.pop(); };
}

View File

@ -82,6 +82,36 @@ private:
};
};
class TemperatureWidget : public Widget {
public:
explicit constexpr TemperatureWidget(
Rect parent_rect
) : Widget { parent_rect }
{
}
void paint(Painter& painter) override;
private:
};
class TemperatureView : public View {
public:
explicit TemperatureView(NavigationView& nav);
void focus() override;
private:
TemperatureWidget temperature_widget {
{ 0, 16, 240, 192 },
};
Button button_done {
{ 72, 256, 96, 24 },
"Done"
};
};
struct RegistersWidgetConfig {
size_t registers_count;
size_t legend_length;