File: rotary_encoder.c

package info (click to toggle)
pigpio 1.78-1.1
  • links: PTS
  • area: main
  • in suites: sid, trixie
  • size: 7,088 kB
  • sloc: ansic: 17,891; python: 4,232; sh: 741; cpp: 281; makefile: 135
file content (94 lines) | stat: -rw-r--r-- 1,934 bytes parent folder | download | duplicates (3)
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
#include <stdio.h>
#include <stdlib.h>

#include <pigpio.h>

#include "rotary_encoder.h"

struct _Pi_Renc_s
{
   int gpioA;
   int gpioB;
   Pi_Renc_CB_t callback;
   int levA;
   int levB;
   int lastGpio;
};

/*

             +---------+         +---------+      0
             |         |         |         |
   A         |         |         |         |
             |         |         |         |
   +---------+         +---------+         +----- 1

       +---------+         +---------+            0
       |         |         |         |
   B   |         |         |         |
       |         |         |         |
   ----+         +---------+         +---------+  1

*/

static void _cb(int gpio, int level, uint32_t tick, void *user)
{
   Pi_Renc_t *renc;

   renc = user;

   if (gpio == renc->gpioA) renc->levA = level; else renc->levB = level;

   if (gpio != renc->lastGpio) /* debounce */
   {
      renc->lastGpio = gpio;

      if ((gpio == renc->gpioA) && (level == 1))
      {
         if (renc->levB) (renc->callback)(1);
      }
      else if ((gpio == renc->gpioB) && (level == 1))
      {
         if (renc->levA) (renc->callback)(-1);
      }
   }
}

Pi_Renc_t * Pi_Renc(int gpioA, int gpioB, Pi_Renc_CB_t callback)
{
   Pi_Renc_t *renc;

   renc = malloc(sizeof(Pi_Renc_t));

   renc->gpioA = gpioA;
   renc->gpioB = gpioB;
   renc->callback = callback;
   renc->levA=0;
   renc->levB=0;
   renc->lastGpio = -1;

   gpioSetMode(gpioA, PI_INPUT);
   gpioSetMode(gpioB, PI_INPUT);

   /* pull up is needed as encoder common is grounded */

   gpioSetPullUpDown(gpioA, PI_PUD_UP);
   gpioSetPullUpDown(gpioB, PI_PUD_UP);

   /* monitor encoder level changes */

   gpioSetAlertFuncEx(gpioA, _cb, renc);
   gpioSetAlertFuncEx(gpioB, _cb, renc);
}

void Pi_Renc_cancel(Pi_Renc_t *renc)
{
   if (renc)
   {
      gpioSetAlertFunc(renc->gpioA, 0);
      gpioSetAlertFunc(renc->gpioB, 0);

      free(renc);
   }
}