summaryrefslogtreecommitdiff
path: root/rotaryencoder.cpp
blob: 41d56e83e83aae6c67fe5a2f45087bcdb707ad7c (plain)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "rotaryencoder.h"

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <vector>

#include <QDebug>
#include <QElapsedTimer>

#include <wiringPi.h>

// got from https://gist.github.com/ast/a19813fce9d34c7240091db11b8190dd
// https://gist.github.com/ast
// Inspired by Paul Stoffregen's excellent Arduino library Encoder:
// https://github.com/PaulStoffregen/Encoder

constexpr int gpioA = 17;
constexpr int gpioB = 27;
// constexpr int gpioA = 0;
// constexpr int gpioB = 2;
// constexpr int gpioA = 11;
// constexpr int gpioB = 13;

const std::vector<int> encoderTable = {
    0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0
};

volatile int64_t positionSteps;
volatile uint8_t state;

void pin_isr(void) {
    uint8_t p1val = digitalRead(gpioA);
    uint8_t p2val = digitalRead(gpioB);
    uint8_t s = state & 3;

    if (p1val) s |= 4;
    if (p2val) s |= 8;

    state = (s >> 2);

    switch (s) {
    case 1: case 7: case 8: case 14:
        positionSteps = positionSteps + 1;
        return;
    case 2: case 4: case 11: case 13:
        positionSteps = positionSteps - 1;
        return;
    case 3: case 12:
        positionSteps = positionSteps + 2;
        return;
    case 6: case 9:
        positionSteps = positionSteps - 2;
        return;
    }
}

rotaryencoder::rotaryencoder()
{
    QElapsedTimer t;
    t.start();

    if (wiringPiSetupGpio()) {
        perror("wiringPiSetupGpio");
        exit(EXIT_FAILURE);
    }

    qDebug() << "msecs to setup wiringPi:" << t.elapsed();

    if ( wiringPiISR (gpioA, INT_EDGE_BOTH, &pin_isr) < 0 ) {
        perror("wiringPiISR");
        exit(EXIT_FAILURE);
    }

    qDebug() << "msecs to register interruption A:" << t.elapsed();

    if ( wiringPiISR (gpioB, INT_EDGE_BOTH, &pin_isr) < 0 ) {
        perror("wiringPiISR");
        exit(EXIT_FAILURE);
    }

    qDebug() << "msecs to register interruption B:" << t.elapsed();

    // pinMode (gpioA,  INPUT) ;
    // pinMode (gpioB,  INPUT) ;
    // pullUpDnControl(gpioA, PUD_UP);
    // pullUpDnControl(gpioB, PUD_UP);

    qDebug() << "encoder is ok";

    // // Show position every second
    // while ( 1 ) {
    //     constexpr double stepsPerMm = 200;
    //     const double positionMm = ::positionSteps / stepsPerMm;
    //     qDebug() << ::positionSteps
    //              << '-'
    //              << QString::number(positionMm, 'f', 3)
    //              << "(mm)";
    //     // printf( "%ld\n", ::position);
    //     usleep( 100 * 1000 ); // wait 1 second
    // }
}

int64_t rotaryencoder::position() const
{
    return ::positionSteps;
}