-
Notifications
You must be signed in to change notification settings - Fork 4
/
encoder.cpp
90 lines (77 loc) · 2.92 KB
/
encoder.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017 Dimitry Ishenko
// Contact: dimitry (dot) ishenko (at) (gee) mail (dot) com
//
// Distributed under the GNU GPL license. See the LICENSE.md file for details.
////////////////////////////////////////////////////////////////////////////////
#include "encoder.hpp"
#include <functional>
#include <stdexcept>
#include <utility>
////////////////////////////////////////////////////////////////////////////////
namespace firmata
{
////////////////////////////////////////////////////////////////////////////////
encoder::encoder(pin& pin1, pin& pin2) : pin1_(&pin1), pin2_(&pin2)
{
if(pin1_->mode() != digital_in && pin1_->mode() != pullup_in)
throw std::invalid_argument("Invalid pin1 mode");
if(pin2_->mode() != digital_in && pin2_->mode() != pullup_in)
throw std::invalid_argument("Invalid pin2 mode");
using namespace std::placeholders;
id_ = pin1_->on_state_changed(std::bind(&encoder::pin_state_changed, this, _1));
}
////////////////////////////////////////////////////////////////////////////////
encoder::~encoder() { if(pin1_) pin1_->remove_call(id_); }
////////////////////////////////////////////////////////////////////////////////
void encoder::swap(encoder& rhs) noexcept
{
using namespace std::placeholders;
using std::swap;
swap(pin1_, rhs.pin1_);
swap(pin2_, rhs.pin2_);
swap(id_ , rhs.id_ );
if(pin1_)
{
pin1_->remove_call(id_);
id_ = pin1_->on_state_changed(std::bind(&encoder::pin_state_changed, this, _1));
}
if(rhs.pin1_)
{
rhs.pin1_->remove_call(rhs.id_);
rhs.id_ = rhs.pin1_->on_state_changed(std::bind(&encoder::pin_state_changed, &rhs, _1));
}
swap(rotate_ , rhs.rotate_ );
swap(rotate_cw_ , rhs.rotate_cw_ );
swap(rotate_ccw_, rhs.rotate_ccw_);
swap(step_ , rhs.step_ );
}
////////////////////////////////////////////////////////////////////////////////
cid encoder::on_rotate(int_call fn) { return rotate_.insert(std::move(fn)); }
cid encoder::on_rotate_cw(void_call fn) { return rotate_cw_.insert(std::move(fn)); }
cid encoder::on_rotate_ccw(void_call fn) { return rotate_ccw_.insert(std::move(fn)); }
bool encoder::remove_call(cid id)
{
return rotate_.erase(id) || rotate_cw_.erase(id) || rotate_ccw_.erase(id);
}
////////////////////////////////////////////////////////////////////////////////
void encoder::pin_state_changed(int state)
{
if(state)
{
auto step = pin2_->state() ? cw : ccw;
if(step == step_)
{
switch(step)
{
case no: break;
case cw: rotate_( 1); rotate_cw_(); break;
case ccw: rotate_(-1); rotate_ccw_(); break;
}
}
step_ = no;
}
else step_ = pin2_->state() ? ccw : cw;
}
////////////////////////////////////////////////////////////////////////////////
}