File syn_encoder.c¶
File List > input > syn_encoder.c
Go to the documentation of this file
#if __has_include("syn_config.h")
#include "syn_config.h"
#endif
#if !defined(SYN_USE_ENCODER) || SYN_USE_ENCODER
#include "../drivers/syn_gpio.h"
#include "../util/syn_assert.h"
#include "syn_encoder.h"
#include <string.h>
static const int8_t quad_table[16] = {
/* new: 00 01 10 11 */
/* prev 00 */ 0, -1, +1, 0,
/* prev 01 */ +1, 0, 0, -1,
/* prev 10 */ -1, 0, 0, +1,
/* prev 11 */ 0, +1, -1, 0,
};
void syn_encoder_init(SYN_Encoder *enc, SYN_GPIO_Pin pin_a, SYN_GPIO_Pin pin_b)
{
SYN_ASSERT(enc != NULL);
memset(enc, 0, sizeof(*enc));
enc->pin_a = pin_a;
enc->pin_b = pin_b;
enc->steps_per_detent = 1;
/* Read initial state */
uint8_t a = (syn_gpio_read(pin_a) == SYN_GPIO_HIGH) ? 1 : 0;
uint8_t b = (syn_gpio_read(pin_b) == SYN_GPIO_HIGH) ? 1 : 0;
enc->last_state = (uint8_t)((a << 1) | b);
}
void syn_encoder_set_steps_per_detent(SYN_Encoder *enc, uint8_t spd)
{
SYN_ASSERT(enc != NULL);
SYN_ASSERT(spd > 0);
enc->steps_per_detent = spd;
enc->sub_count = 0;
}
void syn_encoder_update(SYN_Encoder *enc)
{
SYN_ASSERT(enc != NULL);
uint8_t a = (syn_gpio_read(enc->pin_a) == SYN_GPIO_HIGH) ? 1 : 0;
uint8_t b = (syn_gpio_read(enc->pin_b) == SYN_GPIO_HIGH) ? 1 : 0;
uint8_t new_state = (uint8_t)((a << 1) | b);
if (new_state == enc->last_state)
return;
uint8_t idx = (uint8_t)((enc->last_state << 2) | new_state);
int8_t dir = quad_table[idx];
enc->last_state = new_state;
if (dir == 0)
return; /* invalid transition (noise) — ignore */
enc->last_dir = dir;
if (enc->steps_per_detent <= 1) {
enc->position += dir;
enc->delta += dir;
} else {
enc->sub_count += dir;
if (enc->sub_count >= (int8_t)enc->steps_per_detent) {
enc->position++;
enc->delta++;
enc->sub_count = 0;
} else if (enc->sub_count <= -(int8_t)enc->steps_per_detent) {
enc->position--;
enc->delta--;
enc->sub_count = 0;
}
}
}
int32_t syn_encoder_get_delta(SYN_Encoder *enc)
{
SYN_ASSERT(enc != NULL);
int32_t d = enc->delta;
enc->delta = 0;
/* Push to velocity stats window (if attached) */
if (enc->stats != NULL) {
syn_signal_push(enc->stats, d);
}
return d;
}
void syn_encoder_set_stats(SYN_Encoder *enc, SYN_Signal *stats)
{
SYN_ASSERT(enc != NULL);
enc->stats = stats;
}
#endif /* SYN_USE_ENCODER */