Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright (C) 2016 Marc Poulhiès | ||
* Copyright (C) 2011 Ben Buxton <bb@cactii.net> | ||
* | ||
* Licensed under the GNU GPL Version 3 | ||
*/ | ||
|
||
/** | ||
* @defgroup drivers_rotary_encoder | ||
* @{ | ||
* | ||
* @file | ||
* @brief Low-level rotary encoder implementation | ||
* | ||
* @author Marc Poulhiès <dkm@kataplop.net> | ||
* | ||
* @} | ||
*/ | ||
|
||
#ifndef ROTARY_ENC_H | ||
#define ROTARY_ENC_H | ||
|
||
#include "kernel_types.h" | ||
#include <periph/gpio.h> | ||
|
||
typedef struct { | ||
gpio_t pin1, pin2; | ||
kernel_pid_t listener; | ||
unsigned int state; | ||
} rotary_t; | ||
|
||
int rotary_init(rotary_t *dev, gpio_t pin1, gpio_t pin2); | ||
void rotary_register(rotary_t *dev, kernel_pid_t pid); | ||
|
||
#define ROTARY_MSG_EVENT 1 | ||
|
||
#define ROTARY_MSG_CLICK 2 | ||
|
||
enum rotary_dir_t { | ||
DIR_NONE = 0x0, /* No complete step yet. */ | ||
DIR_CW = 0x10, /* Clockwise step. */ | ||
DIR_CCW = 0x20, /* Anti-clockwise step. */ | ||
}; | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
MODULE = rotary_encoder | ||
|
||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* Copyright (C) 2016 Marc Poulhiès | ||
* Copyright (C) 2011 Ben Buxton <bb@cactii.net> | ||
* | ||
* Licensed under the GNU GPL Version 3 | ||
*/ | ||
|
||
/** | ||
* @ingroup drivers_rotary_encoder | ||
* @{ | ||
* | ||
* @file | ||
* @brief Low-level rotary encoder implementation | ||
* | ||
* @author Marc Poulhiès <dkm@kataplop.net> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include "rotary.h" | ||
|
||
/* | ||
* Code mainly based on http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html | ||
*/ | ||
|
||
#define ENABLE_DEBUG (0) | ||
|
||
#include "debug.h" | ||
|
||
#define R_START 0x0 | ||
|
||
#ifndef HALF_STEP | ||
#define HALF_STEP 0 | ||
#endif | ||
|
||
#if HALF_STEP | ||
|
||
/* Use the half-step state table (emits a code at 00 and 11) */ | ||
#define R_CCW_BEGIN 0x1 | ||
#define R_CW_BEGIN 0x2 | ||
#define R_START_M 0x3 | ||
#define R_CW_BEGIN_M 0x4 | ||
#define R_CCW_BEGIN_M 0x5 | ||
|
||
static const unsigned char ttable[6][4] = { | ||
/* R_START (00) */ | ||
{ R_START_M, R_CW_BEGIN, R_CCW_BEGIN, R_START }, | ||
/* R_CCW_BEGIN */ | ||
{ R_START_M | DIR_CCW, R_START, R_CCW_BEGIN, R_START }, | ||
/* R_CW_BEGIN */ | ||
{ R_START_M | DIR_CW, R_CW_BEGIN, R_START, R_START }, | ||
/* R_START_M (11) */ | ||
{ R_START_M, R_CCW_BEGIN_M, R_CW_BEGIN_M, R_START }, | ||
/* R_CW_BEGIN_M */ | ||
{ R_START_M, R_START_M, R_CW_BEGIN_M, R_START | DIR_CW }, | ||
/* R_CCW_BEGIN_M */ | ||
{ R_START_M, R_CCW_BEGIN_M, R_START_M, R_START | DIR_CCW }, | ||
}; | ||
#else | ||
|
||
/* Use the full-step state table (emits a code at 00 only) */ | ||
#define R_CW_FINAL 0x1 | ||
#define R_CW_BEGIN 0x2 | ||
#define R_CW_NEXT 0x3 | ||
#define R_CCW_BEGIN 0x4 | ||
#define R_CCW_FINAL 0x5 | ||
#define R_CCW_NEXT 0x6 | ||
|
||
static const unsigned char ttable[7][4] = { | ||
/* R_START */ | ||
{ R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START }, | ||
/* R_CW_FINAL */ | ||
{ R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW }, | ||
/* R_CW_BEGIN */ | ||
{ R_CW_NEXT, R_CW_BEGIN, R_START, R_START }, | ||
/* R_CW_NEXT */ | ||
{ R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START }, | ||
/* R_CCW_BEGIN */ | ||
{ R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START }, | ||
/* R_CCW_FINAL */ | ||
{ R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW }, | ||
/* R_CCW_NEXT */ | ||
{ R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START }, | ||
}; | ||
#endif | ||
|
||
static void rotary_cb(void *rot_dev) | ||
{ | ||
rotary_t *dev = (rotary_t *) rot_dev; | ||
const unsigned int b1_v = gpio_read(dev->pin1); | ||
const unsigned int b2_v = gpio_read(dev->pin2); | ||
const unsigned int pinstate = (b1_v ? 2 : 0) | (b2_v ? 1 : 0); | ||
unsigned dir = 0; | ||
|
||
dev->state = ttable[dev->state & 0xf][pinstate]; | ||
|
||
switch (dev->state & 0x30) { | ||
case DIR_CCW: | ||
case DIR_CW: | ||
dir = dev->state & 0x30; | ||
break; | ||
case DIR_NONE: | ||
default: | ||
break; | ||
} | ||
|
||
if (dev->listener != KERNEL_PID_UNDEF && dir != 0) { | ||
msg_t m; | ||
m.type = ROTARY_MSG_EVENT; | ||
m.content.value = dir; | ||
DEBUG("Dispatching event : %d to pid %d\n", dir, dev->listener); | ||
if (msg_send_int(&m, dev->listener) != 1) { | ||
DEBUG("Not sent, queue full ?\n"); | ||
} | ||
; | ||
} | ||
} | ||
|
||
int rotary_init(rotary_t *dev, gpio_t pin1, gpio_t pin2) | ||
{ | ||
gpio_init_int(pin1, GPIO_IN_PU, GPIO_BOTH, rotary_cb, dev); | ||
gpio_init_int(pin2, GPIO_IN_PU, GPIO_BOTH, rotary_cb, dev); | ||
|
||
dev->pin1 = pin1; | ||
dev->pin2 = pin2; | ||
|
||
dev->state = R_START; | ||
dev->listener = KERNEL_PID_UNDEF; | ||
|
||
return 0; | ||
} | ||
|
||
void rotary_register(rotary_t *dev, kernel_pid_t pid) | ||
{ | ||
dev->listener = pid; | ||
} |