; filename: matrixscope.asm ; 24x16 LED Matrix Display Scope with 8x8 LED matrix displays (A-1088BS) and HEF4094B shift registers ; 221209 v0.1 Copied from LED PPM (and others) ; 221209 v0.2 Lose OE (always H). This saves clock cycles. ; 221212 v0.3 Trigger. This is a 1 µs wide positive pulse on RB0/INT pin. ; GPL Copyleft 2022 pic@polonai.se LIST P=16F818, F=INHX8M #include <p16f818.inc> __CONFIG _WDT_OFF & _PWRTE_OFF & _HS_OSC & _MCLR_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_ENABLE_OFF & _DEBUG_OFF & _CCP1_RB2 & _CP_OFF ERRORLEVEL -302 ; sod message about using proper bank ; Equates RESET_V EQU 0x00 ; Address of RESET Vector ; Registers FLAGS EQU 0x20 ; Various flags SWP EQU 0x21 ; Sweep time value SWPCNT EQU 0x22 ; Sweep time counter SWPPOS EQU 0x23 ; Sweep position counter Y EQU 0x24 ; Vertical value (4 bit) ; PORTA,0 A/D input for vertical has no name defined #define DN PORTA,3 ; SW1 (DN) Slower sweep button #define UP PORTA,4 ; SW2 (UP) Faster sweep button ; PORTB,0 RB0/INT input for trigger has no name defined #define SDI PORTB,1 ; Serial Data line of HEF4094s #define CLKX PORTB,2 ; Clock for horizontal HEF4094s (high pulse) #define CLKY PORTB,3 ; Clock for vertical HEF4094s (high pulse) #define STROE PORTB,4 ; Strobe for HEF4094s (high pulse) #define HELD FLAGS,0 ; Button Held flag to provide rudimentary debounce org 0x00 GOTO START org 0x04 ; Interrupts ; Timer0/RB0/INT Interrupt Handler ; Runs every 32768 µs and RB0/INT trigger event BTFSC INTCON,INTF GOTO Trigger BCF INTCON,TMR0IF ; Clear TMR0 interrupt BTFSS UP ; <UP> button pressed? GOTO Sweep_INC ; Sweep faster BTFSS DN ; <DN> button pressed? GOTO Sweep_DEC ; Sweep slower BCF HELD ; Debounce reset RETFIE Sweep_INC BTFSC HELD ; Button held? RETFIE ; Yes BSF HELD BCF STATUS,C ; Clear carry RRF SWP,F ; Half sweep time BTFSS STATUS,C ; Did the single one shift into the carry? RETFIE MOVLW B'10000000' ; Load longest sweep time MOVWF SWP RETFIE Sweep_DEC BTFSC HELD ; Button held? RETFIE ; Yes BSF HELD BCF STATUS,C ; Clear carry RLF SWP,F ; Double sweep time BTFSS STATUS,C ; Did the single one shift into the carry? RETFIE MOVLW B'00000001' ; Load shortest sweep time MOVWF SWP RETFIE Trigger BCF INTCON,INTF ; Clear RB0/INT interrupt MOVLW 0x0A SUBWF SWPPOS,W BTFSC STATUS,C ; Sweep position near the end? RETFIE ; No MOVFW SWP ; Restore sweep time MOVWF SWPCNT BSF CLKX BCF CLKX DECFSZ SWPPOS ; Clock out single zero until it's gone GOTO $-3 MOVLW 0x20 MOVWF SWPPOS BCF SDI ; Clock out the single 0 BSF CLKX BCF CLKX BSF SDI BSF STROE BCF STROE RETFIE ; End interrupt routines START ; Init stuff CLRF STATUS ; Do initialization, Select bank 0 CLRF INTCON CLRF PCLATH ; Keep in lower 2KByte CLRF CCP1CON BSF STATUS,RP0 ; Select bank 1 MOVLW B'00111101' MOVWF TRISA ; RA7,6,1 Outputs, 5-2,0 Inputs MOVLW B'00000001' MOVWF TRISB ; RB7-1 Outputs, 0 Input MOVLW B'00000110' ; Timer0, prescaler 1:128 MOVWF OPTION_REG MOVLW B'01110000' ; 8 MHz clock MOVWF OSCCON MOVLW B'00001110' ; AN0 Analog input, AN1-4 Digital IO, ADRESH only (ADRESL discarded) MOVWF ADCON1 BCF STATUS,RP0 ; Select bank 0 MOVLW B'01000001' ; AD conv ON, AN0 Selected, Fosc/8 (T(AD)=1us) MOVWF ADCON0 CLRF PORTA ; Make all PORT A outputs low CLRF PORTB ; Make all PORT B outputs low CLRF TMR0 ; Reset Timer 0 MOVLW B'10000000' ; Load longest sweep time MOVWF SWP MOVWF SWPCNT ; and sweep counter MOVLW 0x20 MOVWF SWPPOS ; Preload position BSF INTCON,TMR0IE ; Enable Timer0 interrupt BSF INTCON,INTE ; Enable external interrupt on RB0 BSF INTCON,GIE ; Enable global interrupts MAIN CALL YDECODE ; Determine vertical position DECFSZ SWPCNT,F ; Next sweep point? GOTO MAIN ; No MOVFW SWP ; Get new sweep time MOVWF SWPCNT BSF CLKX BCF CLKX BSF STROE BCF STROE ; Clock out the single 0 further on DECFSZ SWPPOS GOTO MAIN MOVLW 0x20 MOVWF SWPPOS ; Preload position. Note that the 0 gets clocked out beyond 24 LEDs. BCF SDI ; Clock out the single 0 to first position BSF CLKX BCF CLKX BSF SDI BSF STROE BCF STROE GOTO MAIN ; Subroutines YDECODE ; Read A/D and load vertical shift register BCF INTCON,GIE ; Disable global interrupts BSF ADCON0,GO ; Start A/D (Vertical Input) CONV NOP BTFSC ADCON0,GO ; Test if done GOTO CONV ; Not done MOVLW 0xF0 ANDWF ADRESH,W ; Get A/D value and blank lower nibble MOVWF Y ; Store it in Y MOVLW 0x80 SUBWF Y,W ; Test for 0x80. Note that IC1 and 2 were swapped in the prototype so the sequence is too. BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0x90 SUBWF Y,W ; Test for 0x90 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0xA0 SUBWF Y,W ; Test for 0xA0 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0xB0 SUBWF Y,W ; Test for 0xB0 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0xC0 SUBWF Y,W ; Test for 0xC0 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0xD0 SUBWF Y,W ; Test for 0xD0 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0xE0 SUBWF Y,W ; Test for 0xE0 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0xF0 SUBWF Y,W ; Test for 0xF0 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit CLRW SUBWF Y,W ; Test for 0x00 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0x10 SUBWF Y,W ; Test for 0x10 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0x20 SUBWF Y,W ; Test for 0x20 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0x30 SUBWF Y,W ; Test for 0x30 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0x40 SUBWF Y,W ; Test for 0x40 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0x50 SUBWF Y,W ; Test for 0x50 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0x60 SUBWF Y,W ; Test for 0x60 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit MOVLW 0x70 SUBWF Y,W ; Test for 0x70 BCF SDI BTFSC STATUS,Z ; Match? BSF SDI ; Yes BSF CLKY BCF CLKY ; Clock out bit BSF STROE BCF STROE BSF SDI ; Make sure horizontal sweep works BSF INTCON,GIE ; Re-enable interrupts RETURN END