Skip to content

Commit

Permalink
Centralized interval reporter (MarlinFirmware#10)
Browse files Browse the repository at this point in the history
* create centralized interval reporter, use reporter for opt surf probe

* use arduino channels instead of STM

* remove state tracking

* refactor to eliminate more variables, use optionals, and support more channels

* change interval report interface

* simplify and remove some STL dependencies

* add config flags

* separate declarations and definitions
  • Loading branch information
arades79 committed Dec 10, 2021
1 parent a953a60 commit 01c48da
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 26 deletions.
7 changes: 7 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -4263,6 +4263,13 @@
#define ____HELLO____ :)
#endif

//#define GLOBAL_INTERVAL_REPORTER
#if ENABLED(GLOBAL_INTERVAL_REPORTER)
#define INTERVAL_REPORTER_TIMER TIM12
#define NUM_INTERVAL_REPORTER_SLOTS 4
#define INTERVAL_REPORTER_DEFAULT_INTERVAL 1'000'000
#endif

// @section develop

//
Expand Down
67 changes: 67 additions & 0 deletions Marlin/src/feature/interval_reporter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "../inc/MarlinConfig.h"


#if ENABLED(GLOBAL_INTERVAL_REPORTER)


#include "interval_reporter.h"

IntervalReporter::IntervalReporter(callback_function_t reporter) : channel(nullptr)
{
for (auto &reporter_slot : reporters)
{
if (!reporter_slot.valid)
{
reporter_slot = Reporter(reporter);
channel = &reporter_slot;
break;
}
}

if (!channel)
{
SERIAL_ERROR_MSG("Too many reporters registered! Some reports will not appear!");
return;
}

refresh();
}

IntervalReporter::~IntervalReporter()
{
if (channel)
{
channel->valid = false;
channel->enabled = false;
}
}

void IntervalReporter::set_interval_us(const uint32_t interval_us)
{
timer.setOverflow(interval_us, TimerFormat_t::MICROSEC_FORMAT);
refresh();
}

void IntervalReporter::report_all()
{
for (const auto &reporter : reporters)
if (reporter.enabled)
reporter.fn();
}

void IntervalReporter::refresh()
{
timer.pause();
timer.refresh();
timer.resume();
}

HardwareTimer IntervalReporter::timer{[]() {
HardwareTimer timer{INTERVAL_REPORTER_TIMER};
timer.setOverflow(INTERVAL_REPORTER_DEFAULT_INTERVAL, TimerFormat_t::MICROSEC_FORMAT);
timer.attachInterrupt(IntervalReporter::report_all);
return timer;
}()};
IntervalReporter::ReporterArray IntervalReporter::reporters{};

#endif // GLOBAL_INTERVAL_REPORTER
51 changes: 51 additions & 0 deletions Marlin/src/feature/interval_reporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include "../inc/MarlinConfig.h"

#include <array>

struct IntervalReporter
{

explicit IntervalReporter(callback_function_t reporter);

~IntervalReporter();

inline void start() { if (channel) channel->enabled = true; }

inline void stop() { if (channel) channel->enabled = false; }

inline static const uint32_t get_interval_ms() { return get_interval_us() / 1000UL; }

inline static const uint32_t get_interval_us() {
return timer.getOverflow(TimerFormat_t::MICROSEC_FORMAT);
}

inline static void set_interval_ms(const uint32_t interval_ms) {
set_interval_us(interval_ms * 1000);
}

static void set_interval_us(const uint32_t interval_us);

private:
static HardwareTimer timer;

struct Reporter
{
bool valid;
bool enabled;
callback_function_t fn;

Reporter() = default;
explicit Reporter(callback_function_t fn) : valid(true), fn(fn) {}
};

Reporter * channel;

using ReporterArray = std::array<Reporter, NUM_INTERVAL_REPORTER_SLOTS>;
static ReporterArray reporters;

static void report_all();

static void refresh();
};
9 changes: 7 additions & 2 deletions Marlin/src/feature/optical_surface_probe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@
const auto val = probe.get_distance();
SERIAL_ECHOLNPAIR("Probe raw reading: ", val);

const auto ms = parser.intval('P', 0);
probe.interval_report(ms);
#if ENABLED(GLOBAL_INTERVAL_REPORTER)
const auto ms = parser.intval('P', 0);
if (ms > 0) IntervalReporter::set_interval_ms(ms);

const auto start = parser.boolval('S');
probe.interval_report(start);
#endif
}

#endif // OPTICAL_SURFACE_PROBE
52 changes: 28 additions & 24 deletions Marlin/src/feature/optical_surface_probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

#include "../module/planner.h"

#if ENABLED(GLOBAL_INTERVAL_REPORTER)
#include "interval_reporter.h"
#endif

#include <string_view>
// using namespace std::string_view_literals;

Expand All @@ -19,34 +23,26 @@ struct OpticalSurfaceProbe

void init();

const auto get_distance() const
const uint32_t get_distance() const
{
return analogRead(OPT_SURF_IN_PIN);
}

/**
* @brief reports analog sensor reading at a set interval
* using a hardware timer based interrupt
*
* @param ms milliseconds between reports
*/
void interval_report(const int ms)
{
// requires static lifetime for interrupts to trigger,
// and to ensure we can stop the timer later.
static HardwareTimer timer{TIM12};
timer.pause();
if (ms <= 0)
return;

timer.setOverflow(ms * 1000, TimerFormat_t::MICROSEC_FORMAT);
timer.attachInterrupt([this]
{
const auto position = planner.get_axis_positions_mm();
SERIAL_ECHOLNPAIR("prb:", get_distance(), ",X:", position.x, ",Y:", position.y, ",Z:", position.z);
});
timer.resume();
}
#if ENABLED(GLOBAL_INTERVAL_REPORTER)
/**
* @brief reports analog sensor reading at a set interval
* using a hardware timer based interrupt
*
* @param ms milliseconds between reports
*/
void interval_report(bool start)
{
if (start)
reporter.start();
else
reporter.stop();
}
#endif

/**
* @brief TODO: unimplemented, intended to alter sensor angle
Expand All @@ -63,6 +59,14 @@ struct OpticalSurfaceProbe
private:
constexpr static size_t READ_BUFFER_SIZE{255};

#if ENABLED(GLOBAL_INTERVAL_REPORTER)
IntervalReporter reporter{[this]
{
const auto position = planner.get_axis_positions_mm();
SERIAL_ECHOLNPAIR("prb:", get_distance(), ",X:", position.x, ",Y:", position.y, ",Z:", position.z);
}};
#endif

/**
* @brief Private inner struct for holding serial communication
* protocols and other sensor specific implementation details
Expand Down

0 comments on commit 01c48da

Please sign in to comment.