Skip to content

Commit

Permalink
improved modm:driver:encoder_input.bitbang
Browse files Browse the repository at this point in the history
  • Loading branch information
TomSaw committed Nov 12, 2021
1 parent 6632a19 commit 7e7d2e9
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 31 deletions.
23 changes: 12 additions & 11 deletions src/modm/driver/encoder/bitbang_encoder_input.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@ namespace modm
*
* @tparam SignalA First modm::platform::Gpio pin to input the encoder signal.
* @tparam SignalB Second modm::platform::Gpio pin to input the encoder signal.
* @tparam POSTSCALER n_cycles to count as one in-/decrement.
* @tparam DeltaType Must be signed integer and fit at least POSTSCALER. The Bigger
* @tparam PRESCALER n_cycles to count as one in-/decrement.
* @tparam DeltaType Must be signed integral and fit at least PRESCALER. The Bigger
* DeltaType, the more inc-/decrements can be stored temporarily.
* @tparam ValueType Must be unsigned integral.
*/
template<typename SignalA, typename SignalB, uint8_t POSTSCALER = 4,
template<typename SignalA, typename SignalB, uint8_t PRESCALER = 4,
std::signed_integral DeltaType = int8_t>
class BitBangEncoderInput
{
static_assert(std::popcount(POSTSCALER) == 1,
"POSTSCALER must be an integer to basis 2 and not 0: 1, 2, 4, 8, 16, ...");
static_assert(POSTSCALER <= std::numeric_limits<DeltaType>::max(),
"DeltaType is to small for POSTSCALER.");
static_assert(std::popcount(PRESCALER) == 1,
"PRESCALER must be an integer to basis 2 and not 0: 1, 2, 4, 8, 16, ...");
static_assert(PRESCALER <= std::numeric_limits<DeltaType>::max(),
"DeltaType is to small for PRESCALER.");

using Signals = modm::platform::SoftwareGpioPort<SignalA, SignalB>;

Expand All @@ -47,19 +48,19 @@ class BitBangEncoderInput
uint8_t inline getRaw();

public:
using ValueType = DeltaType;
BitBangEncoderInput() : raw_last(0), delta(0){};

using InputType = modm::platform::Gpio::InputType;
// Connect SingalA and SignalB and store power-up state
inline void
connect();
initialize(const modm::platform::Gpio::InputType inputType = modm::platform::Gpio::InputType::PullUp);

// Call @1kHz for manual movement
inline void
update();

ValueType
getIncrement();
DeltaType
getDelta();

private:
uint8_t raw_last;
Expand Down
2 changes: 1 addition & 1 deletion src/modm/driver/encoder/bitbang_encoder_input.lb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def init(module):
module.description = """
# Quadrature Encoder Input
This driver decodes a AB (incremental) encoder signal.
This driver decodes an AB (incremental) encoder signal.
Ported from code created by Peter Dannegger:
https://www.mikrocontroller.net/articles/Drehgeber.
"""
Expand Down
35 changes: 16 additions & 19 deletions src/modm/driver/encoder/bitbang_encoder_input_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@

#include <cmath>

template<typename SignalA, typename SignalB, uint8_t POSTSCALER,
std::signed_integral DeltaType>
template<typename SignalA, typename SignalB, uint8_t PRESCALER, std::signed_integral DeltaType>
inline uint8_t
modm::BitBangEncoderInput<SignalA, SignalB, POSTSCALER, DeltaType>::getRaw()
modm::BitBangEncoderInput<SignalA, SignalB, PRESCALER, DeltaType>::getRaw()
{
const uint8_t read = Signals::read();
// convert graycode to binary
Expand All @@ -28,42 +27,40 @@ modm::BitBangEncoderInput<SignalA, SignalB, POSTSCALER, DeltaType>::getRaw()
return raw;
}

template<typename SignalA, typename SignalB, uint8_t POSTSCALER,
std::signed_integral DeltaType>
template<typename SignalA, typename SignalB, uint8_t PRESCALER, std::signed_integral DeltaType>
inline void
modm::BitBangEncoderInput<SignalA, SignalB, POSTSCALER, DeltaType>::connect()
modm::BitBangEncoderInput<SignalA, SignalB, PRESCALER, DeltaType>::initialize(
const modm::platform::Gpio::InputType inputType
)
{
Signals::setInput(::Gpio::InputType::PullUp);
Signals::setInput(inputType);

// Tare power-on state
modm::delay(10us);
raw_last = getRaw();
}

template<typename SignalA, typename SignalB, uint8_t POSTSCALER,
std::signed_integral DeltaType>
template<typename SignalA, typename SignalB, uint8_t PRESCALER, std::signed_integral DeltaType>
inline void
modm::BitBangEncoderInput<SignalA, SignalB, POSTSCALER, DeltaType>::update()
modm::BitBangEncoderInput<SignalA, SignalB, PRESCALER, DeltaType>::update()
{
uint8_t raw = getRaw();
const uint8_t raw = getRaw();
const uint8_t diff = raw_last - raw;

if (diff & 0b01)
{
raw_last = raw;
delta += (diff & 0b10) - 1; // bit 1 = direction (+/-)
}
}

template<typename SignalA, typename SignalB, uint8_t POSTSCALER,
std::signed_integral DeltaType>
template<typename SignalA, typename SignalB, uint8_t PRESCALER, std::signed_integral DeltaType>
DeltaType
modm::BitBangEncoderInput<SignalA, SignalB, POSTSCALER, DeltaType>::getIncrement()
modm::BitBangEncoderInput<SignalA, SignalB, PRESCALER, DeltaType>::getDelta()
{
::modm::atomic::Lock _;
DeltaType val = delta;

delta &= (POSTSCALER - 1); // mask out higher bits

constexpr uint8_t shift = std::log2(POSTSCALER); // Number of fraction bits
return val >> shift; // return whats left without fractions
DeltaType ret = delta;
delta &= (PRESCALER - 1); // Only keep prescaler fraction
return ret >> int(std::log2(PRESCALER)); // return delta without prescaler fraction
}

0 comments on commit 7e7d2e9

Please sign in to comment.