;-------------------------------------------------------------------------
; DSK_ECHO.ASM
; 
; basiert auf dem zum DSK mitgelieferten LOOPAIC.ASM
;
; Prinzip:
;	
;	x(n)                                            y(n)
;	----------------------------------------->(+)------>
;               |                                  |
;               |----[short delay]--(*scale_s)--->(+)
;               |                                  |
;                ----[long delay]---(*scale_l)--->(+)
;
; Mit den Werten in der Skizze kann experimentiert werden, allerdings sollte 
; (short delay < long delay) und (long delay<=0xffff) gelten.  
;
; Peter Schwalbach
; Ing.-Buero Bayer, Neuss	
; 12.96
;
;-------------------------------------------------------------------------
          .start  "AICTEST",0x809802 ; Start assembling here
          .sect   "AICTEST"          ;
;------------------------------------
; Define constants used by program
;------------------------------------
T0_ctrl   .set   0x808020            ; TIM0 gl control
T0_count  .set   0x808024            ; TIM0 count
T0_prd    .set   0x808028            ; TIM0 prd
S0_gctrl  .set   0x808040            ; SP 0 global control
S0_xctrl  .set   0x808042            ; SP 0 FSX/DX/CLKX port ctl
S0_rctrl  .set   0x808043            ; SP 0 FSR/DR/CLKR port ctl
S0_xdata  .set   0x808048            ; SP 0 Data transmit
S0_rdata  .set   0x80804C            ; SP 0 Data receive
TA        .set   12                  ; AIC timing register values
TB        .set   15                  ;
RA        .set   12                  ;
RB        .set   15                  ;
GIE       .set   0x2000              ; This bit in ST turns on interrupts
;------------------------------------
; Define some constant storage data
;------------------------------------
A_REG        .word  (TA<<9)+(RA<<2)+0 ; A registers
B_REG        .word  (TB<<9)+(RB<<2)+2 ; B registers
C_REG        .word  10000011b         ; control
S0_gctrl_val .word  0x0E970300        ; Serial port control register values
S0_xctrl_val .word  0x00000111        ;
S0_rctrl_val .word  0x00000111        ;

last		.word	0
long_delay     	.word	0xffff		; Bufferlaenge fuer langen Weg (<=0xffff)  	
buffer_base  	.word	0x900000	; Basisadresse des Ringspeichers
short_delay	.word	0x900fff	; Basisadresse + Offset fuer kurzen Weg	
	
scale_l		.float	0.4		; Verstärkung langer Weg 	
scale_s		.float	0.7		; Verstärkung kurzer Weg

;****************************************************
; Begin main code loop here
;****************************************************
main   
	ldi	@long_delay,BK		; set buffersize
        ldi	@buffer_base,AR0       
        ldi	@short_delay,AR1      
			

	ldi	0xffff,RC	; Ringspeicher loeschen
	ldi	0,R0
	rptb	CLEAR
CLEAR	sti	R0,*AR0++%	
	
	

loop	or    GIE,ST          ; Turn on INTS
        ldi   0xF4,IE         ; Enable XINT/RINT/INT2
        b     loop            ; Do it again!
;-------------------------------
DAC2    push  	ST              ; DAC Interrupt service routine
        push  	R2              ;
	push 	R3
	push	R4
	push	R5
	
	ldf	@last,R3	; aktuelles Sample x(n)
	ldf   	*AR0,R2    	; langer Weg
	ldf	*AR1++%,R4	; kurzer Weg
	ldf	@scale_l,R5
	mpyf	R5,R2		; verstärken 
	ldf	@scale_s,R5
	mpyf	R5,R4
	addf	R4,R2
	addf	R2,R3
	fix	R3,R3		; float -> int
	lsh	-16,R3		; int fuer DAC anpassen 
	andn	3,R3		; AIC Controlbits ausblenden
	sti   	R3,@S0_xdata    ; Output the new DAC value
        
	pop	R5              
        pop	R4  
	pop   	R3     
        pop	R2
	pop	ST
	reti      
;-------------------------------

ADC2	push	ST
	push	R3
	ldi   	@S0_rdata,R3    ; x(n)
	lsh	16,R3		; ADC Wert -> MSBs
	float	R3,R3		; int -> float
	stf	R3,@last
	stf	R3,*AR0++%	; in Buffer

	pop	R3             
        pop	ST             
	reti                 
;*****************************************************;
; The startup stub is used during initialization only ;
; and can be safely overwritten by the stack or data  ;
;*****************************************************;
          .entry   ST_STUB      ; Debugger starts here
ST_STUB   ldp   T0_ctrl         ; Use kernel data page and stack
          ldi   @stack,SP
          ldi   0,R0            ; Halt TIM0 & TIM1
          sti   R0,@T0_ctrl     ;
          sti   R0,@T0_count    ; Set counts to 0
          ldi   1,R0            ; Set periods to 1
          sti   R0,@T0_prd      ;
          ldi   0x2C1,R0        ; Restart both timers
          sti   R0,@T0_ctrl     ;
          ;---------------------
          ldi   @S0_xctrl_val,R0;
          sti   R0,@S0_xctrl    ; transmit control
          ldi   @S0_rctrl_val,R0;
          sti   R0,@S0_rctrl    ; receive control
          ldi   0,R0            ;
          sti   R0,@S0_xdata    ; DXR data value
          ldi   @S0_gctrl_val,R0; Setup serial port
          sti   R0,@S0_gctrl    ; global control
;======================================================;
; This section of code initializes the AIC             ;
;======================================================;
AIC_INIT  LDI   0x10,IE         ; Enable only XINT interrupt
          andn  0x34,IF         ;
          ldi   0,R0            ;
          sti   R0,@S0_xdata    ;
          RPTS  0x040           ;
          LDI   2,IOF           ; XF0=0 resets AIC
          rpts  0x40            ;
          LDI   6,IOF           ; XF0=1 runs AIC
          ;---------------------
          ldi   @C_REG,R0       ; Setup control register
          call  prog_AIC        ;
          ldi   0xfffc  ,R0     ; Program the AIC to be real slow
          call  prog_AIC        ;
          ldi   0xfffc|2,R0     ;
          call  prog_AIC        ;
          ldi   @B_REG,R0       ; Bump up the Fs to final rate
          call  prog_AIC        ; (smallest divisor should be last)
          ldi   @A_REG,R0       ;
;-------------------------------
prog_AIC  ldi   @S0_xdata,R1    ; Use original DXR data during 2 ndy
          sti   R1,@S0_xdata    ;
          idle
          ldi   @S0_xdata,R1    ; Use original DXR data during 2 ndy
          or    3,R1            ; Request 2 ndy XMIT
          sti   R1,@S0_xdata    ;
          idle                  ;
          sti   R0,@S0_xdata    ; Send register value
          idle                  ;
          andn  3,R1            ;
          sti   R1,@S0_xdata    ; Leave with original safe value in DXR
          ;---------------------
          ldi   @S0_rdata,R0    ; Fix the receiver underrun by reading
          b     main            ; the DRR before going to the main loop

stack     .word   $             ; Put stack here
;****************************************************;
; Install the XINT/RINT ISR handler directly into    ;
; the vector RAM location it will be used for        ;
;****************************************************;
          .start   "SP0VECTS",0x809FC5
          .sect    "SP0VECTS"
          B        DAC2         ; XINT0
          B        ADC2         ; RINT0
