The PIC12LF1571 is programmed in assembly. The code wakes up every 16ms using the watchdog timer - this is a frequency of 62.5 Hz, above the flicker-fusion rate, so you don't notice the blinking unless the light is moving. Each time the code wakes, it pulses the LED 6 times. The PIC oscillator is set to 500 kHz to save power. The desired 8 us current pulse to the inductor is one instruction cycle long at this frequency.
A few techniques have been used in the code to enhance reliability; this code is supposed to wake up about 20 billion times over the life of the battery. First, all unused locations in the instruction memory are filled with the "reset" instruction. If the program counter gets screwed up and points to a random place, it will just reset the code and everything will start clean again. The code itself actually issues a reset instruction every 256 times it wakes - this periodically re-initializes any register settings that may have become corrupted. It might be safer to reset every time, but this adds a lot of overhead, resulting in excessive current drain and reduced efficiency.
The OSCTUNE register is used to adjust the current drain of the assembled PCB. Since the inductor has a 30% tolerance, the software may require tweaking to obtain the desired battery life. Even though the OSCTUNE register only allows +/-12% adjustment, I have so far always been able to tune the current to the desired value (40 uA). If an inductor was discovered that didn't allow this, the number of LED pulses could be changed from 6 to either 5 or 7 to roughly tune the power, then the OSCTUNE adjustment could be again used for fine tuning.
Here is the code listing. Of course, if you want the code, you should get it from the GitHub repo.
;;; ;;; ten_year_lamp.asm : ;;; PIC12LF1571 code for (2x) LiFeS2 AA-powered LED glow marker ;;; ;;; 20161106 TCY LIST P=12LF1571 #include <p12lf1571.inc> ERRORLEVEL -302 ERRORLEVEL -305 ERRORLEVEL -207 ;;; ;;; OSCTUNE_VAL: set to fine-tune current draw for compensating for ;;; component tolerances ; OSCTUNE_VAL equ 0 OSCTUNE_VAL equ b'00100000' ; OSCTUNE_VAL equ b'00011111' ;;; ;;; number of LED pulses per WDT timeout loop ;;; N_PULSES equ 6 LED_PULSE macro variable i i = 0 while i < N_PULSES - 1 movwf LATA ;start inductor ramp-up clrf LATA ;end inductor ramp-up nop ; 2 nops here - tuned for minimum current nop i += 1 endw movwf LATA ;start inductor ramp-up clrf LATA ;end inductor ramp-up endm ;;; ;;; I/O pin configuration ;;; GATE_DRIVE_A equ 4 GATE_DRIVE_B equ 5 __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOREN_OFF & _CLKOUTEN_OFF __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_HI & _LPBOREN_OFF & _LVP_ON ;;; ;;; variables in Common RAM (accessable from all banks) ;;; CBLOCK 0x70 reset_counter ENDC ORG 0 RESET_VEC: nop nop nop nop INTERRUPT_VEC: BANKSEL OSCCON movlw b'00111011' ; 500 kHz MF osc movwf OSCCON BANKSEL OSCTUNE movlw OSCTUNE_VAL movwf OSCTUNE movlw .255 movwf reset_counter BANKSEL ANSELA movlw b'00000000' ; all digital I/O movwf ANSELA BANKSEL LATA clrf LATA BANKSEL TRISA clrf TRISA ; set all lines as outputs BANKSEL WDTCON movlw b'00001001' ; WDT 16ms timeout movwf WDTCON BANKSEL LATA movlw (1 << GATE_DRIVE_A) | (1 << GATE_DRIVE_B) MAIN_LOOP: LED_PULSE sleep decfsz reset_counter goto MAIN_LOOP reset ;; fill remainder of program memory with reset instructions fill (reset), 0x0400-$ END