Merge pull request #4580 from jepler/incrementalencoder-refactor
IncrementalEncoder: factor out the quadrature state machine
This commit is contained in:
commit
1b60c9d033
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "common-hal/rotaryio/IncrementalEncoder.h"
|
||||
#include "shared-module/rotaryio/IncrementalEncoder.h"
|
||||
|
||||
#include "atmel_start_pins.h"
|
||||
|
||||
|
@ -68,11 +69,9 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
|
|||
self->position = 0;
|
||||
self->quarter_count = 0;
|
||||
|
||||
// Top two bits of self->last_state don't matter, because they'll be gone as soon as
|
||||
// interrupt handler is called.
|
||||
self->last_state =
|
||||
shared_module_softencoder_state_init(self,
|
||||
((uint8_t) gpio_get_pin_level(self->pin_a) << 1) |
|
||||
(uint8_t) gpio_get_pin_level(self->pin_b);
|
||||
(uint8_t) gpio_get_pin_level(self->pin_b));
|
||||
|
||||
claim_pin(pin_a);
|
||||
claim_pin(pin_b);
|
||||
|
@ -106,66 +105,12 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o
|
|||
self->pin_b = NO_PIN;
|
||||
}
|
||||
|
||||
mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t* self) {
|
||||
return self->position;
|
||||
}
|
||||
|
||||
void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t* self,
|
||||
mp_int_t new_position) {
|
||||
self->position = new_position;
|
||||
}
|
||||
|
||||
void incrementalencoder_interrupt_handler(uint8_t channel) {
|
||||
rotaryio_incrementalencoder_obj_t* self = get_eic_channel_data(channel);
|
||||
|
||||
// This table also works for detent both at 11 and 00
|
||||
// For 11 at detent:
|
||||
// Turning cw: 11->01->00->10->11
|
||||
// Turning ccw: 11->10->00->01->11
|
||||
// For 00 at detent:
|
||||
// Turning cw: 00->10->11->10->00
|
||||
// Turning ccw: 00->01->11->10->00
|
||||
|
||||
// index table by state <oldA><oldB><newA><newB>
|
||||
#define BAD 7
|
||||
static const int8_t transitions[16] = {
|
||||
0, // 00 -> 00 no movement
|
||||
-1, // 00 -> 01 3/4 ccw (11 detent) or 1/4 ccw (00 at detent)
|
||||
+1, // 00 -> 10 3/4 cw or 1/4 cw
|
||||
BAD, // 00 -> 11 non-Gray-code transition
|
||||
+1, // 01 -> 00 2/4 or 4/4 cw
|
||||
0, // 01 -> 01 no movement
|
||||
BAD, // 01 -> 10 non-Gray-code transition
|
||||
-1, // 01 -> 11 4/4 or 2/4 ccw
|
||||
-1, // 10 -> 00 2/4 or 4/4 ccw
|
||||
BAD, // 10 -> 01 non-Gray-code transition
|
||||
0, // 10 -> 10 no movement
|
||||
+1, // 10 -> 11 4/4 or 2/4 cw
|
||||
BAD, // 11 -> 00 non-Gray-code transition
|
||||
+1, // 11 -> 01 1/4 or 3/4 cw
|
||||
-1, // 11 -> 10 1/4 or 3/4 ccw
|
||||
0, // 11 -> 11 no movement
|
||||
};
|
||||
|
||||
// Shift the old AB bits to the "old" position, and set the new AB bits.
|
||||
// TODO(tannewt): If we need more speed then read the pin directly. gpio_get_pin_level has
|
||||
// smarts to compensate for pin direction we don't need.
|
||||
self->last_state = (self->last_state & 0x3) << 2 |
|
||||
uint8_t new_state =
|
||||
((uint8_t) gpio_get_pin_level(self->pin_a) << 1) |
|
||||
(uint8_t) gpio_get_pin_level(self->pin_b);
|
||||
|
||||
int8_t quarter_incr = transitions[self->last_state];
|
||||
if (quarter_incr == BAD) {
|
||||
// Missed a transition. We don't know which way we're going, so do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
self->quarter_count += quarter_incr;
|
||||
if (self->quarter_count >= 4) {
|
||||
self->position += 1;
|
||||
self->quarter_count = 0;
|
||||
} else if (self->quarter_count <= -4) {
|
||||
self->position -= 1;
|
||||
self->quarter_count = 0;
|
||||
}
|
||||
shared_module_softencoder_state_update(self, new_state);
|
||||
}
|
||||
|
|
|
@ -35,10 +35,10 @@ typedef struct {
|
|||
mp_obj_base_t base;
|
||||
uint8_t pin_a;
|
||||
uint8_t pin_b;
|
||||
uint8_t eic_channel_a:4;
|
||||
uint8_t eic_channel_b:4;
|
||||
uint8_t last_state:4; // <old A><old B><new A><new B>
|
||||
int8_t quarter_count:4; // count intermediate transitions between detents
|
||||
uint8_t eic_channel_a;
|
||||
uint8_t eic_channel_b;
|
||||
uint8_t state; // <old A><old B>
|
||||
int8_t quarter_count; // count intermediate transitions between detents
|
||||
mp_int_t position;
|
||||
} rotaryio_incrementalencoder_obj_t;
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ USB_SERIAL_NUMBER_LENGTH = 32
|
|||
# Number of USB endpoint pairs.
|
||||
USB_NUM_EP = 8
|
||||
|
||||
CIRCUITPY_ROTARYIO_SOFTENCODER = 1
|
||||
|
||||
######################################################################
|
||||
# Put samd21-only choices here.
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "common-hal/rotaryio/IncrementalEncoder.h"
|
||||
#include "shared-module/rotaryio/IncrementalEncoder.h"
|
||||
#include "nrfx_gpiote.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
@ -40,29 +41,11 @@ static void _intr_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
|
|||
return;
|
||||
}
|
||||
|
||||
// reads a state 0 .. 3 *in order*.
|
||||
uint8_t new_state = nrf_gpio_pin_read(self->pin_a);
|
||||
new_state = (new_state << 1) + (new_state ^ nrf_gpio_pin_read(self->pin_b));
|
||||
uint8_t new_state =
|
||||
((uint8_t) nrf_gpio_pin_read(self->pin_a) << 1) |
|
||||
(uint8_t) nrf_gpio_pin_read(self->pin_b);
|
||||
|
||||
uint8_t change = (new_state - self->state) & 0x03;
|
||||
if (change == 1) {
|
||||
self->quarter++;
|
||||
} else if (change == 3) {
|
||||
self->quarter--;
|
||||
}
|
||||
// ignore other state transitions
|
||||
|
||||
self->state = new_state;
|
||||
|
||||
// logic from the atmel-samd port: provides some damping and scales movement
|
||||
// down by 4:1.
|
||||
if (self->quarter >= 4) {
|
||||
self->position++;
|
||||
self->quarter = 0;
|
||||
} else if (self->quarter <= -4) {
|
||||
self->position--;
|
||||
self->quarter = 0;
|
||||
}
|
||||
shared_module_softencoder_state_update(self, new_state);
|
||||
}
|
||||
|
||||
void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self,
|
||||
|
@ -110,12 +93,3 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o
|
|||
self->pin_a = NO_PIN;
|
||||
self->pin_b = NO_PIN;
|
||||
}
|
||||
|
||||
mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t *self) {
|
||||
return self->position;
|
||||
}
|
||||
|
||||
void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t *self,
|
||||
mp_int_t new_position) {
|
||||
self->position = new_position;
|
||||
}
|
||||
|
|
|
@ -35,8 +35,8 @@ typedef struct {
|
|||
mp_obj_base_t base;
|
||||
uint8_t pin_a;
|
||||
uint8_t pin_b;
|
||||
uint8_t state;
|
||||
int8_t quarter;
|
||||
uint8_t state; // <old A><old B>
|
||||
int8_t quarter_count; // count intermediate transitions between detents
|
||||
mp_int_t position;
|
||||
} rotaryio_incrementalencoder_obj_t;
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ CIRCUITPY_RTC ?= 1
|
|||
CIRCUITPY_FREQUENCYIO = 0
|
||||
|
||||
CIRCUITPY_RGBMATRIX ?= 1
|
||||
CIRCUITPY_ROTARYIO_SOFTENCODER = 1
|
||||
CIRCUITPY_FRAMEBUFFERIO ?= 1
|
||||
|
||||
CIRCUITPY_COUNTIO = 0
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <hardware/regs/pio.h>
|
||||
#include "common-hal/rotaryio/IncrementalEncoder.h"
|
||||
#include "shared-module/rotaryio/IncrementalEncoder.h"
|
||||
#include "bindings/rp2pio/__init__.h"
|
||||
#include "bindings/rp2pio/StateMachine.h"
|
||||
|
||||
|
@ -60,9 +61,12 @@ STATIC void incrementalencoder_interrupt_handler(void *self_in);
|
|||
void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self,
|
||||
const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) {
|
||||
mp_obj_t pins[] = {MP_OBJ_FROM_PTR(pin_a), MP_OBJ_FROM_PTR(pin_b)};
|
||||
// Start out with swapped to match behavior with other ports.
|
||||
self->swapped = true;
|
||||
if (!common_hal_rp2pio_pins_are_sequential(2, pins)) {
|
||||
pins[0] = MP_OBJ_FROM_PTR(pin_b);
|
||||
pins[1] = MP_OBJ_FROM_PTR(pin_a);
|
||||
self->swapped = false;
|
||||
if (!common_hal_rp2pio_pins_are_sequential(2, pins)) {
|
||||
mp_raise_RuntimeError(translate("Pins must be sequential"));
|
||||
}
|
||||
|
@ -88,12 +92,10 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
|
|||
common_hal_rp2pio_statemachine_run(&self->state_machine, encoder_init, MP_ARRAY_SIZE(encoder_init));
|
||||
|
||||
// We're guaranteed by the init code that some output will be available promptly
|
||||
uint8_t state;
|
||||
common_hal_rp2pio_statemachine_readinto(&self->state_machine, &state, 1, 1);
|
||||
// Top two bits of self->last_state don't matter, because they'll be gone as soon as
|
||||
// interrupt handler is called.
|
||||
self->last_state = state & 3;
|
||||
uint8_t quiescent_state;
|
||||
common_hal_rp2pio_statemachine_readinto(&self->state_machine, &quiescent_state, 1, 1);
|
||||
|
||||
shared_module_softencoder_state_init(self, quiescent_state & 3);
|
||||
common_hal_rp2pio_statemachine_set_interrupt_handler(&self->state_machine, incrementalencoder_interrupt_handler, self, PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS);
|
||||
}
|
||||
|
||||
|
@ -109,67 +111,20 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o
|
|||
common_hal_rp2pio_statemachine_deinit(&self->state_machine);
|
||||
}
|
||||
|
||||
mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t *self) {
|
||||
return self->position;
|
||||
}
|
||||
|
||||
void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t *self,
|
||||
mp_int_t new_position) {
|
||||
self->position = new_position;
|
||||
}
|
||||
|
||||
STATIC void incrementalencoder_interrupt_handler(void *self_in) {
|
||||
rotaryio_incrementalencoder_obj_t *self = self_in;
|
||||
// This table also works for detent both at 11 and 00
|
||||
// For 11 at detent:
|
||||
// Turning cw: 11->01->00->10->11
|
||||
// Turning ccw: 11->10->00->01->11
|
||||
// For 00 at detent:
|
||||
// Turning cw: 00->10->11->10->00
|
||||
// Turning ccw: 00->01->11->10->00
|
||||
|
||||
// index table by state <oldA><oldB><newA><newB>
|
||||
#define BAD 7
|
||||
static const int8_t transitions[16] = {
|
||||
0, // 00 -> 00 no movement
|
||||
-1, // 00 -> 01 3/4 ccw (11 detent) or 1/4 ccw (00 at detent)
|
||||
+1, // 00 -> 10 3/4 cw or 1/4 cw
|
||||
BAD, // 00 -> 11 non-Gray-code transition
|
||||
+1, // 01 -> 00 2/4 or 4/4 cw
|
||||
0, // 01 -> 01 no movement
|
||||
BAD, // 01 -> 10 non-Gray-code transition
|
||||
-1, // 01 -> 11 4/4 or 2/4 ccw
|
||||
-1, // 10 -> 00 2/4 or 4/4 ccw
|
||||
BAD, // 10 -> 01 non-Gray-code transition
|
||||
0, // 10 -> 10 no movement
|
||||
+1, // 10 -> 11 4/4 or 2/4 cw
|
||||
BAD, // 11 -> 00 non-Gray-code transition
|
||||
+1, // 11 -> 01 1/4 or 3/4 cw
|
||||
-1, // 11 -> 10 1/4 or 3/4 ccw
|
||||
0, // 11 -> 11 no movement
|
||||
};
|
||||
|
||||
while (common_hal_rp2pio_statemachine_get_in_waiting(&self->state_machine)) {
|
||||
// Bypass all the logic of StateMachine.c:_transfer, we need something
|
||||
// very simple and fast for an interrupt!
|
||||
uint8_t new = self->state_machine.pio->rxf[self->state_machine.state_machine];
|
||||
|
||||
// Shift the old AB bits to the "old" position, and set the new AB bits.
|
||||
self->last_state = (self->last_state & 0x3) << 2 | (new & 0x3);
|
||||
|
||||
int8_t quarter_incr = transitions[self->last_state];
|
||||
if (quarter_incr == BAD) {
|
||||
// Missed a transition. We don't know which way we're going, so do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
self->quarter_count += quarter_incr;
|
||||
if (self->quarter_count >= 4) {
|
||||
self->position += 1;
|
||||
self->quarter_count = 0;
|
||||
} else if (self->quarter_count <= -4) {
|
||||
self->position -= 1;
|
||||
self->quarter_count = 0;
|
||||
uint8_t new_state = self->state_machine.pio->rxf[self->state_machine.state_machine];
|
||||
if (self->swapped) {
|
||||
if (new_state == 0x1) {
|
||||
new_state = 0x2;
|
||||
} else if (new_state == 0x2) {
|
||||
new_state = 0x1;
|
||||
}
|
||||
}
|
||||
shared_module_softencoder_state_update(self, new_state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
rp2pio_statemachine_obj_t state_machine;
|
||||
uint8_t last_state : 4; // <old A><old B><new A><new B>
|
||||
int8_t quarter_count : 4; // count intermediate transitions between detents
|
||||
uint8_t state; // <old A><old B>
|
||||
int8_t quarter_count; // count intermediate transitions between detents
|
||||
bool swapped; // Did the pins need to be swapped to be sequential?
|
||||
mp_int_t position;
|
||||
} rotaryio_incrementalencoder_obj_t;
|
||||
|
|
|
@ -26,6 +26,7 @@ CIRCUITPY_BITOPS ?= 1
|
|||
CIRCUITPY_PWMIO ?= 1
|
||||
CIRCUITPY_RGBMATRIX ?= 1
|
||||
CIRCUITPY_ROTARYIO ?= 1
|
||||
CIRCUITPY_ROTARYIO_SOFTENCODER = 1
|
||||
|
||||
# Things that need to be implemented.
|
||||
# Use PWM interally
|
||||
|
|
|
@ -518,6 +518,7 @@ SRC_SHARED_MODULE_ALL = \
|
|||
random/__init__.c \
|
||||
rgbmatrix/RGBMatrix.c \
|
||||
rgbmatrix/__init__.c \
|
||||
rotaryio/IncrementalEncoder.c \
|
||||
sharpdisplay/SharpMemoryFramebuffer.c \
|
||||
sharpdisplay/__init__.c \
|
||||
socket/__init__.c \
|
||||
|
|
|
@ -271,6 +271,9 @@ CFLAGS += -DCIRCUITPY_RGBMATRIX=$(CIRCUITPY_RGBMATRIX)
|
|||
CIRCUITPY_ROTARYIO ?= 1
|
||||
CFLAGS += -DCIRCUITPY_ROTARYIO=$(CIRCUITPY_ROTARYIO)
|
||||
|
||||
CIRCUITPY_ROTARYIO_SOFTENCODER ?= 0
|
||||
CFLAGS += -DCIRCUITPY_ROTARYIO_SOFTENCODER=$(CIRCUITPY_ROTARYIO_SOFTENCODER)
|
||||
|
||||
CIRCUITPY_RTC ?= 1
|
||||
CFLAGS += -DCIRCUITPY_RTC=$(CIRCUITPY_RTC)
|
||||
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if CIRCUITPY_ROTARYIO && CIRCUITPY_ROTARYIO_SOFTENCODER
|
||||
#include "shared-module/rotaryio/IncrementalEncoder.h"
|
||||
#include "common-hal/rotaryio/IncrementalEncoder.h"
|
||||
|
||||
void shared_module_softencoder_state_init(rotaryio_incrementalencoder_obj_t *self, uint8_t quiescent_state) {
|
||||
self->state = quiescent_state;
|
||||
self->quarter_count = 0;
|
||||
common_hal_rotaryio_incrementalencoder_set_position(self, 0);
|
||||
}
|
||||
|
||||
void shared_module_softencoder_state_update(rotaryio_incrementalencoder_obj_t *self, uint8_t new_state) {
|
||||
#define BAD 7
|
||||
static const int8_t transitions[16] = {
|
||||
0, // 00 -> 00 no movement
|
||||
-1, // 00 -> 01 3/4 ccw (11 detent) or 1/4 ccw (00 at detent)
|
||||
+1, // 00 -> 10 3/4 cw or 1/4 cw
|
||||
BAD, // 00 -> 11 non-Gray-code transition
|
||||
+1, // 01 -> 00 2/4 or 4/4 cw
|
||||
0, // 01 -> 01 no movement
|
||||
BAD, // 01 -> 10 non-Gray-code transition
|
||||
-1, // 01 -> 11 4/4 or 2/4 ccw
|
||||
-1, // 10 -> 00 2/4 or 4/4 ccw
|
||||
BAD, // 10 -> 01 non-Gray-code transition
|
||||
0, // 10 -> 10 no movement
|
||||
+1, // 10 -> 11 4/4 or 2/4 cw
|
||||
BAD, // 11 -> 00 non-Gray-code transition
|
||||
+1, // 11 -> 01 1/4 or 3/4 cw
|
||||
-1, // 11 -> 10 1/4 or 3/4 ccw
|
||||
0, // 11 -> 11 no movement
|
||||
};
|
||||
|
||||
new_state &= 0x3;
|
||||
int idx = (self->state << 2) | new_state;
|
||||
self->state = new_state;
|
||||
|
||||
int8_t quarter_incr = transitions[idx];
|
||||
if (quarter_incr == BAD) {
|
||||
// Missed a transition. We don't know which way we're going, so do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
self->quarter_count += quarter_incr;
|
||||
|
||||
if (self->quarter_count >= 4) {
|
||||
self->position += 1;
|
||||
self->quarter_count = 0;
|
||||
} else if (self->quarter_count <= -4) {
|
||||
self->position -= 1;
|
||||
self->quarter_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t *self) {
|
||||
return self->position;
|
||||
}
|
||||
|
||||
void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t *self, mp_int_t position) {
|
||||
self->position = position;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jeff Epler for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common-hal/rotaryio/IncrementalEncoder.h"
|
||||
|
||||
void shared_module_softencoder_state_init(rotaryio_incrementalencoder_obj_t *self, uint8_t quiescent_state);
|
||||
void shared_module_softencoder_state_update(rotaryio_incrementalencoder_obj_t *self, uint8_t new_state);
|
||||
mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t *self);
|
||||
void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t *self, mp_int_t position);
|
Loading…
Reference in New Issue