parent
925201d77a
commit
f0a042c1b6
|
|
@ -39,6 +39,9 @@ bool FeedToFinda::Step() {
|
|||
mm::motion.PlanMove(-600, 0, 0, 4000, 0, 0); //@@TODO constants
|
||||
} else if (mm::motion.QueueEmpty()) { // all moves have been finished and FINDA didn't switch on
|
||||
state = Failed;
|
||||
// @@TODO - shall we disengage the idler?
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::off);
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::red, ml::blink0);
|
||||
}
|
||||
return false;
|
||||
case UnloadBackToPTFE:
|
||||
|
|
@ -52,6 +55,7 @@ bool FeedToFinda::Step() {
|
|||
state = OK;
|
||||
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::on);
|
||||
}
|
||||
// @@TODO FINDA must be reported as OFF again as we are pulling the filament from it - is this correct?
|
||||
return false;
|
||||
case OK:
|
||||
case Failed:
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ struct FeedToFinda {
|
|||
/// @param feedPhaseLimited
|
||||
/// * true feed phase is limited, doesn't react on button press
|
||||
/// * false feed phase is unlimited, can be interrupted by any button press after blanking time
|
||||
/// Beware: the function returns immediately without actually doing anything if the FINDA is "pressed", i.e. the filament is already at the FINDA
|
||||
void Reset(bool feedPhaseLimited);
|
||||
|
||||
/// @returns true if the state machine finished its job, false otherwise
|
||||
|
|
|
|||
|
|
@ -6,6 +6,14 @@ namespace motion {
|
|||
|
||||
Motion motion;
|
||||
|
||||
void Motion::InitAxis(Axis axis) {}
|
||||
|
||||
void Motion::DisableAxis(Axis axis) {}
|
||||
|
||||
bool Motion::StallGuard(Axis axis) { return false; }
|
||||
|
||||
void Motion::ClearStallGuardFlag(Axis axis) {}
|
||||
|
||||
void Motion::PlanMove(uint16_t pulley, uint16_t idler, uint16_t selector, uint16_t feedrate, uint16_t starting_speed, uint16_t ending_speed) {}
|
||||
|
||||
void Motion::Home(Axis axis, bool direction) {}
|
||||
|
|
@ -14,6 +22,10 @@ void Motion::SetMode(MotorMode mode) {}
|
|||
|
||||
void Motion::Step() {}
|
||||
|
||||
bool Motion::QueueEmpty() const { return false; }
|
||||
|
||||
void Motion::AbortPlannedMoves() {}
|
||||
|
||||
void ISR() {}
|
||||
|
||||
//@@TODO check the directions
|
||||
|
|
|
|||
|
|
@ -63,16 +63,16 @@ class Motion {
|
|||
public:
|
||||
/// Init axis driver - @@TODO this should be probably hidden somewhere deeper ... something should manage the axes and their state
|
||||
/// especially when the TMC may get randomly reset (deinited)
|
||||
void InitAxis(Axis axis) {}
|
||||
void InitAxis(Axis axis);
|
||||
|
||||
/// Disable axis motor
|
||||
void DisableAxis(Axis axis) {}
|
||||
void DisableAxis(Axis axis);
|
||||
|
||||
/// @returns true if a stall guard event occurred recently on the axis
|
||||
bool StallGuard(Axis axis) { return false; }
|
||||
bool StallGuard(Axis axis);
|
||||
|
||||
/// clear stall guard flag reported on an axis
|
||||
void ClearStallGuardFlag(Axis axis) {}
|
||||
void ClearStallGuardFlag(Axis axis);
|
||||
|
||||
/// Enqueue move of a specific motor/axis into planner buffer
|
||||
/// @param pulley, idler, selector - target coords
|
||||
|
|
@ -90,10 +90,10 @@ public:
|
|||
void Step();
|
||||
|
||||
/// @returns true if all planned moves have been finished
|
||||
bool QueueEmpty() const { return false; }
|
||||
bool QueueEmpty() const;
|
||||
|
||||
/// stop whatever moves are being done
|
||||
void AbortPlannedMoves() {}
|
||||
void AbortPlannedMoves();
|
||||
|
||||
/// probably higher-level operations knowing the semantic meaning of axes
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
add_subdirectory(cut_filament)
|
||||
|
||||
# add_subdirectory(feed_to_finda)
|
||||
add_subdirectory(feed_to_finda)
|
||||
|
||||
# add_subdirectory(feed_to_bondtech)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@ add_executable(
|
|||
../../../../src/modules/globals.cpp
|
||||
../../../../src/modules/idler.cpp
|
||||
../../../../src/modules/leds.cpp
|
||||
../../../../src/modules/motion.cpp
|
||||
../../../../src/modules/permanent_storage.cpp
|
||||
../../../../src/modules/selector.cpp
|
||||
../../modules/stubs/stub_adc.cpp
|
||||
../../modules/stubs/stub_eeprom.cpp
|
||||
../../modules/stubs/stub_shr16.cpp
|
||||
../stubs/main_loop_stub.cpp
|
||||
../stubs/stub_motion.cpp
|
||||
test_cut_filament.cpp
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,19 +6,71 @@
|
|||
#include "../../../../src/modules/globals.h"
|
||||
#include "../../../../src/modules/idler.h"
|
||||
#include "../../../../src/modules/leds.h"
|
||||
#include "../../../../src/modules/motion.h"
|
||||
#include "../../../../src/modules/permanent_storage.h"
|
||||
#include "../../../../src/modules/selector.h"
|
||||
|
||||
#include "../../../../src/logic/cut_filament.h"
|
||||
|
||||
#include "../../modules/stubs/stub_adc.h"
|
||||
|
||||
#include "../stubs/main_loop_stub.h"
|
||||
#include "../stubs/stub_motion.h"
|
||||
|
||||
using Catch::Matchers::Equals;
|
||||
|
||||
TEST_CASE("cut_filament::basic1", "[cut_filament]") {
|
||||
template <typename COND>
|
||||
bool WhileCondition(COND cond, uint32_t maxLoops = 5000) {
|
||||
while (cond() && --maxLoops) {
|
||||
main_loop();
|
||||
}
|
||||
return maxLoops > 0;
|
||||
}
|
||||
|
||||
TEST_CASE("cut_filament::cut0", "[cut_filament]") {
|
||||
using namespace logic;
|
||||
CutFilament cf;
|
||||
currentCommand = &cf;
|
||||
main_loop();
|
||||
|
||||
// let's assume we have the filament NOT loaded
|
||||
modules::globals::globals.SetFilamentLoaded(false);
|
||||
|
||||
// restart the automaton
|
||||
currentCommand = &cf;
|
||||
cf.Reset(0);
|
||||
|
||||
// it should have instructed the selector and idler to move to slot 1
|
||||
// check if the idler and selector have the right command
|
||||
CHECK(modules::motion::axes[modules::motion::Idler].targetPos == 0); // @@TODO constants
|
||||
CHECK(modules::motion::axes[modules::motion::Selector].targetPos == 0); // @@TODO constants
|
||||
|
||||
// now cycle at most some number of cycles (to be determined yet) and then verify, that the idler and selector reached their target positions
|
||||
REQUIRE(WhileCondition([&]() { return cf.State() == ProgressCode::SelectingFilamentSlot; }, 5000));
|
||||
|
||||
// idler and selector reached their target positions and the CF automaton will start feeding to FINDA as the next step
|
||||
REQUIRE(cf.State() == ProgressCode::FeedingToFinda);
|
||||
REQUIRE(WhileCondition([&]() { return cf.State() == ProgressCode::FeedingToFinda; }, 5000));
|
||||
|
||||
// filament fed into FINDA, cutting...
|
||||
REQUIRE(cf.State() == ProgressCode::PreparingBlade);
|
||||
REQUIRE(WhileCondition([&]() { return cf.State() == ProgressCode::EngagingIdler; }, 5000));
|
||||
|
||||
// the idler should be at the active slot @@TODO
|
||||
REQUIRE(cf.State() == ProgressCode::PushingFilament);
|
||||
REQUIRE(WhileCondition([&]() { return cf.State() == ProgressCode::PushingFilament; }, 5000));
|
||||
|
||||
// filament pushed - performing cut
|
||||
REQUIRE(cf.State() == ProgressCode::PerformingCut);
|
||||
REQUIRE(WhileCondition([&]() { return cf.State() == ProgressCode::PerformingCut; }, 5000));
|
||||
|
||||
// returning selector
|
||||
REQUIRE(cf.State() == ProgressCode::ReturningSelector);
|
||||
REQUIRE(WhileCondition([&]() { return cf.State() == ProgressCode::ReturningSelector; }, 5000));
|
||||
|
||||
// the next states are still @@TODO
|
||||
}
|
||||
|
||||
// comments:
|
||||
// The tricky part of the whole state machine are the edge cases - filament not loaded, stall guards etc.
|
||||
// ... all the external influence we can get on the real HW
|
||||
// But the good news is we can simulate them all in the unit test and thus ensure proper handling
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
# define the test executable
|
||||
add_executable(
|
||||
feed_to_finda_tests
|
||||
../../../../src/logic/feed_to_finda.cpp
|
||||
../../../../src/modules/buttons.cpp
|
||||
../../../../src/modules/debouncer.cpp
|
||||
../../../../src/modules/finda.cpp
|
||||
../../../../src/modules/fsensor.cpp
|
||||
../../../../src/modules/globals.cpp
|
||||
../../../../src/modules/idler.cpp
|
||||
../../../../src/modules/leds.cpp
|
||||
../../../../src/modules/permanent_storage.cpp
|
||||
../../../../src/modules/selector.cpp
|
||||
../../modules/stubs/stub_adc.cpp
|
||||
../../modules/stubs/stub_eeprom.cpp
|
||||
../../modules/stubs/stub_shr16.cpp
|
||||
../stubs/main_loop_stub.cpp
|
||||
../stubs/stub_motion.cpp
|
||||
test_feed_to_finda.cpp
|
||||
)
|
||||
|
||||
# define required search paths
|
||||
target_include_directories(
|
||||
feed_to_finda_tests PUBLIC ${CMAKE_SOURCE_DIR}/src/modules ${CMAKE_SOURCE_DIR}/src/hal
|
||||
${CMAKE_SOURCE_DIR}/src/logic
|
||||
)
|
||||
|
||||
# tell build system about the test case
|
||||
add_catch_test(feed_to_finda_tests)
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
#include "catch2/catch.hpp"
|
||||
|
||||
#include "../../../../src/modules/buttons.h"
|
||||
#include "../../../../src/modules/finda.h"
|
||||
#include "../../../../src/modules/fsensor.h"
|
||||
#include "../../../../src/modules/globals.h"
|
||||
#include "../../../../src/modules/idler.h"
|
||||
#include "../../../../src/modules/leds.h"
|
||||
#include "../../../../src/modules/motion.h"
|
||||
#include "../../../../src/modules/permanent_storage.h"
|
||||
#include "../../../../src/modules/selector.h"
|
||||
|
||||
#include "../../../../src/logic/feed_to_finda.h"
|
||||
|
||||
#include "../../modules/stubs/stub_adc.h"
|
||||
|
||||
#include "../stubs/main_loop_stub.h"
|
||||
#include "../stubs/stub_motion.h"
|
||||
|
||||
using Catch::Matchers::Equals;
|
||||
|
||||
template <typename COND>
|
||||
bool WhileCondition(logic::FeedToFinda &ff, COND cond, uint32_t maxLoops = 5000) {
|
||||
while (cond() && --maxLoops) {
|
||||
main_loop();
|
||||
ff.Step();
|
||||
}
|
||||
return maxLoops > 0;
|
||||
}
|
||||
|
||||
TEST_CASE("feed_to_finda::feed_phase_unlimited", "[feed_to_finda]") {
|
||||
using namespace logic;
|
||||
FeedToFinda ff;
|
||||
main_loop();
|
||||
|
||||
// let's assume we have the filament NOT loaded and active slot 0
|
||||
modules::globals::globals.SetFilamentLoaded(false);
|
||||
modules::globals::globals.SetActiveSlot(0);
|
||||
|
||||
// restart the automaton
|
||||
ff.Reset(false);
|
||||
|
||||
REQUIRE(ff.State() == FeedToFinda::EngagingIdler);
|
||||
|
||||
// it should have instructed the selector and idler to move to slot 1
|
||||
// check if the idler and selector have the right command
|
||||
CHECK(modules::motion::axes[modules::motion::Idler].targetPos == 0); // @@TODO constants
|
||||
CHECK(modules::motion::axes[modules::motion::Selector].targetPos == 0); // @@TODO constants
|
||||
|
||||
// engaging idler
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return !modules::idler::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// idler engaged, we'll start pushing filament
|
||||
REQUIRE(ff.State() == FeedToFinda::PushingFilament);
|
||||
// at least at the beginning the LED should shine green (it should be blinking, but this mode has been already verified in the LED's unit test)
|
||||
REQUIRE(modules::leds::leds.LedOn(modules::globals::globals.ActiveSlot(), modules::leds::Color::green));
|
||||
|
||||
// now let the filament be pushed into the FINDA - do 500 steps without triggering the condition
|
||||
// and then let the simulated ADC channel 1 create a FINDA switch
|
||||
hal::adc::TADCData switchFindaOn({ 0, 600, 700, 800, 900 });
|
||||
hal::adc::ReinitADC(1, std::move(switchFindaOn), 100);
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return ff.State() == FeedToFinda::PushingFilament; },
|
||||
1500));
|
||||
// From now on the FINDA is reported as ON
|
||||
|
||||
// unloading back to PTFE
|
||||
REQUIRE(ff.State() == FeedToFinda::UnloadBackToPTFE);
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return ff.State() == FeedToFinda::UnloadBackToPTFE; },
|
||||
5000));
|
||||
|
||||
// disengaging idler
|
||||
REQUIRE(ff.State() == FeedToFinda::DisengagingIdler);
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return modules::idler::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// state machine finished ok, the green LED should be on
|
||||
REQUIRE(ff.State() == FeedToFinda::OK);
|
||||
REQUIRE(modules::leds::leds.LedOn(modules::globals::globals.ActiveSlot(), modules::leds::Color::green));
|
||||
|
||||
REQUIRE(ff.Step() == true); // the automaton finished its work, any consecutive calls to Step must return true
|
||||
}
|
||||
|
||||
TEST_CASE("feed_to_finda::FINDA_failed", "[feed_to_finda]") {
|
||||
using namespace logic;
|
||||
FeedToFinda ff;
|
||||
main_loop();
|
||||
|
||||
// let's assume we have the filament NOT loaded and active slot 0
|
||||
modules::globals::globals.SetFilamentLoaded(false);
|
||||
modules::globals::globals.SetActiveSlot(0);
|
||||
|
||||
// restart the automaton - we want the limited version of the feed
|
||||
ff.Reset(true);
|
||||
|
||||
REQUIRE(ff.State() == FeedToFinda::EngagingIdler);
|
||||
|
||||
// it should have instructed the selector and idler to move to slot 1
|
||||
// check if the idler and selector have the right command
|
||||
CHECK(modules::motion::axes[modules::motion::Idler].targetPos == 0); // @@TODO constants
|
||||
CHECK(modules::motion::axes[modules::motion::Selector].targetPos == 0); // @@TODO constants
|
||||
|
||||
// engaging idler
|
||||
REQUIRE(WhileCondition(
|
||||
ff,
|
||||
[&]() { return !modules::idler::idler.Engaged(); },
|
||||
5000));
|
||||
|
||||
// idler engaged, we'll start pushing filament
|
||||
REQUIRE(ff.State() == FeedToFinda::PushingFilament);
|
||||
// at least at the beginning the LED should shine green (it should be blinking, but this mode has been already verified in the LED's unit test)
|
||||
REQUIRE(modules::leds::leds.LedOn(modules::globals::globals.ActiveSlot(), modules::leds::Color::green));
|
||||
|
||||
// now let the filament be pushed into the FINDA - but we make sure the FINDA doesn't trigger at all
|
||||
hal::adc::TADCData switchFindaOff({ 0 });
|
||||
hal::adc::ReinitADC(1, std::move(switchFindaOff), 100);
|
||||
REQUIRE(!WhileCondition(
|
||||
ff, // boo, this formatting is UGLY!
|
||||
[&]() { return ff.State() == FeedToFinda::PushingFilament; },
|
||||
5000));
|
||||
|
||||
// the FINDA didn't trigger, we should be in the Failed state
|
||||
REQUIRE(ff.State() == FeedToFinda::Failed);
|
||||
|
||||
REQUIRE(ff.Step() == true); // the automaton finished its work, any consecutive calls to Step must return true
|
||||
}
|
||||
|
|
@ -13,10 +13,11 @@ logic::CommandBase *currentCommand = nullptr;
|
|||
// just like in the real FW, step all the known automata
|
||||
void main_loop() {
|
||||
modules::buttons::buttons.Step(hal::adc::ReadADC(0));
|
||||
modules::leds::leds.Step(0);
|
||||
modules::finda::finda.Step(0);
|
||||
modules::fsensor::fsensor.Step(0);
|
||||
modules::leds::leds.Step(1);
|
||||
modules::finda::finda.Step(1);
|
||||
modules::fsensor::fsensor.Step(1);
|
||||
modules::idler::idler.Step();
|
||||
modules::selector::selector.Step();
|
||||
if (currentCommand)
|
||||
currentCommand->Step();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
#include "motion.h"
|
||||
#include "stub_motion.h"
|
||||
|
||||
namespace modules {
|
||||
namespace motion {
|
||||
|
||||
Motion motion;
|
||||
AxisSim axes[3];
|
||||
|
||||
void Motion::InitAxis(Axis axis) {
|
||||
axes[axis].enabled = true;
|
||||
}
|
||||
|
||||
void Motion::DisableAxis(Axis axis) {
|
||||
axes[axis].enabled = false;
|
||||
}
|
||||
|
||||
bool Motion::StallGuard(Axis axis) {
|
||||
return axes[axis].stallGuard;
|
||||
}
|
||||
|
||||
void Motion::ClearStallGuardFlag(Axis axis) {
|
||||
axes[axis].stallGuard = false;
|
||||
}
|
||||
|
||||
void Motion::PlanMove(uint16_t pulley, uint16_t idler, uint16_t selector, uint16_t feedrate, uint16_t starting_speed, uint16_t ending_speed) {
|
||||
axes[Pulley].targetPos = axes[Pulley].pos + pulley;
|
||||
axes[Idler].targetPos = axes[Idler].pos + pulley;
|
||||
axes[Selector].targetPos = axes[Selector].pos + pulley;
|
||||
// speeds and feedrates are not simulated yet
|
||||
}
|
||||
|
||||
void Motion::Home(Axis axis, bool direction) {
|
||||
axes[Pulley].homed = true;
|
||||
}
|
||||
|
||||
void Motion::SetMode(MotorMode mode) {
|
||||
}
|
||||
|
||||
void Motion::Step() {
|
||||
for (uint8_t i = 0; i < 3; ++i) {
|
||||
if (axes[i].pos != axes[i].targetPos) {
|
||||
int8_t dirInc = (axes[i].pos < axes[i].targetPos) ? 1 : -1;
|
||||
axes[i].pos += dirInc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Motion::QueueEmpty() const {
|
||||
for (uint8_t i = 0; i < 3; ++i) {
|
||||
if (axes[i].pos != axes[i].targetPos)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Motion::AbortPlannedMoves() {
|
||||
for (uint8_t i = 0; i < 3; ++i) {
|
||||
axes[i].targetPos = axes[i].pos; // leave the axis where it was at the time of abort
|
||||
}
|
||||
}
|
||||
|
||||
/// probably higher-level operations knowing the semantic meaning of axes
|
||||
|
||||
} // namespace motion
|
||||
} // namespace modules
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
namespace modules {
|
||||
namespace motion {
|
||||
|
||||
struct AxisSim {
|
||||
uint32_t pos;
|
||||
uint32_t targetPos;
|
||||
bool enabled;
|
||||
bool homed;
|
||||
bool stallGuard;
|
||||
};
|
||||
|
||||
extern AxisSim axes[3];
|
||||
|
||||
} // namespace motion
|
||||
} // namespace modules
|
||||
|
|
@ -34,7 +34,7 @@ bool Step_Basic_One_Button(hal::adc::TADCData &&d, uint8_t testedButtonIndex) {
|
|||
|
||||
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
|
||||
constexpr uint8_t oversampleFactor = 100;
|
||||
hal::adc::ReinitADC(std::move(d), oversampleFactor);
|
||||
hal::adc::ReinitADC(0, std::move(d), oversampleFactor);
|
||||
|
||||
uint8_t otherButton1 = 1, otherButton2 = 2;
|
||||
switch (testedButtonIndex) {
|
||||
|
|
@ -76,7 +76,7 @@ TEST_CASE("buttons::Step-basic-button-one-after-other", "[buttons]") {
|
|||
|
||||
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
|
||||
constexpr uint8_t oversampleFactor = 100;
|
||||
hal::adc::ReinitADC(std::move(d), oversampleFactor);
|
||||
hal::adc::ReinitADC(0, std::move(d), oversampleFactor);
|
||||
|
||||
CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 0, 1, 2));
|
||||
CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 1, 0, 2));
|
||||
|
|
@ -92,7 +92,7 @@ TEST_CASE("buttons::Step-debounce-one-button", "[buttons]") {
|
|||
|
||||
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
|
||||
constexpr uint8_t oversampleFactor = 25;
|
||||
hal::adc::ReinitADC(std::move(d), oversampleFactor);
|
||||
hal::adc::ReinitADC(0, std::move(d), oversampleFactor);
|
||||
|
||||
Buttons b;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,27 +5,27 @@
|
|||
namespace hal {
|
||||
namespace adc {
|
||||
|
||||
static TADCData values2Return;
|
||||
static TADCData::const_iterator rdptr = values2Return.cbegin();
|
||||
static TADCData values2Return[2];
|
||||
static TADCData::const_iterator rdptr[2] = { values2Return[0].cbegin(), values2Return[1].cbegin() };
|
||||
static uint8_t oversampleFactor = 1;
|
||||
static uint8_t oversample = 1; ///< current count of oversampled values returned from the ADC - will get filled with oversampleFactor once it reaches zero
|
||||
|
||||
void ReinitADC(TADCData &&d, uint8_t ovsmpl) {
|
||||
values2Return = std::move(d);
|
||||
void ReinitADC(uint8_t channel, TADCData &&d, uint8_t ovsmpl) {
|
||||
values2Return[channel] = std::move(d);
|
||||
oversampleFactor = ovsmpl;
|
||||
oversample = ovsmpl;
|
||||
rdptr = values2Return.cbegin();
|
||||
rdptr[channel] = values2Return[channel].cbegin();
|
||||
}
|
||||
|
||||
/// ADC access routines
|
||||
uint16_t ReadADC(uint8_t /*adc*/) {
|
||||
uint16_t ReadADC(uint8_t adc) {
|
||||
if (!oversample) {
|
||||
++rdptr;
|
||||
++rdptr[adc];
|
||||
oversample = oversampleFactor;
|
||||
} else {
|
||||
--oversample;
|
||||
}
|
||||
return rdptr != values2Return.end() ? *rdptr : 1023;
|
||||
return rdptr[adc] != values2Return[adc].end() ? *rdptr[adc] : values2Return[adc].back();
|
||||
}
|
||||
|
||||
} // namespace adc
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace adc {
|
|||
|
||||
using TADCData = std::vector<uint16_t>;
|
||||
|
||||
void ReinitADC(TADCData &&d, uint8_t ovsmpl);
|
||||
void ReinitADC(uint8_t channel, TADCData &&d, uint8_t ovsmpl);
|
||||
|
||||
} // namespace adc
|
||||
} // namespace hal
|
||||
|
|
|
|||
Loading…
Reference in New Issue