;******************************************************************
;* *
;* Filename: 16F628A Mux Test.asm *
;* Author: Mike McLaren, K8LH *
;* (C)2010: Micro Application Consultants *
;* Date: 25-May-10 *
;* *
;* test the 4-digit interrupt display driver architecture *
;* *
;* MPLab: 8.50 (tabs = 8) *
;* MPAsm: 5.35 *
;* *
;******************************************************************
include "P16F628A.inc"
errorlevel -302 ; suppress bank warnings
list st=off ; suppress symbol table
radix dec ; default radix = decimal
__CONFIG _LVP_OFF & _WDT_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_OFF
;--< variables >---------------------------------------------------
column equ 0x20 ; column number, 0..3
colsel equ 0x21 ; column select bit
huns equ 0x22 ; huns, 0..1
tens equ 0x23 ; tens, 0..9
ones equ 0x24 ; ones, 0..9
tenths equ 0x25 ; tenths, 0..9
w_isr equ 0x70 ;
s_isr equ 0x71 ;
p_isr equ 0x72 ;
f_isr equ 0x73 ;
;******************************************************************
; reset vector *
;******************************************************************
org 0x000
vReset
clrf STATUS ; force bank 0, IRP = 0 |B0
goto Init ; |B0
;******************************************************************
; interrupt vector, 1 msec Timer 2 interrupts *
;******************************************************************
;
; unsigned char column = 0; // column (digit) number, 0..3
; unsigned char colsel = 8; // column select bit '00001000'
;
; unsigned char disp[] = { 1,2,3,4 }; // huns,tens,ones,tenths
;
; const rom char seg[] = { 0b11101110, // "0" B|A|F|-|E|D|C|-
; 0b10000010, // "1" B|-|-|-|-|-|C|-
; 0b11011100, // "2" B|A|-|G|E|D|-|-
; 0b11010110, // "3" B|A|-|G|-|D|C|-
; 0b10110010, // "4" B|-|F|G|-|-|C|-
; 0b01110110, // "5" -|A|F|G|-|D|C|-
; 0b01111110, // "6" -|A|F|G|E|D|C|-
; 0b11000010, // "7" B|A|-|-|-|-|C|-
; 0b11111110, // "8" B|A|F|G|E|D|C|-
; 0b11110110, // "9" B|A|F|G|-|D|C|-
; 0b00000000, // " " -|-|-|-|-|-|-|-
; 0b00010000 }; // "-" -|-|-|G|-|-|-|-
;
; void interrupt()
; { pir1.TMR2IF = 0; // clear timer 2 interrupt flag
; portb = 0; // blank the display
; porta &= 0xF0 // turn off column select bits
; porta |= colsel; // select new column (digit)
; portb = seg[disp[column]]; // display new column (digit)
; column = (column + 1) & 3; // bump column, 0..3 inclusive
; colsel >>= 1; // shift column select bit
; if(colsel == 0) // if last column
; colsel = 8; // reset to '00001000'
; } //
;
org 0x004
vInt
movwf w_isr ; save WREG |B?
swapf STATUS,W ; don't change STATUS bits |B?
movwf s_isr ; save STATUS reg |B?
clrf STATUS ; bank 0 |B0
movf PCLATH,W ; |B0
movwf p_isr ; save PCLATH |B0
clrf PCLATH ; force page 0 |B0
movf FSR,W ; |B0
movwf f_isr ; save FSR |B0
bcf PIR1,TMR2IF ; clear TMR2 interrupt flag |B0
;
; refresh display
;
clrf PORTB ; blank the display |B0
movf PORTA,W ; |B0
andlw b'11110000' ; clear column select bits |B0
iorwf colsel,W ; `1000,`0100, `0010, or `0001 |B0
movwf PORTA ; select new column |B0
movf column,W ; column number, 0..3 |B0
addlw huns ; add to 'huns' address |B0
movwf FSR ; FSR = &temp[column] |B0
movf INDF,W ; WREG = 0..9 |B0
call segtable ; get segment data |B0
btfsc colsel,1 ; 2nd column? no, skip, else |B0
iorlw 1 ; set "decimal point" bit |B0
movwf PORTB ; display new column |B0
;
; prepare for next column interrupt
;
incf column,F ; bump column number |B0
bcf column,2 ; 0..3, inclusive |B0
clrc ; |B0
rrf colsel,F ; advance column select bit |B0
skpnc ; last column? no, skip, else |B0
bsf colsel,3 ; reset to column 1 (00001000) |B0
;
; restore context
;
movf f_isr,W ; |B0
movwf FSR ; restore FSR |B0
movf p_isr,W ; |B0
movwf PCLATH ; restore PCLATH |B0
swapf s_isr,W ; |B0
movwf STATUS ; restore STATUS |B?
swapf w_isr,f ; don't change STATUS bits |B?
swapf w_isr,W ; restore WREG |B?
retfie ; |B?
;
; segment data table (caveat, non-boundary tolerant)
;
segtable ; map B|A|F|G|E|D|C|P
addwf PCL,F ; |B0
retlw b'11101110' ; "0" B|A|F|-|E|D|C|- |B0
retlw b'10000010' ; "1" B|-|-|-|-|-|C|- |B0
retlw b'11011100' ; "2" B|A|-|G|E|D|-|- |B0
retlw b'11010110' ; "3" B|A|-|G|-|D|C|- |B0
retlw b'10110010' ; "4" B|-|F|G|-|-|C|- |B0
retlw b'01110110' ; "5" -|A|F|G|-|D|C|- |B0
retlw b'01111110' ; "6" -|A|F|G|E|D|C|- |B0
retlw b'11000010' ; "7" B|A|-|-|-|-|C|- |B0
retlw b'11111110' ; "8" B|A|F|G|E|D|C|- |B0
retlw b'11110110' ; "9" B|A|F|G|-|D|C|- |B0
retlw b'00000000' ; " " -|-|-|-|-|-|-|- |B0
retlw b'00010000' ; "-" -|-|-|G|-|-|-|- |B0
;******************************************************************
; main.init *
;******************************************************************
Init
movlw 7 ; |B0
movwf CMCON ; |B0
bsf STATUS,RP0 ; bank 1 |B1
movlw b'11110000' ; |B1
movwf TRISA ; A7-A4 inputs, A3-A0 outputs |B1
clrf TRISB ; portb all outputs |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PORTB ; clear portb output latches |B0
;
; init program variables
;
clrf column ; column = 0 (1st column) |B0
movlw b'00001000' ; column select bit mask |B0
movwf colsel ; |B0
movlw 1 ; display "123.4"
movwf huns ;
movlw 2 ;
movwf tens ;
movlw 3 ;
movwf ones ;
movlw 4 ;
movwf tenths ;
;
; setup TMR2 for 1 msec periodic interrupts (4 MHz clock)
;
clrf TMR2 ; clear TMR2 register |B0
bsf STATUS,RP0 ; bank 1 |B1
clrf PIE1 ; mask all peripheral irqs |B1
bsf PIE1,TMR2IE ; except for TMR2 irq |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf PIR1 ; clear peripheral irq flags |B0
movlw b'00000001' ; '00000001' |B0
; '0-------' unused
; '-0000---' postscale 1
; '-----0--' TMR2 off
; '------01' prescale 4
movwf T2CON ; for 4-usec ticks (4-MHz clk) |B0
bsf STATUS,RP0 ; bank 1 |B1
movlw d'250'-1 ; 250 X 4-usec ticks = 1-msec |B1
movwf PR2 ; for 1-msec interrupts |B1
bcf STATUS,RP0 ; bank 0 |B0
bsf INTCON,GIE ; enable global irqs |B0
bsf INTCON,PEIE ; enable peripheral irqs |B0
bsf T2CON,TMR2ON ; start TMR2 |B0
Loop
goto $ ; |B0
;******************************************************************
end