tof_control/device/
si5345b.rs

1#![allow(unused)]
2use crate::constant::*;
3
4use csv;
5use i2cdev::core::*;
6use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError};
7use std::thread;
8use std::time::Duration;
9
10const SET_PAGE: u16 = 0x01;
11
12const LOL_HOLD_STATUS: u16 = 0x00E;
13const SOFT_RST_ALL: u16 = 0x001C; // Bits: 0
14const HARD_RST: u16 = 0x001E; // Bits: 1
15                              // Registers for NVM Programming
16const ACTIVE_NVM_BANK: u16 = 0x00E2; // [7:0], R, Indicates number of user bank writes carried out so far.A
17const NVM_WRITE: u16 = 0x00E3; // [7:0], R/W, Initiates an NVM write when written with 0xC7
18const NVM_READ_BANK: u16 = 0x00E4; // [0], S, Download register values with content stored in NVM
19const DEVICE_READY: u16 = 0x00FE; // [7:0], R, Indicates that the device serial interface is ready to accept commands.
20
21pub struct SI5345B {
22    bus: u8,
23    address: u16,
24}
25
26impl SI5345B {
27    pub fn new(bus: u8, address: u16) -> Self {
28        Self { bus, address }
29    }
30
31    pub fn read_lol_status(&self) -> Result<(bool), LinuxI2CError> {
32        let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
33        dev.smbus_write_byte_data(SET_PAGE as u8, ((LOL_HOLD_STATUS >> 8) as u8));
34
35        let mut lol_status = dev.smbus_read_byte_data(LOL_HOLD_STATUS as u8)?;
36        lol_status = lol_status & 0x02;
37
38        if lol_status == 1 {
39            Ok(true)
40        } else {
41            Ok(false)
42        }
43    }
44
45    pub fn read_holdover_status(&self) -> Result<(bool), LinuxI2CError> {
46        let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
47        dev.smbus_write_byte_data(SET_PAGE as u8, ((LOL_HOLD_STATUS >> 8) as u8));
48
49        let mut dspll_mode = dev.smbus_read_byte_data(LOL_HOLD_STATUS as u8)?;
50        dspll_mode = dspll_mode & 0x20;
51
52        if dspll_mode == 1 {
53            Ok(true)
54        } else {
55            Ok(false)
56        }
57    }
58
59    pub fn configure_si5345b(&self) -> Result<(), LinuxI2CError> {
60        let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
61
62        let si5345b_csv = include_str!("../config/rb_config/si5345b.csv");
63        let mut reader = csv::ReaderBuilder::new()
64            .comment(Some(b'#'))
65            .escape(Some(b'\\'))
66            .flexible(true)
67            .from_reader(si5345b_csv.as_bytes());
68
69        for (i, record) in reader.records().enumerate() {
70            let record = record.expect("failed to convert record");
71            let address = i64::from_str_radix(&record[0].trim_start_matches("0x"), 16)
72                .expect("cannot convert register from address");
73            let data = i64::from_str_radix(&record[1].trim_start_matches("0x"), 16)
74                .expect("cannot convert register from data");
75            let page = address >> 8;
76            let register = address & 0xFF;
77            // println!("{} {:?} {:?}", i, address, data);
78
79            dev.smbus_write_byte_data(SET_PAGE as u8, page as u8);
80            dev.smbus_write_byte_data(register as u8, data as u8);
81
82            if i == 2 {
83                thread::sleep(Duration::from_millis(300));
84            }
85        }
86
87        Ok(())
88    }
89
90    /// Check how many user bank writes has carried out so far
91    pub fn read_available_nvm_bank(&self) -> Result<u8, LinuxI2CError> {
92        let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
93
94        let active_nvm_bank_page = ACTIVE_NVM_BANK >> 8;
95        let active_nvm_bank_reg = ACTIVE_NVM_BANK & 0xFF;
96        dev.smbus_write_byte_data(SET_PAGE as u8, active_nvm_bank_page as u8);
97        let active_nvm_bank = dev.smbus_read_byte_data(active_nvm_bank_reg as u8)?;
98        
99        let mut num_available_bank: u8;
100        match active_nvm_bank {
101            3 => num_available_bank = 2,
102            15 => num_available_bank = 1,
103            63 => num_available_bank = 0,
104            _ => num_available_bank = u8::MAX,
105        }
106
107        Ok((num_available_bank))
108    }
109
110    pub fn configure_nvm_si5345b(&self) -> Result<(), LinuxI2CError> {
111        let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
112
113        // /// Write all registers as needed
114        // self.configure_si5345b()?;
115        // thread::sleep(Duration::from_millis(300));
116
117        /// Write identification into the user scratch space (registers 0x026B to 0x0272)
118        let design_id = String::from("RB2.5.2");
119        let mut design_id_ary: [u8; 8] = [0; 8];
120        for (i, char) in design_id.clone().into_bytes().iter().enumerate() {
121            design_id_ary[i] = *char;
122        }
123        let mut scratch_space_reg: u16 = 0x026B;
124        // println!("Writing identification into the user scratch space (registers 0x026B to 0x0272)...");
125        for byte in design_id_ary.iter() {
126            let page = scratch_space_reg >> 8;
127            let register = scratch_space_reg & 0xFF;
128            dev.smbus_write_byte_data(SET_PAGE as u8, page as u8);
129            dev.smbus_write_byte_data(register as u8, *byte);
130
131            scratch_space_reg += 1;
132        }
133
134        /// Write 0xC7 to NVM_WRITE (0x00E3) register
135        let nvm_write_page = NVM_WRITE >> 8;
136        let nvm_write_reg = NVM_WRITE & 0xFF;
137        // println!("Writing 0xC7 to NVM_WRITE (0x00E3) register...");
138        dev.smbus_write_byte_data(SET_PAGE as u8, nvm_write_page as u8);
139        dev.smbus_write_byte_data(nvm_write_reg as u8, 0xC7);
140        thread::sleep(Duration::from_millis(300));
141
142        /// Wait until DEVICE_READY (0x00FE) = 0x0F
143        let device_ready_page = DEVICE_READY >> 8;
144        let device_ready_reg = DEVICE_READY & 0xFF;
145        dev.smbus_write_byte_data(SET_PAGE as u8, device_ready_page as u8);
146        let mut device_ready_data = dev.smbus_read_byte_data(device_ready_reg as u8)?;
147        while device_ready_data != 0x0F {
148            thread::sleep(Duration::from_millis(300));
149            dev.smbus_write_byte_data(SET_PAGE as u8, device_ready_page as u8);
150            device_ready_data = dev.smbus_read_byte_data(device_ready_reg as u8)?;
151        }
152
153        /// Set NVM_READ_BANK (0x00E4[0]) = “1”
154        let nvm_read_bank_page = NVM_READ_BANK >> 8;
155        let nvm_read_bank_reg = NVM_READ_BANK & 0xFF;
156        // println!("Writing 1 to NVM_READ_BANK (0x00E4[0]) register...");
157        dev.smbus_write_byte_data(SET_PAGE as u8, nvm_read_bank_page as u8);
158        dev.smbus_write_byte_data(nvm_read_bank_reg as u8, 0x01);
159        thread::sleep(Duration::from_millis(300));
160
161        /// Wait until DEVICE_READY (0x00FE) = 0x0F
162        dev.smbus_write_byte_data(SET_PAGE as u8, device_ready_page as u8);
163        device_ready_data = dev.smbus_read_byte_data(device_ready_reg as u8)?;
164        while device_ready_data != 0x0F {
165            thread::sleep(Duration::from_millis(300));
166            dev.smbus_write_byte_data(SET_PAGE as u8, device_ready_page as u8);
167            device_ready_data = dev.smbus_read_byte_data(device_ready_reg as u8)?;
168        }
169
170        Ok(())
171    }
172
173    pub fn hard_reset_si5345b(&self) -> Result<(), LinuxI2CError> {
174        let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
175        dev.smbus_write_byte_data(SET_PAGE as u8, ((HARD_RST >> 8) as u8));
176
177        let mut value = dev.smbus_read_byte_data((HARD_RST & 0xFF) as u8)?;
178        value = value | 0x02;
179        dev.smbus_write_byte_data((HARD_RST & 0xFF) as u8, value);
180
181        value = value & 0xFD;
182        dev.smbus_write_byte_data((HARD_RST & 0xFF) as u8, value);
183
184        Ok(())
185    }
186
187    pub fn soft_reset_si5345b(&self) -> Result<(), LinuxI2CError> {
188        let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
189        dev.smbus_write_byte_data(SET_PAGE as u8, ((SOFT_RST_ALL >> 8) as u8));
190
191        dev.smbus_write_byte_data((SOFT_RST_ALL & 0xFF) as u8, 0x01);
192
193        Ok(())
194    }
195}