;***************************************************************************** ;* shutter8.asm * ;* The Shutter Project, AST6 Macro-Assembler source * ;* Mar 05, 2000 * ;***************************************************************************** ; Copyright 2000 by Georg Holderied and Markus Karrer Ostermayer ; ; Purpose: software control of a photo shutter, providing automatic ; and manual time modes, including self timer. ; ; Version: 0.8 beta, written for AST6 Macro Assembler Version 4.50 ; ; Warning: contains time dependent code, relying on a 4.000 MHz clock ! ; When using different crystals, scale delay subroutines accordingly. ; Note: at 4 MHz, one machine cycle takes 3.25 Microseconds ;|===========================================================================| ;| Assembly method without linker : ast6 -l -e shutter7.asm | ;|===========================================================================| ; ;|===========================================================================| ;| Assembly directives | ;|===========================================================================| .display "Now assembling Version 0.8 beta !" .title "SHUTTER PROJECT" ; Define title for page header .comment 80 .DP_ON ;data space is segmented in pages .PP_ON ;program space is segmented in 2K pages .W_ON ;data space window to program space .romsize 4 .VERS "ST6225" ;has 4K ROM ;|---------------------------------------------------------------------------| ;| ST6225 Registers Declaration | ;| | ;|---------------------------------------------------------------------------| x .def 80h ; Index register. y .def 81h ; Index register. v .def 82h ; Short direct register. w .def 83h ; Short direct register. a .def 0ffh ; Accumulator. dra .def 0c0h ; Port a data register. drb .def 0c1h ; Port b data register. drc .def 0c2h ; Port c data register. ddra .def 0c4h ; Port a direction register. ddrb .def 0c5h ; Port b direction register. ddrc .def 0c6h ; Port c direction register. opra .def 0cch ; Port a option register. oprb .def 0cdh ; Port b option register. oprc .def 0ceh ; Port c option register. ior .def 0c8h ; Interrupt option register. drwr .def 0c9h ; Data rom window register. adr .def 0d0h ; A/D data register. adcr .def 0d1h ; A/D control register. psc .def 0d2h ; Timer prescaler register. tcr .def 0d3h ; Timer counter register. tscr .def 0d4h ; Timer status control register. wdr .def 0d8h ; Watchdog register. ; ******************************* ; * Program work variables and * ; * declarations (as one byte * ; * dataspace addresses) * ; ******************************* DATARAM .equ 084h ; base data ram address d128fac .def DATARAM ; factor for the delay_128 subroutine c_copy .def DATARAM+1 ; copy of c port for safe data transition I .def DATARAM+2 ; 1st loop counter, general purpose K .def DATARAM+3 ; 2nd loop counter, general purpose b1 .def DATARAM+4 ; for setting of BCD 1st digit (B3-B0) b2 .def DATARAM+5 ; for setting of BCD 2nd digit (A7-A4) b3 .def DATARAM+6 ; for setting of BCD 3rd digit (A3-A0) num_sec .def DATARAM+7 ; to hold a requested delay in seconds num_ms .def DATARAM+8 ; to hold a requested delay in ms err_flag .def DATARAM+9 ; to flag a bad switch setting ENDRAM .EQU DATARAM+10 ; end of data ram address range ; ;|===========================================================================| ;| constants definition | ;|===========================================================================| ; ;bit positions ; button .equ 7 ; bit #7 (PC7) = shutter button input led_stat .equ 6 ; bit #6 (PC6) = status (yellow led) out flash .equ 5 ; bit #5 (PC5) = flash sync (pink led) out shuttr .equ 4 ; bit #4 (PC4) = shutter output (red led) tmz .equ 7 ; timer zero bit, clear before timer count ; *************************** ; * MAIN PROGRAM * ; *************************** .section 1 ; logical partitioning of program space init ldi wdr,0feh ; Load the watchdog with max. divider (64) clr c_copy ; clr b1 ; clear the BCD switch setting save posn clr b2 ; clr b3 ; clr num_sec ; clear seconds delay preset clr err_flag ; clear error flag (no error) ldi opra,00000000b ; Port A is with pull up ldi ddra,00000000b ; Port A is all input (0=In 1=Out) ldi dra,00000000b ; Port A is witout interrupt ldi oprb,00000000b ; Port B is with pull up ldi ddrb,00000000b ; Port B is all input ldi drb,00000000b ; Port B is without interrupt ldi oprc,01111111b ; Port C options (PC7 no interrupt) ldi ddrc,01111111b ; Port C directions (PC7 is input) ; Port C6 is status led output ; Port C5 is flash sync output ; Port C4 is shutter output reti ; end of reset process, pg continues... ; with next instruction ldi wdr,0feh ; Load the watchdog call res_ok ; reset blinks status LED 3 times ;******************************************************** ;*** WAIT HERE FOR SHUTTER BUTTON USE in endless LOOP * ;******************************************************** waitbutn clr b1 clr b2 clr b3 clr num_sec ldi wdr, 0feh ; prevent timeout of watchdog ld a, drc ; load drc port ld c_copy, a ; copy drc port to c_copy jrr button,c_copy,readMode ; shutter button pressed? ->read Mode sw jp waitbutn ; else loop endlessly ;************************************************** ;comes here after shutter button on PC7 is pressed ;in order to read the HEX switch (for mode info) ;HEX mode switch is on B7,B6,B5,B4 pins (8/4/2/1) ;************************************************** readMode ld a,drb ; read Port B andi a,11110000b ; mask the 4 LSB's of the Hex code sw. rH6 jrnz cp_B ; acc is not zero jp self30 ; HEX switch is set to"F-self timer 30s" cp_B cpi a,01000000b ; compare with "B" jrz bmode ; HEX switch is set to "Manual mode" jp rH1 ;******************************************************* ;MANUAL mode (open shutter as long as button is pressed) ;******************************************************* bmode call ShutH ; OPEN SHUTTER ldi num_ms,60 ; load ms preset call delay_ms ; debounce time delay 60ms monitor ldi wdr,0feh ; Load the watchdog with max. divider (64) ld a,drc ; load c port contents ld c_copy, a ; copy port contents jrs button,c_copy,b_end ; if button is off (port HI) now, go b_end jp monitor ; button is still pressed (port LO),wait b_end call ShutL ; CLOSE SHUTTER jp waitbutn ; return to read shutter button rH1 cpi a,00110000b ; compare with "C" jrz tmode ; HEX switch is set to "Toggle mode" jp rH2 ;******************************************************* ;TOGGLE mode (press to open shutter, again to close it) ;******************************************************* tmode ldi wdr,0feh ; Load the watchdog with max. divider (64) call ShutH ; OPEN SHUTTER ldi a,255 ld num_ms,a call delay_ms ; delay for 255ms call delay_ms ; delay for another 255ms to release butn moni_2 ldi wdr,0feh ; Load the watchdog with max. divider (64) ld a,drc ; load c port contents ld c_copy, a ; copy port contents jrs button,c_copy,moni_2 ; button still released (port HI)? call ShutL ; no, button pressed again, toggle CLOSE ldi a,255 ld num_ms,a call delay_ms ; delay for 255ms call delay_ms ; delay for another 255ms before return jp waitbutn ; return to read shutter button rH2 cpi a,11110000b ; compare with "0" jrz smode ; HEX switch is set to "Seconds mode" jp rH3 ; ;******************************************************* ;SECONDS mode (shutter AUTOMATIC for XXX seconds) ;******************************************************* smode call BCD_sec ; sub reads b1,b2,b3 and calculates ; num_secs, opens&closes shutter ldi a,255 ld num_ms,a call delay_ms ; delay for 255ms call delay_ms ; delay for another 255ms before return jp waitbutn ; to read the button rH3 cpi a,01010000b ; compare with "A" jrz standard ; HEX switch is set to "Standard mode" jp rH4 ; ;****************************************************************** ;Standard mode (shutter AUTOMATIC for 1/125,60,30,16,8,4,2,1 sec) ;****************************************************************** standard call BCD_frac ; reads b1,b2 and b3 and calculates ; d128fac to determine 1/128's needed ; opens & closes shutter ldi a,1 ; wait 1s ld num_sec,a ; before call delay_s ; returning jp waitbutn ; to read the button rH4 cpi a,00100000b ; compare with "D" jrz self10 ; HEX switch is set to "self timer 10s" jp rH5 ; ;****************************************************************** ;Selftimer mode (10 s & AUTOMATIC for 1/125,60,30,16,8,4,2 seconds) ;****************************************************************** self10 ldi wdr,0feh ; disable watchdog here call chk_frac ; check for correctness before delaying ld a,err_flag ; load the error flag set/reset in sub jrz self1_ok ; if it is clear, the mode is ok call errStat ; else the setting is incorrect jp waitbutn self1_ok ldi a,10 ld num_sec,a call Stat_On ; status warn led on call delay_s ; delay for 10s call Stat_Off ; status warn led off call BCD_frac ; then normal fractions jp waitbutn rH5 cpi a,00010000b ; compare with "E" jrz self20 ; HEX switch is set to "self timer 20s" jp notValid ; other setting ;****************************************************************** ;Selftimer mode (20 s & AUTOMATIC for 1/125,60,30,16,8,4,2 seconds) ;****************************************************************** self20 ldi wdr,0feh ; disable watchdog here call chk_frac ; check for correctness before delaying ld a,err_flag ; load the error flag set/reset in sub jrz self2_ok ; if it is clear, the mode is ok call errStat ; else the setting is incorrect jp waitbutn self2_ok ldi a,20 ld num_sec,a call Stat_On call delay_s ; delay for 20s call Stat_Off call BCD_frac ; then normal fractions jp waitbutn notValid call errStat ; other HEX switch settings invalid ; (not 0 or A to F) jp waitbutn ;****************************************************************** ;Selftimer mode (30 s & AUTOMATIC for 1/125,60,30,16,8,4,2 seconds) ;****************************************************************** self30 ldi wdr,0feh ; disable watchdog here call chk_frac ; check for correctness before delaying ld a,err_flag ; load the error flag set/reset in sub jrz self3_ok ; if it is clear, the mode is ok call errStat ; else the setting is incorrect jp waitbutn self3_ok ldi a,30 ld num_sec,a call Stat_On ; status led on for self timer warning call delay_s ; delay for 30s call Stat_Off ; status led off call BCD_frac ; then normal fractions jp waitbutn ;|===========================================================================| ;| interrupt routines | ;|===========================================================================| ;************************ ;comes here after an NMI* VECTOR 0 ;************************ nmi_int nop ; do not use nmi reti ;************************ ;comes here PORT A INT * VECTOR 1 ;************************ p_a_int nop ; port a has no int detection reti ;************************ ;comes here PORT BC INT * VECTOR 2 ;************************ p_bc_int nop ; port bc have no int detection reti ;************************ ;comes here TIMER INT * VECTOR 3 ;************************ tim_int nop ; timer int not used here reti ;***************************************************************************** ;* Subroutines * ;***************************************************************************** ; ;|---------------------------------------------------------------------------| ;| res_ok | ;|---------------------------------------------------------------------------| ;Subroutine res_ok makes 3 blinks on the status led ; ; res_ok ldi K,3 ; repeat 3 times rok1 ldi wdr, 0feh ; prevent timeout of watchdog ld a,drc ; load contents of c port ld c_copy, a ; keep copy of c port set led_stat,c_copy ; set status led bit high ld a,c_copy ; load copy in acc ld drc,a ; write complete port at once ldi num_ms,100 call delay_ms ; delay 100 ms ld a,drc ; load contents of c port ld c_copy, a ; keep copy of c port res led_stat,c_copy ; set status led bit low ld a,c_copy ; load copy in acc ld drc,a ; write complete port at once call delay_ms dec K jrnz rok2 ; K > 0 ? ret rok2 jp rok1 ; ;|---------------------------------------------------------------------------| ;| errStat | ;|---------------------------------------------------------------------------| ;Subroutine errStat makes 6 fast blinks on PC5 (status LED) ; ; errStat ldi K,6 ; repeat 6 times bp1 ldi wdr, 0feh ; prevent timeout of watchdog ld a,drc ; load contents of c port ld c_copy, a ; keep copy of c port set led_stat,c_copy ; set status led bit high ld a,c_copy ; load copy in acc ld drc,a ; write complete port at once ldi num_ms,80 ; preset ms request call delay_ms ; delay 80ms ld a,drc ; load contents of c port ld c_copy, a ; keep copy of c port res led_stat,c_copy ; set status led bit low ld a,c_copy ; load copy in acc ld drc,a ; write complete port at once ldi num_ms,80 ; preset ms request call delay_ms ; delay 80ms dec K jrnz bp2 ; K > 0 ? ret bp2 jp bp1 ;|---------------------------------------------------------------------------| ;| one_sec | ;|---------------------------------------------------------------------------| ;Subroutine one_sec creates a delay of 1s (at 4 MHz crystal) one_sec: ; Software delay ldi wdr,0feh ; disable watchdog here ldi x,100 ; outer loop x (100 times) ldi y,0ffh ; inner loop y (255 times) tloop dec y ; tloop represents 12 instruction cycles. nop ; nop ; nop ; jrnz tloop ; inner loop ldi wdr,0feh ; disable watchdog here dec x ; outer loop jrnz tloop ; x>0 => new loop tempend ret ; x reaches 0 => end of one_sec ;|---------------------------------------------------------------------------| ;| delay_s | ;|---------------------------------------------------------------------------| ;Subroutine delay_s uses the one_second sub to create a delay of (num_sec) s delay_s ldi wdr,0feh ; disable watchdog here ld a,num_sec ; load number of seconds to delay ld I,a ; load I loop counter with num_sec oneS call one_sec ; delay 1s dec I jrnz oneS ; I is > 0 ret ; end of delay_s ;|---------------------------------------------------------------------------| ;| delay_ms | ;|---------------------------------------------------------------------------| ;Subroutine delay_ms creates a delay of about (num_ms) ms at 4 MHZ crystal ;uses V and W registers. num_ms must be 1 ... 255 and been loaded before ; delay_ms ldi v,0 ; outer loop v (x num_ms) (4 cyc.) d_ms ldi a,24 ; inner loop w (24x14 c.) (4 cyc.) ldi w,0 ; reset inner loop counter(4 cyc.) loop_ms ldi wdr,0feh ; use up time w/dog > (4 cyc.) inc w ; increment w > (4 cyc.) cp a,w ; is w=24 ? > (4 cyc.) jrnz loop_ms ; no, so jump back > (2 cyc.) inc v ; increment outer loop ct.(4 cyc.) ld a, num_ms ; get preset ms delay (1 to 255) cp a,v ; is it reached ? (4 cyc.) jrz fini_ms ; yes, end (2 cyc.) jp d_ms ; no, back for another ms (4 cyc.) fini_ms ret ; return from subroutine (2 cyc.) ; ;|---------------------------------------------------------------------------| ;| ShutL | ;|---------------------------------------------------------------------------| ;Subroutine ShutL switches off the shutter led and shutter (bit LOW on Port) ; ; ShutL ld a,drc ; (4 cyc.)load contents of c port ld c_copy, a ; (4 cyc.)keep copy of c port res shuttr,c_copy ; (4 cyc.)reset shuttr bit ld a,c_copy ; (4 cyc.)load copy in acc ld drc,a ; (4 cyc.) write complete port at once ret ; LED/SHUTTER OFF now ; ;|---------------------------------------------------------------------------| ;| ShutH | ;|---------------------------------------------------------------------------| ;Subroutine ShutH lights the shutter led and sw. shutter ON (bit HI on Port) ; ; ShutH ld a,drc ; (4 cyc.)load contents of c port ld c_copy, a ; (4 cyc.)keep copy of c port set shuttr,c_copy ; (4 cyc.)set shuttr bit ld a,c_copy ; (4 cyc.)load copy in acc ld drc,a ; (4 cyc.) write complete port at once ret ; LED/SHUTTER ON now ; ;|---------------------------------------------------------------------------| ;| Stat_Off | ;|---------------------------------------------------------------------------| ;Subroutine Stat_Off switches off the status led (LOW on Port) ; ; Stat_Off ld a,drc ; (4 cyc.)load contents of c port ld c_copy, a ; (4 cyc.)keep copy of c port res led_stat,c_copy ; (4 cyc.)reset led_stat bit ld a,c_copy ; (4 cyc.)load copy in acc ld drc,a ; (4 cyc.) write complete port at once ret ; status LED OFF now ; ;|---------------------------------------------------------------------------| ;| Stat_On | ;|---------------------------------------------------------------------------| ;Subroutine Stat_On lights the status led (HI on PortC) ; ; Stat_On ld a,drc ; (4 cyc.)load contents of c port ld c_copy, a ; (4 cyc.)work on a copy of c port set led_stat,c_copy ; (4 cyc.)set led_stat bit ld a,c_copy ; (4 cyc.)load copy in acc ld drc,a ; (4 cyc.)write complete port at once ret ; status LED ON now ; ;|---------------------------------------------------------------------------| ;| flashOff | ;|---------------------------------------------------------------------------| ;Subroutine flashOff resets the flash bit (LOW on Port) ; ; flashOff ld a,drc ; (4 cyc.)load contents of c port ld c_copy, a ; (4 cyc.)work on a copy of c port res flash,c_copy ; (4 cyc.)reset flash bit ld a,c_copy ; (4 cyc.)load copy in acc ld drc,a ; (4 cyc.)write complete port at once ret ; flash bit OFF now ; ;|---------------------------------------------------------------------------| ;| flashOn | ;|---------------------------------------------------------------------------| ;Subroutine flashOn sets the flash bit (HI on PortC) ; ; flashOn ld a,drc ; (4 cyc.)load contents of c port ld c_copy, a ; (4 cyc.)keep copy of c port set flash,c_copy ; (4 cyc.)set flash bit ld a,c_copy ; (4 cyc.)load copy in acc ld drc,a ; (4 cyc.) write complete port at once ret ; flash bit ON now ;|---------------------------------------------------------------------------| ;| BCD_sec | ;|---------------------------------------------------------------------------| ; ;Subroutine BCD_sec reads Ports B and A in case of full seconds ;selected by the HEX switch (0 X X X) allowed are 0-001 to 0-255 ;Note: switch is ON-GND, meaning a bit position "0" must be inverted to "1" BCD_sec ldi wdr,0feh ; disable watchdog here ld a,drb ; read Port B (Hex-BCD1) com a ; complement (an ON to GND means bit HI) jrz bcd1_ok ; zero,acc =00000000 is valid (Hex-0 BCD1-0) cpi a,1 ; test if BCD1 is 1 jrz bcd1_ok ; yes, acc =00000001 is valid (Hex-0 BDC1-1) cpi a,2 ; test if BCD1 is 2 jrz bcd1_ok ; yes, acc =00000010 is valid (Hex-0 BDC1-2) call errStat ; no setup is not [0]-0xx to [0]-2xx, error ret ; back after status error blinking bcd1_ok ld b1, a ; save valid hundreds (b1) setting ldi wdr,0feh ; disable watchdog here ld a,dra ; read port A (BCD2-BCD3) cpi a,11111111b ; port A reads "0" and "0" ? jrz allnull ; yes if BCD1 is also 0 ->error jp bcd23_v ; no, we have a correct setting allnull ld a,b1 ; BCD1,BCD2 and BCD3 = 0 ? jrnz bcd23_v ; no, we have a valid setting (100 or 200) call errStat ; yes, incorrect setting (0-000) ret ; back after status error blinking bcd23_v ld a, dra ; load the acc again (BCD2 and BCD3) andi a,11110000b ; mask the lower nibble of BCD3 switch rlc a ; rotate left through carry rlc a ; rotate left through carry rlc a ; rotate left through carry rlc a ; rotate left through carry rlc a ; shift higher nibble to lower andi a,00001111b ; clear eventual carry bit com a ; complement acc andi a,00001111b ; do use only lower nibble here ld b2, a ; save valid b2 setting ldi wdr,0feh ; disable watchdog here ld a,dra ; read port A again for lower nibble andi a,00001111b ; mask higher nibble com a ; complement acc andi a,00001111b ; use only lower nibble here ld b3, a ; save valid b3 setting ; setting in b1,b2,b3 now ; calculate num_sec next ld a,b1 ; load b1 cpi a,2 ; is it 2 ? jrz t2xx ; yes, add 200 to num_sec cpi a,1 ; ist it 1 ? jrz t1xx ; yes, add 100 to num_sec jp tens ; b1 is 0, so go to tens position t2xx ldi num_sec,200 ; load 200 to num_sec ldi wdr,0feh ; disable watchdog here jp tens ; add number of ten's t1xx ldi num_sec,100 ; load 100 to num_sec tens ld a,b2 ; load 10's position jrz ones ; add one's ld y,a ; load counter y with 1...9 tensloop ldi wdr,0feh ; disable watchdog here ldi a,10 ; add 10 add a,num_sec ; add num_sec+10 in accumulator ld num_sec, a ; put result back to num_sec dec y ; decrement counter for 10's to add jrnz tensloop ; add as many 10's as b2 says ones ldi wdr,0feh ; disable watchdog here ld a,b3 ; one's to add jrz ns_ok ; no ones to add add a,num_sec ; add num_sec+b3 (ones) in acc ld num_sec, a ; put result back to num_sec ns_ok call ShutH ; SHUTTER OPENS HERE call delay_s ; sub delays for num_secs call flash_it ; make flash impulse of 20ms before closing call ShutL ; SHUTTER CLOSES AGAIN ret ;|---------------------------------------------------------------------------| ;| chk_frac | ;|---------------------------------------------------------------------------| ; ;Subroutine chk_frac checks Ports B and A in case of fractional second mode ;selected by the HEX switch (A-XXX) / (D-XXX) / (E-XXX) / (F-XXX) ;and sets the err_flag on return, if the switch setting is not ok chk_frac ldi wdr,0feh ; disable watchdog here ld a,drb ; read Port B com a ; complement it (digital switches to GND) andi a,00001111b ; mask the 4 MSB's of the Hex code sw. cpi a,1 ; compare with 1 decimal jrz chk1_1 ; BCD1 switch is set to 1 cpi a,0 ; compare with 0 jrz cgo1_0 ; BCD1 switch is set to 0 jp err_set ; BCD1 not 1 and not 0 ->set error flag cgo1_0 jp chk1_0 ; prevent 5-bit displacement overflow chk1_1 ldi wdr,0feh ; disable watchdog here ld a,dra ; read port A com a ; complement it cpi a,00100101b ; port A reads "2" and "5" ? jrz ok128 ; yes, is 1/125 second jp err_set ; incorrect setting (not 1/125) ok128 jp err_res ; no error in sw setting chk1_0 ldi wdr,0feh ; disable watchdog here ld a,dra ; read Port A for next 2 switches com a ; complement it cpi a,01100000b ; test for "6" and "0" ? jrnz ckxt01 ; no, next test jp err_res ; yes, setting ok ckxt01 cpi a,00110000b ; test for "3" and "0" ? jrnz ckxt02 ; no, next test jp err_res ; yes, ok 1/30 second ckxt02 cpi a,00010110b ; test for "1" and "6" ? jrnz ckxt03 ; no, next test jp err_res ; yes, ok 1/16 second ckxt03 cpi a,00001000b ; test for "0" and "8" ? jrnz ckxt04 ; no, next test jp err_res ; yes, no error ckxt04 cpi a,00000100b ; test for "0" and "4" ? jrnz ckxt05 ; no, next test jp err_res ; yes no error ckxt05 cpi a,00000010b ; test for "0" and "2" ? jrnz ckxt06 ; no, last test jp err_res ; yes no error ckxt06 cpi a,00000001b ; test for "0" and "1" ? jrz err_res ; yes, last test ok err_set ldi err_flag,1 ; no, all other settings incorrect ret ; and go back err_res clr err_flag ; clear the error flag ret ; and go back ;|---------------------------------------------------------------------------| ;| BCD_frac | ;|---------------------------------------------------------------------------| ; ;Subroutine BCD_frac reads Ports B and A in case of fractional second mode ;selected by the HEX switch (A-XXX) / (D-XXX) / (E-XXX) / (F-XXX) ; BCD_frac ldi wdr,0feh ; disable watchdog here ld a,drb ; read Port B com a ; complement it (digital switches to GND) andi a,00001111b ; mask the 4 MSB's of the Hex code sw. cpi a,1 ; compare with 1 decimal jrz bcd1_1 ; BCD1 switch is set to 1 cpi a,0 ; compare with 0 jrz go1_0 ; BCD1 switch is set to 0 call errStat ; BCD1 switch not 1 and not 0 ->error ret ; back after error signaling go1_0 jp bcd1_0 ; prevent 5-bit displacement overflow bcd1_1 ldi wdr,0feh ; disable watchdog here ld a,dra ; read port A com a ; complement it cpi a,00100101b ; port A reads "2" and "5" ? jrz do128 ; yes, do 1/125 second call errStat ; incorrect setting (not 1/125) ret ; back after error signaling do128 ldi d128fac,1 ; setup correct delay factor for sub call delay_128 ; subroutine delay_128 does it ret ; back after 1/125 sec bcd1_0 ldi wdr,0feh ; disable watchdog here ld a,dra ; read Port A for next 2 switches com a ; complement it cpi a,01100000b ; test for "6" and "0" ? jrz cp01 ; yes, do 1/60 second jp next01 ; no, goto next comparison cp01 jp do60 ; subroutine makes 1/60 s next01 cpi a,00110000b ; test for "3" and "0" ? jrz cp02 jp next02 cp02 jp do30 ; yes, do 1/30 second next02 cpi a,00010110b ; test for "1" and "6" ? jrz cp03 ; yes, do 1/16 second jp next03 cp03 jp do16 next03 cpi a,00001000b ; test for "0" and "8" ? jrz cp04 ; yes, do 1/8 second jp next04 cp04 jp do8 next04 cpi a,00000100b ; test for "0" and "4" ? jrz cp05 ; yes, do 1/4 second jp next05 cp05 jp do4 next05 cpi a,00000010b ; test for "0" and "2" ? jrz cp06 ; yes, do 1/2 second jp next06 cp06 jp do2 next06 cpi a,00000001b ; test for "0" and "1" ? jrz cp07 ; yes, do 1/1 second call errStat ; no, all other settings incorrect ret cp07 jp do1 do60 ldi d128fac,2 ; setup correct delay factor for sub call delay_128 ; subroutine for 2/128 = 1/64s ret do30 ldi d128fac,4 ; setup correct delay factor for sub call delay_128 ; subroutine for 4/128 = 1/32s ret do16 ldi d128fac,8 ; setup correct delay factor for sub call delay_128 ; subroutine for 8/128 = 1/16s ret do8 ldi d128fac,16 ; setup correct delay factor for sub call delay_128 ; subroutine for 16/128 = 1/8s ret do4 ldi d128fac,32 ; setup correct delay factor for sub call delay_128 ; subroutine for 32/128 = 1/4s ret do2 ldi d128fac,64 ; setup correct delay factor for sub call delay_128 ; subroutine for 64/128 = 1/2s ret do1 ldi d128fac,128 ; setup correct delay factor for sub call delay_128 ; subroutine for 128/128 = 1/1s ret ;|---------------------------------------------------------------------------| ;| delay_128 | ;|---------------------------------------------------------------------------| ; ;Subroutine delay_128 opens shutter for (d128fac) * 1/128 s ; delay_128 ldi wdr,0feh ; disable watchdog here ld a,d128fac ; (4 cyc.) load the factor in a ld K,a ; (4 cyc.) put factor in K ld a,drc ; load contents of c port ld c_copy, a ; keep copy of c port set shuttr,c_copy ; set shutter (shutter led) bit ld a,c_copy ; load copy in acc ld drc,a ; write complete port at once ; SHUTTER OPENS HERE ; must use up K * 2404 cycles now ! begin_0 nop ; (2 cyc.) ldi I,0 ; (4 cyc.) reset loop counter I (4 cyc.) ldi a,169 ; (4 cyc.) loop factor 169 wait_10 ldi wdr,0feh ; (4 cyc.)\ inc I ; (4 cyc.) \ cp a,I ; (4 cyc.) >14 cycles inner loop jrnz wait_10 ; (2 cyc.) / times 169 = 2366 cycles dec K ; (4 cyc.) jrz done ; (2 cyc.) jp begin_0 ; (2 cyc.) done call flash_it ; in all cases use the flash 20 ms ld a,drc ; (4 cyc.) load contents of c port ld c_copy, a ; (4 cyc.) keep copy of c port res shuttr,c_copy ; (4 cyc.) reset the shutter/led bit ld a,c_copy ; (4 cyc.) load copy in acc ld drc,a ; (4 cyc.) write complete port at once ret ; SHUTTER CLOSES HERE ;|---------------------------------------------------------------------------| ;| flash_it | ;|---------------------------------------------------------------------------| ; ;Subroutine flash_it sets the flash output ON for 20ms flash_it call flashOn ; flash output ON ldi num_ms,20 ; preset ms request call delay_ms ; delay 20ms call flashOff ; flash output OFF ; **************************** ; **************************** ; ** SYSTEM ROUTINES AREA ** ; **************************** ; **************************** ; ***************************** ; * RESET: * ; ***************************** reset jp init ; ***************************** ; * RESET/NMI VECTORS * ; ***************************** ;section 32 begins at 0ff0h .SECTION 32 .block 2 ; vector #4 at address ff0 and ff1 is not used ; (ADC peripheral) irq3 jp tim_int ; vector #3 at FF2h and FF3h is service interrupt of timer irq2 jp p_bc_int ; vector #2 at FF4h and FF5h is B/C port pins irq1 jp p_a_int ; vector #1 at FF6h and FF7h is A port pins .block 4 ; addresses ff8h to ffBh are blocked (not used) nmi jp nmi_int ; vector #0 at FFCh and FFDh is nmi vector vrst jp reset ; this is the reset vector at FFEh and FFFh .end