|
@@ -1,16 +1,13 @@
|
|
|
+use core::mem::size_of;
|
|
|
use field_offset::offset_of;
|
|
|
-use stm32l4xx_hal::prelude::{
|
|
|
- _embedded_hal_blocking_i2c_Write, _embedded_hal_blocking_i2c_WriteRead,
|
|
|
-};
|
|
|
+use stm32l4xx_hal::prelude::_embedded_hal_blocking_i2c_Write;
|
|
|
use tock_registers::{
|
|
|
interfaces::{ReadWriteable, Readable, Writeable},
|
|
|
register_bitfields, register_structs,
|
|
|
registers::InMemoryRegister,
|
|
|
};
|
|
|
|
|
|
-const PCA9685_ADDR_1: u8 = 0x41;
|
|
|
-const PCA9685_ADDR_2: u8 = 0x42;
|
|
|
-const PCA9685_ADDR_3: u8 = 0x43;
|
|
|
+const MAX_BRIGHTNESS: u32 = 4096;
|
|
|
|
|
|
register_bitfields![
|
|
|
u8,
|
|
@@ -59,95 +56,86 @@ register_structs! {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl Pca9685Registers {
|
|
|
- const fn default() -> Self {
|
|
|
- const ZERO_LED: InMemoryRegister<u32, LED_CTRL::Register> = InMemoryRegister::new(0x00);
|
|
|
- Self {
|
|
|
- mode1: InMemoryRegister::new(0x00),
|
|
|
- mode2: InMemoryRegister::new(0x00),
|
|
|
- subaddress1: InMemoryRegister::new(0x00),
|
|
|
- subaddress2: InMemoryRegister::new(0x00),
|
|
|
- subaddress3: InMemoryRegister::new(0x00),
|
|
|
- allcalladdr: InMemoryRegister::new(0x00),
|
|
|
- led: [ZERO_LED; 16],
|
|
|
- _reserved: [0; 180],
|
|
|
- all_led: InMemoryRegister::new(0x00),
|
|
|
- prescale: InMemoryRegister::new(0x00),
|
|
|
- testmode: InMemoryRegister::new(0x00),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
|
|
|
+ let mode1_reg: InMemoryRegister<u8, MODE_1::Register> = InMemoryRegister::new(0);
|
|
|
+ let mode2_reg: InMemoryRegister<u8, MODE_2::Register> = InMemoryRegister::new(0);
|
|
|
|
|
|
-const MAP_ADDR: usize = 0;
|
|
|
-const MAP_PIN: usize = 1;
|
|
|
-
|
|
|
-static PCA9685_MAPPING: [[[u8; 2]; 10]; 4] = [
|
|
|
- [
|
|
|
- [PCA9685_ADDR_1, 8], // Tube 0 Digit 0
|
|
|
- [PCA9685_ADDR_1, 9], // Tube 0 Digit 1
|
|
|
- [PCA9685_ADDR_1, 10], // Tube 0 Digit 2
|
|
|
- [PCA9685_ADDR_1, 12], // Tube 0 Digit 3
|
|
|
- [PCA9685_ADDR_1, 15], // Tube 0 Digit 4
|
|
|
- [PCA9685_ADDR_1, 14], // Tube 0 Digit 5
|
|
|
- [PCA9685_ADDR_1, 11], // Tube 0 Digit 6
|
|
|
- [PCA9685_ADDR_1, 0], // Tube 0 Digit 7
|
|
|
- [PCA9685_ADDR_1, 1], // Tube 0 Digit 8
|
|
|
- [PCA9685_ADDR_1, 13], // Tube 0 Digit 9
|
|
|
- ],
|
|
|
- [
|
|
|
- [PCA9685_ADDR_1, 5], // Tube 1 Digit 0
|
|
|
- [PCA9685_ADDR_1, 6], // Tube 1 Digit 1
|
|
|
- [PCA9685_ADDR_1, 7], // Tube 1 Digit 2
|
|
|
- [PCA9685_ADDR_1, 2], // Tube 1 Digit 3
|
|
|
- [PCA9685_ADDR_2, 4], // Tube 1 Digit 4
|
|
|
- [PCA9685_ADDR_2, 1], // Tube 1 Digit 5
|
|
|
- [PCA9685_ADDR_1, 4], // Tube 1 Digit 6
|
|
|
- [PCA9685_ADDR_2, 2], // Tube 1 Digit 7
|
|
|
- [PCA9685_ADDR_2, 3], // Tube 1 Digit 8
|
|
|
- [PCA9685_ADDR_1, 3], // Tube 1 Digit 9
|
|
|
- ],
|
|
|
- [
|
|
|
- [PCA9685_ADDR_3, 8], // Tube 2 Digit 0
|
|
|
- [PCA9685_ADDR_3, 9], // Tube 2 Digit 1
|
|
|
- [PCA9685_ADDR_3, 10], // Tube 2 Digit 2
|
|
|
- [PCA9685_ADDR_3, 12], // Tube 2 Digit 3
|
|
|
- [PCA9685_ADDR_2, 12], // Tube 2 Digit 4
|
|
|
- [PCA9685_ADDR_2, 13], // Tube 2 Digit 5
|
|
|
- [PCA9685_ADDR_3, 11], // Tube 2 Digit 6
|
|
|
- [PCA9685_ADDR_2, 14], // Tube 2 Digit 7
|
|
|
- [PCA9685_ADDR_2, 11], // Tube 2 Digit 8
|
|
|
- [PCA9685_ADDR_3, 13], // Tube 2 Digit 9
|
|
|
- ],
|
|
|
- [
|
|
|
- [PCA9685_ADDR_3, 5], // Tube 3 Digit 0
|
|
|
- [PCA9685_ADDR_3, 6], // Tube 3 Digit 1
|
|
|
- [PCA9685_ADDR_3, 7], // Tube 3 Digit 2
|
|
|
- [PCA9685_ADDR_3, 2], // Tube 3 Digit 3
|
|
|
- [PCA9685_ADDR_3, 14], // Tube 3 Digit 4
|
|
|
- [PCA9685_ADDR_3, 15], // Tube 3 Digit 5
|
|
|
- [PCA9685_ADDR_3, 4], // Tube 3 Digit 6
|
|
|
- [PCA9685_ADDR_3, 1], // Tube 3 Digit 7
|
|
|
- [PCA9685_ADDR_3, 0], // Tube 3 Digit 8
|
|
|
- [PCA9685_ADDR_3, 3], // Tube 3 Digit 9
|
|
|
- ],
|
|
|
-];
|
|
|
+ // Turn on autoincrement
|
|
|
+ // Start disabled
|
|
|
+ // Enable response to all call address
|
|
|
+ mode1_reg.modify(MODE_1::AI::SET + MODE_1::SLEEP::SET + MODE_1::ALLCALL::SET);
|
|
|
|
|
|
-pub fn init(i2c: &mut impl _embedded_hal_blocking_i2c_Write, ) {
|
|
|
+ // Configure output for totem pole drive
|
|
|
+ mode2_reg.modify(MODE_2::OUTDRV::SET);
|
|
|
|
|
|
-}
|
|
|
+ let buffer: [u8; 3] = [
|
|
|
+ offset_of!(Pca9685Registers => mode1).get_byte_offset() as u8,
|
|
|
+ mode1_reg.get(),
|
|
|
+ mode2_reg.get(),
|
|
|
+ ];
|
|
|
|
|
|
-pub fn set_voltage(percent: f32) {
|
|
|
-
|
|
|
-}
|
|
|
+ match i2c.write(address, &buffer) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
|
|
|
-pub fn set_digit(tube: u32, digit: u32, pwm_start: u32, pwm_end: u32) {
|
|
|
+ let prescale_reg: InMemoryRegister<u8> = InMemoryRegister::new(0);
|
|
|
|
|
|
-}
|
|
|
+ // Set PWM frequency to 1526Hz
|
|
|
+ prescale_reg.set(0x03);
|
|
|
+
|
|
|
+ let buffer: [u8; 2] = [
|
|
|
+ offset_of!(Pca9685Registers => prescale).get_byte_offset() as u8,
|
|
|
+ prescale_reg.get(),
|
|
|
+ ];
|
|
|
+
|
|
|
+ match i2c.write(address, &buffer) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
|
|
|
-pub fn set_dot(pwm_start: u32, pwm_end: u32) {
|
|
|
+ // Re-enable outputs
|
|
|
+ mode1_reg.modify(MODE_1::SLEEP::CLEAR);
|
|
|
|
|
|
+ let buffer: [u8; 2] = [
|
|
|
+ offset_of!(Pca9685Registers => mode1).get_byte_offset() as u8,
|
|
|
+ mode1_reg.get(),
|
|
|
+ ];
|
|
|
+
|
|
|
+ match i2c.write(address, &buffer) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-pub fn enable_output(enabled: bool) {
|
|
|
+pub fn set_digit(
|
|
|
+ address: u8,
|
|
|
+ i2c: &mut impl _embedded_hal_blocking_i2c_Write,
|
|
|
+ digit: usize,
|
|
|
+ pwm_start: u32,
|
|
|
+ pwm_end: u32,
|
|
|
+) {
|
|
|
+ let led_reg: InMemoryRegister<u32, LED_CTRL::Register> = InMemoryRegister::new(0);
|
|
|
+
|
|
|
+ led_reg.modify(LED_CTRL::On.val(pwm_start));
|
|
|
+ led_reg.modify(LED_CTRL::On.val(pwm_end));
|
|
|
+
|
|
|
+ if pwm_end == 0 {
|
|
|
+ led_reg.modify(LED_CTRL::Off_Full::SET)
|
|
|
+ } else if pwm_end >= MAX_BRIGHTNESS {
|
|
|
+ led_reg.modify(LED_CTRL::On_Full::SET)
|
|
|
+ }
|
|
|
|
|
|
-}
|
|
|
+ let buffer: [u8; 5] = [
|
|
|
+ (offset_of!(Pca9685Registers => led).get_byte_offset() + size_of::<u32>() * digit) as u8,
|
|
|
+ led_reg.get().to_le_bytes()[0],
|
|
|
+ led_reg.get().to_le_bytes()[1],
|
|
|
+ led_reg.get().to_le_bytes()[2],
|
|
|
+ led_reg.get().to_le_bytes()[3],
|
|
|
+ ];
|
|
|
+
|
|
|
+ match i2c.write(address, &buffer) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(_) => panic!(),
|
|
|
+ }
|
|
|
+}
|