;********************************************************************
; This is a dimmer based on application note
; using a Z86E04 MCU running on CCP
; This program is assembled only by ZiLOG ZASM assembler
;********************************************************************
;
;********************************************************************
; Quando e' desiderato una partenza lenta impostare l'equ
; SOFTSTART_WISHED to 1
;********************************************************************
SOFTSTART_WISHED .equ 0 ; 1 = Yes 0 = No
;********************************************************************
; Bit number definitions
;********************************************************************
bitno0 .equ %01
bitno1 .equ %02
bitno2 .equ %04
bitno3 .equ %08
bitno4 .equ %10
bitno5 .equ %20
bitno6 .equ %40
bitno7 .equ %80
;********************************************************************
; PORTS DEFINITION
;********************************************************************
; Port 2 pin
; P20 : output for triac gate
.triac_gate .equ bitno0
; P21-P27 : output idle N.C.
; Port 0 pin
; P00 : power. UP key
.upkey .equ bitno0
; P01 : power. DOWN key
.downkey .equ bitno1
; P02 : idle input
; Port 3 pin
; P31 : idle input, pull to ground
; P32 : AC zero crossing detection
.acinput .equ bitno2
; P33 : Voltage reference = GND
;********************************************************************
; REGISTERS DEFINITION
;********************************************************************
power_level .equ @rr4 ; phase table add. of actual power level
power_levelHB .equ r4 ; address offset HB for phase table
power_levelLB .equ r5 ; address offset LB (lower nibble = ; power level value)
dimmerflags .equ r6 ; register used by the dimmer
; routines
period_count .equ r7 ; counts the numbers of periods
shadow .equ r8 ; general purpose shadow
;softstartcounter .set r9 ; counts time for softstart
delay_counter .equ %FE ; counter for delay routine
;
;********************************************************************
; BITS DEFINITION
;********************************************************************
old_ac_level .equ bitno0
new_ac_level .equ bitno1
is_ignition_on? .equ bitno2
positive_part .equ bitno3
;
;********************************************************************
; CONSTANTS DEFINITION
;********************************************************************
fifty_Hz .equ 11110010b ; prescaler1=60 single shot
sixty_Hz .equ 11001010b ; prescaler1=50 single shot
start_up_power .equ %f7 ; power start level <= (15+%f0)
maxpower .equ %f9 ; maximum power <= (15+%f0)
minpower .equ %f1 ; minimum power >= (0+%f0)
T_to_2ignition .equ 156 ; time between 1st and 2nd ignition
zcforskey .equ 20 ; scankey on every xth zero crossing
softstart_time .equ 20 ; softstart takes x * 20 millisec.
ignition_time .equ 3 ; ignition on for app. 150Ęsec.
;
;********************************************************************
; MACROS
; Refer to Z8 technical manual for macro definition
;********************************************************************
bset: .macro arg1,arg2
or arg1,#arg2
.endm
bclr: .macro arg3,arg4
and arg3,#^c (arg4) ^& 0ffh
.endm
brset: .macro arg1,arg2,arg3
tm arg1,#arg2
jr nz,arg3
.endm
brclr: .macro arg1,arg2,arg3
tm arg1,#arg2
jr z,arg3
.endm
release_ignition: .macro
bset p2,.triac_gate
.endm
ignite_triac: .macro
bclr p2,.triac_gate
.endm
start_T1: .macro
ld tmr,#00001100b
.endm
;********************************************************************
; INTERRUPTS VECTOR
;********************************************************************
.mlist on
.list on
; Interrupt vector address %00 to %0C
.ORG %0000
;********************************************************************
; solo per l'emulatore CCP
;********************************************************************
; .word comparator2 ; for emulation only
; .word irq1 ; for emulation only
; .word irq2 ; for emulation only
; .word irq3 ; for emulation only
; .word irq4 ; for emulation only
; .word timer1 ; for emulation only
;********************************************************************
; solo per programmazione OTPs
;********************************************************************
.word irq0
.word irq1
.word irq2
.word comparator2
.word irq4
.word timer1
;************************************************
; PROGRAM STARTS HERE *
;************************************************
BEGINNING:
.ORG %0C
irq0:
irq1:
irq2:
irq3:
irq4:
di
ld P01M,#00000101b
;P0, P1 input, internal stack
ld P2M,#00000000b
;P20-P27 output
ld P3M,#00000011b
;P3 analog + P2 push pull
or P2,#00000001b ;Switchoff the triac
clr SPH
ld SPL,#%40 ;INIT STACK POINTER
;********************************************************************
; FOR EMULATION
;********************************************************************
; ld IPR,#00011100b ; for emulation only
; ld IMR,#00100100b ; for emulation only
; ld IRQ,#01000000b ; for emulation only
;********************************************************************
; FOR BURNING OTPs
;********************************************************************
ld IPR,#00101010b ; IRQ3 > IRQ5
ld IMR,#00101000b ; enable T1 interrupt
; + Comparator2
; (rising edge) interrupt
; INITIALIZE RAM TO "0"
srp #%30
ld R14,#%3d
ZRAM: clr @R14
djnz R14,ZRAM
; Initialize all registers
srp #%00 ; set working register to %00
call delay40mS ; wait for AC to be stable
ld power_levelHB,#%01 ; offset for phase table add.
ld pre1,#fifty_Hz ; T1 preset for 50H
.IF SOFTSTART_WISHED
ld power_levelLB,#minpower ; preset power level
ei
call softstart ; increase power slowly
.ELSE
ld power_levelLB,#start_up_power
ei
.ENDIF
;********************************************************************
;
;********************************************************************
; MAIN USER PROGRAM
; The dimmer runs as a batch task via T1 + C2 interrupt.
; This is the user program that runs in front.
;********************************************************************
Main:
NOP
jr Main
;********************************************************************
; SUBROUTINES
;********************************************************************
call delay40mS:
call delay10mS
call delay10mS
call delay10mS
call delay10mS
ret
; 1.5uS x (30x222) = 10 mS
delay10mS:
ld delay_counter,#222 ; 6 cycles
loop1:
nop ; 6 cycles
nop ; 6 cycles
dec delay_counter ; 6 cycles
jr nz,loop1 ; 12 cycles
ret
; Increase power slowly after the start
; for long light bulb life.
softstart:
.IF SOFTSTART_WISHED
softstartcounter .set r5 ; counts time for softstart
cp power_levelLB,#start_up_power ; if power level is
jr GE,end_softstart ; below start level
softstart_delay:
ld softstartcounter,#softstart_time
call delay10mS ; then increase power
djnz softstartcounter,softstart_delay ; every x millisec.
inc power_levelLB
jr softstart
end_softstart:
ret
.ENDIF
Scan key in every 20th period
; ie 20mS x 20 = 400mS for 50Hz AC
; 16.7mS x 20 = 334mS for 60Hz AC
scankey:
djnz period_count,end_scankey ; check keys on every
; 20th period
ld period_count,#zcforskey
brset P0,.upkey,increase_power ; check increment key
brset P0,.downkey,decrease_power ; check decrement key
jr end_scankey
; Increment the output power if UP key is pressed
; Maximum level = 15
increase_power:
inc power_levelLB
cp power_levelLB,#maxpower ; if the power level
jr LE,end_scankey ; is too high, then
ld power_levelLB,#maxpower ; keep at max. power
jr end_scankey
; Decrement the output power if DOWN key is pressed
; Minimum level = 0
decrease_power:
dec power_levelLB
cp power_levelLB,#minpower ; if the power level
jr GE,end_scankey ; is too low, then
ld power_levelLB,#minpower ; keep at min. power
end_scankey:
ret
; Whenever a zero crossing from negative to positive occurs, means
; the AC period starts, a comparator2 interrupt is serviced.
; AC line change in every 10mS for 50Hz, 8.3mS for 60Hz
comparator2: ; ac had a negative to positive
push rp ; zero crossing
srp #%00
ldc shadow,power_level
ld T1,shadow ; let T1 run till phase angle
start_T1 ; for 1st ignition is reached
bset dimmerflags,positive_part
pop rp ; positive part of
iret ; ac period
; Timer1 interrupt occurs 4 times during one ac period.
; 2 times to ignite the triac and two times to release the ignition
; again.
timer1:
push rp ; working register
srp #%00 ; group 0 reserved
; for timer1
; interrupt
brset dimmerflags,is_ignition_on?,turn_off_ignition
turn_on_ignition:
ignite_triac ; ignite the triac
ld T1,#ignition_time ; let T1 run for the
start_T1 ; ignition time
bset dimmerflags,is_ignition_on?
jr end_of_interrupt
turn_off_ignition:
release_ignition
bclr dimmerflags,is_ignition_on?
brclr dimmerflags,positive_part,end_of_interrupt
ld T1,#T_to_2ignition ; let T1 run for
start_T1 ; 10 or 8.3 milli
call scankey ; seconds
bclr dimmerflags,positive_part
end_of_interrupt:
pop rp
iret
; Currently no more than 16 values are possible in
; the phase table without other changes to the program.
.org %1f0
phase_table:
.byte 145 ; zero power
.byte 124 ; 1/10 power
.byte 111 ; 2/10 power
.byte 101 ; 3/10 power
.byte 92 ; 4/10 power
.byte 83 ; 5/10 power
.byte 75 ; 6/10 power
.byte 66 ; 7/10 power
.byte 56 ; 8/10 power
.byte 43 ; 9/10 power
.byte 07 ; full power
.end