pca9685.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. use core::mem::size_of;
  2. use field_offset::offset_of;
  3. use stm32l4xx_hal::prelude::_embedded_hal_blocking_i2c_Write;
  4. use tock_registers::{
  5. interfaces::{ReadWriteable, Readable, Writeable},
  6. register_bitfields, register_structs,
  7. registers::InMemoryRegister,
  8. };
  9. const MAX_BRIGHTNESS: u32 = 4096;
  10. register_bitfields![
  11. u8,
  12. MODE_1 [
  13. ALLCALL 0,
  14. SUB3 1,
  15. SUB2 2,
  16. SUB1 3,
  17. SLEEP 4,
  18. AI 5,
  19. EXTCLK 6,
  20. RESTART 7,
  21. ],
  22. MODE_2 [
  23. OUTNE OFFSET(0) NUMBITS(2) [],
  24. OUTDRV OFFSET(2) NUMBITS(1) [],
  25. OCH OFFSET(3) NUMBITS(1) [],
  26. INVRT OFFSET(4) NUMBITS(1) [],
  27. ],
  28. ];
  29. register_bitfields![
  30. u32,
  31. LED_CTRL [
  32. On OFFSET(0) NUMBITS(12) [],
  33. On_Full OFFSET(12) NUMBITS(1) [],
  34. Off OFFSET(16) NUMBITS(12) [],
  35. Off_Full OFFSET(28) NUMBITS(1) [],
  36. ],
  37. ];
  38. register_structs! {
  39. Pca9685Registers {
  40. (0x00 => mode1: InMemoryRegister<u8, MODE_1::Register>),
  41. (0x01 => mode2: InMemoryRegister<u8, MODE_2::Register>),
  42. (0x02 => subaddress1: InMemoryRegister<u8>),
  43. (0x03 => subaddress2: InMemoryRegister<u8>),
  44. (0x04 => subaddress3: InMemoryRegister<u8>),
  45. (0x05 => allcalladdr: InMemoryRegister<u8>),
  46. (0x06 => led: [InMemoryRegister<u32, LED_CTRL::Register>; 16]),
  47. (0x46 => _reserved),
  48. (0xFA => all_led: InMemoryRegister<u32, LED_CTRL::Register>),
  49. (0xFE => prescale: InMemoryRegister<u8>),
  50. (0xFF => testmode: InMemoryRegister<u8>),
  51. (0x100 => @END),
  52. }
  53. }
  54. pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
  55. let mode1_reg: InMemoryRegister<u8, MODE_1::Register> = InMemoryRegister::new(0);
  56. let mode2_reg: InMemoryRegister<u8, MODE_2::Register> = InMemoryRegister::new(0);
  57. // Turn on autoincrement
  58. // Start disabled
  59. // Enable response to all call address
  60. mode1_reg.modify(MODE_1::AI::SET + MODE_1::SLEEP::SET + MODE_1::ALLCALL::SET);
  61. // Configure output for totem pole drive
  62. mode2_reg.modify(MODE_2::OUTDRV::SET);
  63. let buffer: [u8; 3] = [
  64. offset_of!(Pca9685Registers => mode1).get_byte_offset() as u8,
  65. mode1_reg.get(),
  66. mode2_reg.get(),
  67. ];
  68. match i2c.write(address, &buffer) {
  69. Ok(_) => (),
  70. Err(_) => panic!(),
  71. }
  72. let prescale_reg: InMemoryRegister<u8> = InMemoryRegister::new(0);
  73. // Set PWM frequency to 1526Hz
  74. prescale_reg.set(0x03);
  75. let buffer: [u8; 2] = [
  76. offset_of!(Pca9685Registers => prescale).get_byte_offset() as u8,
  77. prescale_reg.get(),
  78. ];
  79. match i2c.write(address, &buffer) {
  80. Ok(_) => (),
  81. Err(_) => panic!(),
  82. }
  83. // Re-enable outputs
  84. mode1_reg.modify(MODE_1::SLEEP::CLEAR);
  85. let buffer: [u8; 2] = [
  86. offset_of!(Pca9685Registers => mode1).get_byte_offset() as u8,
  87. mode1_reg.get(),
  88. ];
  89. match i2c.write(address, &buffer) {
  90. Ok(_) => (),
  91. Err(_) => panic!(),
  92. }
  93. }
  94. pub fn set_digit(
  95. address: u8,
  96. i2c: &mut impl _embedded_hal_blocking_i2c_Write,
  97. digit: usize,
  98. pwm_start: u32,
  99. pwm_end: u32,
  100. ) {
  101. let led_reg: InMemoryRegister<u32, LED_CTRL::Register> = InMemoryRegister::new(0);
  102. led_reg.modify(LED_CTRL::On.val(pwm_start));
  103. led_reg.modify(LED_CTRL::On.val(pwm_end));
  104. if pwm_end == 0 {
  105. led_reg.modify(LED_CTRL::Off_Full::SET)
  106. } else if pwm_end >= MAX_BRIGHTNESS {
  107. led_reg.modify(LED_CTRL::On_Full::SET)
  108. }
  109. let buffer: [u8; 5] = [
  110. (offset_of!(Pca9685Registers => led).get_byte_offset() + size_of::<u32>() * digit) as u8,
  111. led_reg.get().to_le_bytes()[0],
  112. led_reg.get().to_le_bytes()[1],
  113. led_reg.get().to_le_bytes()[2],
  114. led_reg.get().to_le_bytes()[3],
  115. ];
  116. match i2c.write(address, &buffer) {
  117. Ok(_) => (),
  118. Err(_) => panic!(),
  119. }
  120. }