Skip to main content

vlfd_rs/
config.rs

1mod word {
2    pub const VERICOMM_CLOCK_HIGH_DELAY: usize = 0;
3    pub const VERICOMM_CLOCK_LOW_DELAY: usize = 1;
4    pub const VERICOMM_MISC: usize = 2;
5    pub const MODE_AND_CHANNEL: usize = 3;
6    pub const FLASH_BEGIN_BLOCK: usize = 4;
7    pub const FLASH_BEGIN_CLUSTER: usize = 5;
8    pub const FLASH_READ_END_BLOCK: usize = 6;
9    pub const FLASH_READ_END_CLUSTER: usize = 7;
10    pub const LICENCE_AND_SECURITY_KEY: usize = 31;
11    pub const SMIMS_VERSION: usize = 32;
12    pub const FIFO_SIZE_WORDS: usize = 33;
13    pub const FLASH_TOTAL_BLOCK: usize = 34;
14    pub const FLASH_BLOCK_SIZE: usize = 35;
15    pub const FLASH_CLUSTER_SIZE: usize = 36;
16    pub const ABILITY_FLAGS: usize = 37;
17    pub const PROGRAM_STATE: usize = 48;
18    pub const CLOCK_STATE: usize = 49;
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct Config {
23    words: [u16; Self::WORD_COUNT],
24}
25
26impl Default for Config {
27    fn default() -> Self {
28        Self {
29            words: [0u16; Self::WORD_COUNT],
30        }
31    }
32}
33
34impl Config {
35    pub const WORD_COUNT: usize = 64;
36
37    pub fn new() -> Self {
38        Self::default()
39    }
40
41    pub fn from_words(words: [u16; Self::WORD_COUNT]) -> Self {
42        Self { words }
43    }
44
45    pub fn words(&self) -> &[u16; Self::WORD_COUNT] {
46        &self.words
47    }
48
49    pub fn vericomm_clock_high_delay(&self) -> u16 {
50        self.words[word::VERICOMM_CLOCK_HIGH_DELAY]
51    }
52
53    pub fn set_vericomm_clock_high_delay(&mut self, delay: u16) {
54        self.words[word::VERICOMM_CLOCK_HIGH_DELAY] = delay;
55    }
56
57    pub fn vericomm_clock_low_delay(&self) -> u16 {
58        self.words[word::VERICOMM_CLOCK_LOW_DELAY]
59    }
60
61    pub fn set_vericomm_clock_low_delay(&mut self, delay: u16) {
62        self.words[word::VERICOMM_CLOCK_LOW_DELAY] = delay;
63    }
64
65    pub fn vericomm_isv(&self) -> u8 {
66        ((self.words[word::VERICOMM_MISC] >> 4) & 0x000f) as u8
67    }
68
69    pub fn set_vericomm_isv(&mut self, value: u8) {
70        let value = (value & 0x0f) as u16;
71        let clock_check = self.words[word::VERICOMM_MISC] & 0x0001;
72        self.words[word::VERICOMM_MISC] = (value << 4) | clock_check;
73    }
74
75    pub fn vericomm_clock_check_enabled(&self) -> bool {
76        self.words[word::VERICOMM_MISC] & 0x0001 != 0
77    }
78
79    pub fn set_vericomm_clock_check_enabled(&mut self, enabled: bool) {
80        if enabled {
81            self.words[word::VERICOMM_MISC] |= 0x0001;
82        } else {
83            self.words[word::VERICOMM_MISC] &= !0x0001;
84        }
85    }
86
87    pub fn veri_sdk_channel_selector(&self) -> u8 {
88        (self.words[word::MODE_AND_CHANNEL] & 0x00ff) as u8
89    }
90
91    pub fn set_veri_sdk_channel_selector(&mut self, channel: u8) {
92        self.words[word::MODE_AND_CHANNEL] =
93            (self.words[word::MODE_AND_CHANNEL] & 0xff00) | channel as u16;
94    }
95
96    pub fn mode_selector(&self) -> u8 {
97        (self.words[word::MODE_AND_CHANNEL] >> 8) as u8
98    }
99
100    pub fn set_mode_selector(&mut self, mode: u8) {
101        self.words[word::MODE_AND_CHANNEL] =
102            (self.words[word::MODE_AND_CHANNEL] & 0x00ff) | ((mode as u16) << 8);
103    }
104
105    pub fn flash_begin_block_addr(&self) -> u16 {
106        self.words[word::FLASH_BEGIN_BLOCK]
107    }
108
109    pub fn set_flash_begin_block_addr(&mut self, addr: u16) {
110        self.words[word::FLASH_BEGIN_BLOCK] = addr;
111    }
112
113    pub fn flash_begin_cluster_addr(&self) -> u16 {
114        self.words[word::FLASH_BEGIN_CLUSTER]
115    }
116
117    pub fn set_flash_begin_cluster_addr(&mut self, addr: u16) {
118        self.words[word::FLASH_BEGIN_CLUSTER] = addr;
119    }
120
121    pub fn flash_read_end_block_addr(&self) -> u16 {
122        self.words[word::FLASH_READ_END_BLOCK]
123    }
124
125    pub fn set_flash_read_end_block_addr(&mut self, addr: u16) {
126        self.words[word::FLASH_READ_END_BLOCK] = addr;
127    }
128
129    pub fn flash_read_end_cluster_addr(&self) -> u16 {
130        self.words[word::FLASH_READ_END_CLUSTER]
131    }
132
133    pub fn set_flash_read_end_cluster_addr(&mut self, addr: u16) {
134        self.words[word::FLASH_READ_END_CLUSTER] = addr;
135    }
136
137    pub fn licence_key(&self) -> u16 {
138        self.words[word::LICENCE_AND_SECURITY_KEY]
139    }
140
141    /// The hardware exposes the security key through the same configuration
142    /// word used for the active license key.
143    pub fn security_key(&self) -> u16 {
144        self.words[word::LICENCE_AND_SECURITY_KEY]
145    }
146
147    pub fn set_licence_key(&mut self, key: u16) {
148        self.words[word::LICENCE_AND_SECURITY_KEY] = key;
149    }
150
151    pub fn smims_version_raw(&self) -> u16 {
152        self.words[word::SMIMS_VERSION]
153    }
154
155    pub fn smims_major_version(&self) -> u8 {
156        (self.words[word::SMIMS_VERSION] >> 8) as u8
157    }
158
159    pub fn smims_sub_version(&self) -> u8 {
160        ((self.words[word::SMIMS_VERSION] >> 4) & 0x000f) as u8
161    }
162
163    pub fn smims_patch_version(&self) -> u8 {
164        (self.words[word::SMIMS_VERSION] & 0x000f) as u8
165    }
166
167    /// Returns the FIFO capacity in 16-bit words.
168    ///
169    /// This matches the legacy C++ implementation, where `CFG[33]` is passed
170    /// directly to `SMIMS_FIFO_Write` / `SMIMS_FIFO_Read` as a word count.
171    pub fn fifo_size_words(&self) -> u16 {
172        self.words[word::FIFO_SIZE_WORDS]
173    }
174
175    /// Legacy alias for [`Self::fifo_size_words`].
176    pub fn fifo_size(&self) -> u16 {
177        self.fifo_size_words()
178    }
179
180    pub fn flash_total_block(&self) -> u16 {
181        self.words[word::FLASH_TOTAL_BLOCK]
182    }
183
184    pub fn flash_block_size(&self) -> u16 {
185        self.words[word::FLASH_BLOCK_SIZE]
186    }
187
188    pub fn flash_cluster_size(&self) -> u16 {
189        self.words[word::FLASH_CLUSTER_SIZE]
190    }
191
192    pub fn vericomm_ability(&self) -> bool {
193        self.has_state_flag(0x0001)
194    }
195
196    pub fn veri_instrument_ability(&self) -> bool {
197        self.has_state_flag(0x0002)
198    }
199
200    pub fn veri_link_ability(&self) -> bool {
201        self.has_state_flag(0x0004)
202    }
203
204    pub fn veri_soc_ability(&self) -> bool {
205        self.has_state_flag(0x0008)
206    }
207
208    pub fn vericomm_pro_ability(&self) -> bool {
209        self.has_state_flag(0x0010)
210    }
211
212    pub fn veri_sdk_ability(&self) -> bool {
213        self.has_state_flag(0x0100)
214    }
215
216    pub fn is_programmed(&self) -> bool {
217        self.words[word::PROGRAM_STATE] & 0x0001 != 0
218    }
219
220    pub fn is_pcb_connected(&self) -> bool {
221        self.words[word::PROGRAM_STATE] & 0x0100 == 0
222    }
223
224    pub fn vericomm_clock_continues(&self) -> bool {
225        self.words[word::CLOCK_STATE] & 0x0001 == 0
226    }
227
228    fn has_state_flag(&self, mask: u16) -> bool {
229        self.words[word::ABILITY_FLAGS] & mask != 0
230    }
231}
232
233#[cfg(test)]
234mod tests {
235    use super::Config;
236
237    #[test]
238    fn mode_and_channel_share_the_same_word_without_clobbering_each_other() {
239        let mut config = Config::new();
240        config.set_mode_selector(0x12);
241        config.set_veri_sdk_channel_selector(0x34);
242        assert_eq!(config.mode_selector(), 0x12);
243        assert_eq!(config.veri_sdk_channel_selector(), 0x34);
244        assert_eq!(config.words()[3], 0x1234);
245    }
246
247    #[test]
248    fn fifo_size_aliases_are_word_based() {
249        let mut words = [0u16; Config::WORD_COUNT];
250        words[33] = 512;
251        let config = Config::from_words(words);
252        assert_eq!(config.fifo_size(), 512);
253        assert_eq!(config.fifo_size_words(), 512);
254    }
255
256    #[test]
257    fn licence_and_security_key_share_the_same_backing_word() {
258        let mut config = Config::new();
259        config.set_licence_key(0x55aa);
260        assert_eq!(config.licence_key(), 0x55aa);
261        assert_eq!(config.security_key(), 0x55aa);
262    }
263}