tusb322.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. use field_offset::offset_of;
  2. use stm32l4xx_hal::prelude::_embedded_hal_blocking_i2c_Write;
  3. use tock_registers::{
  4. interfaces::{ReadWriteable, Readable},
  5. register_bitfields, register_structs,
  6. registers::InMemoryRegister,
  7. };
  8. register_bitfields![
  9. u8,
  10. // Connection status register
  11. ConnStatus1 [
  12. // Indicates that active cable has been plugged in
  13. ACTIVE_CABLE_DETECTION OFFSET(0) NUMBITS(1) [],
  14. // Read by the application to determine if accessory was attached
  15. ACCESSORY_CONNECTED OFFSET(1) NUMBITS(3) [
  16. None = 0,
  17. Audio = 4,
  18. AudioCharged = 5,
  19. DebugDfp = 6,
  20. DebugUfp = 7,
  21. ],
  22. // Set in UFP mode with the detected current mode
  23. CURRENT_MODE_DETECT OFFSET(4) NUMBITS(2) [
  24. Default = 0,
  25. Medium = 1,
  26. ChargeThrough = 2,
  27. High = 3,
  28. ],
  29. // Programmed by application to change current advertisement
  30. CURRENT_MODE_ADVERTISE OFFSET(6) NUMBITS(2) [
  31. Default = 0,
  32. Mid = 1,
  33. High = 2,
  34. Reserved = 3,
  35. ],
  36. ],
  37. // Connection status and control register
  38. ConnStatus2 [
  39. // Setting this field will disable UFP accessory support
  40. DISABLE_UFP_ACCESSORY OFFSET(0) NUMBITS(1) [],
  41. // Percentage of time that a DRP advertised DFP during tDRP
  42. DRP_DUTY_CYCLE OFFSET(1) NUMBITS(2) [
  43. p30 = 0,
  44. p40 = 1,
  45. p50 = 2,
  46. p60 = 3,
  47. ],
  48. // Set when over-current limit is triggered
  49. VCONN_FAULT OFFSET(3) NUMBITS(1) [],
  50. // Pulled low when a control or status register changes
  51. INTERRUPT_STATUS OFFSET(4) NUMBITS(1) [
  52. Clear = 0,
  53. Changed = 1,
  54. ],
  55. // Cable orientation
  56. CABLE_DIR OFFSET(5) NUMBITS(1) [
  57. CC1 = 0,
  58. CC2 = 1,
  59. ],
  60. // Attached state (same as ID pin)
  61. ATTACHED_STATE OFFSET(6) NUMBITS(2) [
  62. NotAttached = 0,
  63. AttachedSrc_DFP = 1,
  64. AttachedSnk_UFP = 2,
  65. AttachedAccessory = 3,
  66. ],
  67. ],
  68. // General control register
  69. Control [
  70. // Disable CC pin termination
  71. DISABLE_TERM OFFSET(0) NUMBITS(1) [],
  72. // Control behavior when configured as DRP
  73. SOURCE_PERF OFFSET(1) NUMBITS(2) [
  74. StandardDrp = 0,
  75. DrpTrySnk = 1,
  76. Reserved = 2,
  77. DrpTrySrc = 3,
  78. ],
  79. // Soft reset internal logic (self-clearing)
  80. I2C_SOFT_RESET OFFSET(3) NUMBITS(1) [],
  81. // Configure device operation mode
  82. MODE_SELECT OFFSET(4) NUMBITS(2) [
  83. Drp = 0,
  84. Ufp = 1,
  85. Dfp = 2,
  86. ],
  87. // Debounce time on CC pins
  88. DEBOUNCE OFFSET(6) NUMBITS(2) [
  89. ms168 = 0,
  90. ms118 = 1,
  91. ms134 = 2,
  92. ms152 = 3,
  93. ],
  94. ],
  95. ];
  96. register_structs! {
  97. Tusb322Registers {
  98. (0x00 => id: [u8; 8]),
  99. (0x09 => stat1: InMemoryRegister<u8, ConnStatus1::Register>),
  100. (0x0A => stat2: InMemoryRegister<u8, ConnStatus2::Register>),
  101. (0x0B => ctrl: InMemoryRegister<u8, Control::Register>),
  102. (0x0C => @END),
  103. }
  104. }
  105. impl Tusb322Registers {
  106. const fn default() -> Self {
  107. Self {
  108. id: [0; 8],
  109. stat1: InMemoryRegister::new(0x00),
  110. stat2: InMemoryRegister::new(0x00),
  111. ctrl: InMemoryRegister::new(0x00),
  112. }
  113. }
  114. // Program control registers
  115. fn i2c_write_regs(&self, address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
  116. let mut buffer: [u8; 4] = [0; 4];
  117. buffer[0] = offset_of!(Tusb322Registers => stat1).get_byte_offset() as u8;
  118. buffer[1] = self.stat1.get();
  119. buffer[2] = self.stat2.get();
  120. buffer[3] = self.ctrl.get();
  121. match i2c.write(address, &buffer) {
  122. Ok(_) => (),
  123. Err(_) => panic!(),
  124. }
  125. }
  126. }
  127. pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
  128. let reg: Tusb322Registers = Tusb322Registers::default();
  129. // Disable UFP accessory support (otherwise IC stays in DRP mode)
  130. reg.stat2.modify(ConnStatus2::DISABLE_UFP_ACCESSORY::SET);
  131. // Disable CC termination to change to UFP mode
  132. reg.ctrl.modify(Control::DISABLE_TERM::SET);
  133. // For operation in UFP mode
  134. reg.ctrl.modify(Control::MODE_SELECT::Ufp);
  135. reg.i2c_write_regs(address, i2c);
  136. // Re-enable CC termination
  137. reg.ctrl.modify(Control::DISABLE_TERM::CLEAR);
  138. reg.i2c_write_regs(address, i2c);
  139. }