;****************************************************************
; SCAN.ASM for TMS320C31 DSP STARTERS KIT
; Keith Larson
; TMS320 DSP Applications
; (C) Copyright 1995,1996
; Texas Instruments Incorporated
;
; This is unsupported freeware with no implied warranties or
; liabilities.  See the disclaimer document for details
;
; NOTE: A shareware 640x480x256 BGI SVGA graphics driver was
;	used to develop this application.  It is NOT distributed
;	the DSK software.  You must obtain this driver from the
;	original author.  Read README. for details.
;----------------------------------------------------------------;
; This code is designed to drive the TSL1402 256 x1 Linear Sensor;
; Array using the following circuit for the C3x DSK.  The best   ;
; construction technique is as shown.  Normaly the components    ;
; would be placed on the ground plane side of the project board  ;
; but in this case the light needs to hit the device from the    ;
; bottom.                                                        ;
;                                                                ;
; The project boards I prefer to use have a solid ground plane   ;
; on one side (component side) and pads on the other. This type  ;
; of board has proven to be very reliable and easy to use with   ;
; excellent analog signals.                                      ;
;                                                                ;
; In my case mounting of the TSL1402 was achieved by removing    ;
; a small piece of the ground plane.  This was done cutting the  ;
; plane (not very deep) and then by soldering a piece of         ;
; solder-wick to the plane so it could be pulled away.  This     ;
; will slightly damage the underlying fiberglass, but is not too ;
; drastic.                                                       ;
;                                                                ;
; If you use a board with a ground plane and choose to leave the ;
; ground plane intact, use a wire-wrap socket with leads that are;
; long enough to easily solder or wire-wrap to without causing a ;
; short to the ground plane.                                     ;
;                                                                ;
; NOTE: The TLC5510 8 bit flash converter is an ideal converter  ;
;       for this application.  However since this device is only ;
;       available in surface mount and is not as easy to wire    ;
;       up it is not showcased with this application note.       ;
;----------------------------------------------------------------;
;                                                                ;
;  DSK (side view)                                               ;
;                                                                ;
;                     +---+                                      ;
;     +-------+       | C |                                      ;
;DB25 | +----+|       | A |                    +------+          ;
;     | |PWR ||       | P |                    |RCA   |          ;
;     +-|    ||       |   |                    |    +-+          ;
;       =============================================            ;
;             |            |      |            | <- Female conns ;
;             +------------+      +------------+    go here      ;
;                                                                ;
;                                                                ;
;(component side)                                                ;
;              ||||||||||||        ||||||||||||  <- Male conns   ;
;Gnd plane side||||||||||||        ||||||||||||     go here      ;
;       =============================================            ;
;Pad side                   |   |                                ;
;                           =====                                ;
;                           |   |  TLS1402                       ;
;                           +---+                                ;
;                             ^                                  ;
;                             |                                  ;
;                           Focused                              ;
;                           Light                                ;
;                                                                ;
;----------------------------------------------------------------;
; SCHEMATIC                                                      ;
; ---------                                                      ;
;                                                                ;
;  C3x DSK Headers						 ;
;	     |			  TSL1402 or TSL215		 ;
;	     |			 +--------------+		 ;
;	     |			 |		|		 ;
;	 VCC |--------+----------|Vdd	      NC|		 ;
;	     |	      | 	 |		|		 ;
;	TIM1 |-------------------|SI1	     S01|------+	 ;
;	     |	      | 	 |		|      |	 ;
;        XF1 |-------------------|CLK	     GND|---+  |	 ;
;	     |	      | 	 |		|   |  |	 ;
;	     |	      |  +-------|A01	      NC|  /// |	 ;
;	     |	      |  |	 |		|      |	 ;
;	     |	      |  |   +---|GND	     SI2|------+	 ;
;	     |	      |  |   |	 |		|		 ;
;	     |	      |  |  ///  |S02	      NC|		 ;
;	     |	      |  |	 |		|		 ;
;	     |	      +----------|Vdd	     A02|----+-----+	 ;
;	AGND |---+    |  |	 |		|    |	   |	 ;
;	     |	 |    |  |	 +--------------+    |	   R	 ;
;	     |	///   |  |                           |     R 330 ;
;	AIN+ |-----------+---------------------------+	   |	 ;
;	     |	      |	                                  ///    ;
;                    === Cbypass                                 ;
;                     |                                          ;
;                    ///                                         ;
;                                                                ;
;****************************************************************;
; AIC startup values                   ;
TA        .set     6 ;  4              ;
TB        .set    12 ; 12  48*2=96     ;
RA        .set     6 ;  4              ;
RB        .set    12 ; 12              ;
TPRD      .set     2 ;  2              ;
Hrate     .set  25e6 ; DSK MIP rate    ;
;--------------------------------------;
          .include "C3XMMRS.ASM"       ;
          .start   "AICTEST",0x809800  ;
          .sect    "AICTEST"           ;
