Skip to content

Commit

Permalink
Added encoder.hpp
Browse files Browse the repository at this point in the history
  • Loading branch information
TomSaw committed Mar 17, 2021
1 parent 850b554 commit 9e63605
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 0 deletions.
72 changes: 72 additions & 0 deletions src/modm/driver/encoder/encoder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2021, Thomas Sommer
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_ENCODER_HPP
#define MODM_ENCODER_HPP

#include <modm/platform.hpp>
#include <type_traits>

namespace modm
{
/**
* \brief Encoder
*
* \ingroup modm_ui_encoder
* \author 2021 Thomas Sommer
*/
struct encoder
{
typedef enum Division
{
ONE,
TWO,
FOUR
} Division_t;
};

template<typename PH_A, typename PH_B, encoder::Division_t DIVISION,
typename UnderlyingType = int8_t>
class Encoder
{
public:
Encoder() : enc_delta(0), raw_last(0) {};

inline void
connect()
{
PH_A::setInput(::Gpio::InputType::PullUp);
PH_B::setInput(::Gpio::InputType::PullUp);

// Tare power-on state
modm::delay(10us);
UnderlyingType raw = 0;
if (PH_A::read()) raw = 3;
if (PH_B::read()) raw ^= 1;
raw_last = raw;
}

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

UnderlyingType
getValue();

private:
UnderlyingType enc_delta;
UnderlyingType raw_last;
};
} // namespace modm

#include "encoder_impl.hpp"

#endif // MODM_ENCODER_HPP
27 changes: 27 additions & 0 deletions src/modm/driver/encoder/encoder.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2019, Thomas Sommer
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------

def init(module):
module.name = ":driver:encoder"
module.description = """
Software graycode ported from C-Code of Peter Dannegger:
https://www.mikrocontroller.net/articles/Drehgeber.
"""

def prepare(module, options):
module.depends(":architecture:atomic")
return True

def build(env):
env.outbasepath = "modm/src/modm/driver/encoder"
env.copy("encoder.hpp")
env.copy("encoder_impl.hpp")
49 changes: 49 additions & 0 deletions src/modm/driver/encoder/encoder_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef MODM_ENCODER_HPP
#error "Don't include this file directly, use 'encoder.hpp' instead!"
#endif

template<typename PH_A, typename PH_B, modm::encoder::Division_t DIVISION, typename UnderlyingType>
inline void
modm::Encoder<PH_A, PH_B, DIVISION, UnderlyingType>::update()
{
static_assert(std::is_signed<UnderlyingType>::value and std::is_integral<UnderlyingType>::value,
"UnderlyingType must be signed integral");
// Tare on power-on
UnderlyingType raw = 0;
UnderlyingType diff;

if (PH_A::read()) raw = 3;
if (PH_B::read()) raw ^= 1; // convert gray to binary

diff = raw_last - raw;
if (diff & 1)
{
raw_last = raw; // store new as next last
enc_delta += (diff & 2) - 1; // bit 1 = direction (+/-)
}
}

template<typename PH_A, typename PH_B, modm::encoder::Division_t DIVISION, typename UnderlyingType>
UnderlyingType
modm::Encoder<PH_A, PH_B, DIVISION, UnderlyingType>::getValue()
{
static_assert(std::is_signed<UnderlyingType>::value and std::is_integral<UnderlyingType>::value,
"UnderlyingType must be signed integral");
cli();
UnderlyingType val = enc_delta; // counts since last call
switch (DIVISION)
{
case encoder::Division::ONE:
enc_delta = 0;
break;
case encoder::Division::TWO:
enc_delta = val & 1;
val >>= 1;
break;
case encoder::Division::FOUR:
enc_delta = val & 3;
val >>= 2;
}
sei();
return val;
}

0 comments on commit 9e63605

Please sign in to comment.