;************************************************************************** ; FILE: baird.asm * ; CONTENTS: Baird television * ; COPYRIGHT: MadLab Ltd. 2003-2005 * ; AUTHOR: James Hutchby * ; UPDATED: 25/01/05 * ;************************************************************************** list p=12F629 #include "p12f629.inc" __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _PWRTE_ON & _BODEN_ON & _CP_ON & _CPD_ON __idlocs h'DF11' errorlevel -207,-302,-305,-306 ;************************************************************************** ; * ; Specification * ; * ;************************************************************************** ; power-up self-test - LED bars flash twice ; if pushbutton held down on power-up, echoes sensor to LEDs ; motor takes > 10s to come to speed ; display area = 30mm x 20mm ; 15 x 10 pixels (approx. 2mm square pixels) ; pushbutton toggles between two animation sequences ;************************************************************************** ; * ; Port assignments * ; * ;************************************************************************** GPIO_IO equ b'011111' ; port I/O status LED equ 5 ; LED bars SENSOR equ 1 ; opto sensor BUTTON equ 0 ; pushbutton ;************************************************************************** ; * ; Constants and timings * ; * ;************************************************************************** CLOCK equ d'4000000' ; processor clock frequency in Hz ROWS equ d'15' ; number of pixel rows COLUMNS equ d'10' ; number of pixel columns TLC equ -d'16' ; index of top left corner (was -17) ;************************************************************************** ; * ; File register usage * ; * ;************************************************************************** RAM equ h'20' cblock RAM flags ; various flags anim ; animation, 0 or 1 ndx ; pixel index (0 to ROWS*COLUMNS-1) pixel ; pixel counter loop ; loop counter counter ; frame counter timing ; timing delay timer ; timer work1, work2 ; work registers endc ; flags PULSE equ 0 ; set if pulse detected PRESS equ 1 ; set if pushbutton currently pressed PRESS_ equ 2 ; set if pushbutton previously pressed ;************************************************************************** ; * ; Macros * ; * ;************************************************************************** routine macro label ; routine label endm table macro label ; define lookup table label addwf PCL endm entry macro value ; define table entry retlw value endm index macro label ; index lookup table call label endm jump macro label ; jump through table goto label endm tstw macro ; test w register iorlw 0 endm movff macro f1,f2 ; move file to file movfw f1 movwf f2 endm movlf macro n,f ; move literal to file movlw n movwf f endm tris_ macro t movlw t bsf STATUS,RP0 movwf TRISIO bcf STATUS,RP0 endm ;-------------------------------------------------------------------------- ; reset vector ;-------------------------------------------------------------------------- org 0 bsf STATUS,RP0 call h'3ff' movwf OSCCAL bcf STATUS,RP0 goto main_entry lookup movwf PCL ;************************************************************************** ; * ; Lookup tables * ; * ;************************************************************************** table masks entry b'10000000' entry b'01000000' entry b'00100000' entry b'00010000' entry b'00001000' entry b'00000100' entry b'00000010' entry b'00000001' frame_begin macro dots set 0 pixels set 0 endm line macro pix dots set (dots<= d'16' entry high (dots>>(pixels-d'16')) entry low (dots>>(pixels-d'16')) dots set dots&((1<<(pixels-d'16'))-1) pixels set pixels-d'16' endif endm frame_end macro dots set dots<<(d'16'-pixels) entry high dots if pixels > d'8' entry low dots endif endm table frames frame macro addr entry low addr entry high addr endm frame run1 ; animation #1 frame run2 frame run3 frame run4 frame run1 frame run2 frame run3 frame run4 frame run1 frame run2 frame run3 frame run4 frame run1 frame run2 frame run3 frame run4 frame run1 frame run2 frame run3 frame run4 frame run1 frame run2 frame run3 frame run4 frame hurdle1 frame hurdle2 frame hurdle3 frame hurdle4 frame hurdle5 frame hurdle6 frame hurdle7 frame hurdle8 frame jump1 ; animation #2 frame jump1 frame jump1 frame jump1 frame jump1 frame jump1 frame jump1 frame jump1 frame jump2 frame jump3 frame jump4 frame jump5 frame jump6 frame jump7 frame jump8 frame jump9 frame jump10 frame jump11 frame jump12 frame jump1 frame jump1 frame jump2 frame jump3 frame jump4 frame jump5 frame jump6 frame jump7 frame jump8 frame jump9 frame jump10 frame jump11 frame jump12 run1 frame_begin line b'0000000000' line b'0000000000' line b'0000011000' line b'0000011000' line b'0000000000' line b'0011110000' line b'0010111010' line b'0010110100' line b'0000110000' line b'0001111100' line b'0001000100' line b'0111000100' line b'1000000011' line b'0000000000' line b'1111111111' frame_end run2 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000011000' line b'0000011000' line b'0000000000' line b'0001110000' line b'0010111100' line b'0010110000' line b'0000101000' line b'0000100100' line b'0111100100' line b'0100000110' line b'0000000010' line b'1111111111' frame_end run3 frame_begin line b'0000000000' line b'0000000000' line b'0000011000' line b'0000011000' line b'0000000000' line b'0000110000' line b'0000110000' line b'0000111000' line b'0000110100' line b'0000110000' line b'0000101000' line b'0111000100' line b'0100000100' line b'0000000110' line b'1111111111' frame_end run4 frame_begin line b'0000000000' line b'0000000000' line b'0000011000' line b'0000011000' line b'0000000000' line b'0000110000' line b'0001110000' line b'0001110000' line b'0000111000' line b'0000100000' line b'0000110000' line b'0011110000' line b'0010010000' line b'0000011000' line b'1111111111' frame_end hurdle1 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000011000' line b'0000011000' line b'0001110000' line b'0010110000' line b'0100110000' line b'0000100000' line b'1101010001' line b'1010001001' line b'0000010001' line b'0000011001' line b'1111111111' frame_end org h'100' hurdle2 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000110000' line b'0000110000' line b'0000000000' line b'0000110000' line b'0001110000' line b'0010110000' line b'0010100000' line b'0000010010' line b'0000001010' line b'0000110010' line b'0000100010' line b'1111111111' frame_end hurdle3 frame_begin line b'0000000000' line b'0000000000' line b'0000110000' line b'0000110010' line b'0000000100' line b'0000111000' line b'0000110000' line b'0000111000' line b'0000110101' line b'0000100010' line b'0001000100' line b'0010000100' line b'0100000100' line b'0010000100' line b'1111111111' frame_end hurdle4 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000110100' line b'0001111000' line b'0011000000' line b'0011100000' line b'0111010100' line b'0100001000' line b'0000000000' line b'0000010000' line b'0000010000' line b'0000010000' line b'0000010000' line b'1111111111' frame_end hurdle5 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000110000' line b'0011111100' line b'0011000000' line b'0011100000' line b'0011111000' line b'0000001000' line b'0000001100' line b'0001000000' line b'0001000000' line b'0001000000' line b'0001000000' line b'1111111111' frame_end hurdle6 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0100000000' line b'0010110000' line b'0010110000' line b'0011000000' line b'0001100000' line b'0001100000' line b'0001110000' line b'0100010000' line b'0100001000' line b'0100001010' line b'0100000100' line b'1111111111' frame_end hurdle7 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000011000' line b'0011111000' line b'0010111010' line b'0010111100' line b'0000110000' line b'0000010000' line b'1000001000' line b'1000010000' line b'1000100000' line b'1000110000' line b'1111111111' frame_end hurdle8 frame_begin line b'0000000000' line b'0000000000' line b'0000001100' line b'0000001100' line b'0000000001' line b'0000111101' line b'0011001010' line b'0000001000' line b'0000001110' line b'0000010010' line b'0000100010' line b'0001000011' line b'0010000000' line b'0001000000' line b'1111111111' frame_end jump1 frame_begin line b'0000000000' line b'0000000000' line b'0000110000' line b'0000110000' line b'0000000000' line b'0001111000' line b'0010110100' line b'0010110100' line b'0010110100' line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0001111000' line b'0000000000' frame_end jump2 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000110000' line b'0100110010' line b'0010110100' line b'0001111000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0001111000' line b'0010000100' line b'0001001000' line b'0011001100' line b'0000000000' frame_end jump3 frame_begin line b'0000000000' line b'0000000000' line b'0000110000' line b'0000110000' line b'0000000000' line b'0001111000' line b'0010110100' line b'0100110010' line b'0000110000' line b'0001111000' line b'0011001100' line b'0010000100' line b'0001001000' line b'0011001100' line b'0000000000' frame_end jump4 frame_begin line b'0001111000' line b'0010110100' line b'0010110100' line b'0010110100' line b'0000110000' line b'0000110000' line b'0000110000' line b'0001111000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' frame_end jump5 frame_begin line b'0000110000' line b'0000110000' line b'0000110000' line b'0001111000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' frame_end jump6 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' frame_end org h'200' jump7 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' frame_end jump8 frame_begin line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0001111000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' frame_end jump9 frame_begin line b'0000110000' line b'0000000000' line b'0001111000' line b'0010110100' line b'0010110100' line b'0010110100' line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0001111000' line b'0000000000' line b'0000000000' line b'0000000000' line b'0000000000' frame_end jump10 frame_begin line b'0000000000' line b'0000000000' line b'0000110000' line b'0000110000' line b'0000000000' line b'0111111110' line b'0000110000' line b'0000110000' line b'0000110000' line b'0001111000' line b'0011001100' line b'0010000100' line b'0001001000' line b'0011001100' line b'0000000000' frame_end jump11 frame_begin line b'0000000000' line b'0000000000' line b'0000000000' line b'0000110000' line b'0100110010' line b'0010000100' line b'0001111000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0001111000' line b'0010000100' line b'0001001000' line b'0011001100' line b'0000000000' frame_end jump12 frame_begin line b'0000000000' line b'0000000000' line b'0000110000' line b'0000110000' line b'0000000000' line b'0001111000' line b'0010110100' line b'0100110010' line b'0000110000' line b'0001111000' line b'0011001100' line b'0010000100' line b'0001001000' line b'0011001100' line b'0000000000' frame_end if 0 frame1 frame_begin line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' line b'1111111111' line b'1111111111' line b'1111111111' line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' line b'0000110000' frame_end frame2 frame_begin line b'1000000001' line b'0100000010' line b'0100000010' line b'0010000100' line b'0010000100' line b'0001001000' line b'0001001000' line b'0000110000' line b'0001001000' line b'0001001000' line b'0010000100' line b'0010000100' line b'0100000010' line b'0100000010' line b'1000000001' frame_end frame3 frame_begin line b'0000000000' line b'0111111110' line b'0100000010' line b'0100000010' line b'0100000010' line b'0100000010' line b'0100000010' line b'0100000010' line b'0100000010' line b'0100000010' line b'0100000010' line b'0100000010' line b'0100000010' line b'0111111110' line b'0000000000' frame_end frame4 frame_begin line b'0000000000' line b'0000110000' line b'0001001000' line b'0001001000' line b'0010000100' line b'0100000010' line b'0100000010' line b'1000000001' line b'0100000010' line b'0100000010' line b'0010000100' line b'0001001000' line b'0001001000' line b'0000110000' line b'0000000000' frame_end endif ;************************************************************************** ; * ; Procedures * ; * ;************************************************************************** org h'300' ;-------------------------------------------------------------------------- ; delay ;-------------------------------------------------------------------------- nop ; [4] nop ; [4] nop ; [4] nop ; [4] nop ; [4] nop ; [4] delay16 return ; [8] ldelay movwf work1 ; [4] ldel1 decfsz work1 ; [4/8] goto ldel1 ; [8/0] return ; [8] delay macro cycles ; delay for a number of cycles if (cycles) < 0 error "Delay negative cycles" endif variable i = cycles if i > d'40' variable n = (i-d'20')/d'12' i -= (n*d'12')+d'20' movlw n ; [4] call ldelay ; [8] else if i >= d'16' variable n = (i-d'16')/d'4' i -= (n*d'4')+d'16' call delay16-n ; [8] endif endif while i > 0 nop ; [4] i -= d'4' endw endm ;-------------------------------------------------------------------------- ; waits for the number of ms in w reg ;-------------------------------------------------------------------------- routine wait_ms movwf loop waitm1 movlf (CLOCK/(d'1000'*d'80'))+1,timer waitm2 delay d'68' ; [68] decfsz timer ; [4/8] goto waitm2 ; [8/0] clrwdt ; [0/4] decfsz loop goto waitm1 return ;-------------------------------------------------------------------------- ; displays a pixel ;-------------------------------------------------------------------------- do_pixel macro rrf ndx,w ; get pixel [4] movwf work1 ; [4] rrf work1 ; [4] rrf work1,w ; [4] andlw b'11111' ; [4] movwf work1 ; [4] clrf PCLATH ; [4] rrf counter,w ; [4] andlw b'111110' ; [4] btfsc anim,0 ; [8/4] iorlw h'40' ; [0/4] movwf work2 ; [4] index frames ; [24] addwf work1 ; [4] incf work2,w ; [4] index frames ; [24] movwf PCLATH ; [4] movfw work1 ; [4] call lookup ; [24] movwf work1 ; [4] clrf PCLATH ; pixel mask [4] movfw ndx ; [4] andlw b'111' ; [4] index masks ; [24] andwf work1 ; [4] skpz ; set pixel [8/4] bsf GPIO,LED ; [0/4] skpnz ; [8/4] bcf GPIO,LED ; [0/4] endm DO_PIXEL equ d'196' ;-------------------------------------------------------------------------- ; timing delay ;-------------------------------------------------------------------------- do_timing macro movlf high delay16,PCLATH ; fine delay [8] movlf low delay16,work1 ; [8] movfw timing ; [4] andlw b'11' ; [4] subwf work1,w ; [4] call lookup ; [24+0/4/8/12] clrc ; [4] rrf timing,w ; [4] movwf work1 ; [4] clrc ; [4] rrf work1 ; timing >> 2 [4] dot1 clrwdt ; coarse delay [4] decfsz work1 ; [4/8] goto dot1 ; [8/0] nop ; [0/4] endm DO_TIMING equ d'72' ;-------------------------------------------------------------------------- ; main entry point ;-------------------------------------------------------------------------- routine main_entry clrf GPIO ; initialise port tris_ GPIO_IO bsf STATUS,RP0 ; prescale RTCC 1:2, movlw b'00000000' ; weak pull-ups enabled movwf OPTION_REG movlf (1<= 0 ; initialise index movlw TLC ; [4/0] else movlw ROWS*COLUMNS+TLC ; [0/4] endif movwf ndx ; [4] clrf pixel ; clear pixel counter [4] incf counter ; increment frame counter [4] ; -- start of display loop -- poll macro bsf GPIO,SENSOR ; poll sensor [4] nop ; [4] btfsc GPIO,SENSOR ; [8/4] bsf flags,PULSE ; [0/4] endm loop2 do_pixel ; display pixel bcf flags,PULSE ; [4] poll ; poll sensor [16] do_timing ; timing delay poll ; poll sensor [16] delay d'160' poll ; poll sensor [16] movlw (ROWS*COLUMNS)/8 ; ignore multiple pulses [4] subwf pixel,w ; [4] skpc ; [8/4] bcf flags,PULSE ; [0/4] incf ndx ; next pixel [4] movlw ROWS*COLUMNS ; wrap around [4] subwf ndx,w ; [4] skpnz ; [8/4] clrf ndx ; [0/4] btfsc flags,PULSE ; new frame ? [8] goto loop5 ; branch if yes incf pixel ; increment pixel counter [4] skpnz ; [8/4] decf pixel ; [0/4] movlw ROWS*COLUMNS-1 ; last pixel ? [4] subwf pixel,w ; [4] bnz loop2 ; loop if not [12] ; -- end of display loop -- bcf GPIO,LED ; LEDs off [4] clrf work1 ; wait for next frame [4] loop3 incf work1 ; [4] skpnz ; [8/4] decf work1 ; [0/4] bsf GPIO,SENSOR ; [4] clrwdt ; [4] btfss GPIO,SENSOR ; [4] goto loop3 ; [8] clrf work2 ; * 8 [4] clrc ; [4] rlf work1 ; [4] rlf work2 ; [4] rlf work1 ; [4] rlf work2 ; [4] rlf work1 ; [4] rlf work2 ; [4] MARGIN equ d'90' OFFSET set (CYCLES-d'156')/d'4'-MARGIN movlw OFFSET ; [4] subwf work1 ; [4] skpc ; [8/4] decf work2 ; [0/4] tstf work2 ; [4] bnz loop4 ; [8] movfw work1 ; [4] subwf timing,w ; [4] bc loop1 ; [12] loop4 incf timing ; adjust delay skpnz decf timing goto loop1 loop5 decf timing ; adjust delay skpnz incf timing goto loop1 end