GIE       .set     0x2000              ;
_CVTLINE  .set     1                   ;
;=================================================================
TIMERACK      .word  0                 ; 0x809800
A_REG         .word  (TA<<9)+(RA<<2)+0 ; 0x809802
B_REG         .word  (TB<<9)+(RB<<2)+2 ; 0x809803
C_REG	      .word  01000011b	       ; 0x809804   +/- 6.0 V Aux
;-------------------------------;
PIX_DATA      .word  0x809A00   ;
S0_gctrl_val  .word  0x0E970300 ;
;S0_gctrl_val .word  0x0E973300 ; CLKX/R are inverted
S0_xctrl_val  .word  0x00000111 ;
S0_rctrl_val  .word  0x00000111 ;
T_scale       .float Hrate/(4.0*1.0e6) ; Converts uS/line to C3x clocks
;-------------------------------;
main      ldi   @S0_rdata,R0    ;
          ldi   @S0_rdata,R0    ;
          ldi   @JR_HOST,AR1    ; Get sub-function from host
          callu AR1             ;
          cmpi  _CVTLINE,R0     ;
          bz    CVTLINE         ;
main2     ldi   @USER_RET,R0    ;
          b     R0              ; back to SR2 (or chain) for return
;******************************************************************
Pattern   .word 0x01010101      ;
CVTLINE   ldi   @JR_HOST,AR1    ;
          callu AR1             ; Get timer count in mS from host
          float R0,R0           ;
          mpyf  @T_scale,R0     ; mpyi by C3x cycles/mS 1000/40e-9
          fix   R0,R0           ;
          ;---------------------;
          ldi   0,R0            ;
          ldi   @PIX_DATA,AR0   ;
          ldi   128,RC          ;
          rptb  Loop            ;
          addi  @Pattern,R0     ;
Loop      sti   R0,*AR0++       ;
          ;---------------------;
          call  LINECVT         ;
          b     main2           ; return and let the host poll
;*************************************************************
LINECVT   ldi   @PIX_DATA,AR0   ;
          andn  0x20,IF         ; Take care of missed RINT
          call  get_pix         ;
          call  get_pix         ;
          ldi   127,RC          ; RC = (256/2)-1
          call  SIpulse         ;
          ;- - - - - - - - - - -;
          rptb  samples         ; packing 2 ints per word
          call  get_pix         ;
          ldi   R0,R2           ;
          and   0xFFFF,R2       ;
          call  CLK             ; clock the pixels
          call  get_pix         ;
      ;   call  CLK2            ; clock the pixels
          lsh   16,R0           ;
          or    R2,R0           ;
samples   sti   R0,*AR0++       ; store to data array
          rets                  ;
;-------------------------------;
get_pix   ldi   @CPUINT,IE      ;
Not_ADC   or    GIE,ST          ;
          ldi   @S0_gctrl,R0    ;
          tstb  1,R0            ; the LSBs of S0_rdata
          bz    Not_ADC         ;
clkSRG    ;---------------------;
          ldi   @S0_rdata,R0    ;
      ;   call  CLK             ; clock the pixels
          lsh   16,R0           ;
          ash   -16,R0          ;
          ash   -2,R0           ; Convert to unsigned 14 bit
          addi  0x2000,R0       ;
          rets                  ;
**************************************************************
prog_AIC  ldi   0,R1            ; put safe value in DXR
          sti   R1,@S0_xdata    ;
          idle                  ;
          ldi   3,R1            ; Request 2 ndy XMIT
          sti   R1,@S0_xdata    ;
          idle                  ;
          sti   R0,@S0_xdata    ; Send register value
          idle                  ;
          ldi   0,R1            ;
          sti   R1,@S0_xdata    ; Leave with safe value in DXR
          rets                  ;
;*************************************************************
TIM1L    push     R0            ;
         ldi      2,R0          ; Drive TCLK1 low
         b        T1RET         ;
         ;----------------------;
TIM1H    push     R0            ;
         ldi      6,R0          ; Drive TCLK1 high
T1RET    sti      R0,@T1_ctrl   ;
         pop      R0            ;
         rets                   ;
