	.EQU start, 0x8000
#include "XR80C320.h"


	mov mflags, #0
	mov Zaehler, #0x00
	mov PWM1, #0x00
	mov PWM2, #0x03
	mov PWM3, #0x00
	mov PWMinc, #0x08		; R4 Bank 1. Fr PWM unbedingt n”tig. 256/PWMinc
					; muá restlos teilbar sein.


PWMdemo:
			; Schaltet M3 in 5 Stufen, dann Drehrichtungswechsel
	mov r6, #0x50
loop1:
	ACALL PWM
	mov dptr, #0x0005
	lcall ustime
	djnz R6, loop1

	djnz R5, PWMdemo

	mov a, PWM3
	add a, #0x3F
	mov PWM3, a
	jnc PWMdemo
	cpl m3rl
	mov PWM3, #0x03
	ajmp PWMdemo



PWM:
; **************************************************************
; Routine zur Ansteuerung von 3 Motoren an PortB mittels Pulsweitenmodulation.
; Zur Erh”hung des Z„hlers muá R4 vorbesetzt werden (mov 0x0C, #0x08).
; Register werden benutzt, damit es schneller geht.
; Wenn Zaehler_ == 0 Motoren Einschalten => 128 bis 164 Zyklen.
; Sonst entscheiden, ob ausschalten => 140 bis 164 Zyklen.
; Max also 1/(24*10^6)*164= ? æs in der Routine. Softwaregesteuerte PWM ist
; 6*8=48 Zyklen schneller als interruptgesteuerte, da PUSH und POP wegfallen.
; Andernfalls wuerden 220 Zyklen gebraucht.
; Routine benutzt Registerbank 1 und benutzt B nicht.
; **************************************************************
; Summe = 32 Zyklen
	push	PSW
	push	Acc
	push	dpl
	push	dph
	setb	RS0			;  8 Zyklen. Auf Registerbank 1 umschalten
	clr 	RS1			;  8. Sichergehen
	mov	a, Zaehler_		;  4 Zyklen. Zaehler_ laden
	add	a, PWMINC_		;  4 Zyklen. ADD A, #0x08 wrde 8 Zyklen dauern
	mov	Zaehler_, a		;  4 Zyklen
	jnz	m1_aus			; 12 Zyklen. Wenn Zaehler_ !=0 nur auf
					;            Ausschalten testen.
;
m1_ein:
; Summe = 24 Zyklen
	mov	a, PWM1_		;  4 Zyklen. PWM1_ Wert nach A.
	jz	m2_ein			; 12 Zyklen. Wenn null, bei M2 weiter
	setb	m1io			;  8 Zyklen. Motor 1 einschalten, wenn PWM1_ Wert !=0.
m2_ein:
; Summe = 24 Zyklen
	mov	a, PWM2_
	jz	m3_ein
	setb	m2io			; Motor 2 einschalten, wenn PWM2_ Wert !=0
m3_ein:
; Summe = 24 Zyklen
	mov	a, PWM3_
	jz	Motor_ende		; Gleich zum Ende springen
	setb	m3io			; Motor 3 einschalten, wenn PWM3_ Wert !=0
;
	sjmp	Motor_ende
					; 12 Zyklen. Auch hier gleich zum Ende springen, 
					; denn es ist unsinnig einen gerade
					; eingeschalteten Motor auszuschalten.
;
m1_aus:
; Summe = 28 Zyklen
;	jnb m1io, m2_aus		; 16 Zyklen. Wenn M1 schon aus, bei M2 weitermachen
; Das Einfgen dieses Befehls verkrzt die durchschnittliche Laufzeit erheblich, erh”ht
; die maximale Laufzeit jedoch um 30 \%. Diese muá jedoch unter allen Umst„nden gering
; gehalten werden.
					; Zaehler_ befindet sich bereits in A
	clr	C			;  4 Zyklen
	subb	a, PWM1_		;  4 Zyklen
	jc	m2_aus			; 12 Zyklen. Springe zu Motor2_aus,
					;            wenn Zaehler_ < PWM1_.
	clr	m1io			;  8 Zyklen. Sonst Motor 1 ausschalten.
m2_aus:
; Summe = 32 Zyklen
	mov	a, Zaehler_		; 4 Zyklen
	clr	C
	subb	a, PWM2_
	jc	m3_aus
					; Springe zu Motor3_aus, wenn Zaehler_ < PWM2_
	clr	m2io			; sonst Motor 2 ausschalten
m3_aus:
; Summe = 32 Zyklen
	mov	a, Zaehler_		; 4 Zyklen
	clr	C
	subb	a, PWM3_
	jc	Motor_ende	
					; Springe zum Ende, wenn Zaehler_ < PWM3_
	clr	m3io			; sonst Motor 3 ausschalten
;
Motor_ende:				; Ausgabe des Steuerbefehls
; Summe = 44 Zyklen
					; šberspringen der Ausgabe wenn sich
					; nichts ge„ndert hat liegt nahe, die
					; Entscheidung zu treffen kostet aber
					; mehr Zeit, als man spart.
        mov	dptr, #PortB		; 12 Zyklen. Adresse Port B laden.
	mov	a, mflags		;  4 Zyklen. Flags (m1rl ...) laden
        movx	@dptr, a		;  8-36 Zyklen. Port B schreiben => Motorsteuerung.
	clr	RS0			;  8 Zyklen. Umschalten auf Bank 0
	pop	dph
	pop	dpl
	pop	Acc
	pop	PSW
	RET				; 16 Zyklen


