| 
					
				 | 
			
			
				@@ -1,7 +1,6 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #![cfg_attr(test, allow(unused_imports))] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #![cfg_attr(not(test), no_std)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #![cfg_attr(not(test), no_main)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// #![feature(generic_const_exprs)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #![feature(half_open_range_patterns)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #![feature(exclusive_range_pattern)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #![allow(dead_code)] 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -11,14 +10,15 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use core::panic::PanicInfo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use core::{cell::RefCell, ops::DerefMut}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// use cortex_m::asm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-use cortex_m::{interrupt::free, interrupt::Mutex, peripheral::NVIC}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use cortex_m::{asm, interrupt::free, interrupt::Mutex, peripheral::NVIC}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use cortex_m_rt::entry; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // use cortex_m_semihosting::hprintln; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use stm32l4xx_hal::{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     delay::Delay, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     device::I2C1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpio::{Alternate, Edge, Input, OpenDrain, Output, PullUp, PushPull, AF4, PA3, PC15}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpio::{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Alternate, Edge, Floating, Input, OpenDrain, Output, PullUp, PushPull, AF4, PA3, PB5, PC15, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpio::{State, PA10, PA9}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     i2c::I2c, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     interrupt, pac, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -28,9 +28,13 @@ use stm32l4xx_hal::{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 mod ds3231; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-mod tusb322; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+mod nixie; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 mod pca9685; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+mod tusb322; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use nixie::*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static RTC_INT: Mutex<RefCell<Option<PB5<Input<Floating>>>>> = Mutex::new(RefCell::new(None)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 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)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static I2C: Mutex< 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -47,68 +51,6 @@ static I2C: Mutex< 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     >, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 > = Mutex::new(RefCell::new(None)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const DS3231_ADDR: u8 = 0x68; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const TUSB322_ADDR: u8 = 0x47; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const PCA9685_ADDR_1: u8 = 0x41; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const PCA9685_ADDR_2: u8 = 0x42; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const PCA9685_ADDR_3: u8 = 0x43; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-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 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// NewType wrapper for the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //     core::slice::from_raw_parts( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //         (p as *const T) as *const u8, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -144,17 +86,26 @@ fn main() -> ! { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let clocks = rcc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         .cfgr 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         .pll_source(rcc::PllSource::HSI16) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .sysclk(80.mhz()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .hclk(80.mhz()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .pclk1(80.mhz()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .pclk2(80.mhz()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .sysclk(64.mhz()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .hclk(64.mhz()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .pclk1(64.mhz()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .pclk2(64.mhz()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         .freeze(&mut flash.acr, &mut pwr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Configure abstract timer that operates off systick timer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut timer = Delay::new(cp.SYST, clocks); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // Split GPIO peripheral into independent pins and registers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // let mut gpiob = dp.GPIOB.split(&mut rcc.ahb2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let mut gpioa = dp.GPIOA.split(&mut rcc.ahb2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut gpiob = dp.GPIOB.split(&mut rcc.ahb2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let mut gpioc = dp.GPIOC.split(&mut rcc.ahb2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Configure high voltage PSU enable pin on PA2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut hv_enable = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpioa 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .pa2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .into_push_pull_output_with_state(&mut gpioa.moder, &mut gpioa.otyper, State::Low); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // Configure fault LED output on PC15 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let fault_led = gpioc.pc15.into_push_pull_output_with_state( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         &mut gpioc.moder, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -162,7 +113,7 @@ fn main() -> ! { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         State::Low, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Store fault LED in global static variable as it is accessed in interrupts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Store fault LED in static singleton so that interrupt has access to it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     free(|cs| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         FAULT_LED.borrow(cs).replace(Some(fault_led)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -182,7 +133,7 @@ fn main() -> ! { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             NVIC::unmask(Interrupt::EXTI3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Store fault input in global static variable as it is accessed in interrupt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Store fault interrupt in static singleton so that interrupt has access to it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         free(|cs| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             FAULT_INT.borrow(cs).replace(Some(fault_int)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -190,12 +141,6 @@ fn main() -> ! { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         panic!(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Start with HV PSU disabled (enable pin on PA2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let mut _hv_en = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        gpioa 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .pa2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .into_push_pull_output_with_state(&mut gpioa.moder, &mut gpioa.otyper, State::Low); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     // Configure I2C SCL 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let scl = gpioa 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         .pa9 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -208,26 +153,79 @@ fn main() -> ! { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         .into_open_drain_output(&mut gpioa.moder, &mut gpioa.otyper); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     let sda = sda.into_af4(&mut gpioa.moder, &mut gpioa.afrh); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Initialize I2C 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let mut i2c = I2c::i2c1(dp.I2C1, (scl, sda), 100.khz(), clocks, &mut rcc.apb1r1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Initialize I2C (configured for 1Mhz, but actually runs at 600kHz) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut i2c = I2c::i2c1(dp.I2C1, (scl, sda), 1.mhz(), clocks, &mut rcc.apb1r1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Initialize TUSB322 (USB Type-C configuration chip) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tusb322::init(TUSB322_ADDR, &mut i2c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Initialize DS3231 (RTC) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ds3231::init(DS3231_ADDR, &mut i2c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Configure input interrupt pin from DS3231 on PB5 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Interrupt is pulled high, with open drain on DS3231 to pull low 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut rtc_int = gpiob 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .pb5 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .into_floating_input(&mut gpiob.moder, &mut gpiob.pupdr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    rtc_int.make_interrupt_source(&mut dp.SYSCFG, &mut rcc.apb2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    rtc_int.enable_interrupt(&mut dp.EXTI); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    rtc_int.trigger_on_edge(&mut dp.EXTI, Edge::FALLING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Configure NVIC mask to enable interrupt source 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    unsafe { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        NVIC::unmask(Interrupt::EXTI9_5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Store RTC interrupt in static singleton so that interrupt has access to it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    free(|cs| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RTC_INT.borrow(cs).replace(Some(rtc_int)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Configure DAC AMP enable pin for AD8591 on PB1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut _dac_enable = gpiob.pb1.into_push_pull_output_with_state( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut gpiob.moder, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut gpiob.otyper, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        State::High, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Configure DAC VIN for AD8591 on PA5 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Note that this pin should actually be configured as analog output (for DAC) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // but stm32l4xx_hal doesn't have support for the DAC as of now. We also currently 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // set the output to only the highest possible voltage, so the same functionality 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // can be achieved by configuring the pin as a digital output set to high. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut _dac_output = gpioa.pa5.into_push_pull_output_with_state( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut gpioa.moder, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut gpioa.otyper, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        State::High, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Configure PWM enable pin (active low) for PCA9685 on PA7 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut pwm_enable = gpioa.pa7.into_push_pull_output_with_state( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut gpioa.moder, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut gpioa.otyper, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        State::High, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Small delay to ensure that PCA9685 is fully powered on before writing to it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    timer.delay_us(10_u32); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Initialize PCA9685 (PWM driver) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pca9685::init(PCA9685_ALL_CALL, &mut i2c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Enable PWM output after PCA9685 has been initialized 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pwm_enable.set_low().unwrap(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pca9685::set_digit(PCA9685_ADDR_1, &mut i2c, 0, 0, 4096); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Store I2C peripheral in global static variable as it is used in interrupt 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     free(|cs| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         I2C.borrow(cs).replace(Some(i2c)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Configure abstract timer that operates off systick timer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    let mut timer = Delay::new(cp.SYST, clocks); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Enable the high voltage power supply last 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    hv_enable.set_high().unwrap(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    loop { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        timer.delay_ms(1000_u32); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_fault_led(State::High); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        timer.delay_ms(1000_u32); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        set_fault_led(State::Low); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    loop {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 fn set_fault_led(state: State) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -242,6 +240,21 @@ fn set_fault_led(state: State) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[interrupt] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+fn EXTI9_5() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    free(|cs| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let mut rtc_int_ref = RTC_INT.borrow(cs).borrow_mut(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if let Some(ref mut rtc_int) = rtc_int_ref.deref_mut() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if rtc_int.check_interrupt() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                rtc_int.clear_interrupt_pending_bit(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                set_fault_led(State::High); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                asm::delay(8_000_000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                set_fault_led(State::Low); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #[interrupt] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 fn EXTI3() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     free(|cs| { 
			 |