1use crate::device::PoKeysDevice;
13use crate::error::{PoKeysError, Result};
14use serde::{Deserialize, Serialize};
15
16pub const MAX_ENCODERS: usize = 25;
18
19pub const MAX_FAST_ENCODERS: usize = 3;
21
22pub const ULTRA_FAST_ENCODER_INDEX: u8 = 25;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct EncoderOptions {
28 pub enabled: bool,
30 pub sampling_4x: bool,
32 pub sampling_2x: bool,
34 pub direct_key_mapping_a: bool,
36 pub macro_mapping_a: bool,
38 pub direct_key_mapping_b: bool,
40 pub macro_mapping_b: bool,
42}
43
44impl Default for EncoderOptions {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl EncoderOptions {
51 pub fn new() -> Self {
53 Self {
54 enabled: false,
55 sampling_4x: false,
56 sampling_2x: false,
57 direct_key_mapping_a: false,
58 macro_mapping_a: false,
59 direct_key_mapping_b: false,
60 macro_mapping_b: false,
61 }
62 }
63
64 pub fn with_4x_sampling() -> Self {
66 Self {
67 enabled: true,
68 sampling_4x: true,
69 sampling_2x: false,
70 direct_key_mapping_a: false,
71 macro_mapping_a: false,
72 direct_key_mapping_b: false,
73 macro_mapping_b: false,
74 }
75 }
76
77 pub fn with_2x_sampling() -> Self {
79 Self {
80 enabled: true,
81 sampling_4x: false,
82 sampling_2x: true,
83 direct_key_mapping_a: false,
84 macro_mapping_a: false,
85 direct_key_mapping_b: false,
86 macro_mapping_b: false,
87 }
88 }
89
90 pub fn to_byte(&self) -> u8 {
93 let mut options = 0u8;
94 if self.enabled {
95 options |= 1 << 0;
96 }
97 if self.sampling_4x {
98 options |= 1 << 1;
99 }
100 if self.sampling_2x {
101 options |= 1 << 2;
102 }
103 if self.direct_key_mapping_a {
105 options |= 1 << 4;
106 }
107 if self.macro_mapping_a {
108 options |= 1 << 5;
109 }
110 if self.direct_key_mapping_b {
111 options |= 1 << 6;
112 }
113 if self.macro_mapping_b {
114 options |= 1 << 7;
115 }
116 options
117 }
118
119 pub fn from_byte(byte: u8) -> Self {
121 Self {
122 enabled: (byte & (1 << 0)) != 0,
123 sampling_4x: (byte & (1 << 1)) != 0,
124 sampling_2x: (byte & (1 << 2)) != 0,
125 direct_key_mapping_a: (byte & (1 << 4)) != 0,
126 macro_mapping_a: (byte & (1 << 5)) != 0,
127 direct_key_mapping_b: (byte & (1 << 6)) != 0,
128 macro_mapping_b: (byte & (1 << 7)) != 0,
129 }
130 }
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
140pub enum FastEncoderConfiguration {
141 Disabled,
143 Config1,
146 Config2,
149}
150
151impl FastEncoderConfiguration {
152 pub fn to_byte(self) -> u8 {
156 match self {
157 FastEncoderConfiguration::Disabled => 0x00,
158 FastEncoderConfiguration::Config1 => 0x01,
159 FastEncoderConfiguration::Config2 => 0x10,
160 }
161 }
162
163 pub fn from_byte(byte: u8) -> Self {
166 match byte {
167 0x01 => FastEncoderConfiguration::Config1,
168 0x10 => FastEncoderConfiguration::Config2,
169 _ => FastEncoderConfiguration::Disabled,
170 }
171 }
172}
173
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
189pub struct FastEncoderOptions {
190 pub disable_4x_sampling: bool,
192 pub invert_direction_1: bool,
194 pub invert_direction_2: bool,
196 pub invert_direction_3: bool,
198}
199
200pub(crate) const FAST_ENCODER_DISABLE_4X_SAMPLING: u8 = 0x10;
202pub(crate) const FAST_ENCODER_INVERT_E1: u8 = 0x20;
204pub(crate) const FAST_ENCODER_INVERT_E2: u8 = 0x40;
206pub(crate) const FAST_ENCODER_INVERT_E3: u8 = 0x80;
208
209impl FastEncoderOptions {
210 pub fn to_byte(self) -> u8 {
212 let mut b = 0u8;
213 if self.disable_4x_sampling {
214 b |= FAST_ENCODER_DISABLE_4X_SAMPLING;
215 }
216 if self.invert_direction_1 {
217 b |= FAST_ENCODER_INVERT_E1;
218 }
219 if self.invert_direction_2 {
220 b |= FAST_ENCODER_INVERT_E2;
221 }
222 if self.invert_direction_3 {
223 b |= FAST_ENCODER_INVERT_E3;
224 }
225 b
226 }
227
228 pub fn from_byte(byte: u8) -> Self {
230 Self {
231 disable_4x_sampling: (byte & FAST_ENCODER_DISABLE_4X_SAMPLING) != 0,
232 invert_direction_1: (byte & FAST_ENCODER_INVERT_E1) != 0,
233 invert_direction_2: (byte & FAST_ENCODER_INVERT_E2) != 0,
234 invert_direction_3: (byte & FAST_ENCODER_INVERT_E3) != 0,
235 }
236 }
237}
238
239#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
251pub struct UltraFastEncoderOptions {
252 pub invert_direction: bool,
254 pub signal_mode_direction_clock: bool,
257 pub enable_4x_sampling: bool,
259}
260
261pub(crate) const UFENC_INVERT_DIRECTION: u8 = 0x01;
263pub(crate) const UFENC_SIGNAL_MODE: u8 = 0x02;
265pub(crate) const UFENC_ENABLE_4X_SAMPLING: u8 = 0x04;
267
268impl UltraFastEncoderOptions {
269 pub fn to_byte(self) -> u8 {
271 let mut b = 0u8;
272 if self.invert_direction {
273 b |= UFENC_INVERT_DIRECTION;
274 }
275 if self.signal_mode_direction_clock {
276 b |= UFENC_SIGNAL_MODE;
277 }
278 if self.enable_4x_sampling {
279 b |= UFENC_ENABLE_4X_SAMPLING;
280 }
281 b
282 }
283
284 pub fn from_byte(byte: u8) -> Self {
286 Self {
287 invert_direction: (byte & UFENC_INVERT_DIRECTION) != 0,
288 signal_mode_direction_clock: (byte & UFENC_SIGNAL_MODE) != 0,
289 enable_4x_sampling: (byte & UFENC_ENABLE_4X_SAMPLING) != 0,
290 }
291 }
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
296pub struct EncoderData {
297 pub encoder_value: i32,
299 pub encoder_options: u8,
301 pub channel_a_pin: u8,
303 pub channel_b_pin: u8,
305 pub dir_a_key_code: u8,
307 pub dir_a_key_modifier: u8,
309 pub dir_b_key_code: u8,
311 pub dir_b_key_modifier: u8,
313}
314
315impl EncoderData {
316 pub fn new() -> Self {
318 Self {
319 encoder_value: 0,
320 encoder_options: 0,
321 channel_a_pin: 0,
322 channel_b_pin: 0,
323 dir_a_key_code: 0,
324 dir_a_key_modifier: 0,
325 dir_b_key_code: 0,
326 dir_b_key_modifier: 0,
327 }
328 }
329
330 pub fn get_options(&self) -> EncoderOptions {
332 EncoderOptions::from_byte(self.encoder_options)
333 }
334
335 pub fn set_options(&mut self, options: EncoderOptions) {
337 self.encoder_options = options.to_byte();
338 }
339
340 pub fn is_enabled(&self) -> bool {
342 (self.encoder_options & 1) != 0
343 }
344
345 pub fn is_4x_sampling(&self) -> bool {
347 (self.encoder_options & (1 << 1)) != 0
348 }
349
350 pub fn is_2x_sampling(&self) -> bool {
352 (self.encoder_options & (1 << 2)) != 0
353 }
354
355 pub fn sampling_mode_str(&self) -> &'static str {
357 if self.is_4x_sampling() {
358 "4x (both edges)"
359 } else if self.is_2x_sampling() {
360 "2x (A edges only)"
361 } else {
362 "1x (disabled)"
363 }
364 }
365}
366
367impl Default for EncoderData {
368 fn default() -> Self {
369 Self::new()
370 }
371}
372
373impl PoKeysDevice {
374 pub fn configure_encoder(
377 &mut self,
378 encoder_id: u8,
379 channel_a_pin: u8,
380 channel_b_pin: u8,
381 options: EncoderOptions,
382 ) -> Result<()> {
383 if encoder_id as usize >= self.encoders.len() {
384 return Err(PoKeysError::Parameter(format!(
385 "Invalid encoder ID: {}",
386 encoder_id
387 )));
388 }
389
390 let protocol_pin_a = if channel_a_pin > 0 {
393 channel_a_pin - 1
394 } else {
395 0
396 };
397 let protocol_pin_b = if channel_b_pin > 0 {
398 channel_b_pin - 1
399 } else {
400 0
401 };
402
403 let encoder = &mut self.encoders[encoder_id as usize];
404 encoder.channel_a_pin = protocol_pin_a; encoder.channel_b_pin = protocol_pin_b; encoder.set_options(options);
407
408 log::debug!(
409 "Configuring encoder {} with pins A={}, B={} (1-based: A={}, B={}), options={:08b} using protocol 0x11",
410 encoder_id,
411 protocol_pin_a,
412 protocol_pin_b,
413 channel_a_pin,
414 channel_b_pin,
415 options.to_byte()
416 );
417
418 let response = self.send_request(
421 0x11, encoder_id, options.to_byte(), protocol_pin_a, protocol_pin_b, )?;
427
428 log::debug!("Encoder configuration response: {:?}", &response[0..8]);
429
430 if response.len() > 2 {
432 match response[2] {
433 0 => {
435 log::debug!("Encoder {} configuration successful", encoder_id);
436 }
437 1 => {
438 return Err(PoKeysError::Protocol(format!(
439 "Encoder {} configuration failed: encoder ID out of range or configuration locked",
440 encoder_id
441 )));
442 }
443 other => {
444 return Err(PoKeysError::Protocol(format!(
445 "Encoder {} configuration failed with status: {} (0x{:02X})",
446 encoder_id, other, other
447 )));
448 }
449 }
450 }
451
452 Ok(())
453 }
454
455 pub fn read_encoder_settings(&mut self, encoder_id: u8) -> Result<EncoderData> {
457 if encoder_id >= MAX_ENCODERS as u8 {
458 return Err(PoKeysError::Parameter(format!(
459 "Encoder ID {} exceeds maximum {}",
460 encoder_id, MAX_ENCODERS
461 )));
462 }
463
464 log::debug!(
465 "Reading encoder {} settings using protocol 0x16",
466 encoder_id
467 );
468
469 let response = self.send_request(
472 0x16, encoder_id, 0, 0, 0, )?;
478
479 log::debug!("Read encoder settings response: {:?}", &response[0..8]);
480
481 if response.len() >= 6 {
484 let returned_encoder_id = response[2]; let options_byte = response[3]; let channel_a_pin = response[4]; let channel_b_pin = response[5]; if returned_encoder_id != encoder_id {
490 log::warn!(
491 "Response encoder ID {} doesn't match requested {}",
492 returned_encoder_id,
493 encoder_id
494 );
495 }
496
497 let display_pin_a = channel_a_pin + 1;
499 let display_pin_b = channel_b_pin + 1;
500
501 let settings = EncoderData {
502 channel_a_pin: display_pin_a, channel_b_pin: display_pin_b, encoder_options: options_byte,
505 ..Default::default()
506 };
507
508 log::debug!(
509 "Encoder {} settings: A={}, B={} (protocol: A={}, B={}), options={:08b}",
510 encoder_id,
511 display_pin_a,
512 display_pin_b,
513 channel_a_pin,
514 channel_b_pin,
515 options_byte
516 );
517
518 Ok(settings)
519 } else {
520 Err(PoKeysError::Protocol(
521 "Invalid encoder settings response length".to_string(),
522 ))
523 }
524 }
525
526 pub fn enable_encoder(&mut self, encoder_id: u8, enable: bool) -> Result<()> {
528 if encoder_id as usize >= self.encoders.len() {
529 return Err(PoKeysError::Parameter(format!(
530 "Invalid encoder ID: {}",
531 encoder_id
532 )));
533 }
534
535 let (channel_a_pin, channel_b_pin) = {
537 let encoder = &self.encoders[encoder_id as usize];
538 (encoder.channel_a_pin, encoder.channel_b_pin)
539 };
540
541 let mut options = {
543 let encoder = &self.encoders[encoder_id as usize];
544 encoder.get_options()
545 };
546 options.enabled = enable;
547
548 self.configure_encoder(encoder_id, channel_a_pin, channel_b_pin, options)
549 }
550
551 pub fn set_encoder_sampling(
553 &mut self,
554 encoder_id: u8,
555 sampling_4x: bool,
556 sampling_2x: bool,
557 ) -> Result<()> {
558 if encoder_id as usize >= self.encoders.len() {
559 return Err(PoKeysError::Parameter(format!(
560 "Invalid encoder ID: {}",
561 encoder_id
562 )));
563 }
564
565 if sampling_4x && sampling_2x {
567 return Err(PoKeysError::Parameter(
568 "Cannot enable both 4x and 2x sampling simultaneously".to_string(),
569 ));
570 }
571
572 let (channel_a_pin, channel_b_pin) = {
574 let encoder = &self.encoders[encoder_id as usize];
575 (encoder.channel_a_pin, encoder.channel_b_pin)
576 };
577
578 let mut options = {
580 let encoder = &self.encoders[encoder_id as usize];
581 encoder.get_options()
582 };
583 options.sampling_4x = sampling_4x;
584 options.sampling_2x = sampling_2x;
585
586 self.configure_encoder(encoder_id, channel_a_pin, channel_b_pin, options)
587 }
588
589 pub fn configure_encoder_key_mapping_a(
592 &mut self,
593 encoder_id: u8,
594 key_code: u8,
595 key_modifier: u8,
596 ) -> Result<()> {
597 if encoder_id as usize >= self.encoders.len() {
598 return Err(PoKeysError::Parameter(format!(
599 "Invalid encoder ID: {}",
600 encoder_id
601 )));
602 }
603
604 let encoder = &mut self.encoders[encoder_id as usize];
605 encoder.dir_a_key_code = key_code;
606 encoder.dir_a_key_modifier = key_modifier;
607
608 let response = self.send_request(
610 0x12, encoder_id, 0, key_code, key_modifier, )?;
616
617 if response.len() > 3 && response[3] != 0 {
619 return Err(PoKeysError::Protocol(format!(
620 "Encoder key mapping A failed for encoder {}: status {}",
621 encoder_id, response[3]
622 )));
623 }
624
625 Ok(())
626 }
627
628 pub fn configure_encoder_key_mapping_b(
631 &mut self,
632 encoder_id: u8,
633 key_code: u8,
634 key_modifier: u8,
635 ) -> Result<()> {
636 if encoder_id as usize >= self.encoders.len() {
637 return Err(PoKeysError::Parameter(format!(
638 "Invalid encoder ID: {}",
639 encoder_id
640 )));
641 }
642
643 let encoder = &mut self.encoders[encoder_id as usize];
644 encoder.dir_b_key_code = key_code;
645 encoder.dir_b_key_modifier = key_modifier;
646
647 let response = self.send_request(
649 0x13, encoder_id, 0, key_code, key_modifier, )?;
655
656 if response.len() > 3 && response[3] != 0 {
658 return Err(PoKeysError::Protocol(format!(
659 "Encoder key mapping B failed for encoder {}: status {}",
660 encoder_id, response[3]
661 )));
662 }
663
664 Ok(())
665 }
666
667 pub fn read_encoder_key_mapping_a(&mut self, encoder_id: u8) -> Result<(u8, u8)> {
670 if encoder_id as usize >= self.encoders.len() {
671 return Err(PoKeysError::Parameter(format!(
672 "Invalid encoder ID: {}",
673 encoder_id
674 )));
675 }
676
677 let response = self.send_request(
678 0x17, encoder_id, 0, 0, 0, )?;
684
685 if response.len() < 8 {
686 return Err(PoKeysError::Protocol("Invalid response length".to_string()));
687 }
688
689 let key_code = response[5];
691 let key_modifier = response[6];
692
693 self.encoders[encoder_id as usize].dir_a_key_code = key_code;
695 self.encoders[encoder_id as usize].dir_a_key_modifier = key_modifier;
696
697 Ok((key_code, key_modifier))
698 }
699
700 pub fn read_encoder_key_mapping_b(&mut self, encoder_id: u8) -> Result<(u8, u8)> {
703 if encoder_id as usize >= self.encoders.len() {
704 return Err(PoKeysError::Parameter(format!(
705 "Invalid encoder ID: {}",
706 encoder_id
707 )));
708 }
709
710 let response = self.send_request(
711 0x18, encoder_id, 0, 0, 0, )?;
717
718 if response.len() < 8 {
719 return Err(PoKeysError::Protocol("Invalid response length".to_string()));
720 }
721
722 let key_code = response[5];
724 let key_modifier = response[6];
725
726 self.encoders[encoder_id as usize].dir_b_key_code = key_code;
728 self.encoders[encoder_id as usize].dir_b_key_modifier = key_modifier;
729
730 Ok((key_code, key_modifier))
731 }
732
733 pub fn read_encoder_raw_value(&mut self, encoder_id: u8) -> Result<i32> {
736 if encoder_id as usize >= self.encoders.len() {
737 return Err(PoKeysError::Parameter(format!(
738 "Invalid encoder ID: {}",
739 encoder_id
740 )));
741 }
742
743 let response = self.send_request(
744 0x19, encoder_id, 0, 0, 0, )?;
750
751 if response.len() < 8 {
752 return Err(PoKeysError::Protocol("Invalid response length".to_string()));
753 }
754
755 let raw_value = response[4] as i8 as i32; self.encoders[encoder_id as usize].encoder_value = raw_value;
761
762 Ok(raw_value)
763 }
764
765 pub fn reset_encoder_raw_value(&mut self, encoder_id: u8) -> Result<()> {
768 if encoder_id as usize >= self.encoders.len() {
769 return Err(PoKeysError::Parameter(format!(
770 "Invalid encoder ID: {}",
771 encoder_id
772 )));
773 }
774
775 let response = self.send_request(
776 0x1A, encoder_id, 0, 0, 0, )?;
782
783 if response.len() < 8 {
785 return Err(PoKeysError::Protocol("Invalid response length".to_string()));
786 }
787
788 self.encoders[encoder_id as usize].encoder_value = 0;
790
791 Ok(())
792 }
793
794 pub fn get_encoder_value(&mut self, encoder_id: u8) -> Result<i32> {
796 self.read_encoder_raw_value(encoder_id)
797 }
798
799 pub fn reset_encoder(&mut self, encoder_id: u8) -> Result<()> {
801 self.reset_encoder_raw_value(encoder_id)
802 }
803
804 pub fn read_encoder_long_values(&mut self, group: u8) -> Result<Vec<i32>> {
808 if group > 1 {
809 return Err(PoKeysError::Parameter(
810 "Group must be 0 (encoders 1-13) or 1 (encoders 14-26)".to_string(),
811 ));
812 }
813
814 let response = self.send_request(
815 0xCD, group, 0, 0, 0, )?;
821
822 if response.len() < 64 {
823 return Err(PoKeysError::Protocol(
824 "Invalid response length for bulk encoder read".to_string(),
825 ));
826 }
827
828 let mut values = Vec::new();
829
830 for i in 0..13 {
833 let byte_offset = 8 + (i * 4); if byte_offset + 3 < response.len() {
835 let value = i32::from_le_bytes([
836 response[byte_offset],
837 response[byte_offset + 1],
838 response[byte_offset + 2],
839 response[byte_offset + 3],
840 ]);
841 values.push(value);
842
843 let encoder_index = if group == 0 { i } else { 13 + i };
845 if encoder_index < self.encoders.len() {
846 self.encoders[encoder_index].encoder_value = value;
847 }
848 }
849 }
850
851 if group == 1 && response.len() >= 60 {
853 let ultra_fast_value = i32::from_le_bytes([
854 response[56], response[57], response[58], response[59], ]);
859 if self.encoders.len() > 25 {
861 self.encoders[25].encoder_value = ultra_fast_value;
862 }
863 }
864
865 log::debug!("Bulk read group {} returned {} values", group, values.len());
866 Ok(values)
867 }
868
869 pub fn set_encoder_long_values(&mut self, group: u8, values: &[i32]) -> Result<()> {
875 if group > 1 {
876 return Err(PoKeysError::Parameter(
877 "Group must be 0 (encoders 1-13) or 1 (encoders 14-26)".to_string(),
878 ));
879 }
880
881 let expected_count = if group == 0 { 13 } else { 12 }; if values.len() < expected_count {
883 return Err(PoKeysError::Parameter(format!(
884 "Need {} values for group {}",
885 expected_count, group
886 )));
887 }
888
889 let count = values.len().min(13);
893 let mut payload = [0u8; 52];
894 for (i, &value) in values.iter().take(count).enumerate() {
895 let offset = i * 4;
896 payload[offset..offset + 4].copy_from_slice(&value.to_le_bytes());
897 }
898
899 let _response = self.send_request_with_data(
900 0xCD,
901 group + 10, 0,
903 0,
904 0,
905 &payload[..count * 4],
906 )?;
907
908 let start_encoder = if group == 0 { 1 } else { 14 };
910 for (i, &value) in values.iter().enumerate() {
911 let encoder_index = start_encoder + i;
912 if encoder_index < self.encoders.len() {
913 self.encoders[encoder_index].encoder_value = value;
914 }
915 }
916
917 Ok(())
918 }
919
920 pub fn read_all_encoder_values(&mut self) -> Result<Vec<i32>> {
922 let mut all_values = Vec::new();
923
924 let group1_values = self.read_encoder_long_values(0)?;
926 all_values.extend(group1_values);
927
928 let group2_values = self.read_encoder_long_values(1)?;
930 all_values.extend(group2_values);
931
932 Ok(all_values)
933 }
934
935 pub fn configure_encoder_options_bulk(&mut self, options: &[u8]) -> Result<Vec<u8>> {
940 if options.len() != 25 {
941 return Err(PoKeysError::Parameter(
942 "Need exactly 25 encoder options".to_string(),
943 ));
944 }
945
946 let response = self.send_request_with_data(0xC4, 1, 0, 0, 0, options)?;
947
948 let mut returned_options = Vec::with_capacity(25);
950 if response.len() >= 33 {
951 for i in 0..25 {
952 returned_options.push(response[8 + i]);
953 if i < self.encoders.len() {
954 self.encoders[i].encoder_options = response[8 + i];
955 }
956 }
957 }
958
959 Ok(returned_options)
960 }
961
962 pub fn read_encoder_options_bulk(&mut self) -> Result<Vec<u8>> {
967 let response = self.send_request(0xC4, 0, 0, 0, 0)?;
968
969 let mut options = Vec::with_capacity(25);
970 if response.len() >= 33 {
971 for i in 0..25 {
972 options.push(response[8 + i]);
973 if i < self.encoders.len() {
974 self.encoders[i].encoder_options = response[8 + i];
975 }
976 }
977 }
978
979 Ok(options)
980 }
981
982 pub fn configure_fast_encoders(
992 &mut self,
993 config: FastEncoderConfiguration,
994 options: FastEncoderOptions,
995 ) -> Result<()> {
996 let config_byte = config.to_byte();
997 let options_byte = options.to_byte();
998
999 self.fast_encoders_configuration = config_byte;
1000 self.fast_encoders_options = options_byte;
1001
1002 let response = self.send_request(
1003 0xCE, config_byte, options_byte, 0, 0, )?;
1009
1010 if response.len() > 2 {
1012 let status = response[2];
1013 if status != 0 {
1014 return Err(PoKeysError::Protocol(format!(
1015 "Fast encoder configuration failed: status {}",
1016 status
1017 )));
1018 }
1019 }
1020
1021 Ok(())
1022 }
1023
1024 pub fn read_fast_encoder_values(&mut self) -> Result<[i32; 3]> {
1026 let values = self.read_encoder_long_values(0)?;
1028
1029 let mut fast_values = [0i32; 3];
1030 let copy_len = 3.min(values.len());
1031 fast_values[..copy_len].copy_from_slice(&values[..copy_len]);
1032
1033 Ok(fast_values)
1034 }
1035
1036 pub fn configure_ultra_fast_encoder(
1046 &mut self,
1047 enable: bool,
1048 options: UltraFastEncoderOptions,
1049 reset_on_index: bool,
1050 filter_delay: u32,
1051 ) -> Result<()> {
1052 let options_byte = options.to_byte();
1053
1054 self.ultra_fast_encoder_configuration = if enable { 1 } else { 0 };
1055 self.ultra_fast_encoder_options = options_byte;
1056 self.ultra_fast_encoder_filter = filter_delay;
1057
1058 let filter_bytes = filter_delay.to_le_bytes();
1065 let response = self.send_request_with_data(
1066 0x1C,
1067 if enable { 1 } else { 0 },
1068 options_byte,
1069 if reset_on_index { 1 } else { 0 },
1070 0,
1071 &filter_bytes,
1072 )?;
1073
1074 if response.len() > 2 {
1076 let status = response[2];
1077 if status != 0 {
1078 return Err(PoKeysError::Protocol(format!(
1079 "Ultra-fast encoder configuration failed: status {}",
1080 status
1081 )));
1082 }
1083 }
1084
1085 Ok(())
1086 }
1087
1088 pub fn read_ultra_fast_encoder_config(
1094 &mut self,
1095 ) -> Result<(bool, UltraFastEncoderOptions, u32)> {
1096 let response = self.send_request(0x1C, 0xFF, 0, 0, 0)?;
1097
1098 if response.len() < 12 {
1099 return Err(PoKeysError::Protocol("Invalid response length".to_string()));
1100 }
1101
1102 let enabled = response[2] != 0;
1104 let options = UltraFastEncoderOptions::from_byte(response[3]);
1105 let filter_delay =
1106 u32::from_le_bytes([response[8], response[9], response[10], response[11]]);
1107
1108 Ok((enabled, options, filter_delay))
1109 }
1110
1111 pub fn read_ultra_fast_encoder_value(&mut self) -> Result<i32> {
1113 let values = self.read_encoder_long_values(1)?;
1115
1116 if let Some(&value) = values.last() {
1118 Ok(value)
1119 } else {
1120 Err(PoKeysError::Protocol(
1121 "No ultra-fast encoder value in response".to_string(),
1122 ))
1123 }
1124 }
1125
1126 pub fn set_ultra_fast_encoder_value(&mut self, value: i32) -> Result<()> {
1128 let mut values = self.read_encoder_long_values(1)?;
1131
1132 if let Some(last) = values.last_mut() {
1134 *last = value;
1135 } else {
1136 return Err(PoKeysError::Protocol(
1137 "Cannot set ultra-fast encoder value".to_string(),
1138 ));
1139 }
1140
1141 self.set_encoder_long_values(1, &values)
1142 }
1143 #[allow(clippy::too_many_arguments)]
1145 pub fn configure_encoder_with_keys(
1146 &mut self,
1147 encoder_id: u8,
1148 channel_a_pin: u8,
1149 channel_b_pin: u8,
1150 sampling_4x: bool,
1151 sampling_2x: bool,
1152 dir_a_key_code: u8,
1153 dir_a_key_modifier: u8,
1154 dir_b_key_code: u8,
1155 dir_b_key_modifier: u8,
1156 ) -> Result<()> {
1157 let mut options = EncoderOptions::new();
1159 options.enabled = true;
1160 options.sampling_4x = sampling_4x;
1161 options.sampling_2x = sampling_2x;
1162 options.direct_key_mapping_a = true;
1163 options.direct_key_mapping_b = true;
1164
1165 self.configure_encoder(encoder_id, channel_a_pin, channel_b_pin, options)?;
1166
1167 self.configure_encoder_key_mapping_a(encoder_id, dir_a_key_code, dir_a_key_modifier)?;
1169 self.configure_encoder_key_mapping_b(encoder_id, dir_b_key_code, dir_b_key_modifier)?;
1170
1171 Ok(())
1172 }
1173
1174 pub fn get_encoder_sampling_mode(&self, encoder_id: u8) -> Result<String> {
1176 if encoder_id as usize >= self.encoders.len() {
1177 return Err(PoKeysError::Parameter(format!(
1178 "Invalid encoder ID: {}",
1179 encoder_id
1180 )));
1181 }
1182
1183 let encoder = &self.encoders[encoder_id as usize];
1184 Ok(encoder.sampling_mode_str().to_string())
1185 }
1186
1187 pub fn is_encoder_4x_sampling(&self, encoder_id: u8) -> Result<bool> {
1189 if encoder_id as usize >= self.encoders.len() {
1190 return Err(PoKeysError::Parameter(format!(
1191 "Invalid encoder ID: {}",
1192 encoder_id
1193 )));
1194 }
1195
1196 Ok(self.encoders[encoder_id as usize].is_4x_sampling())
1197 }
1198
1199 pub fn is_encoder_2x_sampling(&self, encoder_id: u8) -> Result<bool> {
1201 if encoder_id as usize >= self.encoders.len() {
1202 return Err(PoKeysError::Parameter(format!(
1203 "Invalid encoder ID: {}",
1204 encoder_id
1205 )));
1206 }
1207
1208 Ok(self.encoders[encoder_id as usize].is_2x_sampling())
1209 }
1210
1211 pub fn get_enabled_encoders(&self) -> Vec<u8> {
1213 self.encoders
1214 .iter()
1215 .enumerate()
1216 .filter_map(|(i, encoder)| {
1217 if encoder.is_enabled() {
1218 Some(i as u8)
1219 } else {
1220 None
1221 }
1222 })
1223 .collect()
1224 }
1225}
1226
1227#[cfg(test)]
1228mod tests {
1229 use super::*;
1230
1231 #[test]
1232 fn test_encoder_options_4x_sampling() {
1233 let options = EncoderOptions::with_4x_sampling();
1234 assert!(options.enabled);
1235 assert!(options.sampling_4x);
1236 assert!(!options.sampling_2x);
1237
1238 let byte = options.to_byte();
1239 assert_eq!(byte & 0b00000011, 0b00000011); let options_from_byte = EncoderOptions::from_byte(byte);
1242 assert!(options_from_byte.enabled);
1243 assert!(options_from_byte.sampling_4x);
1244 assert!(!options_from_byte.sampling_2x);
1245 }
1246
1247 #[test]
1248 fn test_encoder_options_2x_sampling() {
1249 let options = EncoderOptions::with_2x_sampling();
1250 assert!(options.enabled);
1251 assert!(!options.sampling_4x);
1252 assert!(options.sampling_2x);
1253
1254 let byte = options.to_byte();
1255 assert_eq!(byte & 0b00000111, 0b00000101); let options_from_byte = EncoderOptions::from_byte(byte);
1258 assert!(options_from_byte.enabled);
1259 assert!(!options_from_byte.sampling_4x);
1260 assert!(options_from_byte.sampling_2x);
1261 }
1262
1263 #[test]
1264 fn test_encoder_options_key_mapping() {
1265 let mut options = EncoderOptions::new();
1266 options.enabled = true;
1267 options.direct_key_mapping_a = true;
1268 options.macro_mapping_b = true;
1269
1270 let byte = options.to_byte();
1271 assert_eq!(byte & 0b11110001, 0b10010001); let options_from_byte = EncoderOptions::from_byte(byte);
1274 assert!(options_from_byte.enabled);
1275 assert!(options_from_byte.direct_key_mapping_a);
1276 assert!(options_from_byte.macro_mapping_b);
1277 assert!(!options_from_byte.direct_key_mapping_b);
1278 assert!(!options_from_byte.macro_mapping_a);
1279 }
1280
1281 #[test]
1282 fn test_encoder_data_sampling_modes() {
1283 let mut encoder = EncoderData::new();
1284
1285 let options_4x = EncoderOptions::with_4x_sampling();
1287 encoder.set_options(options_4x);
1288 assert!(encoder.is_4x_sampling());
1289 assert!(!encoder.is_2x_sampling());
1290 assert_eq!(encoder.sampling_mode_str(), "4x (both edges)");
1291
1292 let options_2x = EncoderOptions::with_2x_sampling();
1294 encoder.set_options(options_2x);
1295 assert!(!encoder.is_4x_sampling());
1296 assert!(encoder.is_2x_sampling());
1297 assert_eq!(encoder.sampling_mode_str(), "2x (A edges only)");
1298
1299 let options_disabled = EncoderOptions::new();
1301 encoder.set_options(options_disabled);
1302 assert!(!encoder.is_4x_sampling());
1303 assert!(!encoder.is_2x_sampling());
1304 assert_eq!(encoder.sampling_mode_str(), "1x (disabled)");
1305 }
1306
1307 #[test]
1308 fn test_encoder_constants() {
1309 assert_eq!(MAX_ENCODERS, 25);
1310 assert_eq!(MAX_FAST_ENCODERS, 3);
1311 assert_eq!(ULTRA_FAST_ENCODER_INDEX, 25);
1312 }
1313
1314 #[test]
1321 fn test_fast_encoder_configuration_to_byte() {
1322 assert_eq!(FastEncoderConfiguration::Disabled.to_byte(), 0x00);
1323 assert_eq!(FastEncoderConfiguration::Config1.to_byte(), 0x01);
1324 assert_eq!(FastEncoderConfiguration::Config2.to_byte(), 0x10);
1325 }
1326
1327 #[test]
1328 fn test_fast_encoder_configuration_round_trip() {
1329 for cfg in [
1330 FastEncoderConfiguration::Disabled,
1331 FastEncoderConfiguration::Config1,
1332 FastEncoderConfiguration::Config2,
1333 ] {
1334 assert_eq!(FastEncoderConfiguration::from_byte(cfg.to_byte()), cfg);
1335 }
1336 }
1337
1338 #[test]
1339 fn test_fast_encoder_options_bit_masks() {
1340 assert_eq!(
1342 FastEncoderOptions {
1343 disable_4x_sampling: true,
1344 ..Default::default()
1345 }
1346 .to_byte(),
1347 0x10
1348 );
1349 assert_eq!(
1350 FastEncoderOptions {
1351 invert_direction_1: true,
1352 ..Default::default()
1353 }
1354 .to_byte(),
1355 0x20
1356 );
1357 assert_eq!(
1358 FastEncoderOptions {
1359 invert_direction_2: true,
1360 ..Default::default()
1361 }
1362 .to_byte(),
1363 0x40
1364 );
1365 assert_eq!(
1366 FastEncoderOptions {
1367 invert_direction_3: true,
1368 ..Default::default()
1369 }
1370 .to_byte(),
1371 0x80
1372 );
1373 }
1374
1375 #[test]
1376 fn test_fast_encoder_options_combined() {
1377 let all = FastEncoderOptions {
1379 disable_4x_sampling: true,
1380 invert_direction_1: true,
1381 invert_direction_2: true,
1382 invert_direction_3: true,
1383 };
1384 assert_eq!(all.to_byte(), 0xF0);
1385 }
1386
1387 #[test]
1388 fn test_fast_encoder_options_round_trip() {
1389 let o = FastEncoderOptions {
1390 disable_4x_sampling: false,
1391 invert_direction_1: true,
1392 invert_direction_2: false,
1393 invert_direction_3: true,
1394 };
1395 assert_eq!(FastEncoderOptions::from_byte(o.to_byte()), o);
1396 }
1397
1398 #[test]
1399 fn test_fast_encoder_options_ignores_reserved_low_nibble() {
1400 let decoded = FastEncoderOptions::from_byte(0x0F);
1402 assert_eq!(decoded, FastEncoderOptions::default());
1403 }
1404
1405 #[test]
1411 fn test_ultra_fast_encoder_options_bit_masks() {
1412 assert_eq!(
1413 UltraFastEncoderOptions {
1414 invert_direction: true,
1415 ..Default::default()
1416 }
1417 .to_byte(),
1418 0x01
1419 );
1420 assert_eq!(
1421 UltraFastEncoderOptions {
1422 signal_mode_direction_clock: true,
1423 ..Default::default()
1424 }
1425 .to_byte(),
1426 0x02
1427 );
1428 assert_eq!(
1429 UltraFastEncoderOptions {
1430 enable_4x_sampling: true,
1431 ..Default::default()
1432 }
1433 .to_byte(),
1434 0x04
1435 );
1436 }
1437
1438 #[test]
1439 fn test_ultra_fast_encoder_options_combined() {
1440 let all = UltraFastEncoderOptions {
1442 invert_direction: true,
1443 signal_mode_direction_clock: true,
1444 enable_4x_sampling: true,
1445 };
1446 assert_eq!(all.to_byte(), 0x07);
1447 }
1448
1449 #[test]
1450 fn test_ultra_fast_encoder_options_round_trip() {
1451 let o = UltraFastEncoderOptions {
1452 invert_direction: true,
1453 signal_mode_direction_clock: false,
1454 enable_4x_sampling: true,
1455 };
1456 assert_eq!(UltraFastEncoderOptions::from_byte(o.to_byte()), o);
1457 }
1458
1459 #[test]
1460 fn test_ultra_fast_encoder_options_ignores_reserved_high_bits() {
1461 let decoded = UltraFastEncoderOptions::from_byte(0xF8);
1463 assert_eq!(decoded, UltraFastEncoderOptions::default());
1464 }
1465}