Skip to main content

AS5600_Driver/
driver.rs

1use crate::regs::*;
2use crate::traits::AS5600Interface;
3use crate::types::*;
4use crate::error::AS56Error;
5use embedded_hal::i2c::{I2c, SevenBitAddress};
6
7/// Main driver for the AS5600 sensor.
8pub struct AS5600Driver<I2C> {
9    i2c: I2C,
10    address: u8,
11}
12
13impl<I2C: I2c<SevenBitAddress>> AS5600Driver<I2C> {
14    /// Creates a new driver instance with the default I2C address (0x36).
15    pub fn new(i2c: I2C) -> Self {
16        Self {
17            i2c,
18            address: DEFAULT_ADDR,
19        }
20    }
21
22    /// Creates a new driver instance with a custom I2C address.
23    pub fn with_address(i2c: I2C, address: u8) -> Self {
24        Self { i2c, address }
25    }
26
27    /// Internal helper to read a single byte from a register.
28    fn read_u8(&mut self, reg: u8) -> Result<u8, AS56Error<I2C::Error>> {
29        let mut buf = [0u8; 1];
30        self.i2c
31            .write_read(self.address, &[reg], &mut buf)
32            .map_err(AS56Error::I2c)?;
33        Ok(buf[0])
34    }
35
36    /// Internal helper to write a single byte to a register.
37    fn write_u8(&mut self, reg: u8, value: u8) -> Result<(), AS56Error<I2C::Error>> {
38        self.i2c
39            .write(self.address, &[reg, value])
40            .map_err(AS56Error::I2c)?;
41        Ok(())
42    }
43
44    /// Internal helper to read a 12-bit value from two consecutive registers.
45    fn read_u16(&mut self, reg_hi: u8) -> Result<u16, AS56Error<I2C::Error>> {
46        let mut buf = [0u8; 2];
47        self.i2c
48            .write_read(self.address, &[reg_hi], &mut buf)
49            .map_err(AS56Error::I2c)?;
50        Ok(u16::from_be_bytes(buf) & 0x0FFF)
51    }
52
53    /// Internal helper to write a 12-bit value to two consecutive registers.
54    fn write_u16(&mut self, reg_hi: u8, value: u16) -> Result<(), AS56Error<I2C::Error>> {
55        let bytes = value.to_be_bytes();
56        self.i2c
57            .write(self.address, &[reg_hi, bytes[0], bytes[1]])
58            .map_err(AS56Error::I2c)?;
59        Ok(())
60    }
61
62    /// **DANGER**: Permanently burns ZPOS and MPOS settings to the chip.
63    pub unsafe fn danger_permanent_burn_settings(&mut self) -> Result<(), AS56Error<I2C::Error>> {
64        self.i2c
65            .write(self.address, &[regs::BURN, 0x80])
66            .map_err(AS56Error::I2c)?;
67        Ok(())
68    }
69
70    /// **DANGER**: Permanently burns Configuration settings to the chip.
71    pub unsafe fn danger_permanent_burn_config(&mut self) -> Result<(), AS56Error<I2C::Error>> {
72        self.i2c
73            .write(self.address, &[regs::BURN, 0x40])
74            .map_err(AS56Error::I2c)?;
75        Ok(())
76    }
77}
78
79impl<I2C: I2c<SevenBitAddress>> AS5600Interface for AS5600Driver<I2C> {
80    type Error = I2C::Error;
81
82    fn read_raw_angle(&mut self) -> Result<u16, AS56Error<Self::Error>> {
83        self.read_u16(regs::RAW_ANGLE_HI)
84    }
85
86    fn read_angle(&mut self) -> Result<u16, AS56Error<Self::Error>> {
87        self.read_u16(regs::ANGLE_HI)
88    }
89
90    fn get_burn_count(&mut self) -> Result<u8, AS56Error<Self::Error>> {
91        Ok(self.read_u8(regs::ZMCO)? & 0x03)
92    }
93
94    fn get_status_raw(&mut self) -> Result<u8, AS56Error<Self::Error>> {
95        self.read_u8(regs::STATUS)
96    }
97
98    fn get_magnet_status(&mut self) -> Result<MagnetStatus, AS56Error<Self::Error>> {
99        let val = self.read_u8(regs::STATUS)?;
100        Ok(MagnetStatus {
101            detected: (val & 0x20) != 0,
102            too_weak: (val & 0x10) != 0,
103            too_strong: (val & 0x08) != 0,
104        })
105    }
106
107    fn get_magnitude(&mut self) -> Result<u16, AS56Error<Self::Error>> {
108        self.read_u16(regs::MAGNITUDE_HI)
109    }
110
111    fn get_agc(&mut self) -> Result<u8, AS56Error<Self::Error>> {
112        self.read_u8(regs::AGC)
113    }
114
115    fn get_config(&mut self) -> Result<Configuration, AS56Error<Self::Error>> {
116        let hi = self.read_u8(regs::CONF_HI)?;
117        let lo = self.read_u8(regs::CONF_LO)?;
118
119        Ok(Configuration {
120            power_mode: match lo & 0x03 {
121                0b01 => PowerMode::LPM1,
122                0b10 => PowerMode::LPM2,
123                0b11 => PowerMode::LPM3,
124                _ => PowerMode::Nominal,
125            },
126            hysteresis: match (lo >> 2) & 0x03 {
127                0b01 => Hysteresis::Lsb1,
128                0b10 => Hysteresis::Lsb2,
129                0b11 => Hysteresis::Lsb3,
130                _ => Hysteresis::Off,
131            },
132            output_stage: match (lo >> 4) & 0x03 {
133                0b01 => OutputStage::AnalogReduced,
134                0b10 => OutputStage::PWM,
135                _ => OutputStage::AnalogFull,
136            },
137            pwm_frequency: match (lo >> 6) & 0x03 {
138                0b01 => PwmFrequency::Hz230,
139                0b10 => PwmFrequency::Hz460,
140                0b11 => PwmFrequency::Hz920,
141                _ => PwmFrequency::Hz115,
142            },
143            slow_filter: match hi & 0x03 {
144                0b01 => SlowFilter::X8,
145                0b10 => SlowFilter::X4,
146                0b11 => SlowFilter::X2,
147                _ => SlowFilter::X16,
148            },
149            fast_filter_threshold: match (hi >> 2) & 0x07 {
150                0b001 => FastFilterThreshold::Lsb6,
151                0b010 => FastFilterThreshold::Lsb7,
152                0b011 => FastFilterThreshold::Lsb9,
153                0b100 => FastFilterThreshold::Lsb18,
154                0b101 => FastFilterThreshold::Lsb21,
155                0b110 => FastFilterThreshold::Lsb24,
156                0b111 => FastFilterThreshold::Lsb10,
157                _ => FastFilterThreshold::SlowOnly,
158            },
159            watchdog: (hi & 0x20) != 0,
160        })
161    }
162
163    fn set_config(&mut self, config: Configuration) -> Result<(), AS56Error<Self::Error>> {
164        let hi = ((config.watchdog as u8) << 5)
165            | ((config.fast_filter_threshold as u8) << 2)
166            | (config.slow_filter as u8);
167
168        let lo = ((config.pwm_frequency as u8) << 6)
169            | ((config.output_stage as u8) << 4)
170            | ((config.hysteresis as u8) << 2)
171            | (config.power_mode as u8);
172
173        self.write_u8(regs::CONF_HI, hi)?;
174        self.write_u8(regs::CONF_LO, lo)?;
175        Ok(())
176    }
177
178    fn get_zero_position(&mut self) -> Result<u16, AS56Error<Self::Error>> {
179        self.read_u16(regs::ZPOS_HI)
180    }
181
182    fn set_zero_position(&mut self, angle: u16) -> Result<(), AS56Error<Self::Error>> {
183        self.write_u16(regs::ZPOS_HI, angle & 0x0FFF)
184    }
185
186    fn get_max_position(&mut self) -> Result<u16, AS56Error<Self::Error>> {
187        self.read_u16(regs::MPOS_HI)
188    }
189
190    fn set_max_position(&mut self, angle: u16) -> Result<(), AS56Error<Self::Error>> {
191        self.write_u16(regs::MPOS_HI, angle & 0x0FFF)
192    }
193
194    fn get_max_angle(&mut self) -> Result<u16, AS56Error<Self::Error>> {
195        self.read_u16(regs::MANG_HI)
196    }
197
198    fn set_max_angle(&mut self, angle: u16) -> Result<(), AS56Error<Self::Error>> {
199        self.write_u16(regs::MANG_HI, angle & 0x0FFF)
200    }
201}