Skip to content
Merged

mr. #33

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 16 additions & 20 deletions ClickEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//
// (c) 2010 [email protected]
// (c) 2014 [email protected]
//
//
// Timer-based rotary encoder logic by Peter Dannegger
// http://www.mikrocontroller.net/articles/Drehgeber
// ----------------------------------------------------------------------------
Expand All @@ -30,14 +30,14 @@
#if ENC_DECODER != ENC_NORMAL
# ifdef ENC_HALFSTEP
// decoding table for hardware with flaky notch (half resolution)
const int8_t ClickEncoder::table[16] __attribute__((__progmem__)) = {
0, 0, -1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, -1, 0, 0
};
const int8_t ClickEncoder::table[16] __attribute__((__progmem__)) = {
0, 0, -1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, -1, 0, 0
};
# else
// decoding table for normal hardware
const int8_t ClickEncoder::table[16] __attribute__((__progmem__)) = {
0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0
};
const int8_t ClickEncoder::table[16] __attribute__((__progmem__)) = {
0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0
};
# endif
#endif

Expand All @@ -53,7 +53,7 @@ ClickEncoder::ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN, uint8_t stepsPerNo
pinMode(pinA, configType);
pinMode(pinB, configType);
pinMode(pinBTN, configType);

if (digitalRead(pinA) == pinsActive) {
last = 3;
}
Expand Down Expand Up @@ -89,7 +89,7 @@ void ClickEncoder::service(void)
last |= 1;
}

