Implement everything

This commit is contained in:
Alex Page 2022-07-29 00:39:15 -04:00
parent ff3e80aacc
commit 1a76174582
3 changed files with 263 additions and 42 deletions

View file

@ -3,8 +3,6 @@ name = "qwiic-twist"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bitvec = { version = "1.0.1", default-features = false }
embedded-hal = "0.2.7"
embedded-time = "0.12.1"

View file

@ -2,13 +2,20 @@
mod registers;
use bitvec::prelude::*;
use embedded_hal::blocking::i2c::{Read, Write, WriteRead};
use embedded_hal::prelude::*;
use embedded_time::rate::Extensions;
use registers::*;
/// 7-bit unshifted default I2C Address
const QWIIC_TWIST_ADDR: u8 = 0x3F;
const STATUS_BUTTON_CLICKED_BIT: usize = 2;
const STATUS_BUTTON_PRESSED_BIT: usize = 1;
const STATUS_ENCODER_MOVED_BIT: usize = 0;
const ENABLE_INTERRUPT_BUTTON_BIT: usize = 1;
const ENABLE_INTERRUPT_ENCODER_BIT: usize = 0;
pub struct QwiicTwist<I2C> {
i2c: I2C,
address: u8,
@ -18,31 +25,245 @@ impl<I2C, E> QwiicTwist<I2C>
where
I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
{
pub fn new(i2c: I2C, address: u8) -> Self {
Self { i2c, address }
pub fn new(i2c: I2C) -> Result<Self, E> {
let mut device = Self {
i2c,
address: QWIIC_TWIST_ADDR,
};
device.get_id()?;
Ok(device)
}
fn read_register(address: u8) -> u8 {
todo!()
}
fn read_register_16(address: u8) -> u16 {
todo!()
pub fn new_with_address(i2c: I2C, address: u8) -> Result<Self, E> {
let mut device = Self { i2c, address };
device.get_id()?;
Ok(device)
}
fn write_register(address: u8, value: u8) {
todo!()
}
fn write_register_16(address: u8, value: u16) {
todo!()
}
fn write_register_24(address: u8, value: u32) {
todo!()
pub fn get_id(&mut self) -> Result<u8, E> {
self.read_register(TWIST_ID)
}
pub fn read_temperature(&mut self) -> Result<u8, E> {
let mut temp = [0];
self.i2c
.write_read(self.address, &[0x78], &mut temp)
.and(Ok(temp[0]))
/// Returns the number of indents the user has turned the knob
pub fn get_count(&mut self) -> Result<i16, E> {
self.read_register_i16(TWIST_COUNT)
}
/// Set the number of indents to a given amount
pub fn set_count(&mut self, amount: i16) -> Result<(), E> {
self.write_register_i16(TWIST_COUNT, amount)
}
/// Returns the number of ticks since last check
pub fn get_diff(&mut self, clear_value: bool) -> Result<i16, E> {
let result = self.read_register_i16(TWIST_DIFFERENCE)?;
if clear_value {
self.write_register_i16(TWIST_DIFFERENCE, 0)?;
}
Ok(result)
}
/// Returns true if knob has been twisted
pub fn is_moved(&mut self) -> Result<bool, E> {
self.get_status_flag(STATUS_ENCODER_MOVED_BIT)
}
/// Return true if button is currently pressed.
pub fn is_pressed(&mut self) -> Result<bool, E> {
self.get_status_flag(STATUS_BUTTON_PRESSED_BIT)
}
/// Returns true if a click event has occurred. Event flag is then reset.
pub fn is_clicked(&mut self) -> Result<bool, E> {
self.get_status_flag(STATUS_BUTTON_CLICKED_BIT)
}
fn get_status_flag(&mut self, flag: usize) -> Result<bool, E> {
let mut result = self.read_register(TWIST_STATUS)?;
let status = result.view_bits_mut::<Lsb0>();
let moved = status.get(flag).map_or(false, |b| *b);
// Reset flag to 0
status.set(flag, false);
self.write_register(TWIST_STATUS, result)?;
Ok(moved)
}
/// Returns the number of milliseconds since the last encoder movement
pub fn time_since_last_movement(&mut self, clear_value: bool) -> Result<u16, E> {
let time_elapsed = self.read_register_u16(TWIST_LAST_ENCODER_EVENT)?;
if clear_value {
self.write_register_u16(TWIST_LAST_ENCODER_EVENT, 0)?;
}
Ok(time_elapsed)
}
/// Returns the number of milliseconds since the last button event (press and release)
pub fn time_since_last_press(&mut self, clear_value: bool) -> Result<u16, E> {
let time_elapsed = self.read_register_u16(TWIST_LAST_BUTTON_EVENT)?;
if clear_value {
self.write_register_u16(TWIST_LAST_BUTTON_EVENT, 0)?;
}
Ok(time_elapsed)
}
/// Clears the moved, clicked, and pressed bits
pub fn clear_interrupts(&mut self) -> Result<(), E> {
self.write_register(TWIST_STATUS, 0)
}
/// Sets the color of the encoder LEDs, 0-255
pub fn set_color(&mut self, red: u8, green: u8, blue: u8) -> Result<(), E> {
self.write_register_24(TWIST_RED, [red, green, blue])
}
/// Set the red LED, 0-255
pub fn set_red(&mut self, red: u8) -> Result<(), E> {
self.write_register(TWIST_RED, red)
}
/// Set the green LED, 0-255
pub fn set_green(&mut self, green: u8) -> Result<(), E> {
self.write_register(TWIST_GREEN, green)
}
/// Set the blue LED, 0-255
pub fn set_blue(&mut self, blue: u8) -> Result<(), E> {
self.write_register(TWIST_BLUE, blue)
}
/// Get current value
pub fn get_red(&mut self) -> Result<u8, E> {
self.read_register(TWIST_RED)
}
/// Get current value
pub fn get_green(&mut self) -> Result<u8, E> {
self.read_register(TWIST_GREEN)
}
/// Get current value
pub fn get_blue(&mut self) -> Result<u8, E> {
self.read_register(TWIST_BLUE)
}
//'Connect' commands Set the relation between each color and the twisting of the knob
//This will connect the LED so it changes [amount] with each encoder tick
//Negative numbers are allowed (so LED gets brighter the more you turn the encoder down)
/// Connect all colors in one command
pub fn connect_color(&mut self, red: i16, green: i16, blue: i16) -> Result<(), E> {
let (red, green, blue) = (red.to_be_bytes(), green.to_be_bytes(), blue.to_be_bytes());
let bytes = [
TWIST_CONNECT_RED.0,
red[0],
red[1],
green[0],
green[1],
blue[0],
blue[1],
];
self.i2c.write(self.address, &bytes)
}
/// Connect individual colors
pub fn connect_red(&mut self, red: i16) -> Result<(), E> {
self.write_register_i16(TWIST_CONNECT_RED, red)
}
/// Connect individual colors
pub fn connect_green(&mut self, green: i16) -> Result<(), E> {
self.write_register_i16(TWIST_CONNECT_GREEN, green)
}
/// Connect individual colors
pub fn connect_blue(&mut self, blue: i16) -> Result<(), E> {
self.write_register_i16(TWIST_CONNECT_BLUE, blue)
}
/// Get the connect value for each color
pub fn get_red_connect(&mut self) -> Result<i16, E> {
self.read_register_i16(TWIST_CONNECT_RED)
}
/// Get the connect value for each color
pub fn get_green_connect(&mut self) -> Result<i16, E> {
self.read_register_i16(TWIST_CONNECT_GREEN)
}
/// Get the connect value for each color
pub fn get_blue_connect(&mut self) -> Result<i16, E> {
self.read_register_i16(TWIST_CONNECT_BLUE)
}
/// Set the limit of what the encoder will go to, then wrap to 0. Set to 0 to disable.
pub fn set_limit(&mut self, limit: u16) -> Result<(), E> {
self.write_register_u16(TWIST_LIMIT, limit)
}
pub fn get_limit(&mut self) -> Result<u16, E> {
self.read_register_u16(TWIST_LIMIT)
}
pub fn set_encoder_interrupt_enabled(&mut self, enabled: bool) -> Result<(), E> {
let mut result = self.read_register(TWIST_ENABLE_INTS)?;
let status = result.view_bits_mut::<Lsb0>();
status.set(ENABLE_INTERRUPT_ENCODER_BIT, enabled);
self.write_register(TWIST_ENABLE_INTS, result)
}
pub fn set_button_interrupt_enabled(&mut self, enabled: bool) -> Result<(), E> {
let mut result = self.read_register(TWIST_ENABLE_INTS)?;
let status = result.view_bits_mut::<Lsb0>();
status.set(ENABLE_INTERRUPT_BUTTON_BIT, enabled);
self.write_register(TWIST_ENABLE_INTS, result)
}
/// Set number of milliseconds that elapse between end of knob turning and interrupt firing
pub fn set_interrupt_timeout(&mut self, timeout: u16) -> Result<(), E> {
self.write_register_u16(TWIST_TURN_INT_TIMEOUT, timeout)
}
/// Get number of milliseconds that must elapse between end of knob turning and interrupt firing
pub fn get_interrupt_timeout(&mut self) -> Result<u16, E> {
self.read_register_u16(TWIST_TURN_INT_TIMEOUT)
}
/// Returns a two byte Major/Minor version number
pub fn get_version(&mut self) -> Result<u16, E> {
self.read_register_u16(TWIST_VERSION)
}
/// Change the I²C address to `new_address`
pub fn change_address(&mut self, new_address: u8) -> Result<(), E> {
self.write_register(TWIST_CHANGE_ADDRESS, new_address)?;
self.address = new_address;
Ok(())
}
/// Reads from a given location from the Twist
fn read_register(&mut self, address: Register) -> Result<u8, E> {
// TODO: See if write_read() will work here
self.i2c.write(self.address, &[address.0])?;
let mut buffer: [u8; 1] = [0; 1];
self.i2c.read(self.address, &mut buffer)?;
Ok(u8::from_le_bytes(buffer))
}
fn read_register_u16(&mut self, address: Register) -> Result<u16, E> {
// TODO: See if write_read() will work here
self.i2c.write(self.address, &[address.0])?;
let mut buffer: [u8; 2] = [0; 2];
self.i2c.read(self.address, &mut buffer)?;
Ok(u16::from_le_bytes(buffer))
}
fn read_register_i16(&mut self, address: Register) -> Result<i16, E> {
let result = self.read_register_u16(address)?;
Ok(i16::from_ne_bytes(result.to_ne_bytes()))
}
/// Write a byte value to a spot in the Twist
fn write_register(&mut self, address: Register, value: u8) -> Result<(), E> {
self.i2c.write(self.address, &[address.0, value])
}
fn write_register_u16(&mut self, address: Register, value: u16) -> Result<(), E> {
let value = value.to_le_bytes();
let bytes = [address.0, value[0], value[1]];
self.i2c.write(self.address, &bytes)
}
fn write_register_i16(&mut self, address: Register, value: i16) -> Result<(), E> {
let value = u16::from_ne_bytes(value.to_ne_bytes());
self.write_register_u16(address, value)
}
fn write_register_24(&mut self, address: Register, value: [u8; 3]) -> Result<(), E> {
let bytes = [address.0, value[0], value[1], value[2]];
self.i2c.write(self.address, &bytes)
}
}

View file

@ -1,35 +1,37 @@
/// Map to the various registers on the Twist
const TWIST_ID: u8 = 0x00;
pub struct Register(pub u8);
pub const TWIST_ID: Register = Register(0x00);
/// - 2 - button clicked
/// - 1 - button pressed
/// - 0 - encoder moved
const TWIST_STATUS: u8 = 0x01;
const TWIST_VERSION: u8 = 0x02;
pub const TWIST_STATUS: Register = Register(0x01);
pub const TWIST_VERSION: Register = Register(0x02);
/// - 1 - button interrupt
/// - 0 - encoder interrupt
const TWIST_ENABLE_INTS: u8 = 0x04;
pub const TWIST_ENABLE_INTS: Register = Register(0x04);
const TWIST_COUNT: u8 = 0x05;
const TWIST_DIFFERENCE: u8 = 0x07;
pub const TWIST_COUNT: Register = Register(0x05);
pub const TWIST_DIFFERENCE: Register = Register(0x07);
/// Milliseconds since the last movement of the knob
const TWIST_LAST_ENCODER_EVENT: u8 = 0x09;
pub const TWIST_LAST_ENCODER_EVENT: Register = Register(0x09);
/// Milliseconds since the last press/release
const TWIST_LAST_BUTTON_EVENT: u8 = 0x0B;
pub const TWIST_LAST_BUTTON_EVENT: Register = Register(0x0B);
const TWIST_RED: u8 = 0x0D;
const TWIST_GREEN: u8 = 0x0E;
const TWIST_BLUE: u8 = 0x0F;
pub const TWIST_RED: Register = Register(0x0D);
pub const TWIST_GREEN: Register = Register(0x0E);
pub const TWIST_BLUE: Register = Register(0x0F);
/// Amount to change the red LED for each encoder tick
const TWIST_CONNECT_RED: u8 = 0x10;
pub const TWIST_CONNECT_RED: Register = Register(0x10);
/// Amount to change the green LED for each encoder tick
const TWIST_CONNECT_GREEN: u8 = 0x12;
pub const TWIST_CONNECT_GREEN: Register = Register(0x12);
/// Amount to change the blue LED for each encoder tick
const TWIST_CONNECT_BLUE: u8 = 0x14;
pub const TWIST_CONNECT_BLUE: Register = Register(0x14);
const TWIST_TURN_INT_TIMEOUT: u8 = 0x16;
const TWIST_CHANGE_ADDRESS: u8 = 0x18;
const TWIST_LIMIT: u8 = 0x19;
pub const TWIST_TURN_INT_TIMEOUT: Register = Register(0x16);
pub const TWIST_CHANGE_ADDRESS: Register = Register(0x18);
pub const TWIST_LIMIT: Register = Register(0x19);