Skip to content
Open
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
89 changes: 61 additions & 28 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
02111-1307 USA.
*/

#include <stdio.h>
Expand Down Expand Up @@ -54,6 +54,7 @@ typedef struct _gpio_rotary{
int gpio_b_mask;
int last_state;
int direction;
int rotHalf;
struct _gpio_rotary *next;
}gpio_rotary_s;

Expand All @@ -71,7 +72,7 @@ typedef struct{

static int find_key(const char *name);
static void add_event(gpio_key_s **ev, int gpio, int key, int xio);
static void add_rotary(gpio_rotary_s **rot, int gpio_a, int gpio_b, int key_a, int key_b);
static void add_rotary(gpio_rotary_s **rot, int gpio_a, int gpio_b, int key_a, int key_b, int rotHalf);
static gpio_key_s *get_event(gpio_key_s *ev, int idx);
static int find_xio(const char *name);
static void setup_xio(int xio);
Expand All @@ -86,7 +87,7 @@ static int xio_count = 0;
static gpio_rotary_s *gpio_rotary[NUM_GPIO];
static gpio_rotary_s *last_gpio_rotary = NULL;
static int last_gpio_rotary_idx = NUM_GPIO;

static int SP;
static keyinfo_s KI;

Expand All @@ -110,7 +111,7 @@ int init_config(void)
int lnno = 0;
char name[32], xname[32], keya[32], keyb[32];
char conffile[80];
int gpio,caddr,regno,gpio2;
int gpio,caddr,regno,gpio2,rotHalf;

for(i=0;i<NUM_GPIO;i++){
gpio_key[i] = NULL;
Expand Down Expand Up @@ -148,8 +149,8 @@ int init_config(void)
}
}
else if(strstr(ln, "ROT") == ln){
n=sscanf(ln, "%s %d %d %s %s", name, &gpio, &gpio2, &keya, &keyb);
if (n == 5) {
n=sscanf(ln, "%s %d %d %s %s %d", name, &gpio, &gpio2, &keya, &keyb, &rotHalf);
if (n == 6) {
ka = find_key(keya);
kb = find_key(keyb);
if (ka && kb && key_names[ka].code < 0x300 && key_names[kb].code < 0x300) {
Expand All @@ -158,8 +159,12 @@ int init_config(void)
gpio = gpio2;
gpio2 = temp;
}

rotHalf = (rotHalf > 0) ? 1 : 0;
printf("HALF = %d\n",rotHalf);

//printf("%d ROT = %d/%d %04x:[%s] %04x:[%s]\n", lnno, gpio, gpio2, ka, keya, kb, keyb);
add_rotary(&gpio_rotary[gpio], gpio, gpio2, key_names[ka].code, key_names[kb].code);
add_rotary(&gpio_rotary[gpio], gpio, gpio2, key_names[ka].code, key_names[kb].code,rotHalf);
}
else {
printf("Line %d: unknown key(s) for rotary encoder: %s, %s\n", lnno, keya, keyb);
Expand Down Expand Up @@ -325,11 +330,11 @@ static void add_event(gpio_key_s **ev, int gpio, int key, int xio)
}
}

static void add_rotary(gpio_rotary_s **rot, int gpio_a, int gpio_b, int key_a, int key_b)
static void add_rotary(gpio_rotary_s **rot, int gpio_a, int gpio_b, int key_a, int key_b, int rotHalf)
{
if(*rot){
/* Recursive call to add the next link in the list */
add_rotary(&(*rot)->next, gpio_a, gpio_b, key_a, key_b);
add_rotary(&(*rot)->next, gpio_a, gpio_b, key_a, key_b, rotHalf);
}
else{
*rot = malloc(sizeof(gpio_rotary_s));
Expand All @@ -346,6 +351,7 @@ static void add_rotary(gpio_rotary_s **rot, int gpio_a, int gpio_b, int key_a, i
(*rot)->next = NULL;
(*rot)->last_state = 0;
(*rot)->direction = 0;
(*rot)->rotHalf = rotHalf;
}
}
}
Expand Down Expand Up @@ -499,15 +505,15 @@ static void setup_xio(int xio)

switch(xio_dev[xio].type){
case IO_MCP23008:
write_iic(addr, 0, cfg_dat, 7);
write_iic(addr, 0, cfg_dat, 7);
printf("Configuring MCP23008\n");
break;
case IO_MCP23017A:
write_iic(addr, 0, cfg_dat, 7);
write_iic(addr, 0, cfg_dat, 7);
printf("Configuring MCP23017 port A\n");
break;
case IO_MCP23017B:
write_iic(addr, 0x10, cfg_dat, 7);
write_iic(addr, 0x10, cfg_dat, 7);
printf("Configuring MCP23017 port B\n");
break;
default:
Expand Down Expand Up @@ -639,33 +645,61 @@ int got_more_rotaries(void)
return last_gpio_rotary_idx < NUM_GPIO;
}

#define R_START 0x0
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_START 0x0
#define DIR_CW 0x10
#define DIR_CCW 0x20


#define R_CCW_BEGIN_H 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5

const unsigned char half_rotary_states[6][4] = {
// R_START (00)
{R_START_M, R_CW_BEGIN, R_CCW_BEGIN_H, R_START},
// R_CCW_BEGIN_H
{R_START_M | DIR_CCW, R_START, R_CCW_BEGIN_H, 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},
};

#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
#define DIR_CW 0x10
#define DIR_CCW 0x20
#define R_CCW_NEXT 0x6

const unsigned char rotary_states[7][4] = {
{R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_START
{R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW}, // R_CW_FINAL
{R_CW_NEXT, R_CW_BEGIN, R_START, R_START}, // R_CW_BEGIN
{R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START}, // R_CW_NEXT
{R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START}, // R_CCW_BEGIN
{R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW},// R_CCW_FINAL
{R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START}, // R_CCW_NEXT
{R_START, R_CW_BEGIN, R_CCW_BEGIN, R_START}, // R_START
{R_CW_NEXT, R_START, R_CW_FINAL, R_START | DIR_CW}, // R_CW_FINAL
{R_CW_NEXT, R_CW_BEGIN, R_START, R_START}, // R_CW_BEGIN
{R_CW_NEXT, R_CW_BEGIN, R_CW_FINAL, R_START}, // R_CW_NEXT
{R_CCW_NEXT, R_START, R_CCW_BEGIN, R_START}, // R_CCW_BEGIN
{R_CCW_NEXT, R_CCW_FINAL, R_START, R_START | DIR_CCW},// R_CCW_FINAL
{R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START}, // R_CCW_NEXT
};


static int update_rotary_keys_sm(int gpio_state, gpio_rotary_s* rotary_ctrl)
{
int bit_a = (gpio_state & rotary_ctrl->gpio_a_mask) ? 1 : 0;
int bit_b = (gpio_state & rotary_ctrl->gpio_b_mask) ? 1 : 0;
int encoder_bits = bit_a | bit_b << 1;

rotary_ctrl->last_state = rotary_states[rotary_ctrl->last_state & 0xf][encoder_bits];
if(rotary_ctrl->rotHalf == 1) {
rotary_ctrl->last_state = half_rotary_states[rotary_ctrl->last_state & 0xf][encoder_bits];
} else {
rotary_ctrl->last_state = rotary_states[rotary_ctrl->last_state & 0xf][encoder_bits];
}

switch(rotary_ctrl->last_state & 0x30)
{
Expand All @@ -688,4 +722,3 @@ int get_next_rotary_key(int gpio_state)
advance_rotary();
return k;
}

4 changes: 3 additions & 1 deletion pikeyd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ KEY_L 21
KEY_O 21

# Set up a rotary encoder generating up & down arrow keys, using GPIOs 4 and 17 for gray code input
ROT 4 17 KEY_DOWN KEY_UP
ROT 4 17 KEY_DOWN KEY_UP 0
# Same as above only it uses a rotary which works with half steps each click
ROT 5 18 KEY_DOWN KEY_UP 1

#define I/O expanders before using them
#XIO(tag) gpio_int_pin/chip_addr:register_no
Expand Down