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::info!(
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::info!("Encoder configuration response: {:?}", &response[0..8]);
429
430 if response.len() > 2 {
432 match response[2] {
433 0 => {
435 log::info!("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::info!(
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::info!("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::info!(
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::info!("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<()> {
873 if group > 1 {
874 return Err(PoKeysError::Parameter(
875 "Group must be 0 (encoders 1-13) or 1 (encoders 14-26)".to_string(),
876 ));
877 }
878
879 let expected_count = if group == 0 { 13 } else { 12 }; if values.len() < expected_count {
881 return Err(PoKeysError::Parameter(format!(
882 "Need {} values for group {}",
883 expected_count, group
884 )));
885 }
886
887 let mut request = vec![0u8; 64];
889 request[2] = 0xCD; request[3] = group + 10; request[7] = self.get_next_request_id(); for (i, &value) in values.iter().enumerate() {
895 let byte_offset = 9 + (i * 4);
896 if byte_offset + 3 < request.len() {
897 let bytes = value.to_le_bytes();
898 request[byte_offset] = bytes[0];
899 request[byte_offset + 1] = bytes[1];
900 request[byte_offset + 2] = bytes[2];
901 request[byte_offset + 3] = bytes[3];
902 }
903 }
904
905 let _response = self.send_raw_request(&request)?;
906
907 let start_encoder = if group == 0 { 1 } else { 14 };
909 for (i, &value) in values.iter().enumerate() {
910 let encoder_index = start_encoder + i;
911 if encoder_index < self.encoders.len() {
912 self.encoders[encoder_index].encoder_value = value;
913 }
914 }
915
916 Ok(())
917 }
918
919 pub fn read_all_encoder_values(&mut self) -> Result<Vec<i32>> {
921 let mut all_values = Vec::new();
922
923 let group1_values = self.read_encoder_long_values(0)?;
925 all_values.extend(group1_values);
926
927 let group2_values = self.read_encoder_long_values(1)?;
929 all_values.extend(group2_values);
930
931 Ok(all_values)
932 }
933
934 pub fn configure_encoder_options_bulk(&mut self, options: &[u8]) -> Result<Vec<u8>> {
937 if options.len() != 25 {
938 return Err(PoKeysError::Parameter(
939 "Need exactly 25 encoder options".to_string(),
940 ));
941 }
942
943 let mut request = vec![0u8; 64];
944 request[2] = 0xC4; request[3] = 1; request[7] = self.get_next_request_id(); for (i, &option) in options.iter().enumerate() {
950 request[9 + i] = option;
951 }
952
953 let response = self.send_raw_request(&request)?;
954
955 let mut returned_options = Vec::new();
957 if response.len() >= 34 {
958 for i in 0..25 {
959 returned_options.push(response[9 + i]);
960 if i < self.encoders.len() {
962 self.encoders[i].encoder_options = response[9 + i];
963 }
964 }
965 }
966
967 Ok(returned_options)
968 }
969
970 pub fn read_encoder_options_bulk(&mut self) -> Result<Vec<u8>> {
973 let response = self.send_request(
974 0xC4, 0, 0, 0, 0, )?;
980
981 let mut options = Vec::new();
982 if response.len() >= 34 {
983 for i in 0..25 {
984 options.push(response[9 + i]);
985 if i < self.encoders.len() {
987 self.encoders[i].encoder_options = response[9 + i];
988 }
989 }
990 }
991
992 Ok(options)
993 }
994
995 pub fn configure_fast_encoders(
1005 &mut self,
1006 config: FastEncoderConfiguration,
1007 options: FastEncoderOptions,
1008 ) -> Result<()> {
1009 let config_byte = config.to_byte();
1010 let options_byte = options.to_byte();
1011
1012 self.fast_encoders_configuration = config_byte;
1013 self.fast_encoders_options = options_byte;
1014
1015 let response = self.send_request(
1016 0xCE, config_byte, options_byte, 0, 0, )?;
1022
1023 if response.len() > 2 {
1025 let status = response[2];
1026 if status != 0 {
1027 return Err(PoKeysError::Protocol(format!(
1028 "Fast encoder configuration failed: status {}",
1029 status
1030 )));
1031 }
1032 }
1033
1034 Ok(())
1035 }
1036
1037 pub fn read_fast_encoder_values(&mut self) -> Result<[i32; 3]> {
1039 let values = self.read_encoder_long_values(0)?;
1041
1042 let mut fast_values = [0i32; 3];
1043 let copy_len = 3.min(values.len());
1044 fast_values[..copy_len].copy_from_slice(&values[..copy_len]);
1045
1046 Ok(fast_values)
1047 }
1048
1049 pub fn configure_ultra_fast_encoder(
1059 &mut self,
1060 enable: bool,
1061 options: UltraFastEncoderOptions,
1062 reset_on_index: bool,
1063 filter_delay: u32,
1064 ) -> Result<()> {
1065 let options_byte = options.to_byte();
1066
1067 self.ultra_fast_encoder_configuration = if enable { 1 } else { 0 };
1068 self.ultra_fast_encoder_options = options_byte;
1069 self.ultra_fast_encoder_filter = filter_delay;
1070
1071 let filter_bytes = filter_delay.to_le_bytes();
1078 let response = self.send_request_with_data(
1079 0x1C,
1080 if enable { 1 } else { 0 },
1081 options_byte,
1082 if reset_on_index { 1 } else { 0 },
1083 0,
1084 &filter_bytes,
1085 )?;
1086
1087 if response.len() > 2 {
1089 let status = response[2];
1090 if status != 0 {
1091 return Err(PoKeysError::Protocol(format!(
1092 "Ultra-fast encoder configuration failed: status {}",
1093 status
1094 )));
1095 }
1096 }
1097
1098 Ok(())
1099 }
1100
1101 pub fn read_ultra_fast_encoder_config(
1107 &mut self,
1108 ) -> Result<(bool, UltraFastEncoderOptions, u32)> {
1109 let response = self.send_request(0x1C, 0xFF, 0, 0, 0)?;
1110
1111 if response.len() < 12 {
1112 return Err(PoKeysError::Protocol("Invalid response length".to_string()));
1113 }
1114
1115 let enabled = response[2] != 0;
1117 let options = UltraFastEncoderOptions::from_byte(response[3]);
1118 let filter_delay =
1119 u32::from_le_bytes([response[8], response[9], response[10], response[11]]);
1120
1121 Ok((enabled, options, filter_delay))
1122 }
1123
1124 pub fn read_ultra_fast_encoder_value(&mut self) -> Result<i32> {
1126 let values = self.read_encoder_long_values(1)?;
1128
1129 if let Some(&value) = values.last() {
1131 Ok(value)
1132 } else {
1133 Err(PoKeysError::Protocol(
1134 "No ultra-fast encoder value in response".to_string(),
1135 ))
1136 }
1137 }
1138
1139 pub fn set_ultra_fast_encoder_value(&mut self, value: i32) -> Result<()> {
1141 let mut values = self.read_encoder_long_values(1)?;
1144
1145 if let Some(last) = values.last_mut() {
1147 *last = value;
1148 } else {
1149 return Err(PoKeysError::Protocol(
1150 "Cannot set ultra-fast encoder value".to_string(),
1151 ));
1152 }
1153
1154 self.set_encoder_long_values(1, &values)
1155 }
1156 #[allow(clippy::too_many_arguments)]
1158 pub fn configure_encoder_with_keys(
1159 &mut self,
1160 encoder_id: u8,
1161 channel_a_pin: u8,
1162 channel_b_pin: u8,
1163 sampling_4x: bool,
1164 sampling_2x: bool,
1165 dir_a_key_code: u8,
1166 dir_a_key_modifier: u8,
1167 dir_b_key_code: u8,
1168 dir_b_key_modifier: u8,
1169 ) -> Result<()> {
1170 let mut options = EncoderOptions::new();
1172 options.enabled = true;
1173 options.sampling_4x = sampling_4x;
1174 options.sampling_2x = sampling_2x;
1175 options.direct_key_mapping_a = true;
1176 options.direct_key_mapping_b = true;
1177
1178 self.configure_encoder(encoder_id, channel_a_pin, channel_b_pin, options)?;
1179
1180 self.configure_encoder_key_mapping_a(encoder_id, dir_a_key_code, dir_a_key_modifier)?;
1182 self.configure_encoder_key_mapping_b(encoder_id, dir_b_key_code, dir_b_key_modifier)?;
1183
1184 Ok(())
1185 }
1186
1187 pub fn get_encoder_sampling_mode(&self, encoder_id: u8) -> Result<String> {
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 let encoder = &self.encoders[encoder_id as usize];
1197 Ok(encoder.sampling_mode_str().to_string())
1198 }
1199
1200 pub fn is_encoder_4x_sampling(&self, encoder_id: u8) -> Result<bool> {
1202 if encoder_id as usize >= self.encoders.len() {
1203 return Err(PoKeysError::Parameter(format!(
1204 "Invalid encoder ID: {}",
1205 encoder_id
1206 )));
1207 }
1208
1209 Ok(self.encoders[encoder_id as usize].is_4x_sampling())
1210 }
1211
1212 pub fn is_encoder_2x_sampling(&self, encoder_id: u8) -> Result<bool> {
1214 if encoder_id as usize >= self.encoders.len() {
1215 return Err(PoKeysError::Parameter(format!(
1216 "Invalid encoder ID: {}",
1217 encoder_id
1218 )));
1219 }
1220
1221 Ok(self.encoders[encoder_id as usize].is_2x_sampling())
1222 }
1223
1224 pub fn get_enabled_encoders(&self) -> Vec<u8> {
1226 self.encoders
1227 .iter()
1228 .enumerate()
1229 .filter_map(|(i, encoder)| {
1230 if encoder.is_enabled() {
1231 Some(i as u8)
1232 } else {
1233 None
1234 }
1235 })
1236 .collect()
1237 }
1238
1239 fn get_next_request_id(&mut self) -> u8 {
1241 static mut REQUEST_ID: u8 = 0;
1244 unsafe {
1245 REQUEST_ID = REQUEST_ID.wrapping_add(1);
1246 REQUEST_ID
1247 }
1248 }
1249
1250 fn send_raw_request(&mut self, request: &[u8]) -> Result<Vec<u8>> {
1252 if request.len() >= 8 {
1255 let response_array =
1256 self.send_request(request[2], request[3], request[4], request[5], request[6])?;
1257 Ok(response_array.to_vec())
1258 } else {
1259 Err(PoKeysError::Protocol("Invalid request format".to_string()))
1260 }
1261 }
1262}
1263
1264#[cfg(test)]
1265mod tests {
1266 use super::*;
1267
1268 #[test]
1269 fn test_encoder_options_4x_sampling() {
1270 let options = EncoderOptions::with_4x_sampling();
1271 assert!(options.enabled);
1272 assert!(options.sampling_4x);
1273 assert!(!options.sampling_2x);
1274
1275 let byte = options.to_byte();
1276 assert_eq!(byte & 0b00000011, 0b00000011); let options_from_byte = EncoderOptions::from_byte(byte);
1279 assert!(options_from_byte.enabled);
1280 assert!(options_from_byte.sampling_4x);
1281 assert!(!options_from_byte.sampling_2x);
1282 }
1283
1284 #[test]
1285 fn test_encoder_options_2x_sampling() {
1286 let options = EncoderOptions::with_2x_sampling();
1287 assert!(options.enabled);
1288 assert!(!options.sampling_4x);
1289 assert!(options.sampling_2x);
1290
1291 let byte = options.to_byte();
1292 assert_eq!(byte & 0b00000111, 0b00000101); let options_from_byte = EncoderOptions::from_byte(byte);
1295 assert!(options_from_byte.enabled);
1296 assert!(!options_from_byte.sampling_4x);
1297 assert!(options_from_byte.sampling_2x);
1298 }
1299
1300 #[test]
1301 fn test_encoder_options_key_mapping() {
1302 let mut options = EncoderOptions::new();
1303 options.enabled = true;
1304 options.direct_key_mapping_a = true;
1305 options.macro_mapping_b = true;
1306
1307 let byte = options.to_byte();
1308 assert_eq!(byte & 0b11110001, 0b10010001); let options_from_byte = EncoderOptions::from_byte(byte);
1311 assert!(options_from_byte.enabled);
1312 assert!(options_from_byte.direct_key_mapping_a);
1313 assert!(options_from_byte.macro_mapping_b);
1314 assert!(!options_from_byte.direct_key_mapping_b);
1315 assert!(!options_from_byte.macro_mapping_a);
1316 }
1317
1318 #[test]
1319 fn test_encoder_data_sampling_modes() {
1320 let mut encoder = EncoderData::new();
1321
1322 let options_4x = EncoderOptions::with_4x_sampling();
1324 encoder.set_options(options_4x);
1325 assert!(encoder.is_4x_sampling());
1326 assert!(!encoder.is_2x_sampling());
1327 assert_eq!(encoder.sampling_mode_str(), "4x (both edges)");
1328
1329 let options_2x = EncoderOptions::with_2x_sampling();
1331 encoder.set_options(options_2x);
1332 assert!(!encoder.is_4x_sampling());
1333 assert!(encoder.is_2x_sampling());
1334 assert_eq!(encoder.sampling_mode_str(), "2x (A edges only)");
1335
1336 let options_disabled = EncoderOptions::new();
1338 encoder.set_options(options_disabled);
1339 assert!(!encoder.is_4x_sampling());
1340 assert!(!encoder.is_2x_sampling());
1341 assert_eq!(encoder.sampling_mode_str(), "1x (disabled)");
1342 }
1343
1344 #[test]
1345 fn test_encoder_constants() {
1346 assert_eq!(MAX_ENCODERS, 25);
1347 assert_eq!(MAX_FAST_ENCODERS, 3);
1348 assert_eq!(ULTRA_FAST_ENCODER_INDEX, 25);
1349 }
1350
1351 #[test]
1358 fn test_fast_encoder_configuration_to_byte() {
1359 assert_eq!(FastEncoderConfiguration::Disabled.to_byte(), 0x00);
1360 assert_eq!(FastEncoderConfiguration::Config1.to_byte(), 0x01);
1361 assert_eq!(FastEncoderConfiguration::Config2.to_byte(), 0x10);
1362 }
1363
1364 #[test]
1365 fn test_fast_encoder_configuration_round_trip() {
1366 for cfg in [
1367 FastEncoderConfiguration::Disabled,
1368 FastEncoderConfiguration::Config1,
1369 FastEncoderConfiguration::Config2,
1370 ] {
1371 assert_eq!(FastEncoderConfiguration::from_byte(cfg.to_byte()), cfg);
1372 }
1373 }
1374
1375 #[test]
1376 fn test_fast_encoder_options_bit_masks() {
1377 assert_eq!(
1379 FastEncoderOptions {
1380 disable_4x_sampling: true,
1381 ..Default::default()
1382 }
1383 .to_byte(),
1384 0x10
1385 );
1386 assert_eq!(
1387 FastEncoderOptions {
1388 invert_direction_1: true,
1389 ..Default::default()
1390 }
1391 .to_byte(),
1392 0x20
1393 );
1394 assert_eq!(
1395 FastEncoderOptions {
1396 invert_direction_2: true,
1397 ..Default::default()
1398 }
1399 .to_byte(),
1400 0x40
1401 );
1402 assert_eq!(
1403 FastEncoderOptions {
1404 invert_direction_3: true,
1405 ..Default::default()
1406 }
1407 .to_byte(),
1408 0x80
1409 );
1410 }
1411
1412 #[test]
1413 fn test_fast_encoder_options_combined() {
1414 let all = FastEncoderOptions {
1416 disable_4x_sampling: true,
1417 invert_direction_1: true,
1418 invert_direction_2: true,
1419 invert_direction_3: true,
1420 };
1421 assert_eq!(all.to_byte(), 0xF0);
1422 }
1423
1424 #[test]
1425 fn test_fast_encoder_options_round_trip() {
1426 let o = FastEncoderOptions {
1427 disable_4x_sampling: false,
1428 invert_direction_1: true,
1429 invert_direction_2: false,
1430 invert_direction_3: true,
1431 };
1432 assert_eq!(FastEncoderOptions::from_byte(o.to_byte()), o);
1433 }
1434
1435 #[test]
1436 fn test_fast_encoder_options_ignores_reserved_low_nibble() {
1437 let decoded = FastEncoderOptions::from_byte(0x0F);
1439 assert_eq!(decoded, FastEncoderOptions::default());
1440 }
1441
1442 #[test]
1448 fn test_ultra_fast_encoder_options_bit_masks() {
1449 assert_eq!(
1450 UltraFastEncoderOptions {
1451 invert_direction: true,
1452 ..Default::default()
1453 }
1454 .to_byte(),
1455 0x01
1456 );
1457 assert_eq!(
1458 UltraFastEncoderOptions {
1459 signal_mode_direction_clock: true,
1460 ..Default::default()
1461 }
1462 .to_byte(),
1463 0x02
1464 );
1465 assert_eq!(
1466 UltraFastEncoderOptions {
1467 enable_4x_sampling: true,
1468 ..Default::default()
1469 }
1470 .to_byte(),
1471 0x04
1472 );
1473 }
1474
1475 #[test]
1476 fn test_ultra_fast_encoder_options_combined() {
1477 let all = UltraFastEncoderOptions {
1479 invert_direction: true,
1480 signal_mode_direction_clock: true,
1481 enable_4x_sampling: true,
1482 };
1483 assert_eq!(all.to_byte(), 0x07);
1484 }
1485
1486 #[test]
1487 fn test_ultra_fast_encoder_options_round_trip() {
1488 let o = UltraFastEncoderOptions {
1489 invert_direction: true,
1490 signal_mode_direction_clock: false,
1491 enable_4x_sampling: true,
1492 };
1493 assert_eq!(UltraFastEncoderOptions::from_byte(o.to_byte()), o);
1494 }
1495
1496 #[test]
1497 fn test_ultra_fast_encoder_options_ignores_reserved_high_bits() {
1498 let decoded = UltraFastEncoderOptions::from_byte(0xF8);
1500 assert_eq!(decoded, UltraFastEncoderOptions::default());
1501 }
1502}