1use crate::{addresses, Error, I2cDevice, Result};
6use embedded_hal::i2c::I2c;
7
8pub struct Knob<I2C> {
31 device: I2cDevice<I2C>,
32 value: i16,
33 pressed: bool,
34 range: Option<(i16, i16)>,
35}
36
37impl<I2C, E> Knob<I2C>
38where
39 I2C: I2c<Error = E>,
40{
41 pub fn new(i2c: I2C) -> Result<Self, E> {
43 Self::new_with_address(i2c, addresses::KNOB[0])
44 }
45
46 pub fn new_with_address(i2c: I2C, address: u8) -> Result<Self, E> {
48 let mut knob = Self {
49 device: I2cDevice::new(i2c, address),
50 value: 0,
51 pressed: false,
52 range: None,
53 };
54
55 knob.update()?;
57
58 Ok(knob)
59 }
60
61 pub fn address(&self) -> u8 {
63 self.device.address
64 }
65
66 fn read_data(&mut self) -> Result<(i16, bool), E> {
68 let mut buf = [0u8; 4]; self.device.read(&mut buf)?;
70
71 let raw_value = i16::from_le_bytes([buf[1], buf[2]]);
73 let pressed = buf[3] != 0;
74
75 Ok((raw_value, pressed))
76 }
77
78 pub fn update(&mut self) -> Result<bool, E> {
83 let previous_value = self.value;
84 let previous_pressed = self.pressed;
85
86 let (mut new_value, new_pressed) = self.read_data()?;
87
88 if let Some((min, max)) = self.range {
90 if new_value < min {
91 new_value = min;
92 self.set_value_internal(min)?;
93 } else if new_value > max {
94 new_value = max;
95 self.set_value_internal(max)?;
96 }
97 }
98
99 self.value = new_value;
100 self.pressed = new_pressed;
101
102 Ok(self.value != previous_value || self.pressed != previous_pressed)
103 }
104
105 pub fn value(&self) -> i16 {
107 self.value
108 }
109
110 pub fn set_value(&mut self, value: i16) -> Result<(), E> {
112 if let Some((min, max)) = self.range {
114 if value < min || value > max {
115 return Err(Error::OutOfRange);
116 }
117 }
118
119 self.set_value_internal(value)?;
120 self.value = value;
121 Ok(())
122 }
123
124 fn set_value_internal(&mut self, value: i16) -> Result<(), E> {
126 let bytes = value.to_le_bytes();
127 let data = [bytes[0], bytes[1], 0, 0];
128 self.device.write(&data)?;
129 Ok(())
130 }
131
132 pub fn reset(&mut self) -> Result<(), E> {
134 self.set_value(0)
135 }
136
137 pub fn pressed(&self) -> bool {
139 self.pressed
140 }
141
142 pub fn set_range(&mut self, min: i16, max: i16) {
147 self.range = Some((min, max));
148
149 if self.value < min {
151 self.value = min;
152 } else if self.value > max {
153 self.value = max;
154 }
155 }
156
157 pub fn clear_range(&mut self) {
159 self.range = None;
160 }
161
162 pub fn range(&self) -> Option<(i16, i16)> {
164 self.range
165 }
166
167 pub fn rotation_delta(&self, previous_value: i16) -> i16 {
174 let diff = self.value.wrapping_sub(previous_value);
176
177 if !(-16384..=16384).contains(&diff) {
179 diff.wrapping_add(i16::MIN)
180 } else {
181 diff
182 }
183 }
184
185 pub fn release(self) -> I2C {
187 self.device.release()
188 }
189}