pimoroni-pico/libraries/breakout_encoder_wheel/breakout_encoder_wheel.cpp

254 wiersze
6.3 KiB
C++

#include "breakout_encoder_wheel.hpp"
#include <algorithm>
#include <cmath>
namespace pimoroni {
namespace encoderwheel {
bool BreakoutEncoderWheel::init(bool skip_chip_id_check) {
bool success = false;
if(ioe.init(skip_chip_id_check, true) && led_ring.init()) {
ioe.setup_rotary_encoder(ENC_CHANNEL, ENC_TERM_A, ENC_TERM_B, 0, true); // count microsteps
ioe.set_mode(SW_UP, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_DOWN, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_LEFT, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_RIGHT, IOExpander::PIN_IN_PU);
ioe.set_mode(SW_CENTRE, IOExpander::PIN_IN_PU);
led_ring.enable({
0b00000000, 0b10111111,
0b00111110, 0b00111110,
0b00111111, 0b10111110,
0b00000111, 0b10000110,
0b00110000, 0b00110000,
0b00111111, 0b10111110,
0b00111111, 0b10111110,
0b01111111, 0b11111110,
0b01111111, 0b00000000
}, 0);
success = true;
}
return success;
}
i2c_inst_t* BreakoutEncoderWheel::get_i2c() const {
return ioe.get_i2c();
}
int BreakoutEncoderWheel::get_ioe_address() const {
return ioe.get_address();
}
int BreakoutEncoderWheel::get_led_address() const {
return led_ring.get_address();
}
int BreakoutEncoderWheel::get_sda() const {
return ioe.get_sda();
}
int BreakoutEncoderWheel::get_scl() const {
return ioe.get_scl();
}
int BreakoutEncoderWheel::get_int() const {
return ioe.get_int();
}
void BreakoutEncoderWheel::set_ioe_address(uint8_t address) {
ioe.set_address(address);
}
bool BreakoutEncoderWheel::get_interrupt_flag() {
return ioe.get_interrupt_flag();
}
void BreakoutEncoderWheel::clear_interrupt_flag() {
ioe.clear_interrupt_flag();
}
bool BreakoutEncoderWheel::pressed(uint button) {
switch(button) {
case 0:
return ioe.input(SW_UP) == 0;
case 1:
return ioe.input(SW_DOWN) == 0;
case 2:
return ioe.input(SW_LEFT) == 0;
case 3:
return ioe.input(SW_RIGHT) == 0;
case 4:
return ioe.input(SW_CENTRE) == 0;
default:
return false;
}
}
int16_t BreakoutEncoderWheel::count() {
take_encoder_reading();
return enc_count;
}
int16_t BreakoutEncoderWheel::delta() {
take_encoder_reading();
// Determine the change in counts since the last time this function was performed
int16_t change = enc_count - last_delta_count;
last_delta_count = enc_count;
return change;
}
void BreakoutEncoderWheel::zero() {
ioe.clear_rotary_encoder(ENC_CHANNEL);
enc_count = 0;
enc_step = 0;
enc_turn = 0;
last_raw_count = 0;
last_delta_count = 0;
}
int16_t BreakoutEncoderWheel::step() {
take_encoder_reading();
return enc_step;
}
int16_t BreakoutEncoderWheel::turn() {
take_encoder_reading();
return enc_turn;
}
float BreakoutEncoderWheel::revolutions() {
return (float)count() / (float)ENC_COUNTS_PER_REV;
}
float BreakoutEncoderWheel::degrees() {
return revolutions() * 360.0f;
}
float BreakoutEncoderWheel::radians() {
return revolutions() * M_PI * 2.0f;
}
Direction BreakoutEncoderWheel::direction() {
return enc_direction;
}
void BreakoutEncoderWheel::direction(Direction direction) {
enc_direction = direction;
}
void BreakoutEncoderWheel::set_rgb(int index, int r, int g, int b) {
RGBLookup rgb = lookup_table[index];
led_ring.set(rgb.r, r);
led_ring.set(rgb.g, g);
led_ring.set(rgb.b, b);
}
void BreakoutEncoderWheel::set_hsv(int index, float h, float s, float v) {
int r, g, b;
if(h < 0.0f) {
h = 1.0f + fmodf(h, 1.0f);
}
int i = int(h * 6);
float f = h * 6 - i;
v = v * 255.0f;
float sv = s * v;
float fsv = f * sv;
auto p = uint8_t(-sv + v);
auto q = uint8_t(-fsv + v);
auto t = uint8_t(fsv - sv + v);
uint8_t bv = uint8_t(v);
switch (i % 6) {
default:
case 0: r = bv; g = t; b = p; break;
case 1: r = q; g = bv; b = p; break;
case 2: r = p; g = bv; b = t; break;
case 3: r = p; g = q; b = bv; break;
case 4: r = t; g = p; b = bv; break;
case 5: r = bv; g = p; b = q; break;
}
set_rgb(index, r, g, b);
}
void BreakoutEncoderWheel::clear() {
led_ring.clear();
}
void BreakoutEncoderWheel::show() {
led_ring.update();
}
uint8_t BreakoutEncoderWheel::gpio_pin_mode(uint8_t gpio) {
assert(gpio < GP7 || gpio > GP9);
return ioe.get_mode(gpio);
}
void BreakoutEncoderWheel::gpio_pin_mode(uint8_t gpio, uint8_t mode) {
assert(gpio < GP7 || gpio > GP9);
ioe.set_mode(gpio, mode);
}
int16_t BreakoutEncoderWheel::gpio_pin_value(uint8_t gpio) {
assert(gpio < GP7 || gpio > GP9);
return ioe.input(gpio);
}
float BreakoutEncoderWheel::gpio_pin_value_as_voltage(uint8_t gpio) {
assert(gpio < GP7 || gpio > GP9);
return ioe.input_as_voltage(gpio);
}
void BreakoutEncoderWheel::gpio_pin_value(uint8_t gpio, uint16_t value, bool load, bool wait_for_load) {
assert(gpio < GP7 || gpio > GP9);
ioe.output(gpio, value, load, wait_for_load);
}
void BreakoutEncoderWheel::gpio_pwm_load(bool wait_for_load) {
ioe.pwm_load(wait_for_load);
}
uint16_t BreakoutEncoderWheel::gpio_pwm_frequency(float frequency, bool load, bool wait_for_load) {
return ioe.set_pwm_frequency(frequency, load, wait_for_load);
}
void BreakoutEncoderWheel::take_encoder_reading() {
// Read the current count
int16_t raw_count = ioe.read_rotary_encoder(ENC_CHANNEL) / ENC_COUNT_DIVIDER;
int16_t raw_change = raw_count - last_raw_count;
last_raw_count = raw_count;
// Invert the change
if(enc_direction == REVERSED_DIR) {
raw_change = 0 - raw_change;
}
enc_count += raw_change;
enc_step += raw_change;
if(raw_change > 0) {
while(enc_step >= ENC_COUNTS_PER_REV) {
enc_step -= ENC_COUNTS_PER_REV;
enc_turn += 1;
}
}
else if(raw_change < 0) {
while(enc_step < 0) {
enc_step += ENC_COUNTS_PER_REV;
enc_turn -= 1;
}
}
}
}
}