;************************************************************************** ; FILE: scope.asm * ; CONTENTS: Miniscope * ; COPYRIGHT: MadLab Ltd. 2002 * ; AUTHOR: James Hutchby * ; UPDATED: 29/03/02 * ;************************************************************************** list p=16C715 ; list p=16F873 ifdef __16C715 include "p16c715.inc" endif ifdef __16F873 include "p16f873.inc" endif ifdef __16F873 ifndef _LVE_OFF variable _LVE_OFF = _LVP_OFF endif ifndef WREN2 variable WREN2 = WREN endif endif ifdef __16C715 ; __config _HS_OSC & _WDT_ON & _PWRTE_ON & _MPEEN_OFF & _BODEN_OFF & _CP_OFF __config _HS_OSC & _WDT_ON & _PWRTE_ON & _MPEEN_OFF & _BODEN_OFF & _CP_ALL endif ifdef __16F873 __config _HS_OSC & _WDT_ON & _PWRTE_ON & _LVE_OFF & _BODEN_OFF & _CP_OFF & _WRT_ENABLE_OFF endif __idlocs h'DA10' errorlevel -207,-302,-305,-306 ;************************************************************************** ; * ; Specification * ; * ;************************************************************************** ; processor spec: 2k ROM, 128 RAM, 20MHz, A/D ; on power-up displays "MINI- SCOPE" for ~2s ; timebases: 4kHz, 2kHz, 1kHz, 500Hz ; timebase displayed as row of dots (1 to 4) below frame ; signal sampled twice every 64us ; pushbutton toggles freezing of trace display ; pushbutton held down cycles through timebases ;************************************************************************** ; * ; Port assignments * ; * ;************************************************************************** ifdef __16C715 PORTA_IO equ b'11111' ; port A I/O status PORTB_IO equ b'11001111' ; port B I/O status #define MIC PORTA,1 ; microphone #define BUTTON PORTB,3 ; button VIDEO equ PORTB ; bits 4,5 ; video signal levels BLACK equ b'00100000' ; black/blank WHITE equ b'00110000' ; white SYNCH equ b'00000000' ; synch endif ifdef __16F873 PORTA_IO equ b'111111' ; port A I/O status PORTB_IO equ b'01111100' ; port B I/O status PORTC_IO equ b'11111111' ; port C I/O status #define MIC PORTA,1 ; microphone #define BUTTON PORTB,2 ; button #define LED PORTB,7 ; LED VIDEO equ PORTB ; bits 0,1 ; video signal levels BLACK equ b'00000001' ; black/blank WHITE equ b'00000011' ; white SYNCH equ b'00000000' ; synch endif ;************************************************************************** ; * ; Constants and timings * ; * ;************************************************************************** CLOCK equ d'20000000' ; processor clock frequency in Hz HRZ_PIXELS equ d'24' ; number of horizontal pixels VRT_PIXELS equ d'32' ; number of vertical pixels PIX_WIDTH equ d'28' ; pixel width in cycles PIX_HEIGHT equ d'6' ; pixel height in scan lines PULSES equ d'5' ; number of equalising/synchronising pulses BLANKING equ d'17' ; number of blanking lines BASELINE equ h'80' ; signal baseline ; PAL timings (in cycles) SCAN_LINE equ (d'640'*(CLOCK/d'1000000'))/d'10' ; scan line period (64us) FRONT_PORCH equ (d'16'*(CLOCK/d'1000000'))/d'10' ; front porch (1.6us) BACK_PORCH equ (d'56'*(CLOCK/d'1000000'))/d'10' ; back porch (5.6us) HRZ_SYNCH equ (d'48'*(CLOCK/d'1000000'))/d'10' ; horizontal synch (4.8us) EQU_SYNCH equ (d'24'*(CLOCK/d'1000000'))/d'10' ; equalising synch (2.4us) VRT_SYNCH equ (d'274'*(CLOCK/d'1000000'))/d'10' ; vertical synch (27.4us) ; screen border LEFT_BORDER equ (d'80'*(CLOCK/d'1000000')/d'10') ; left in cycles (8us) UPPER_BORDER equ d'25' ; upper in scan lines FRAME_WIDTH equ PIX_WIDTH*(1+HRZ_PIXELS+1) ; frame width in cycles FRAME_HEIGHT equ PIX_HEIGHT*(2+VRT_PIXELS+2) ; frame height in scan lines LOWER_BORDER equ d'287'-UPPER_BORDER-FRAME_HEIGHT-PIX_HEIGHT-PIX_HEIGHT*2 ;************************************************************************** ; * ; File register usage * ; * ;************************************************************************** ifdef __16C715 cblock h'20' samples:d'16' ; samples (h'20'-h'2f' + h'b8'-h'bf') RAM:0 endc variable samples_ = h'c0' endif ifdef __16F873 cblock h'20' samples:d'24' ; samples (h'20'-h'37') RAM:0 endc variable samples_ = h'38' endif cblock RAM flags ; various flags timebase ; 1, 2, 4, 8 ndx ; index step:0, start ; step counter/line segment start mask:0, length ; bit mask/line segment length pnt:0, count ; pointer/loop counter repeat ; repeat counter work1 ; work register endc variable timer = TMR0 ; timer ifdef __16C715 cblock h'38' bitmap:d'72' ; bitmap (h'38'-h'7f' + h'a0'-h'b7') endc endif ifdef __16F873 cblock h'a0' bitmap:d'96' ; bitmap (h'a0'-h'ff') endc endif ; flags RELEASE equ 0 ; set if waiting for pushbutton release SIGNON equ 1 ; set if sign-on message displayed FIELD equ 2 ; 0 = field #1, 1 = field #2 TRACE equ 3 ; set if trace display enabled CAPTURE equ 4 ; set if trace capture enabled THRESHOLD equ 5 ; set if below threshold TRIGGER equ 6 ; set if capture triggered FREEZE equ 7 ; set if trace display frozen ;************************************************************************** ; * ; 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 option_ macro ; set options bsf STATUS,RP0 movwf OPTION_REG&h'7f' bcf STATUS,RP0 endm tris_A macro ; tristate port A bsf STATUS,RP0 movwf TRISA&h'7f' bcf STATUS,RP0 endm tris_B macro ; tristate port B bsf STATUS,RP0 movwf TRISB&h'7f' bcf STATUS,RP0 endm bank0 macro ; bank 0 bcf STATUS,RP1 bcf STATUS,RP0 endm bank1 macro ; bank 1 bcf STATUS,RP1 bsf STATUS,RP0 endm bank2 macro ; bank 2 bsf STATUS,RP1 bcf STATUS,RP0 endm bank3 macro ; bank 3 bsf STATUS,RP1 bsf STATUS,RP0 endm ;-------------------------------------------------------------------------- ; reset vector ;-------------------------------------------------------------------------- org 0 goto main_entry ;-------------------------------------------------------------------------- ; interrupt vector ;-------------------------------------------------------------------------- org 4 goto main_entry ;************************************************************************** ; * ; Lookup tables * ; * ;************************************************************************** table signon ; "MINI- SCOPE" row macro pix entry (pix>>d'16')&h'ff' entry (pix>>d'8')&h'ff' entry pix&h'ff' endm row b'000000000000000000000000' row b'000000000000000000000000' row b'010001011101000101110000' row b'011011001001100100100000' row b'010101001001010100100110' row b'010001001001001100100000' row b'010001011101000101110000' row b'000000000000000000000000' row b'000000000000000000000000' row b'001110111011101110111000' row b'001000101010101010100000' row b'001110100010101110110000' row b'000010101010101000100000' row b'001110111011101000111000' row b'000000000000000000000000' row b'000000000000000000000000' table segments segment macro seg entry (seg>>d'24')&h'ff' entry (seg>>d'16')&h'ff' entry (seg>>d'8')&h'ff' entry seg&h'ff' endm segment b'11111111111111111111111111111111' segment b'01111111111111111111111111111111' segment b'00111111111111111111111111111111' segment b'00011111111111111111111111111111' segment b'00001111111111111111111111111111' segment b'00000111111111111111111111111111' segment b'00000011111111111111111111111111' segment b'00000001111111111111111111111111' segment b'00000000111111111111111111111111' segment b'00000000011111111111111111111111' segment b'00000000001111111111111111111111' segment b'00000000000111111111111111111111' segment b'00000000000011111111111111111111' segment b'00000000000001111111111111111111' segment b'00000000000000111111111111111111' segment b'00000000000000011111111111111111' segment b'00000000000000001111111111111111' segment b'00000000000000000111111111111111' segment b'00000000000000000011111111111111' segment b'00000000000000000001111111111111' segment b'00000000000000000000111111111111' segment b'00000000000000000000011111111111' segment b'00000000000000000000001111111111' segment b'00000000000000000000000111111111' segment b'00000000000000000000000011111111' segment b'00000000000000000000000001111111' segment b'00000000000000000000000000111111' segment b'00000000000000000000000000011111' segment b'00000000000000000000000000001111' segment b'00000000000000000000000000000111' segment b'00000000000000000000000000000011' segment b'00000000000000000000000000000001' segment b'00000000000000000000000000000000' ;************************************************************************** ; * ; Procedures * ; * ;************************************************************************** ;-------------------------------------------------------------------------- ; delay ;-------------------------------------------------------------------------- nop ; [4] nop ; [4] nop ; [4] nop ; [4] nop ; [4] nop ; [4] delay16 retlw 0 ; [8] ldelay movwf work1 ; [4] ldel1 decfsz work1 ; [4/8] goto ldel1 ; [8/0] retlw 0 ; [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 ;-------------------------------------------------------------------------- ; polls the pushbutton ;-------------------------------------------------------------------------- poll_button macro incf timer ; increment pushbutton timer [4] bsf BUTTON ; pushbutton pressed ? [4] clrw ; [4] btfss BUTTON ; [8/4] clrz ; [0/4] btfsc flags,SIGNON ; [8/4] clrz ; [0/4] skpnz ; reset timer if not [8/4] movwf timer ; [0/4] clrc ; [4] btfsc flags,RELEASE ; [8/4] setc ; [0/4] bcf flags,RELEASE ; [4] skpz ; [8/4] bsf flags,RELEASE ; signal waiting for release [0/4] skpnc ; [8/4] setz ; [0/4] movlw 1<= BACK_PORCH signal BLACK,BACK_PORCH ; back porch endif endm routine frame clrwdt ; [4] movlf PULSES,count ; [8] ;-------------------------------------------------------------------------- ; vertical synch pulses (5 half-lines) ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE/2 vrt1 synch VRT_SYNCH ; vertical synch signal BLACK,CYCLES-d'16' ; blank movlw PULSES-1 ; [4] decfsz count ; [4/8] goto vrt1 ; [8/0] movwf count ; [0/4] ;-------------------------------------------------------------------------- ; equalising pulses (5 half-lines) ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE/2 equ1 synch EQU_SYNCH ; equalising synch signal BLACK,CYCLES-d'12' ; blank decfsz count ; [4/8] goto equ1 ; [8/0] nop ; [0/4] CYCLES set SCAN_LINE/2 synch EQU_SYNCH ; equalising synch signal BLACK,CYCLES-d'20' ; blank movlf BLANKING-1,count ; [8] btfss flags,FIELD ; [8/4] goto blnk1 ; [0/8] nop ; [4/0] ;-------------------------------------------------------------------------- ; half-line (field #2) ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE/2 signal BLACK,CYCLES ; blank ;-------------------------------------------------------------------------- ; blank lines (17 lines) ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE blnk1 synch HRZ_SYNCH ; horizontal synch signal BLACK,CYCLES-d'12' ; blank decfsz count ; [4/8] goto blnk1 ; [8/0] nop ; [0/4] CYCLES set SCAN_LINE synch HRZ_SYNCH ; horizontal synch signal BLACK,CYCLES-d'20' ; blank movlf UPPER_BORDER,count ; [8] btfsc flags,FIELD ; [8/4] goto bord1 ; [0/8] nop ; [4/0] ;-------------------------------------------------------------------------- ; half-line (field #1) ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE/2 synch HRZ_SYNCH ; horizontal synch signal BLACK,CYCLES ; blank ;-------------------------------------------------------------------------- ; pad half-line (field #1) ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE/2 signal BLACK,CYCLES ; blank ;-------------------------------------------------------------------------- ; upper border ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE bord1 synch HRZ_SYNCH ; horizontal synch signal WHITE,CYCLES-d'16' ; white movlw PIX_HEIGHT*2-1 ; [4] decfsz count ; [4/8] goto bord1 ; [8/0] movwf count ; [0/4] ;-------------------------------------------------------------------------- ; top frame ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE synch HRZ_SYNCH ; horizontal synch signal WHITE,LEFT_BORDER ; left border movlf BLACK,VIDEO ; black [8] poll_button ; poll the pushbutton bsf flags,CAPTURE ; capture on odd fields [4] btfss flags,FIELD ; [8/4] bcf flags,CAPTURE ; [0/4] btfsc flags,FREEZE ; display frozen ? [8/4] bcf flags,CAPTURE ; [0/4] delay FRAME_WIDTH-POLL_BUTTON-d'28' CYCLES set CYCLES-FRAME_WIDTH signal WHITE,CYCLES ; right border CYCLES set SCAN_LINE fram1 synch HRZ_SYNCH ; horizontal synch signal WHITE,LEFT_BORDER ; left border movlf BLACK,VIDEO ; black [8] movlf samples,FSR ; clear samples [8] movlf h'10',repeat ; [8] movlw BASELINE ; [4] fram2 btfsc flags,CAPTURE ; [8/4] movwf 0 ; [0/4] incf FSR ; [4] decfsz repeat ; [4/8] goto fram2 ; [8/0] nop ; [0/4] ifdef __16C715 movlf samples+h'98',FSR ; [8] else movlf samples+h'10',FSR ; [8] endif movlf HRZ_PIXELS-h'10',repeat ; [8] movlw BASELINE ; [4] fram3 btfsc flags,CAPTURE ; [8/4] movwf 0 ; [0/4] incf FSR ; [4] decfsz repeat ; [4/8] goto fram3 ; [8/0] nop ; [0/4] movlf samples,ndx ; [8] bcf flags,TRIGGER ; [4] bcf flags,THRESHOLD ; [4] movlf 1,step ; [8] delay FRAME_WIDTH-d'72'-d'24'*HRZ_PIXELS CYCLES set CYCLES-FRAME_WIDTH signal WHITE,CYCLES-d'40' ; right border movlf bitmap,FSR ; [8] movlf b'10000000',mask ; [8] movlf PIX_HEIGHT,repeat ; [8] movlw VRT_PIXELS ; [4] decfsz count ; [4/8] goto fram1 ; [8/0] movwf count ; [0/4] ;-------------------------------------------------------------------------- ; bitmap lines ;-------------------------------------------------------------------------- pixel macro movfw mask ; [4] andwf 0,w ; [4] movlw WHITE ; [4] skpz ; [8/4] movlw BLACK ; [0/4] movwf VIDEO ; [4] incf FSR ; [4] delay PIX_WIDTH-d'28' CYCLES set CYCLES-PIX_WIDTH endm CYCLES set SCAN_LINE btmp1 synch HRZ_SYNCH ; horizontal synch movlf WHITE,VIDEO ; left border [8] grab_left ; grab trace delay LEFT_BORDER-d'8'-GRAB_LEFT CYCLES set CYCLES-LEFT_BORDER signal BLACK,PIX_WIDTH-d'16' ; left frame variable n = HRZ_PIXELS ; bitmap pixels while n > 0 pixel n -= 1 endw delay d'16' CYCLES set CYCLES-d'16' signal BLACK,PIX_WIDTH-d'16' ; right frame rrf mask,w ; [4] decf repeat,w ; [4] skpnz ; [8/4] rrf mask ; [0/4] CYCLES set CYCLES-d'16' DELAY set CYCLES-GRAB_RIGHT-d'72' signal WHITE,DELAY ; right border grab_right ; grab trace decf repeat,w ; [4] skpz ; [8/4] movlw HRZ_PIXELS ; [0/4] skpc ; [8/4] movlw HRZ_PIXELS ; [0/4] subwf FSR ; [4] ifdef __16C715 btfsc FSR,7 ; [8/4] bsf FSR,5 ; [0/4] else delay d'8' endif decfsz repeat,w ; [8/4] incf count ; [0/4] movlw PIX_HEIGHT ; [4] decf repeat ; [4] skpnz ; [8/4] movwf repeat ; [0/4] movlw PIX_HEIGHT*2 ; [4] decfsz count ; [4/8] goto btmp1 ; [8/0] movwf count ; [0/4] ;-------------------------------------------------------------------------- ; bottom frame ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE fram4 synch HRZ_SYNCH ; horizontal synch signal WHITE,LEFT_BORDER ; left border signal BLACK,FRAME_WIDTH ; black signal WHITE,CYCLES-d'16' ; right border movlw PIX_HEIGHT ; [4] decfsz count ; [4/8] goto fram4 ; [8/0] movwf count ; [0/4] ;-------------------------------------------------------------------------- ; timebase indicator ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE tmbs1 synch HRZ_SYNCH ; horizontal synch signal WHITE,CYCLES-d'16' ; white movlw PIX_HEIGHT*2 ; [4] decfsz count ; [4/8] goto tmbs1 ; [8/0] movwf count ; [0/4] CYCLES set SCAN_LINE tmbs2 synch HRZ_SYNCH ; horizontal synch DELAY set LEFT_BORDER+PIX_WIDTH+((HRZ_PIXELS-d'8')/2)*PIX_WIDTH-d'16'-d'16' signal WHITE,DELAY ; left border clrc ; [4] rlf timebase,w ; [4] movwf work1 ; [4] decf work1 ; [4] CYCLES set CYCLES-d'16' indic macro bit movlw WHITE ; [4] btfsc work1,bit ; [8/4] movlw BLACK ; [0/4] btfss flags,TRACE ; [8/4] movlw WHITE ; [0/4] movwf VIDEO ; [4] delay PIX_WIDTH-d'8' movlw WHITE ; [4] movwf VIDEO ; [4] delay PIX_WIDTH-d'24' CYCLES set CYCLES-PIX_WIDTH*2 endm indic 0 indic 1 indic 2 indic 3 DELAY set d'16'+((HRZ_PIXELS-d'8')/2)*PIX_WIDTH+PIX_WIDTH signal WHITE,DELAY ; right border signal WHITE,CYCLES-d'12' decfsz count ; [4/8] goto tmbs2 ; [8/0] nop ; [0/4] ;-------------------------------------------------------------------------- ; lower border ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE synch HRZ_SYNCH ; horizontal synch signal WHITE,CYCLES-d'40' ; white btfsc timer,7 ; sign-on message timer [8/4] bcf flags,SIGNON ; [0/4] btfss flags,SIGNON ; [8/4] bsf flags,TRACE ; [0/4] movlf bitmap,pnt ; [8] movlf samples,ndx ; [8] movlf HRZ_PIXELS,repeat ; [8] CYCLES set SCAN_LINE bord2 synch HRZ_SYNCH ; horizontal synch movlf WHITE,VIDEO ; white [8] draw_trace ; draw trace delay CYCLES-d'8'-DRAW_TRACE-d'16' COUNT set LOWER_BORDER-HRZ_PIXELS-2 movlw COUNT ; [4] decfsz repeat ; [4/8] goto bord2 ; [8/0] movwf count ; [0/4] CYCLES set SCAN_LINE bord3 synch HRZ_SYNCH ; horizontal synch signal WHITE,CYCLES-d'12' ; white decfsz count ; [4/8] goto bord3 ; [8/0] nop ; [0/4] CYCLES set SCAN_LINE synch HRZ_SYNCH ; horizontal synch signal WHITE,CYCLES-d'20' ; white movlf PULSES-1,count ; [8] btfss flags,FIELD ; [8/4] goto equ2 ; [0/8] nop ; [4/0] ;-------------------------------------------------------------------------- ; pad half-line (field #2) ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE/2 synch HRZ_SYNCH ; horizontal synch signal BLACK,CYCLES ; blank ;-------------------------------------------------------------------------- ; equalising pulses (5 half-lines) ;-------------------------------------------------------------------------- CYCLES set SCAN_LINE/2 equ2 synch EQU_SYNCH ; equalising synch signal BLACK,CYCLES-d'12' ; blank decfsz count ; [4/8] goto equ2 ; [8/0] nop ; [0/4] CYCLES set SCAN_LINE/2 synch EQU_SYNCH ; equalising synch signal BLACK,CYCLES-d'28' ; blank movlw 1<