#pragma once #include "drivers/ioexpander/ioexpander.hpp" #include "drivers/is31fl3731/is31fl3731.hpp" #include "common/pimoroni_common.hpp" namespace pimoroni { namespace encoderwheel { static const uint8_t NUM_LEDS = 24; static const uint8_t NUM_BUTTONS = 5; static const uint8_t NUM_GPIOS = 3; static const uint8_t UP = 0; static const uint8_t DOWN = 1; static const uint8_t LEFT = 2; static const uint8_t RIGHT = 3; static const uint8_t CENTRE = 4; static const uint8_t GP7 = 7; static const uint8_t GP8 = 8; static const uint8_t GP9 = 9; static const uint8_t GPIOS[] = {GP7, GP8, GP9}; class BreakoutEncoderWheel { struct RGBLookup { uint8_t r; uint8_t g; uint8_t b; }; //-------------------------------------------------- // Constants //-------------------------------------------------- public: static const uint8_t DEFAULT_IOE_I2C_ADDRESS = 0x13; static const uint8_t DEFAULT_LED_I2C_ADDRESS = 0x77; static const uint8_t ALTERNATE_LED_I2C_ADDRESS = 0x74; static const Direction DEFAULT_DIRECTION = NORMAL_DIR; static const uint32_t DEFAULT_TIMEOUT = 1; private: static const uint8_t ENC_CHANNEL = 1; static const uint8_t ENC_TERM_A = 3; static const uint8_t ENC_TERM_B = 12; static const uint8_t ENC_COUNTS_PER_REV = 24; static const uint8_t ENC_COUNT_DIVIDER = 2; static const uint8_t SW_UP = 13; static const uint8_t SW_DOWN = 4; static const uint8_t SW_LEFT = 11; static const uint8_t SW_RIGHT = 2; static const uint8_t SW_CENTRE = 1; // This wonderful lookup table maps the LEDs on the encoder wheel // from their 3x24 (remember, they're RGB) configuration to // their specific location in the 144 pixel buffer. static constexpr RGBLookup lookup_table[24] = { {128, 32, 48}, {129, 33, 49}, {130, 17, 50}, {131, 18, 34}, {132, 19, 35}, {133, 20, 36}, {134, 21, 37}, {112, 80, 96}, {113, 81, 97}, {114, 82, 98}, {115, 83, 99}, {116, 84, 100}, {117, 68, 101}, {118, 69, 85}, {127, 47, 63}, {121, 41, 57}, {122, 25, 58}, {123, 26, 42}, {124, 27, 43}, {125, 28, 44}, {126, 29, 45}, {15, 95, 111}, {8, 89, 105}, {9, 90, 106}, }; //-------------------------------------------------- // Variables //-------------------------------------------------- private: IOExpander ioe; IS31FL3731 led_ring; Direction enc_direction = DEFAULT_DIRECTION; int16_t enc_count = 0; int16_t enc_step = 0; int16_t enc_turn = 0; int16_t last_raw_count = 0; int16_t last_delta_count = 0; //-------------------------------------------------- // Constructors/Destructor //-------------------------------------------------- public: BreakoutEncoderWheel(uint8_t ioe_address = DEFAULT_IOE_I2C_ADDRESS, uint8_t led_address = DEFAULT_LED_I2C_ADDRESS) : BreakoutEncoderWheel(new I2C(), ioe_address, led_address) {} BreakoutEncoderWheel(I2C *i2c, uint8_t ioe_address = DEFAULT_IOE_I2C_ADDRESS, uint8_t led_address = DEFAULT_LED_I2C_ADDRESS, uint interrupt = PIN_UNUSED, uint32_t timeout = DEFAULT_TIMEOUT, bool debug = false) : ioe(i2c, ioe_address, interrupt, timeout, debug), led_ring(i2c, led_address) {} //-------------------------------------------------- // Methods //-------------------------------------------------- public: bool init(bool skip_chip_id_check = false); // For print access in micropython i2c_inst_t* get_i2c() const; int get_ioe_address() const; int get_led_address() const; int get_sda() const; int get_scl() const; int get_int() const; // Calls through to IOExpander class void set_ioe_address(uint8_t address); bool get_interrupt_flag(); void clear_interrupt_flag(); // Encoder breakout specific bool pressed(uint button); int16_t count(); int16_t delta(); void zero(); int16_t step(); int16_t turn(); float revolutions(); float degrees(); float radians(); Direction direction(); void direction(Direction direction); void set_rgb(int index, int r, int g, int b); void set_hsv(int index, float h, float s = 1.0f, float v = 1.0f); void clear(); void show(); uint8_t gpio_pin_mode(uint8_t gpio); void gpio_pin_mode(uint8_t gpio, uint8_t mode); int16_t gpio_pin_value(uint8_t gpio); float gpio_pin_value_as_voltage(uint8_t gpio); void gpio_pin_value(uint8_t gpio, uint16_t value, bool load = true, bool wait_for_load = false); void gpio_pwm_load(bool wait_for_load = true); uint16_t gpio_pwm_frequency(float frequency, bool load = true, bool wait_for_load = false); private: void take_encoder_reading(); }; } }