; title "led_ppm.asm"
; LED Peak Program Level Meter with 24 LEDs and 48 dB range using AD8307, PIC12F617 and HEF4094B
; 210225 v0.1 First giraffe
; 210226 v0.2 A/D (note: fix GO bit in p12f617.inc)
; 210226 v0.3 LED24 level test (UNDERFLOW)
; 210226 v0.4 Max Hold and decay
; 210226 v0.5 left justify A/D result to fix underflow
; 210226 v0.6 1 dB steps, 10 dB markings
; 210226 v0.7 A/D conversions interruptized
; 210227 v0.8 That didn't work well... Outputs went crazy! Clockcycle spikes, bar haywire, WTF!
; 210228 v1.0 Release. Still some aliasing at 1.83 kHz but it is about 2 dB.
; GPL Copyleft 2021 pic@polonai.se
LIST P=12F617, F=INHX8M
#include <p12f617.inc>
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_ON & _CP_OFF & _IOSCFS_8MHZ & _BOR_OFF
ERRORLEVEL -302 ; sod compiler message about using proper bank
; Equates
RESET_V EQU 0x00 ; Address of RESET Vector
; Registers
TEMP EQU 0x20 ; TEMP register
HEF1 EQU 0x21 ; First shift register
HEF2 EQU 0x22 ; Second shift register
HEF3 EQU 0x23 ; Third shift register
d1 EQU 0x24 ; Delay registers used during Lamp Test, decay
d2 EQU 0x25
PPM EQU 0x26 ; Value to decode and display
LEVEL EQU 0x27 ; Result from A/D Conversions
; GPIO,2 (AN2) input from AD8307 has no name defined
#define SDI GPIO,0 ; Serial Data line of HEF4094
#define CLK GPIO,1 ; Clock for HEF4094 (high pulse)
#define STRO GPIO,4 ; Strobe for HEF4094 (high pulse)
#define OE GPIO,5 ; Output Enable for HEF4094 (active high)
#define LED1 HEF1,0 ; Q5 output of HEF1, -2 dB LED
#define LED2 HEF1,1 ; Q6 output of HEF1, -4 dB LED
#define LED3 HEF1,2 ; Q7 output of HEF1, -6 dB LED
#define LED4 HEF1,3 ; Q8 output of HEF1, -8 dB LED
#define LED5 HEF1,4 ; Q1 output of HEF1, -10 dB LED
#define LED6 HEF1,5 ; Q2 output of HEF1, -12 dB LED
#define LED7 HEF1,6 ; Q3 output of HEF1, -14 dB LED
#define LED8 HEF1,7 ; Q4 output of HEF1, -16 dB LED
#define LED9 HEF2,0 ; Q5 output of HEF2, -18 dB LED
#define LED10 HEF2,1 ; Q6 output of HEF2, -20 dB LED
#define LED11 HEF2,2 ; Q7 output of HEF2, -22 dB LED
#define LED12 HEF2,3 ; Q8 output of HEF2, -24 dB LED
#define LED13 HEF2,4 ; Q1 output of HEF2, -26 dB LED
#define LED14 HEF2,5 ; Q2 output of HEF2, -28 dB LED
#define LED15 HEF2,6 ; Q3 output of HEF2, -30 dB LED
#define LED16 HEF2,7 ; Q4 output of HEF2, -32 dB LED
#define LED17 HEF3,0 ; Q5 output of HEF3, -34 dB LED
#define LED18 HEF3,1 ; Q6 output of HEF3, -36 dB LED
#define LED19 HEF3,2 ; Q7 output of HEF3, -38 dB LED
#define LED20 HEF3,3 ; Q8 output of HEF3, -40 dB LED
#define LED21 HEF3,4 ; Q1 output of HEF3, -42 dB LED
#define LED22 HEF3,5 ; Q2 output of HEF3, -44 dB LED
#define LED23 HEF3,6 ; Q3 output of HEF3, -46 dB LED
#define LED24 HEF3,7 ; Q4 output of HEF3, -48 dB LED
org 0x00
GOTO START
org 0x04
; Interrupts
; There are none
RETFIE ; Just in case
START
;Init stuff
CLRF STATUS ; Do initialization, select Bank 0
CLRF INTCON ; Clear int-flags, disable interrupts
CLRF PCLATH ; Keep in lower 2KByte
BSF STATUS,RP0 ; Select Bank 1
CLRF OPTION_REG ; TMR0 prescaler 1:2 (256 µs)
MOVLW B'00001100' ; GPIO2,3 inputs, all others outputs
MOVWF TRISIO
MOVLW B'00001100' ; Enable weak pull-ups on GPIO2,3
MOVWF WPU
MOVLW B'01010100' ; 2 µs conversion (Fosc/16), AN2 analog input
MOVWF ANSEL
BCF STATUS,RP0 ; Select Bank 0
MOVLW B'00001001' ; A/D AN2, left justify (ADRESL:7,6 in Bank 1)
MOVWF ADCON0
MOVWF LEVEL ; LEVEL should not be zero due to LEVEL decay
CLRF GPIO
CLRF HEF1
CLRF HEF2
CLRF HEF3
CALL LAMPTEST
MAIN
CALL MEASURE
MOVFW LEVEL ; Get LEVEL
MOVWF PPM ; Save LEVEL to PPM
BCF LED1 ; Test PPM for LED1
ADDLW 0x06
BTFSC STATUS,C
BSF LED1
MOVFW PPM
BCF LED2
ADDLW 0x0B
BTFSC STATUS,C
BSF LED2
MOVFW PPM
BCF LED3
ADDLW 0x10
BTFSC STATUS,C
BSF LED3
MOVFW PPM
BCF LED4
ADDLW 0x16
BTFSC STATUS,C
BSF LED4
MOVFW PPM
BCF LED5
ADDLW 0x1A
BTFSC STATUS,C
BSF LED5
MOVFW PPM
BCF LED6
ADDLW 0x1F
BTFSC STATUS,C
BSF LED6
MOVFW PPM
BCF LED7
ADDLW 0x24
BTFSC STATUS,C
BSF LED7
MOVFW PPM
BCF LED8
ADDLW 0x29
BTFSC STATUS,C
BSF LED8
CALL MEASURE ; Extra measurement to prevent aliasing
MOVFW PPM
BCF LED9
ADDLW 0x2F
BTFSC STATUS,C
BSF LED9
MOVFW PPM
BCF LED10
ADDLW 0x34
BTFSC STATUS,C
BSF LED10
MOVFW PPM
BCF LED11
ADDLW 0x39
BTFSC STATUS,C
BSF LED11
MOVFW PPM
BCF LED12
ADDLW 0x3E
BTFSC STATUS,C
BSF LED12
MOVFW PPM
BCF LED13
ADDLW 0x44
BTFSC STATUS,C
BSF LED13
MOVFW PPM
BCF LED14
ADDLW 0x49
BTFSC STATUS,C
BSF LED14
MOVFW PPM
BCF LED15
ADDLW 0x4E
BTFSC STATUS,C
BSF LED15
MOVFW PPM
BCF LED16
ADDLW 0x53
BTFSC STATUS,C
BSF LED16
MOVFW PPM
BCF LED17
ADDLW 0x59
BTFSC STATUS,C
BSF LED17
MOVFW PPM
BCF LED18
ADDLW 0x5F
BTFSC STATUS,C
BSF LED18
MOVFW PPM
BCF LED19
ADDLW 0x65
BTFSC STATUS,C
BSF LED19
MOVFW PPM
BCF LED20
ADDLW 0x6B
BTFSC STATUS,C
BSF LED20
MOVFW PPM
BCF LED21
ADDLW 0x71
BTFSC STATUS,C
BSF LED21
MOVFW PPM
BCF LED22
ADDLW 0x78
BTFSC STATUS,C
BSF LED22
MOVFW PPM
BCF LED23
ADDLW 0x80
BTFSC STATUS,C
BSF LED23
MOVFW PPM
BCF LED24
ADDLW 0x87
BTFSC STATUS,C
BSF LED24
CALL MEASURE
CALL Show
GOTO MAIN
; Subroutines
Show ; Fill shift register
BCF OE ; Disable (Hi-Z) outputs HEF chip to prevent ghosting
BTFSC LED20 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED20 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED19 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED19 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED18 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED18 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED17 ; Bit clear?
BSF SDI ; Clear Data Line
BTFSS LED17 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED24 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED24 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED23 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED23 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED22 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED22 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED21 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED21 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
CALL MEASURE ; Extra measurement to prevent aliasing
BTFSC LED12 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED12 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED11 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED11 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED10 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED10 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED9 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED9 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED16 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED16 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED15 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED15 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED14 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED14 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED13 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED13 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED4 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED4 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED3 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED3 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED2 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED2 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED1 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED1 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED8 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED8 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED7 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED7 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED6 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED6 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BTFSC LED5 ; Bit clear?
BSF SDI ; No, set Serial Data Line
BTFSS LED5 ; Bit set?
BCF SDI ; No, clear Serial Data Line
BSF CLK
BCF CLK ; Output bit
BSF STRO
BCF STRO ; Strobe latch
BCF SDI ; Clear Data Line
BSF OE ; Done shift register, enable outputs
RETURN
MEASURE ; Measure LEVEL (9 bit A/D)
BSF ADCON0,GO ; Start A/D (read LEVEL)
CONV0
NOP
BTFSC ADCON0,GO ; Test if A/D conversion done
GOTO CONV0
BTFSC ADRESH,7 ; Input > 2.50 V?
GOTO OVERFLOW
BSF STATUS,RP0 ; Select Bank 1
MOVFW ADRESL ; Get A/D result
BCF STATUS,RP0 ; Select Bank 0
MOVWF TEMP ; Save measurement LEVEL
RLF TEMP,F ; Rotale MSB into carry
RLF ADRESH,W ; Rotate carry and ADRESH into W
MOVWF TEMP ; Save for max hold
DECFSZ d1,F ; Decay counter looped?
GOTO MAXH ; No
DECFSZ LEVEL ; Decay level
GOTO MAXH
INCF LEVEL,F ; Ensure LEVEL doesn't become zero
MAXH ; Max Hold routine
MOVFW TEMP ; Get new measurement
SUBWF LEVEL,W ; Subtract W from LEVEL and keep in W
BTFSC STATUS,C ; new measurement larger than LEVEL?
RETURN ; No
MOVFW TEMP ; Retrieve new measurement again
MOVWF LEVEL ; Store new LEVEL
RETURN
OVERFLOW
MOVLW 0xFF
MOVWF LEVEL
RETURN
LONGDLY
; 25 ms delay, used with Lamp Test
MOVLW 0x14
MOVWF d2
LONGDLY_0
DECFSZ d1,F
GOTO $+2
DECFSZ d2,F
GOTO LONGDLY_0
NOP
RETURN
LAMPTEST ; Lamp Test! Yeah!
BSF LED24
CALL Show
CALL LONGDLY
BSF LED23
CALL Show
CALL LONGDLY
BSF LED22
CALL Show
CALL LONGDLY
BSF LED21
CALL Show
CALL LONGDLY
BSF LED20
CALL Show
CALL LONGDLY
BSF LED19
CALL Show
CALL LONGDLY
BSF LED18
CALL Show
CALL LONGDLY
BSF LED17
CALL Show
CALL LONGDLY
BSF LED16
CALL Show
CALL LONGDLY
BSF LED15
CALL Show
CALL LONGDLY
BSF LED14
CALL Show
CALL LONGDLY
BSF LED13
CALL Show
CALL LONGDLY
BSF LED12
CALL Show
CALL LONGDLY
BSF LED11
CALL Show
CALL LONGDLY
BSF LED10
CALL Show
CALL LONGDLY
BSF LED9
CALL Show
CALL LONGDLY
BSF LED8
CALL Show
CALL LONGDLY
BSF LED7
CALL Show
CALL LONGDLY
BSF LED6
CALL Show
CALL LONGDLY
BSF LED5
CALL Show
CALL LONGDLY
BSF LED4
CALL Show
CALL LONGDLY
BSF LED3
CALL Show
CALL LONGDLY
BSF LED2
CALL Show
CALL LONGDLY
BSF LED1
CALL Show
CALL LONGDLY
BCF LED24
CALL Show
CALL LONGDLY
BCF LED23
CALL Show
CALL LONGDLY
BCF LED22
CALL Show
CALL LONGDLY
BCF LED21
CALL Show
CALL LONGDLY
BCF LED20
CALL Show
CALL LONGDLY
BCF LED19
CALL Show
CALL LONGDLY
BCF LED18
CALL Show
CALL LONGDLY
BCF LED17
CALL Show
CALL LONGDLY
BCF LED16
CALL Show
CALL LONGDLY
BCF LED15
CALL Show
CALL LONGDLY
BCF LED14
CALL Show
CALL LONGDLY
BCF LED13
CALL Show
CALL LONGDLY
BCF LED12
CALL Show
CALL LONGDLY
BCF LED11
CALL Show
CALL LONGDLY
BCF LED10
CALL Show
CALL LONGDLY
BCF LED9
CALL Show
CALL LONGDLY
BCF LED8
CALL Show
CALL LONGDLY
BCF LED7
CALL Show
CALL LONGDLY
BCF LED6
CALL Show
CALL LONGDLY
BCF LED5
CALL Show
CALL LONGDLY
BCF LED4
CALL Show
CALL LONGDLY
BCF LED3
CALL Show
CALL LONGDLY
BCF LED2
CALL Show
CALL LONGDLY
BCF LED1
CALL Show
CALL LONGDLY
RETURN
END