Browse Source

Initial support for PCA9685

Kevin Lee 2 years ago
parent
commit
4ccbadde0a

+ 8 - 10
Nixie_Firmware_Rust/src/ds3231.rs

@@ -8,6 +8,8 @@ use tock_registers::{
     registers::InMemoryRegister,
 };
 
+const DS3231_ADDR: u8 = 0x68;
+
 register_bitfields![
     u8,
     T_SECOND [
@@ -219,7 +221,7 @@ impl Ds3231Registers {
     }
 }
 
-pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
+pub fn init(i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
     let regs = Ds3231Registers::default();
 
     regs.control_1.modify(
@@ -235,11 +237,10 @@ pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
     // Disable 32kHz output
     regs.control_2.modify(CONTROL_2::EN32KHZ::CLEAR);
 
-    regs.i2c_write_ctrl(address, i2c);
+    regs.i2c_write_ctrl(DS3231_ADDR, i2c);
 }
 
 pub fn set_time(
-    address: u8,
     i2c: &mut impl _embedded_hal_blocking_i2c_Write,
     second: u32,
     minute: u32,
@@ -253,11 +254,10 @@ pub fn set_time(
         .write(T_MINUTE::Value.val(decimal_to_bcd(minute)));
     regs.hour.write(T_HOUR::Value.val(decimal_to_bcd(hour)));
 
-    regs.i2c_write_time(address, i2c);
+    regs.i2c_write_time(DS3231_ADDR, i2c);
 }
 
 pub fn set_date(
-    address: u8,
     i2c: &mut impl _embedded_hal_blocking_i2c_Write,
     weekday: Weekday,
     day: u32,
@@ -275,16 +275,15 @@ pub fn set_date(
     );
     regs.year.write(T_YEAR::Value.val(decimal_to_bcd(year)));
 
-    regs.i2c_write_time(address, i2c);
+    regs.i2c_write_time(DS3231_ADDR, i2c);
 }
 
 pub fn get_time(
-    address: u8,
     i2c: &mut impl _embedded_hal_blocking_i2c_WriteRead,
 ) -> (u32, u32, u32) {
     let mut regs = Ds3231Registers::default();
 
-    regs.i2c_read_time(address, i2c);
+    regs.i2c_read_time(DS3231_ADDR, i2c);
 
     let second = bcd_to_decimal(regs.second.read(T_SECOND::Value));
     let minute = bcd_to_decimal(regs.minute.read(T_MINUTE::Value));
@@ -294,12 +293,11 @@ pub fn get_time(
 }
 
 pub fn get_date(
-    address: u8,
     i2c: &mut impl _embedded_hal_blocking_i2c_WriteRead,
 ) -> (Weekday, u32, u32, u32, u32) {
     let mut regs = Ds3231Registers::default();
 
-    regs.i2c_read_date(address, i2c);
+    regs.i2c_read_date(DS3231_ADDR, i2c);
 
     let weekday: Weekday = regs.weekday.read(T_WEEKDAY::Value).into();
     let day = bcd_to_decimal(regs.day.read(T_DAY::Value));

+ 3 - 8
Nixie_Firmware_Rust/src/main.rs

@@ -28,14 +28,9 @@ use stm32l4xx_hal::{
     stm32::Interrupt,
 };
 
-const TUSB322_ADDR: u8 = 0x47;
-const DS3231_ADDR: u8 = 0x68;
-const PCA9685_ADDR1: u8 = 0x41;
-const PCA9685_ADDR2: u8 = 0x42;
-const PCA9685_ADDR3: u8 = 0x43;
-
 mod tusb322;
 mod ds3231;
+mod pca9685;
 
 static FAULT_INT: Mutex<RefCell<Option<PA3<Input<PullUp>>>>> = Mutex::new(RefCell::new(None));
 static FAULT_LED: Mutex<RefCell<Option<PC15<Output<PushPull>>>>> = Mutex::new(RefCell::new(None));
@@ -142,9 +137,9 @@ fn main() -> ! {
     // Initialize I2C
     let mut i2c = I2c::i2c1(dp.I2C1, (scl, sda), 100.khz(), clocks, &mut rcc.apb1r1);
 
-    tusb322::init(TUSB322_ADDR, &mut i2c);
+    tusb322::init(&mut i2c);
 
-    ds3231::init(DS3231_ADDR, &mut i2c);
+    ds3231::init(&mut i2c);
 
     // Configure abstract timer that operates off systick timer
     let mut timer = Delay::new(cp.SYST, clocks);

+ 153 - 0
Nixie_Firmware_Rust/src/pca9685.rs

@@ -0,0 +1,153 @@
+use field_offset::offset_of;
+use stm32l4xx_hal::prelude::{
+    _embedded_hal_blocking_i2c_Write, _embedded_hal_blocking_i2c_WriteRead,
+};
+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;
+
+register_bitfields![
+    u8,
+    MODE_1 [
+        ALLCALL 0,
+        SUB3 1,
+        SUB2 2,
+        SUB1 3,
+        SLEEP 4,
+        AI 5,
+        EXTCLK 6,
+        RESTART 7,
+    ],
+    MODE_2 [
+        OUTNE OFFSET(0) NUMBITS(2) [],
+        OUTDRV OFFSET(2) NUMBITS(1) [],
+        OCH OFFSET(3) NUMBITS(1) [],
+        INVRT OFFSET(4) NUMBITS(1) [],
+    ],
+];
+
+register_bitfields![
+    u32,
+    LED_CTRL [
+        On OFFSET(0) NUMBITS(12) [],
+        On_Full OFFSET(12) NUMBITS(1) [],
+        Off OFFSET(16) NUMBITS(12) [],
+        Off_Full OFFSET(28) NUMBITS(1) [],
+    ],
+];
+
+register_structs! {
+    Pca9685Registers {
+        (0x00 => mode1: InMemoryRegister<u8, MODE_1::Register>),
+        (0x01 => mode2: InMemoryRegister<u8, MODE_2::Register>),
+        (0x02 => subaddress1: InMemoryRegister<u8>),
+        (0x03 => subaddress2: InMemoryRegister<u8>),
+        (0x04 => subaddress3: InMemoryRegister<u8>),
+        (0x05 => allcalladdr: InMemoryRegister<u8>),
+        (0x06 => led: [InMemoryRegister<u32, LED_CTRL::Register>; 16]),
+        (0x46 => _reserved),
+        (0xFA => all_led: InMemoryRegister<u32, LED_CTRL::Register>),
+        (0xFE => prescale: InMemoryRegister<u8>),
+        (0xFF => testmode: InMemoryRegister<u8>),
+        (0x100 => @END),
+    }
+}
+
+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),
+        }
+    }
+}
+
+const MAP_ADDR: usize = 0;
+const MAP_PIN: usize = 1;
+
+static 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
+    ],
+];
+
+pub fn init(i2c: &mut impl _embedded_hal_blocking_i2c_Write, ) {
+
+}
+
+pub fn set_voltage(percent: f32) {
+    
+}
+
+pub fn set_digit(tube: u32, digit: u32, pwm_start: u32, pwm_end: u32) {
+
+}
+
+pub fn set_dot(pwm_start: u32, pwm_end: u32) {
+
+}
+
+pub fn enable_output(enabled: bool) {
+
+}

+ 5 - 3
Nixie_Firmware_Rust/src/tusb322.rs

@@ -6,6 +6,8 @@ use tock_registers::{
     registers::InMemoryRegister,
 };
 
+const TUSB322_ADDR: u8 = 0x47;
+
 register_bitfields![
     u8,
     // Connection status register
@@ -129,7 +131,7 @@ impl Tusb322Registers {
     }
 }
 
-pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
+pub fn init(i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
     let reg: Tusb322Registers = Tusb322Registers::default();
 
     // Disable UFP accessory support (otherwise IC stays in DRP mode)
@@ -141,10 +143,10 @@ pub fn init(address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
     // For operation in UFP mode
     reg.ctrl.modify(Control::MODE_SELECT::Ufp);
 
-    reg.i2c_write_regs(address, i2c);
+    reg.i2c_write_regs(TUSB322_ADDR, i2c);
 
     // Re-enable CC termination
     reg.ctrl.modify(Control::DISABLE_TERM::CLEAR);
 
-    reg.i2c_write_regs(address, i2c);
+    reg.i2c_write_regs(TUSB322_ADDR, i2c);
 }