1#![allow(unused)]
2use crate::constant::*;
3
4use i2c_linux_sys::i2c_smbus_read_i2c_block_data;
5use i2cdev::core::*;
6use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError};
7
8const INPUT_PORT_0: u16 = 0x00;
10const INPUT_PORT_1: u16 = 0x01;
11const INPUT_PORT_2: u16 = 0x02;
12const INPUT_PORT_3: u16 = 0x03;
13const INPUT_PORT_4: u16 = 0x04;
14const INPUT_PORT_5: u16 = 0x05;
15const INPUT_PORT_6: u16 = 0x06;
16const INPUT_PORT_7: u16 = 0x07;
17const OUTPUT_PORT_0: u16 = 0x08;
18const OUTPUT_PORT_1: u16 = 0x09;
19const OUTPUT_PORT_2: u16 = 0x0A;
20const OUTPUT_PORT_3: u16 = 0x0B;
21const OUTPUT_PORT_4: u16 = 0x0C;
22const OUTPUT_PORT_5: u16 = 0x0D;
23const OUTPUT_PORT_6: u16 = 0x0E;
24const OUTPUT_PORT_7: u16 = 0x0F;
25const INTERRUPT_STATUS_PORT_0: u16 = 0x10;
26const INTERRUPT_STATUS_PORT_1: u16 = 0x11;
27const INTERRUPT_STATUS_PORT_2: u16 = 0x12;
28const INTERRUPT_STATUS_PORT_3: u16 = 0x13;
29const INTERRUPT_STATUS_PORT_4: u16 = 0x14;
30const INTERRUPT_STATUS_PORT_5: u16 = 0x15;
31const INTERRUPT_STATUS_PORT_6: u16 = 0x16;
32const INTERRUPT_STATUS_PORT_7: u16 = 0x17;
33const PORT_SELECT: u16 = 0x18;
34const INTERRUPT_MASK: u16 = 0x19;
35const PIN_DIRECTION: u16 = 0x1C;
36const DRIVE_MODE_PULL_UP: u16 = 0x1D;
37const DRIVE_MODE_PULL_DOWN: u16 = 0x1E;
38const DRIVE_MODE_OPEN_DRAIN_HIGH: u16 = 0x1F;
39const DRIVE_MODE_OPEN_DRAIN_LOW: u16 = 0x20;
40const DRIVE_MODE_STRONG: u16 = 0x21;
41const DRIVE_MODE_SLOW_STRONG: u16 = 0x22;
42const DRIVE_MODE_HIGH_Z: u16 = 0x23;
43const ENABLE_REGISTER: u16 = 0x2D;
44const DEVICE_INFO: u16 = 0x2E;
45const COMMAND: u16 = 0x30;
46
47#[derive(Copy, Clone)]
48pub struct CY8C9560A {
49 bus: u8,
50 address: u16,
51}
52
53impl CY8C9560A {
54 pub fn new(bus: u8, address: u16) -> Self {
55 Self { bus, address }
56 }
57 pub fn read_device_info(&self) -> Result<(u8, u8), LinuxI2CError> {
58 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
59 let device_info = dev.smbus_read_byte_data(DEVICE_INFO as u8)?;
60 let device_family = (device_info & 0xF0) >> 4;
61 let device_setting = device_info & 0x01;
62
63 Ok((device_family, device_setting))
64 }
65 pub fn read_enable_register(&self) -> Result<u8, LinuxI2CError> {
66 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
67 let enable_register = dev.smbus_read_byte_data(ENABLE_REGISTER as u8)?;
68
69 Ok(enable_register)
70 }
71 pub fn enable_eeprom(&self) -> Result<(), LinuxI2CError> {
72 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
73 let eeprom_enable_sequence: [u8; 4] = [0x43, 0x4D, 0x53, 0x02];
74 dev.smbus_write_i2c_block_data(ENABLE_REGISTER as u8, &eeprom_enable_sequence)?;
75
76 Ok(())
77 }
78 pub fn store_config_eeprom_por(&self) -> Result<(), LinuxI2CError> {
79 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
80 dev.smbus_write_byte_data(COMMAND as u8, 0x01)?;
81
82 Ok(())
83 }
84 pub fn reset_config_eeprom_por(&self) -> Result<(), LinuxI2CError> {
85 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
86 dev.smbus_write_byte_data(COMMAND as u8, 0x02)?;
87
88 Ok(())
89 }
90 pub fn read_port_status(&self, port: u8) -> Result<u8, LinuxI2CError> {
91 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
92 let port_status = dev.smbus_read_byte_data(match port {
93 0 => INPUT_PORT_0 as u8,
94 1 => INPUT_PORT_1 as u8,
95 2 => INPUT_PORT_2 as u8,
96 3 => INPUT_PORT_3 as u8,
97 4 => INPUT_PORT_4 as u8,
98 5 => INPUT_PORT_5 as u8,
99 6 => INPUT_PORT_6 as u8,
100 7 => INPUT_PORT_7 as u8,
101 _ => 0xFF,
102 })?;
103
104 Ok(port_status)
105 }
106 pub fn initialize_all_outputs(&self) -> Result<(), LinuxI2CError> {
107 for i in 0..8 {
108 self.set_output_port(i, 0xFF)?;
109 }
110
111 Ok(())
112 }
113 pub fn set_output_port(&self, port: u8, value: u8) -> Result<(), LinuxI2CError> {
114 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
115 dev.smbus_write_byte_data(
116 match port {
117 0 => OUTPUT_PORT_0 as u8,
118 1 => OUTPUT_PORT_1 as u8,
119 2 => OUTPUT_PORT_2 as u8,
120 3 => OUTPUT_PORT_3 as u8,
121 4 => OUTPUT_PORT_4 as u8,
122 5 => OUTPUT_PORT_5 as u8,
123 6 => OUTPUT_PORT_6 as u8,
124 7 => OUTPUT_PORT_7 as u8,
125 _ => 0xFF,
126 },
127 value,
128 )?;
129
130 Ok(())
131 }
132 pub fn select_port(&self, port: u8) -> Result<(), LinuxI2CError> {
133 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
134 dev.smbus_write_byte_data(PORT_SELECT as u8, port)?;
135
136 Ok(())
137 }
138 pub fn set_interrupt_mask_port(&self, value: u8) -> Result<(), LinuxI2CError> {
139 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
140 dev.smbus_write_byte_data(INTERRUPT_MASK as u8, value)?;
141
142 Ok(())
143 }
144 pub fn set_pin_direction(&self, value: u8) -> Result<(), LinuxI2CError> {
145 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
146 dev.smbus_write_byte_data(PIN_DIRECTION as u8, value)?;
147
148 Ok(())
149 }
150 pub fn set_drive_mode(&self, mode: u8) -> Result<(), LinuxI2CError> {
151 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
152 dev.smbus_write_byte_data(
153 match mode {
154 0 => DRIVE_MODE_PULL_UP as u8,
155 1 => DRIVE_MODE_PULL_DOWN as u8,
156 2 => DRIVE_MODE_OPEN_DRAIN_HIGH as u8,
157 3 => DRIVE_MODE_OPEN_DRAIN_LOW as u8,
158 4 => DRIVE_MODE_STRONG as u8,
159 5 => DRIVE_MODE_SLOW_STRONG as u8,
160 6 => DRIVE_MODE_HIGH_Z as u8,
161 _ => 0xFF,
162 },
163 0x01,
164 )?;
165
166 Ok(())
167 }
168 pub fn set_rf_switch(&self, channel: u8, mode: u8) -> Result<(), LinuxI2CError> {
170 match channel {
171 0 => match mode {
172 0 => {
173 let value: u8 = (0x3F & !0x30) | 0x20;
174 self.set_output_port(7, value)?;
175 }
176 1 => {
177 let value: u8 = (0x3F & !0x30) | 0x10;
178 self.set_output_port(7, value)?;
179 }
180 2 => {
181 let value: u8 = (0x3F & !0x30) | 0x00;
182 self.set_output_port(7, value)?;
183 }
184 _ => {
185 self.set_output_port(7, 0x3F)?;
186 }
187 },
188 1 => match mode {
189 0 => {
190 let value: u8 = (0x3F | 0x0C) & 0x0C;
191 self.set_output_port(7, value)?;
192 }
193 1 => {
194 let value: u8 = (0x3F & !0x0C) | 0x04;
195 self.set_output_port(7, value)?;
196 }
197 2 => {
198 let value: u8 = (0x3F & !0x0C) | 0x00;
199 self.set_output_port(7, value)?;
200 }
201 _ => {
202 self.set_output_port(7, 0x3F)?;
203 }
204 },
205 2 => match mode {
206 0 => {
207 let value: u8 = (0x3F | 0x03) & 0x03;
208 self.set_output_port(7, value)?;
209 }
210 1 => {
211 let value: u8 = (0x3F & !0x03) | 0x01;
212 self.set_output_port(7, value)?;
213 }
214 2 => {
215 let value: u8 = (0x3F & !0x03) | 0x00;
216 self.set_output_port(7, value)?;
217 }
218 _ => {
219 self.set_output_port(7, 0x3F)?;
220 }
221 },
222 3 => match mode {
223 0 => {
224 let value: u8 = (0x03 | 0x03) & 0x03;
225 self.set_output_port(2, value)?;
226 }
227 1 => {
228 let value: u8 = (0x03 & !0x03) | 0x01;
229 self.set_output_port(2, value)?;
230 }
231 2 => {
232 let value: u8 = (0x03 & !0x03) | 0x00;
233 self.set_output_port(2, value)?;
234 }
235 _ => {
236 self.set_output_port(2, 0x03)?;
237 }
238 },
239 4 => match mode {
240 0 => {
241 let value: u8 = (0x33 | 0x03) & 0x03;
242 self.set_output_port(5, value)?;
243 }
244 1 => {
245 let value: u8 = (0x33 & !0x03) | 0x02;
246 self.set_output_port(5, value)?;
247 }
248 2 => {
249 let value: u8 = (0x33 & !0x03) | 0x00;
250 self.set_output_port(5, value)?;
251 }
252 _ => {
253 self.set_output_port(5, 0x33)?;
254 }
255 },
256 5 => match mode {
257 0 => {
258 let value: u8 = (0x33 | 0x30) & 0x30;
259 self.set_output_port(5, value)?;
260 }
261 1 => {
262 let value: u8 = (0x33 & !0x30) | 0x10;
263 self.set_output_port(5, value)?;
264 }
265 2 => {
266 let value: u8 = (0x33 & !0x30) | 0x00;
267 self.set_output_port(5, value)?;
268 }
269 _ => {
270 self.set_output_port(5, 0x33)?;
271 }
272 },
273 6 => match mode {
274 0 => {
275 let value: u8 = (0xFC | 0xC0) & 0xC0;
276 self.set_output_port(4, value)?;
277 }
278 1 => {
279 let value: u8 = (0xFC & !0xC0) | 0x80;
280 self.set_output_port(4, value)?;
281 }
282 2 => {
283 let value: u8 = (0xFC & !0xC0) | 0x00;
284 self.set_output_port(4, value)?;
285 }
286 _ => {
287 self.set_output_port(4, 0xFC)?;
288 }
289 },
290 7 => match mode {
291 0 => {
292 let value: u8 = (0xFC | 0x30) & 0x30;
293 self.set_output_port(4, value)?;
294 }
295 1 => {
296 let value: u8 = (0xFC & !0x30) | 0x20;
297 self.set_output_port(4, value)?;
298 }
299 2 => {
300 let value: u8 = (0xFC & !0x30) | 0x00;
301 self.set_output_port(4, value)?;
302 }
303 _ => {
304 self.set_output_port(4, 0xFC)?;
305 }
306 },
307 8 => match mode {
308 0 => {
309 let value: u8 = (0xFC | 0x0C) & 0x0C;
310 self.set_output_port(4, value)?;
311 }
312 1 => {
313 let value: u8 = (0xFC & !0x0C) | 0x08;
314 self.set_output_port(4, value)?;
315 }
316 2 => {
317 let value: u8 = (0xFC & !0x0C) | 0x00;
318 self.set_output_port(4, value)?;
319 }
320 _ => {
321 self.set_output_port(4, 0xFC)?;
322 }
323 },
324 _ => {}
325 };
326
327 Ok(())
328 }
329 pub fn reset_clock_synthesizer(&self) -> Result<(), LinuxI2CError> {
331 let mut value = (0x03 & !0x02) | 0 << 1;
332 value = (value & !0x01) | 1;
333
334 self.set_output_port(3, value)?;
335
336 Ok(())
337 }
338 pub fn enable_tcal_clock(&self) -> Result<(), LinuxI2CError> {
340 let mut value: u16 = (0x3F | 0x80) | (0x01 << 8);
341 self.set_output_port(7, value as u8)?;
342
343 value = (0x3F | 0x40) | (0x01 << 7);
344 self.set_output_port(7, value as u8)?;
345
346 Ok(())
347 }
348 pub fn disable_tcal_clock(&self) -> Result<(), LinuxI2CError> {
349 let mut value: u16 = (0x3F | 0x80);
350 self.set_output_port(7, value as u8)?;
351
352 value = (0x3F | 0x40);
353 self.set_output_port(7, value as u8)?;
354
355 Ok(())
356 }
357}