![]() |
Applications of AVR Single chip controllers AT90S, ATtiny, ATmega and ATxmega Servomotor controller with an ATtiny24 |
![]() |
;
; ***************************************************
; * Railway gate with an ATtiny24 and a servo motor *
; * V1, 19.07.2014, translated 17.03.2018 *
; * (C)2014-2018 by http://www.avr-asm-tutorial.net *
; ***************************************************
;
; Include file for the AVR type
.NOLIST
.INCLUDE "tn24def.inc" ; Header file for ATtiny24
.LIST
;
; Debug switches (final: all zero)
.equ debugparam=0
;
; ============================================
; H A R D W A R E I N F O R M A T I O N
; ============================================
;
; ______________
; / ATtiny24 |
; +U o--|VCC GND|--o -U
; Duo LED | |
; Red o--|PB0 ADC0|--o Lower trim
; Anode | |
; Red o--|PB1 ADC1|--o Upper trim
; Cat | |
; RESET o--|RESET ADC3|--o Speed trim
; | |
; DWN o--|INT0 PA4|--o NC
; | |
; UP o--|PCINT7 USC0|--o SCK
; | |
; PWM-SIG o--|OC1A/MOSI MISO|--o MISO
; & MOSI |______________|
;
;
; ============================================
; P O R T S A N D P I N S
; ============================================
;
; Ports for LED control
.EQU pLedO = PORTB
.EQU pLedI = PINB
.EQU pLedD = DDRB
.EQU bLedPlO = PORTB0
.EQU bLedPlD = DDB0
.EQU bLedPlI = PINB0
.EQU bLedMiO = PORTB1
.EQU bLedMiD = DDB1
.EQU bLedMiI = PINB1
; Ports fuer Tastensteuerung
.EQU pDwnO = PORTB
.EQU pDwnD = DDRB
.EQU bDwn = PORTB2
.EQU pUpO = PORTA
.EQU pUpD = DDRA
.EQU pUpI = PINA
.EQU bUpO = PORTA7
.EQU bUpD = DDA7
.EQU bUpI = PINA7
; Ports fuer PWM-Signal
.EQU pPwmO = PORTA
.EQU pPwmI = PINA
.EQU pPwmD = DDRA
.EQU bPwmO = PORTA6
.EQU bPwmD = DDA6
.EQU bPwmI = PINA6
;
; =============================================
; C O N S T A N T S T O A D J U S T
; =============================================
;
.EQU cMinMin = 900 ; us shortest PWM signal duration
.EQU cMaxMax = 2100 ; us longest PWM signal duration
.EQU cMinMed = 1000 ; us lower regulation limit
.EQU cMaxMed = 2000 ; us upper regulation limit
.EQU cMid = (cMaxMax+cMinMin) / 2 ; Middle position
.EQU cPwm = 20000 ; us total PWM duration
.EQU cSpeedHigh = 1000000 ; us duration fastest closing
.EQU cSpeedLow = 7000000 ; us duration slowest closing
;
; ===============================================
; F I X E D + D E R I V E D C O N S T A N T S
; ===============================================
;
.EQU cMaxMin = cMaxMax - 511 ; Lower limit closing
.EQU cRoundsFast = cSpeedHigh / cPwm
.EQU cRoundsSlow = cSpeedLow / cPwm
.EQU cAdderFast = (cMaxMed - cMinMed) / cRoundsFast
.EQU cAdderSlow = 1 ; Slow adder
.EQU cSpeedMulti = cAdderFast - cAdderSlow
;
; ===================================
; P R O G R A M S T R U C T U R E
; ===================================
;
; All timing is based on a clock frequency of 1 MHz,
; which is the default clock frequency with CLKDIV8
; set and the 8 MHz RC oscillator selected.
;
; ADC values
; Measuring the trim potentiometer settings runs with
; an ADC clock prescaler of 128. 64 measurements per
; channel are added up in the registers R0 to R5 and
; averaged.
; From this a measuring frequency of 1 Mhz / 128 /
; 13 clock cycles per conversion / 3 channels / 64
; single measurements = approx. 3 Hz results.
; Calculation of those measurements goes as follows:
; Trim 1: Sum/128+cMinMin(900) ==> rClose (Minimum)
; Trim 2: cMaxMax(2100)-Sum/128 ==> rOpen (Maximum)
; Trim 3: (Sum/256*cSpeedMulti)/256+1 ==> rDelta
; (Speed), values vary between 1 and 23
; (1 = 20 seconds closure time, 23 = one second
; closure time
;
; Timer1: Generation of the PWM signal
; TC1 is clocked by the clock signal and a prescaler
; of 1, one tick is therefore 1 us.
; TC1 runs as CTC and generates the PWM signal on the
; output pin OC1A on PA6. The output pin toggles on
; compare match A, TC1 restarts and triggers a
; compare match A intterupt. Depending from the state
; of the output pin either the duration in rCtcAct or
; in rCtcIna is written to the compare register A. The
; resulting looks as follows:
;
; _______ _______ ______
; _____| |_________________| |_________________|
; rCtcAct rCtcIna rCtcAct rCtcIna
; |<======= 20.000 us =====>|<======= 20.000 us =====>|
;
; rCtcAct = 900 .. 2.100 us
; Lower limit adjustable with trim 1 between 900 and 1410 us
; Upper limit adjustable with trim 2 between 1590 and 2100 us
; rCtcIna = 20.000 - rCtcAct
;
; rCtcAct plus rCtcIna always yields 20.000 us, a 50 Hz signal.
; When the OC1A pin is set (after writing rCtcIna) the bPwm flag
; is set, which triggers execution of the routine PwmRdy. This
; determines if the gate is currently moving or not.
; If this is not the case, 25 following PWM signal bursts are
; sent with the current position (0.5 seconds). After that the
; PWM signal output is cleared (by clearing the output pin on
; compare match).
; If the gate is moving the duration of the PWM signal is increased
; by the content of rDelta, if the gate opens, or decreased if
; the gate closes. If, on opening, the upper limit in rOpen is
; exceeded the LED is switched to permanently green and the
; post-PWM period is initiated.
; If, on closing, the lower limit in rClose is reached the LED
; is switched to permanent red and the post-PWM period initiated.
; Bei aktiver Schranke wird die Dauer des PWM-Signals um den Betrag
; rDelta verlaengert (Schranke oeffnet sich) bzw. verkuerzt (Schranke
; schliesst sich). Ist beim Oeffnen die obere Grenze in rOben ueber-
; schritten wird die LED auf gruenes Dauerlicht geschaltet und der
; Nachlauf eingeleitet. Ist beim Schliessen die untere Grenze unter-
; schritten wird die LED auf rotes Dauerlicht geschaltet und der
; Nachlauf eingeleitet.
; If neither the upper nor the lower limit has been reached the
; LED blinks with 0.2 Hz.
;
; Triggering opening and closing of the gate
; If push button 1 is activated, an INT0 interrupt is triggered.
; This clears the upward flag.
; If push button 2 is activated, the PCINT0 interrupt is triggered.
; Following both interrupts and if the toggle bit of TC1 is not
; set, the rCtcIna value is written to the compare A port, the
; toggle mode in TC1 is set and the compare match A interrupt is
; enabled. Finally the "Gate active" flag is set.
;
; Adjusting
; If the value of the up- or down-trim-poentiometer is changed,
; the new value is immediately applied. If the gate is inactive
; (bActive flag cleared), the gate only moves if it is completely
; open (last movement upwards) or completely closed (last movement
; downwards).
; Changes of the speed trim potentiometer come only into effect
; if the gate moves.
;
; Start conditions
; On start up the gate is moved to to its middle position and then
; upwards to the upper limit.
;
; ============================================
; R E G I S T E R D E F I N I T I O N S
; ============================================
;
; R0 .. R5 : ADC sum values, three channels
.DEF rCtcActL = R6 ; Active signal duration, us
.DEF rCtcActH = R7
.DEF rCtcInaL = R8 ; Inactive signal duration, us
.DEF rCtcInaH = R9
.DEF rCloseL = R10 ; Lower limit PWM signal
.DEF rCloseH = R11
.DEF rOpenL = R12 ; Upper limit PWM signal
.DEF rOpenH = R13
.DEF rDelta = R14 ; Step length for gate movement
.DEF rSreg = R15 ; for SREG interim storage in ints
.DEF rmp = R16 ; Multi purpose register
.DEF rimp = R17 ; Multi purpose inside interrupts
.DEF rimp2 = R18 ; 16 bit adder register in interrupts
.DEF rAdcCnt = R19 ; Counter for ADC measurements
.DEF rFlg = R20 ; Flag register
.equ bActive = 0 ; Gate is moving
.equ bHigh = 1 ; Gate is moving up
.equ bAdc = 2 ; ADC sequence complete
.equ bPwmIna = 3 ; Inactive PWM signal, handle flag
.equ bOpen = 4 ; Gate is open
.equ bClose = 5 ; Gate is closed
.equ bToggle = 6 ; CTC toggle is active
.DEF rPwmCtr = R21 ; Downcounter for post-PWM phase
; R22 .. R25 not used
; X = XH:XL Multiplication for speed adjustment
; Y = YH:YL ADC pointer to SRAM
; Z = ZH:ZL Multi purpose register pair outside interrupts
;
; ============================================
; S R A M D E F I N I T I O N S
; ============================================
;
.DSEG
.ORG 0X0060
sAdc: .Byte 6
;
; ==============================================
; R E S E T A N D I N T V E C T O R E N
; ==============================================
;
.CSEG
.ORG $0000
rjmp Main ; Reset-Vector
rjmp IntDwn ; Int Vector INT0
rjmp IntUp ; Int Vector PCINT0
reti ; Int Vector PCINT1
reti ; Int Vector WDT
reti ; Int Vector TC1 Capture
rjmp IntPwmA ; Int Vector TC1 Compare A
reti ; Int Vector TC1 Compare B
reti ; Int Vector TC1 OVF
reti ; Int Vector TC0 Compare A
reti ; Int Vector TC0 Compare B
reti ; Int Vector TC0 OVF
reti ; Int Vector Ana_Comp
rjmp IntAdc ; Int Vector ADC
reti ; Int Vector EEPROM Ready
reti ; Int Vector USI START
reti ; Int Vector USI Overflow
;
; ==========================================
; I N T E R R U P T S E R V I C E
; ==========================================
;
; Downwards push button
IntDwn:
in rSreg,SREG ; Save SREG
cbr rFlg,1<<bHigh ; Clear upward flag
rjmp IntUD
;
; Upwards push button
IntUp:
in rSreg,SREG ; Save SREG
sbic pUpI,bUpI ; Falling edge?
reti ; No, ignore
sbr rFlg,1<<bHigh ; Set upwards flag
IntUD:
; Start move cycle
sbrc rFlg,bActive ; Already active?
rjmp IntUD1 ; Yes, ignore
sbr rFlg,1<<bActive ; Set gate aktice flag
sbrc rFlg,bToggle ; Skip if not in toggle mode
rjmp IntUD1 ; Toggle-Mode is on
ldi rPwmCtr,1 ; Start blink counter
out OCR1AH,rCtcInaH ; Compare match inactive duration
out OCR1AL,rCtcInaL
ldi rimp,1<<COM1A0 ; Enable toggle of output pin
out TCCR1A,rimp
ldi rimp,1<<OCIE1A ; Enable TC1COMPA interrupt
out TIMSK1,rimp
sbr rFlg,1<<bToggle
IntUD1:
out SREG,rSreg ; Restore SREG
reti
;
; TC1 Compare match A interrupt service routine
IntPwmA:
in rSreg,SREG ; Save SREG
sbic pPwmI,bPwmI ; Skip if PWM signal=0
rjmp IntPwmA1
out OCR1AH,rCtcInaH ; Long inactive pause
out OCR1AL,rCtcInaL
sbr rFlg,1<<bPwmIna ; Set flag
rjmp IntPwmA2
IntPwmA1:
out OCR1AH,rCtcActH ; Short active signal
out OCR1AL,rCtcActL
IntPwmA2:
out SREG,rSreg ; Restore SREG
reti
;
; AD conversion complete interrupt service routine
IntAdc:
in rSreg,SREG ; Save SREG
in rimp,ADCL ; Read LSB result
ld rimp2,Y ; Read current sum LSB
add rimp,rimp2 ; Add LSB to current
st Y+,rimp ; and store in SRAM
in rimp,ADCH ; Read MSB result
ld rimp2,Y ; Read MSB current sum
adc rimp,rimp2 ; Add MSBs with carry
st Y+,rimp ; Store MSB
cpi YL,6 ; End of round?
brcs IntAdcRet ; No, continue
clr YL ; Restart
dec rAdcCnt ; Count rounds down
brne IntAdcRet
AdcCopy:
; End of ADC measuring cycle
ldi YL,LOW(sAdc) ; Copy to SRAM
st Y+,R0
st Y+,R1
st Y+,R2
st Y+,R3
st Y+,R4
st Y,R5
clr YL
clr R0 ; Clear sums
clr R1
clr R2
clr R3
clr R4
clr R5
sbr rFlg,1<<bAdc ; Set flag
IntAdcRet:
mov rimp,YL ; Copy MUX channel
lsr rimp ; Divide by two
out ADMUX,rimp ; MUX to next channel
; Start next conversion
ldi rimp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rimp
out SREG,rSreg ; Restore SREG
reti
;
; ============================================
; M A I N P R O G R A M I N I T
; ============================================
;
Main:
; Init stack
ldi rmp, LOW(RAMEND) ; Init LSB stack
out SPL,rmp
; Init port bits
; Init LED pins
sbi pLedD,bLedPlD ; LED pins as output
sbi pLedD,bLedMiD
sbi pLedO,bLedPlO ; Turn red LED on
cbi pLedO,bLedMiO
; Init the push button pins
cbi pDwnD,bDwn ; Close push button as input
sbi pDwnO,bDwn ; Pull up resistor on
cbi pUpD,bUpD ; Close push button as input
sbi pUpO,bUpO ; Pull up resistor on
; Init PWM output pin
sbi pPwmD,bPwmD ; PWM output pin as output
cbi pPwmO,bPwmO ; To low
; Init ADC
; Single measurement at start up
.if debugparam==1
rjmp debugcalc
nop
.endif
rcall AdcGet ; Get first cycle
ldi rmp,HIGH(cMid) ; Position to middle
mov rCtcActH,rmp
ldi rmp,LOW(cMid)
mov rCtcActL,rmp
clr rFlg ; Clear flags
sbr rFlg,(1<<bActive)|(1<<bHigh) ; Move gate up
ldi rPwmCtr,1 ; Init LED blink counter
rcall PwmRdyO ; Blink and correct Inactive duration
; Prepare ADC sequence
ldi YH,HIGH(sAdc) ; Pointer to SRAM
ldi YL,LOW(sAdc)
ldi rmp,0 ; MUX to channel 0
out ADMUX,rmp
ldi rmp,(1<<ADC0D)|(1<<ADC1D)|(1<<ADC0D) ; Digital input driver disable
out DIDR0,rmp
clr rmp ; Results not left adjust
out ADCSRB,rmp
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp
; Init timer 1
out OCR1AH,rCtcInaH ; CTC to inactive duration
out OCR1AL,rCtcInaL
ldi rmp,1<<COM1A0 ; Toggle output A on compare match
out TCCR1A,rmp
ldi rmp,(1<<WGM12)|(1<<CS10) ; CTC mode, prescaler = 1
out TCCR1B,rmp
ldi rmp,1<<OCIE1A ; TC1 Compare Match A Interrupt Enable
out TIMSK1,rmp
sbr rFlg,1<<bToggle ; Toggle is active
; Init PCINT7
ldi rmp,1<<PCINT7 ; Pin-Change Int push button 2
out PCMSK0,rmp
; Init external interrupts and Sleep mode idle
ldi rmp,(1<<SE)|(1<<ISC01) ; Enable sleep and INT0
out MCUCR,rmp
; External interrupts
ldi rmp,(1<<INT0)|(1<<PCIE0) ; Enable INT0 and PCINT0 interrupts
out GIMSK,rmp
sei ; Enable interrupts
;
; ============================================
; P R O G R A M - L O O P
; ============================================
;
Loop:
sleep ; Send to sleep
nop ; Dummy for wake-up
sbrc rFlg,bPwmIna ; PWM flag set?
rcall PwmRdy ; Yes, handle PWM
sbrc rFlg,bAdc ; ADC flag set?
rcall AdcRdy ; Yes, handle ADC
rjmp loop ; Back to loop
;
; PWM ready
PwmRdy:
cbr rFlg,1<<bPwmIna ; Clear flag
sbrc rFlg,bActive ; Skip if gate inactive
rjmp PwmRdyA ; Gate active
; Gate inactive
sbrs rFlg,bToggle ; Skip if toggle is on
ret ; Toggle is off, return
; TC1 toggle is on
dec rPwmCtr ; Count post-PWM down
brne PwmRdy1 ; Not finished yet
ldi rmp,1<<COM1A1 ; Set TC output pin to clear
out TCCR1A,rmp ; Switch toggle off
clr rmp ; Disable TC1 interrupt
out TIMSK1,rmp
cbr rFlg,1<<bToggle ; Toggle flag off
PwmRdy1:
ret
PwmRdyA: ; Gate ist active
sbrc rFlg,bHigh ; Skip if gate is closed
rjmp PwmRdyH ; Gate upwards
; Gate downwards
sub rCtcActL,rDelta ; Reduce PWM signal duration
brcc PwmRdyA1 ; No carry
dec rCtcActH ; MSB downwards
PwmRdyA1:
cp rCtcActL,rCloseL ; Compare with lower limit
cpc rCtcActH,rCloseH
brcc PwmRdyA2 ; Not yet reached
mov rCtcActL,rCloseL ; Reached, set close value
mov rCtcActH,rCloseH
cbr rFlg,1<<bActive ; End gate movement
sbr rFlg,1<<bClose ; Set close flag
sbi pLedO,bLedPlO ; Red LED permanently on
cbi pLedO,bLedMiO
ldi rPwmCtr,25 ; Start repeat counter for post-PWM
rjmp PwmRdyK ; Correct duration PWM
; Not yet on close position
PwmRdyA2:
cbr rFlg,1<<bClose ; Close flag off
rjmp PwmRdyO ; Blink and correct PWM duration
PwmRdyH:
; Gate upwards
add rCtcActL,rDelta ; Add delta to signal duration
brcc PwmRdyH1 ; No carry
inc rCtcActH ; Carry to MSB
PwmRdyH1:
cp rCtcActL,rOpenL ; Compare with upper limit
cpc rCtcActH,rOpenH
brcs PwmRdyH2 ; Not yet reached
mov rCtcActL,rOpenL ; Reached, set upper limit
mov rCtcActH,rOpenH
cbr rFlg,1<<bActive ; End gate movement
sbr rFlg,1<<bOpen ; Gate open flag
cbi pLedO,bLedPlO ; LED permanently green
sbi pLedO,bLedMiO
ldi rPwmCtr,25 ; Start repeat counter for post-PWM
rjmp PwmRdyK ; Correct duration of PWM inactive
PwmRdyH2:
cbr rFlg,1<<bOpen ; Open flag off
rjmp PwmRdyO ; LED blink and CTC-Inactive correction
PwmRdyO:
; LED blink
cbi pLedO,bLedMiO
dec rPwmCtr ; Counter for blink LED
brne PwmRdyK ; Correct inactive duration PWM
ldi rPwmCtr,12 ; Restart counter
sbic pLedI,bLedPlI ; Skip if LED is off
rjmp PwmRdyO1 ; LED is on
sbi pLedO,bLedPlO ; LED on
rjmp PwmRdyK
PwmRdyO1:
cbi pLedO,bLedPlO ; LED off
PwmRdyK:
; Correct inactive duration PWM
ldi rmp,LOW(cPwm) ; Total duration - Active duration
sub rmp,rCtcActL
mov rCtcInaL,rmp ; Copy to inactive duration
ldi rmp,HIGH(cPwm)
sbc rmp,rCtcActH
mov rCtcInaH,rmp
ret
;
; ADC measuring sequence ended
;
AdcRdy:
cbr rFlg,1<<bAdc
push rCloseL
push rCloseH
push rOpenL
push rOpenH
rcall CalcSpeed
pop XH
pop XL
pop ZH
pop ZL
sbrc rFlg,bActive ; Skip if gate still active
ret ; Yes
sbrc rFlg,bToggle ; Skip if toggle active
ret ; Yes
ldi rmp,LOW(cMid) ; Below or above middle?
cp rCtcActL,rmp
ldi rmp,HIGH(cMid)
cpc rCtcActH,rmp
brcc AdcRdyU
; Gate is below middle
mov rCtcActH,rCloseH
mov rCtcActL,rCloseL
rjmp AdcRdyS ; Start move cycle
AdcRdyU:
; Gate is above middle
mov rCtcActH,rOpenH
mov rCtcActL,rOpenL
AdcRdyS:
; Start adjustment
rcall PwmRdyK ; Calculate inactive duration
ldi rPwmCtr,10 ; Start post-PWM cycle
ldi rmp,1<<COM1A0 ; Start toggle
out TCCR1A,rmp
ldi rmp,1<<OCIE1A ; Start interrupt
out TIMSK1,rmp
sbr rFlg,1<<bToggle ; Set toggle flank
ret
;
; =============================================
; A S Y N C H S U B R O U T I N E S
; =============================================
;
; Get ADC results during init
AdcGet:
ldi rmp,(1<<ADC0D)|(1<<ADC1D)|(1<<ADC2D) ; Digital drivers off
out DIDR0,rmp
clr rmp ; Result not left adjusted
out ADCSRB,rmp
ldi YH,HIGH(sAdc) ; Channel counter Y points to SRAM
ldi YL,LOW(sAdc)
GetAdc1:
clr R0 ; Clear result
clr R1
ldi rAdcCnt,64 ; 64 measurements
mov rmp,YL ; MUX channel
lsr rmp
andi rmp,0x03 ; Isolate channel bits
out ADMUX,rmp
GetAdc2:
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp
GetAdc3:
sbic ADCSRA,ADSC ; Wait for result
rjmp GetAdc3
in rmp,ADCL ; Add LSB to result
add R0,rmp
in rmp,ADCH ; Add MSB to result
adc R1,rmp
dec rAdcCnt
brne GetAdc2 ; Again convert
st Y+,R0 ; Store LSB
st Y+,R1 ; Store MSB
cpi YL,sAdc+6 ; All three channels read?
brcs GetAdc1
;
; Calculate delta from speed position
CalcSpeed:
lds rmp,sAdc+5 ; ADC result MSB channel 3
clr XH ; Multiplicator MSB
ldi XL,cSpeedMulti ; LSB = Multiplicator for speed
clr ZH ; Z is result
clr ZL
CalcSpeed1:
lsr rmp ; Bit = 1?
brcc CalcSpeed2 ; No, do not add
add ZL,XL ; Add LSB multiplicator
adc ZH,XH ; Add MSB and carry
CalcSpeed2:
lsl XL ; Double multiplicator
rol XH
tst rmp ; Already done?
brne CalcSpeed1 ; No, further bits
ldi rmp,cAdderSlow
add rmp,ZH ; Add MSB of the result
mov rDelta,rmp
;
; Lower and upper trim potentiometer
AdcConv:
lds rmp,sAdc ; Read LSB lower trim
lds ZL,sAdc+1 ; Read MSB upper trim
clr ZH
lsl rmp ; Upper bit LSB into lower bit LSB
rol ZL ; Rotate into LSB
rol ZH ; And into MSB
ldi rmp,LOW(cMinMin) ; Minimum duration lower limit
add ZL,rmp ; Add to result
ldi rmp,HIGH(cMinMin)
adc ZH,rmp
andi ZL,0xFC ; Clear lowest two bits
mov rCloseH,ZH ; Copy to closure position
mov rCloseL,ZL
lds rmp,sAdc+2 ; Read LSB upper trim
lds ZL,sAdc+3 ; Read MSB upper trim
clr ZH
lsl rmp ; Upper bit LSB to lowest bit LSB
rol ZL ; Rotate bit into LSB in ZL
rol ZH ; And into MSB
ldi rmp,LOW(cMaxMin) ; LSB maximum duration upper position
add ZL,rmp ; Add to LSB
ldi rmp,HIGH(cMaxMin)
adc ZH,rmp ; Add MSB and carry
andi ZL,0xFC ; Clear lowest two bits
mov rOpenL,ZL
mov rOpenH,ZH
ret
.if debugparam==1
debugcalc:
ldi rmp,0xFF
ldi ZH,HIGH(sAdc)
ldi ZL,LOW(sAdc)
st Z+,rmp
st Z+,rmp
st Z+,rmp
st Z+,rmp
st Z+,rmp
st Z+,rmp
rjmp CalcSpeed
.endif
;
; End of source code
; Copyright
.db "(C)2014 by Gerhard Schmidt " ; human readable
.db "C(2)10 4ybG reahdrS hcimtd " ; wordwise
;
Top of page |
---|