uint8_t tbl = pgm_read_byte(&table[last]);
uint8_t tbl = pgm_read_byte(&table[last]);
if (tbl) {
delta += tbl;
moved = true;
Expand All @@ -104,13 +104,13 @@ void ClickEncoder::service(void)
if (digitalRead(pinB) == pinsActive) {
curr ^= 1;
}

int8_t diff = last - curr;

if (diff & 1) { // bit 0 = step
last = curr;
delta += (diff & 2) - 1; // bit 1 = direction (+/-)
moved = true;
moved = true;
}
#else
# error "Error: define ENC_DECODER to ENC_NORMAL or ENC_FLAKY"
Expand All @@ -126,15 +126,11 @@ void ClickEncoder::service(void)
// handle button
//
#ifndef WITHOUT_BUTTON
static uint16_t keyDownTicks = 0;
static uint8_t doubleClickTicks = 0;
static unsigned long lastButtonCheck = 0;

if (pinBTN > 0 // check button only, if a pin has been provided
&& (now - lastButtonCheck) >= ENC_BUTTONINTERVAL) // checking button is sufficient every 10-30ms
{
{
lastButtonCheck = now;

if (digitalRead(pinBTN) == pinsActive) { // key is down
keyDownTicks++;
if (keyDownTicks > (ENC_HOLDTIME / ENC_BUTTONINTERVAL)) {
Expand Down Expand Up @@ -164,7 +160,7 @@ void ClickEncoder::service(void)

keyDownTicks = 0;
}

if (doubleClickTicks > 0) {
doubleClickTicks--;
if (--doubleClickTicks == 0) {
Expand All @@ -181,7 +177,7 @@ void ClickEncoder::service(void)
int16_t ClickEncoder::getValue(void)
{
int16_t val;

cli();
val = delta;

Expand All @@ -190,7 +186,7 @@ int16_t ClickEncoder::getValue(void)
else delta = 0; // default to 1 step per notch

sei();

if (steps == 4) val >>= 2;
if (steps == 2) val >>= 1;

Expand Down
239 changes: 121 additions & 118 deletions ClickEncoder.h
Original file line number Diff line number Diff line change
@@ -1,118 +1,121 @@
// ----------------------------------------------------------------------------
// Rotary Encoder Driver with Acceleration
// Supports Click, DoubleClick, Long Click
//
// (c) 2010 [email protected]
// (c) 2014 [email protected]
//
// Timer-based rotary encoder logic by Peter Dannegger
// http://www.mikrocontroller.net/articles/Drehgeber
// ----------------------------------------------------------------------------

#ifndef __have__ClickEncoder_h__
#define __have__ClickEncoder_h__

// ----------------------------------------------------------------------------

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "Arduino.h"

// ----------------------------------------------------------------------------

#define ENC_NORMAL (1 << 1) // use Peter Danneger's decoder
#define ENC_FLAKY (1 << 2) // use Table-based decoder

// ----------------------------------------------------------------------------

#ifndef ENC_DECODER
# define ENC_DECODER ENC_NORMAL
#endif

#if ENC_DECODER == ENC_FLAKY
# ifndef ENC_HALFSTEP
# define ENC_HALFSTEP 1 // use table for half step per default
# endif
#endif

// ----------------------------------------------------------------------------

class ClickEncoder
{
public:
typedef enum Button_e {
Open = 0,
Closed,

Pressed,
Held,
Released,

Clicked,
DoubleClicked

} Button;

public:
ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN = -1,
uint8_t stepsPerNotch = 1, bool active = LOW);

void service(void);
int16_t getValue(void);

#ifndef WITHOUT_BUTTON
public:
Button getButton(void);
#endif

#ifndef WITHOUT_BUTTON
public:
void setDoubleClickEnabled(const bool &d)
{
doubleClickEnabled = d;
}

const bool getDoubleClickEnabled()
{
return doubleClickEnabled;
}
#endif

public:
void setAccelerationEnabled(const bool &a)
{
accelerationEnabled = a;
if (accelerationEnabled == false) {
acceleration = 0;
}
}

const bool getAccelerationEnabled()
{
return accelerationEnabled;
}

private:
const uint8_t pinA;
const uint8_t pinB;
const uint8_t pinBTN;
const bool pinsActive;
volatile int16_t delta;
volatile int16_t last;
uint8_t steps;
volatile uint16_t acceleration;
#if ENC_DECODER != ENC_NORMAL
static const int8_t table[16];
#endif
#ifndef WITHOUT_BUTTON
volatile Button button;
bool doubleClickEnabled;
bool accelerationEnabled;
#endif
};

// ----------------------------------------------------------------------------

#endif // __have__ClickEncoder_h__
// ----------------------------------------------------------------------------
// Rotary Encoder Driver with Acceleration
// Supports Click, DoubleClick, Long Click
//
// (c) 2010 [email protected]
// (c) 2014 [email protected]
//
// Timer-based rotary encoder logic by Peter Dannegger
// http://www.mikrocontroller.net/articles/Drehgeber
// ----------------------------------------------------------------------------

#ifndef __have__ClickEncoder_h__
#define __have__ClickEncoder_h__

// ----------------------------------------------------------------------------

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "Arduino.h"

// ----------------------------------------------------------------------------

#define ENC_NORMAL (1 << 1) // use Peter Danneger's decoder
#define ENC_FLAKY (1 << 2) // use Table-based decoder

// ----------------------------------------------------------------------------

#ifndef ENC_DECODER
# define ENC_DECODER ENC_NORMAL
#endif

#if ENC_DECODER == ENC_FLAKY
# ifndef ENC_HALFSTEP
# define ENC_HALFSTEP 1 // use table for half step per default
# endif
#endif

// ----------------------------------------------------------------------------

class ClickEncoder
{
public:
typedef enum Button_e {
Open = 0,
Closed,

Pressed,
Held,
Released,

Clicked,
DoubleClicked

} Button;

public:
ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN = -1,
uint8_t stepsPerNotch = 1, bool active = LOW);

void service(void);
int16_t getValue(void);

#ifndef WITHOUT_BUTTON
public:
Button getButton(void);
#endif

#ifndef WITHOUT_BUTTON
public:
void setDoubleClickEnabled(const bool &d)
{
doubleClickEnabled = d;
}

const bool getDoubleClickEnabled()
{
return doubleClickEnabled;
}
#endif

public:
void setAccelerationEnabled(const bool &a)
{
accelerationEnabled = a;
if (accelerationEnabled == false) {
acceleration = 0;
}
}

const bool getAccelerationEnabled()
{
return accelerationEnabled;
}

private:
const uint8_t pinA;
const uint8_t pinB;
const uint8_t pinBTN;
const bool pinsActive;
volatile int16_t delta;
volatile int16_t last;
uint8_t steps;
volatile uint16_t acceleration;
bool accelerationEnabled;
#if ENC_DECODER != ENC_NORMAL
static const int8_t table[16];
#endif
#ifndef WITHOUT_BUTTON
volatile Button button;
bool doubleClickEnabled;
uint16_t keyDownTicks = 0;
uint8_t doubleClickTicks = 0;
unsigned long lastButtonCheck = 0;
#endif
};

// ----------------------------------------------------------------------------

#endif // __have__ClickEncoder_h__
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ ClickEncoder
=============

> Arduino library to handle rotary encoders **with** buttons as a user input device.
Atmel AVR C++ RotaryEncoder with Button Implementation.
Arduino RotaryEncoder with Button Implementation.

**See Arduino Library in the [Branch arduino]**

- Timer-Based: Works on any IO-Pin.
- Supports rotary acceleration, so when the encoder is rotated faster, the encoders value will increment faster
Expand Down
12 changes: 12 additions & 0 deletions library.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "ClickEncoder",
"keywords": "encoder, button, input",
"description": "Arduino library to handle rotary encoders with buttons as a user input device",
"repository":
{
"type": "git",
"url": "https://github.com/0xPIT/encoder.git"
},
"frameworks": "arduino",
"platforms": "atmelavr"
}