;-------------------------------;
XF0L	 .set	   0x02         ; //000000010b
XF0H	 .set	   0x06         ; //000000110b
XF1L	 .set	   0x20         ; //000100000b
XF1H	 .set	   0x60         ; //001100000b
;-------------------------------;
SIpulse  ldi       XF1L|XF0H,IOF; XF0(AIC RESET)= 1
         call      TIM1L        ; TIM1_----____----____--....__----____--
         call      delay        ; XF1 _______----_______.....____________
         ldi       XF1H|XF0H,IOF;          |       |
         call      TIM1L        ;          Loop     B1
         call      delay        ;          Loop     B1
         ldi       XF1H|XF0H,IOF;
         call      TIM1H        ;
         call      delay        ;
         ldi       XF1L|XF0H,IOF;
         call      TIM1H        ;
         call      delay        ;
         ldi       XF1L|XF0H,IOF;
         call      TIM1L        ;
         call      delay        ;
         rets                   ;
	 ;----------------------;
CLK      ldi       XF1L|XF0H,IOF;
         call      TIM1H        ;
         call      delay        ;
         ldi       XF1L|XF0H,IOF;
         call      TIM1L        ;
         call      delay        ;
         rets                   ;
	 ;----------------------;
CLK2     ldi       XF1L|XF0H,IOF;
         call      TIM1L        ;
         call      delay        ;
         ldi       XF1L|XF0H,IOF;
         call      TIM1H        ;
         call      delay        ;
         rets                   ;
;-------------------------------;
     	 call      $+1          ;  60  15   (1+2+3+4+5)*4
         call      $+1          ;  40  10   (1+2+3+4  )*4
         call      $+1	        ;  24  6    (1+2+3    )*4
delay    call      $+1	        ;  12  3    (1+2      )*4
D8	 rets			;   4  1    (1        )*4
;*****************************************************;
; Startup stub...                                     ;
;                                                     ;
; The following section of code is used only once for ;
; initialization and can be safely overwritten by     ;
; assembling it into the stack or volatile data       ;
; storage.                                            ;
;*****************************************************;
USER_RET  .word  0              ;
          .entry   ST_STUB      ;
XSPARE    .word main            ;
ST_STUB   ldp   T0_ctrl         ; Use kernel data page and stack
          ldi   @JSPARE,R0      ;
          sti   R0,@USER_RET    ;
          ldi   @XSPARE,R0      ;
          sti   R0,@JSPARE      ;
          ldi   0,R0            ; Halt TIM0 & TIM1
          sti   R0,@T0_ctrl     ;
          sti   R0,@T0_count    ; count
          ldi   TPRD,R0         ; period
          sti   R0,@T0_prd      ;
          ldi   100,R0          ;
          ldi   0x3C1,R0        ; Restart both timers
          sti   R0,@T0_ctrl     ;
;=====================================================;
; This section of code initializes the AIC            ;
;=====================================================;
          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
          ;---------------------;
AIC_INIT  LDI   0x10,IE         ; Enable only XINT interrupt
          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   @B_REG,R0       ; Bump up the Fs to final rate
          call  prog_AIC        ; (smallest divisor should be last)
          ldi   @A_REG,R0       ;
          call  prog_AIC        ;
          ;---------------------
          ldi   @S0_rdata,R0    ; Fix the receiver underrun by reading
          ldi   @buscon,R0      ;
          sti   R0,@p_buscon    ;
          ldi    0,R0           ;
          sti    R0,@S0_xdata   ;
DMAsetup  ldi    @SRCEX,R0      ; start DMA...
          sti    R0,@DMA_srce   ; ADC->S0_rdata
          ldi    @DESTX,R0      ;
          sti    R0,@DMA_dest   ;
          ldi    11,R0          ; Any count value works
          sti    R0,@DMA_xfr    ;
       ;  ldi    0x103,R0       ; Transfer on dma_interrupt.. Source synch
          ldi    0x003,R0       ; Always write.. No synch
          sti    R0,@DMA_ctrl   ;
          ;- - - - - - - - - - -;
          ldi    @U_stack,SP    ;
          ldi    0,R0           ;
          sti    R0,@S0_xdata   ;
Spin1     ldi    @CPUINT,IE     ;
          or     0x204,IE       ; Enable TINT_1 and INT_2
          or     GIE,ST         ;
          b      Spin1          ; Except for debug, this is now spin0
;-------------------------------;
CPUINT    .word  0x00100020     ; XINT0_DMA  RINT0_CPU
SRCEX     .word  S0_rdata       ;
DESTX     .word  S0_xdata       ;
buscon    .word  0x000010F8     ;
U_stack   .word  $              ;
;*****************************************************;
; Install the XINT/RINT ISR handler directly into     ;
; the vector RAM location it will be used in          ;
;*****************************************************;
          .start "SP0VECTS",0x809FC5
          .sect  "SP0VECTS"     ;
          reti                  ; XINT0 (AIC_2ndy or DMA)
          reti                  ; RINT0
          .start "T1VECTS",0x809FCA
          .sect  "T1VECTS"      ;
          reti                  ;
          .end                  ;
