;************************************************************************** ; picxie2.asm ; Project 98-0380-AUS-P ; Revision 1.00 ; Release Status Public ; Target MCU PIC16C84/PIC16F84 ; ; REFER TO HARDWARE NOTES IN ACCOMPANYING TECHNICAL REFERENCE DOCUMENTS! ; IN BRIEF: To initialize a row/column configuration, place the ROW data ; (desired row select bit should be HIGH, all other row select bits should ; be LOW) on PORTB<0:7> and supply a rising edge on PORTA:1. Now place the ; COLUMN data on PORTB<0:7> (bit meaning is 0=lit LED, 1=dark LED) and ; supply a rising edge on PORTA:0. This order of events may safely be ; reversed. BEFORE moving to the next row, you MUST LATCH UP 'FF' into the ; column lines to blank the display, otherwise you will get 100% ; crosstalk from one row to the next! ; ; DO NOT select multiple rows simultaneously or you may overload the column ; driver IC's current sink capabilities (additionally, some or all LEDs may ; fail to illuminate fully, or indeed at all).
;************************************************************************** TITLE "98-0380-AUS-P (picxie2) V1.00 - (C) 1998 Lewin Edwards (sysadm@zws.com)"
INCLUDE "P16F84.INC"
LIST P=16F84 __CONFIG B'11111111110001' ;All protection off, powerup timer on, WDT off, XT osc
;-------------------------------------------------------------------------- ; Behavioral constants DEFAULT_MULTIPLEX_RATE EQU H'50' ;Multiplex speed. Probably don't need to modify this. DEFAULT_FRAME_RATE EQU H'20' ;Default number of times to display frame SCREEN_HEIGHT EQU H'08' ;Number of lines on screen SCREEN_WIDTH EQU H'08' ;Number of columns on screen
;-------------------------------------------------------------------------- ; RAM assignments in bank 0 (0Ch-4Fh) SDelayCount EQU H'0C' ;Temporary variable used by short (refresh) delay FrameDelay EQU H'0D' ;Temporary variable used by screen display routine
Screen0 EQU H'10' ;The screen is "overscanned". Each buffer occupies 8 bytes. Screen1 EQU H'18' ;So area 10-1Fh is used entirely for video RAM
FrameRate EQU H'44' ;Number of times to display frame BallDY EQU H'45' ;Ball y-velocity (nonvolatile) BallDX EQU H'46' ;Ball x-velocity (nonvolatile) BallY EQU H'47' ;Ball y-coord (nonvolatile) BallX EQU H'48' ;Ball x-coord (nonvolatile) FrameTemp EQU H'49' ;Temporary row select value used by DisplayFrame ;Also used as temporary ball byte by UpdateBall FrameCount EQU H'4A' ;Frame position pointer used by DisplayFrame MultiplexRate EQU H'4B' ;1-FFh, the higher it is, the slower the multiplex rate Scratch0 EQU H'4C' ;scratch value used by: RotateUp,BlankScreen,LightScreen,RepeatFrame Scratch1 EQU H'4D' ;scratch value used by: RotateUp,UpdateBall Scratch2 EQU H'4E' ;scratch value used by: RepeatRotUp,RepeatBall Scratch3 EQU H'4F' ;scratch value used by: Negative
;-------------------------------------------------------------------------- ; Power-on code ; MUST originate at 0x000 because the reset vector will start ; executing there. ; Power-up state of MCU is PC=000h, STATUS=00011xxx ;-------------------------------------------------------------------------- ORG 0 PowerOn BSF STATUS,RP0 ;Select file bank 1
MOVLW H'00' MOVWF TRISB ;Set all PORTB bits as outputs (display driver) MOVWF TRISA ;Set all PORTA bits as outputs (will be inputs in future version) MOVLW B'11010111' ;Turn off PORTB pullups, prescaler to TMR0, 1:256 scaling MOVWF OPTION_REG
;------------------------------------------------------------ ; Setup default refresh and frame rate BCF STATUS,RP0 ;Select file bank 0 MOVLW DEFAULT_MULTIPLEX_RATE MOVWF MultiplexRate MOVLW DEFAULT_FRAME_RATE MOVWF FrameRate
;------------------------------------------------------------ ; Place ball onscreen (ball position is nonvolatile) MOVLW H'03' MOVWF BallX MOVLW H'00' MOVWF BallY MOVLW H'01' MOVWF BallDX MOVWF BallDY
;------------------------------------------------------------ ; Power-on - show version CALL ShowVersion MOVLW H'10' CALL RepeatFrame
;------------------------------------------------------------ ; Main program loop with various sequenced effects MainLoop ; Restore default refresh and frame rate BCF STATUS,RP0 ;Select file bank 0 MOVLW DEFAULT_MULTIPLEX_RATE MOVWF MultiplexRate MOVLW DEFAULT_FRAME_RATE MOVWF FrameRate
;------------------------------------------------------------ ; Show PIC-2 logo and rotate it upwards four times CALL Pic2Logo MOVLW H'10' CALL RepeatFrame MOVLW H'40' CALL RepeatRotUp
;------------------------------------------------------------ ; Fade out
CALL ShowSkull MOVLW H'10' CALL RepeatFrame CALL BlankScreen MOVLW H'04' CALL RepeatFrame CALL ShowSkull MOVLW H'10' CALL RepeatFrame
;------------------------------------------------------------ ; Set faster frame rate, show 256 frames of bouncing ball, ; then restore frame rate to default MOVLW DEFAULT_FRAME_RATE / 2 MOVWF FrameRate
MOVLW H'00' CALL RepeatBall
MOVLW DEFAULT_FRAME_RATE MOVWF FrameRate
;------------------------------------------------------------ ; Loop around until batteries run out (implied conditional expression :-) GOTO MainLoop
;-------------------------------------------------------------------------- ; SUBROUTINE Show the same frame [W] times ; ENTRY W = number of repeats ;-------------------------------------------------------------------------- RepeatFrame MOVWF Scratch0 RFLoop CALL DisplayFrame DECFSZ Scratch0,1 GOTO RFLoop
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Rotate up [W] times ; ENTRY W = number of repeats ;-------------------------------------------------------------------------- RepeatRotUp MOVWF Scratch2 RRULoop CALL RotateUp CALL DisplayFrame DECFSZ Scratch2,1 GOTO RRULoop
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Repeat ball bounce [W] times ; ENTRY W = number of repeats ;-------------------------------------------------------------------------- RepeatBall MOVWF Scratch2 RBLLoop CALL UpdateBall CALL DisplayFrame DECFSZ Scratch2,1 GOTO RBLLoop
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Short delay for multiplexing ;-------------------------------------------------------------------------- ShortDelay MOVF MultiplexRate,0 ;Get current selected multiplex rate MOVWF SDelayCount ;Store desired delay count SDelayLoop NOP NOP NOP NOP DECFSZ SDelayCount,1 GOTO SDelayLoop
RETLW 0 ;Ignore return value
;-------------------------------------------------------------------------- ; SUBROUTINE Show frame for a short interval ;-------------------------------------------------------------------------- DisplayFrame MOVF FrameRate,0 ;get number of frame repeats MOVWF FrameDelay
DFOuterLoop MOVLW SCREEN_HEIGHT ;Set number of lines to show MOVWF FrameCount MOVLW H'01' ;Row 0 (bottom) MOVWF FrameTemp ;Temporary row select value
MOVLW Screen0 + SCREEN_HEIGHT ;Locate top of screen MOVWF FSR
DFLoop MOVLW B'00000000' ;set both row/col flipflop clock lines low (inactive) MOVWF PORTA DECF FSR,1 ;increment row pointer while we're waiting MOVF INDF,0 ;get data for current row MOVWF PORTB MOVLW B'00000001' ;set column strobe MOVWF PORTA MOVF FrameTemp,0 ;get current selected row MOVWF PORTB MOVLW B'00000010' ;set row strobe MOVWF PORTA RLF FrameTemp,1 ;select next row while we're waiting BCF FrameTemp,0 CALL ShortDelay ;let the frame sit for a while MOVLW B'11111111' ;blank the column lines to avoid crosstalk MOVWF PORTB MOVLW B'00000001' ;set column strobe MOVWF PORTA
; NB: It isn't absolutely necessary to blank the row lines, but it does ; prevent slight "ghosting" which will otherwise occur. For example, comment ; out these four lines and look at the LED in the top line, third from the ; right-hand edge, during the V1.0 firmware version screen at powerup. It ; should be completely dark; it will be about 25% on. MOVLW B'00000000' ;blank the row lines to avoid crosstalk MOVWF PORTB MOVLW B'00000010' ;set row strobe MOVWF PORTA
DECFSZ FrameCount,1 ;loop around until all lines are done GOTO DFLoop
DECFSZ FrameDelay,1 GOTO DFOuterLoop
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Show ball in its current position, and update ; BallX, BallY, BallDX and BallDY. ;-------------------------------------------------------------------------- UpdateBall CALL BlankScreen MOVLW Screen0 ;first calculate destination addres MOVWF FSR MOVF BallY,0 ADDWF FSR,1 ;FSR now has destination line MOVLW B'01111111' ;Default (0) position of ball MOVWF FrameTemp MOVF BallX,0 ;get ball X-pos MOVWF Scratch1 INCF Scratch1,1 UBLoop DECF Scratch1,1 ;decrement ball x-pos count BTFSC STATUS,Z ;reached zero? GOTO UBLDone ;yes-> BSF STATUS,C ;set carry RRF FrameTemp,1 GOTO UBLoop
UBLDone MOVF FrameTemp,0 MOVWF INDF ;set ball position
; Now update ball position MOVF BallDX,0 ADDWF BallX,1 MOVF BallDY,0 ADDWF BallY,1
; Update ball velocity if it has bounced MOVLW SCREEN_WIDTH - 1 SUBWF BallX,0 BTFSS STATUS,Z GOTO NoXRBounce
XBounce COMF BallDX,1 ;BallDX = -BallDX INCF BallDX,1 GOTO TestYBounce
NoXRBounce MOVLW H'00' SUBWF BallX,0 BTFSC STATUS,Z GOTO XBounce
TestYBounce MOVLW SCREEN_HEIGHT - 1 SUBWF BallY,0 BTFSS STATUS,Z GOTO NoYBBounce
YBounce COMF BallDY,1 ;BallDY = -BallDY INCF BallDY,1 GOTO YBDone
NoYBBounce MOVLW H'00' SUBWF BallY,0 BTFSC STATUS,Z GOTO YBounce
YBDone
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Show a skull, eyes black ;-------------------------------------------------------------------------- ShowSkull MOVLW B'11000011' MOVWF Screen0 MOVWF Screen0+H'6' MOVLW B'10000001' MOVWF Screen0+H'1' MOVWF Screen0+H'5' MOVLW B'00000000' MOVWF Screen0+H'2' MOVWF Screen0+H'4' MOVLW B'00100100' MOVWF Screen0+H'3' MOVLW B'10100101' MOVWF Screen0+H'7'
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Set up PIC-2 logo in screen buffer (8x16 pixel) ; NB the graphics are "compressed" :-) ;-------------------------------------------------------------------------- Pic2Logo MOVLW B'00110110' MOVWF Screen0 MOVLW B'01010101' MOVWF Screen0+H'1' MOVWF Screen0+H'7' MOVWF Screen0+H'9' MOVLW B'00110101' MOVWF Screen0+H'2' MOVLW B'01110101' MOVWF Screen0+H'3' MOVLW B'01110110' MOVWF Screen0+H'4' MOVLW B'11111111' MOVWF Screen0+H'5' MOVWF Screen0+H'B' MOVWF Screen0+H'F' MOVLW B'01010100' MOVWF Screen0+H'6' MOVWF Screen0+H'A' MOVLW B'10110100' MOVWF Screen0+H'8' MOVLW B'10000001' MOVWF Screen0+H'C' MOVWF Screen0+H'E' MOVLW B'11011011' MOVWF Screen0+H'D'
CALL DisplayFrame
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Rotate screen buffer UP one line (top line of ; offscreen buffer becomes bottom line of onscreen) ; Scratch0 - line counter ; Scratch1 - swap holding register ;-------------------------------------------------------------------------- RotateUp MOVLW (SCREEN_HEIGHT * 2) - 1 MOVWF Scratch0
; Setup destination pointer MOVLW Screen0+1 MOVWF FSR
; Save the top line of the display MOVF Screen0,0 MOVWF Scratch1
RULoop MOVF INDF,0 ;get line DECF FSR,1 ;locate destination MOVWF INDF ;put line data in new location INCF FSR,1 ;locate next line source INCF FSR,1 DECFSZ Scratch0,1 GOTO RULoop
; Restore the top line of the display (now the bottom line) MOVF Scratch1,0 MOVWF Screen0+(SCREEN_HEIGHT * 2) - 1
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Show firmware version number ;-------------------------------------------------------------------------- ShowVersion MOVLW B'01011111' MOVWF Screen0 MOVWF Screen0+H'1' MOVLW B'10111111' MOVWF Screen0+H'2' MOVLW B'11111111' MOVWF Screen0+H'3' MOVLW B'01111011' MOVWF Screen0+H'4' MOVLW B'01110101' MOVWF Screen0+H'5' MOVWF Screen0+H'6' MOVLW B'01011011' MOVWF Screen0+H'7' RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Clear video memory (LEDs off next frame) ;-------------------------------------------------------------------------- BlankScreen MOVLW Screen0 ;Locate top of screen MOVWF FSR ;set pointer MOVLW SCREEN_HEIGHT * 2 ;number of bytes MOVWF Scratch0 MOVLW B'11111111' ;all LEDs off BSLoop MOVWF INDF INCF FSR,1 ;increment pointer DECFSZ Scratch0,1 GOTO BSLoop
RETLW 0
;-------------------------------------------------------------------------- ; SUBROUTINE Clear video memory (LEDs on next frame) ;-------------------------------------------------------------------------- LightScreen MOVLW Screen0 ;Locate top of screen MOVWF FSR ;set pointer MOVLW SCREEN_HEIGHT * 2 ;number of bytes MOVWF Scratch0 MOVLW B'00000000' ;all LEDs on LSLoop MOVWF INDF INCF FSR,1 ;increment pointer DECFSZ Scratch0,1 GOTO LSLoop
RETLW 0
END |