diff options
Diffstat (limited to 'table-fan/rotary.c')
-rw-r--r-- | table-fan/rotary.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/table-fan/rotary.c b/table-fan/rotary.c new file mode 100644 index 0000000..beb95c1 --- /dev/null +++ b/table-fan/rotary.c @@ -0,0 +1,82 @@ +/* + * spreadspace avr utils + * + * + * Copyright (C) 2021 Christian Pointner <equinox@spreadspace.org> + * + * This file is part of spreadspace avr utils. + * + * spreadspace avr utils is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * spreadspace avr utils is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with spreadspace avr utils. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <avr/io.h> +#include <avr/interrupt.h> + +#include "rotary.h" + +#define DEBOUNCE_MAX 100 +uint8_t last_stable = 0; + +static inline uint8_t get_current(void) +{ + return (PINB & ((1<<PB4) | (1<<PB5))) >> PB4; +} + +void rotary_init(void) +{ + DDRB &= ~((1<<PB4) | (1<<PB5)); + PORTB |= (1<<PB4) | (1<<PB5); + last_stable = get_current(); +} + +rotary_dir_t rotary_task(void) +{ + static uint8_t last = 0; + static uint8_t cnt = 0; + + uint8_t current = get_current(); + if(last == current) + cnt += (cnt < DEBOUNCE_MAX) ? 1 : 0; + else + cnt -= (cnt > 0) ? 1 : 0; + last = current; + + if(cnt < DEBOUNCE_MAX) + return rotary_dir_none; + cnt = 0; + + rotary_dir_t dir = rotary_dir_none; + if(last_stable != current) { + switch(last_stable) { + case 0: + if(current == 1) dir = rotary_dir_up; + if(current == 2) dir = rotary_dir_down; + break; + case 1: + if(current == 3) dir = rotary_dir_up; + if(current == 0) dir = rotary_dir_down; + break; + case 2: + if(current == 0) dir = rotary_dir_up; + if(current == 3) dir = rotary_dir_down; + break; + case 3: + if(current == 2) dir = rotary_dir_up; + if(current == 1) dir = rotary_dir_down; + break; + } + } + last_stable = current; + return dir; +} |