Thursday, December 17, 2009

SCIDRV.S

;*****************************************************************************
;*                                                                           *
;*                 S C I   D R I V E R   M O D U L E                         *
;*             UNDER HC16 MULTITASKING EXECUTIVE (MCX16)                     *
;*                         WITH SLIP PROTOCOL                                *
;*                                                                           *
;            Compiled with Whitesmith Cross Assember ver 1.9                 *
;*                        (c) 11 December 1994                               *
;*                            by M. Lutfi                                    *
;*                          Thesis Project                                   *
;*                 Instrumentation and Controls lab.                         *
;*                 Department of Engineering Physics                         *
;*                  FACULTY OF INDUSTRIAL TECHNOLOGY                         *
;*                  BANDUNG INSTITUTE OF TECHNOLOGY                          *
;*****************************************************************************
.PROCESSOR M68HC16
.TITLE "SCI DRIVER MODULE"

.INCLUDE "lgrset.s"

          .PAGE "SCIDRV"
;*******************************************************************************
;*                                                                             *
;*                       S C I   I N P U T   D R I V E R                       *
;*                      with SLIP data-link layer protocol                     *
;*******************************************************************************


sciidrv:
      orp    #INTS_OFF   ; Turn off interrupts while enabling SCI
      ldab   #0Fh
      tbek               ; EK = F (K=Fxxxh)

      ldd    #008Ah
      std    QMCR        ; Set IARB=10 for intermodule bus arbitration

      ldd    QILR        ; Get content of QSM Interrupt Levels Register
      anda   #0E8h       ; Clear out ILSCI field
      oraa   #SCIINTLV   ; Set SCI interrupt level in ILSCI field
      ldab   #SCIINTV    ; Load SCI Interrupt Vector #
      std    QILR        ; Update QILR

      ldd    #RIE+RE+TE  ; Receiver enabled with interrupts active,
                         ; Transmitter enabled without interrupts,
                         ; 1 Start Bit, 1 Stop Bit, 8 Data Bits
      std    SCCR1       ; Set up SCI operating conditions
      ldd    #BR9600     ; Set up 9600 baud rate
      std    SCCR0

rdclr:
      ldd    SCSR        ; Get current status of SCI
      bitb   #RDRF       ; See if receive data ready
      beq    scirdy      ; if not SCI is a
      ldab   SCDR        ; Read input data
      bra    rdclr       ; Loop until clear

scirdy:
      andp   #0FF1Fh      ; Turn interrupts on again

inloop:
      ldab   #1
      tbek               ; EK = 1
      tbxk               ; XK = 1 (K=11xxh)
      ldab   #SCIISEMA
      ldaa   #MCX_WAIT   ; Wait for input character
      swi

      ldaa   inchar      ; Get input character captured by isr
      ldx    #EQ3src     ; Move it to safe place
      staa   0,x
      ldab   #SCIIQ      ; Then move the character into SCIIQ
      ldaa   #MCX_ENQUEUE_W
      swi

      bra    inloop      ; Loop forever

          .PAGE "SCIDRV"
;*******************************************************************************
;*                                                                             *
;*                     S C I   O U T P U T   D R I V E R                       *
;*                                                                             *
;*******************************************************************************

sciodrv:  ldab   #0Fh
          tbek               ; EK=F  (K=Fxxxh)
          ldab   #1
          tbxk               ; XK=1  (K=F1xxh)

scioloop: ldx    #DQ4dest
          ldab   #SCIOQ      ; Get next character from SCIOQ and put it into
          ldaa   #MCX_QUEUE_W  ; DQ4dest as temporary location
          swi

          ldab   0,x         ; Get the character
          cmpb   #0Ah        ; New Line?
          bne    notnl       ; Branch if not "\n"
          ldd    SCSR        ; Get SCI status
          ldaa   #0Dh
          staa   SCDR+1      ; Output a "\r"
          ldd    #RIE+RE+TE+TIE
          std    SCCR1       ; Enable transmitter interrupts
;         ldab   #RIE+RE+TE+TIE
;         stab   SCCR1+1     ; Enable transmitter interrupts

          ldab   #SCIOSEMA   ; Wait for it to be output completely
          ldaa   #MCX_WAIT
          swi

notnl:    ldd    SCSR        ; Read status
          ldaa   0,x         ; Get character to output
          staa   SCDR+1      ; Output it
          ldd    #RIE+RE+TE+TIE
          std    SCCR1       ; Enable transmitter interrupts
;         ldab   #RIE+RE+TE+TIE
;         stab   SCCR1+1     ; Enable transmitter interrupts

          ldab   #SCIOSEMA   ; Wait for it to be output completely
          ldaa   #MCX_WAIT
          swi

          bra    scioloop    ; Loop forever

          .PAGE "SCIDRV"
;�����������������������������������������������������������������������������Ŀ
;�                                                                             �
;�           S C I   I N T E R R U P T   S E R V I C E   R O U T I N E         �
;�                                                                             �
 �������������������������������������������������������������������������������

.MACRO pshsema
          ldab   ?1
          orp    #INTS_OFF
          lde    06h,x
          stab   e,z
          incw   06h,x
          andp   #SCIINTON
 .EXITM

sciisr:
          orp    #INTS_OFF   ; Save the interrupt context
          pshm   d,e,x,y,z,k
          ldab   #1
          tbek               ; EK=1  (K=1xxxh)
          tbyk               ; YK=1  (K=1x1xh)
          tbzk               ; ZK=1  (K=1x11h)
          clrb
          tbxk               ; XK=0  (K=1011h)
          ldx    0000h
          tst    000Ah
          bne    notlvl0
          ldy    0004
          sts    8,y
          lds    14h,x
notlvl0:  inc    000Ah
          andp   #SCIINTON   ; Interrupts back on
          ldz    12h,x

          ldab   #0Fh         ; EK = F  (K=$Fx11)
          tbek
          ldab   #1
          tbxk               ; XK = 1  (K=$F111)
          ldx    #0000
          ldy    #inchar

          ldd    SCCR1       ; If TDRE is set, see if SCCR1 has TIE set
          bitb   #TIE
          beq    notout      ; If not, this is not an output interrupt
          ldd    SCSR        ; Check SCI status register for TDRE
          bita   #TDRE
          beq    chkrd       ; TDRE not set
          ldd    #RIE+RE+TE  ; If so, this is a transmitter interrupt, turn
                             ;  TIE off now that the character is out
          std    SCCR1       ; Update SCCR1. That takes care of the output side

          ldd    SCSR        ; Now treat a possible input interrupt that is
                             ;  simultaneous with the output. Reread the status
          bitb   #RDRF       ; Check for RDRF set
          beq    noin        ; Branch if no input occurred
          ldd    SCDR        ; Yes it did. Read the input character
          andb   #7Fh        ; Strip it to 7 bits
          stab   0,y         ; Store in temporary location (inchar)
          pshsema SCIISEMA   ; Put SCIISEMA into Signal List
noin:     ldaa   #SCIOSEMA   ; Now signal the SCI output semaphore
          jmp    isrrtn

notout:   ldd    SCSR        ; Read status again
chkrd:    bitb   #RDRF       ; See if this is an input interrupt. Check RDRF
          beq    notin       ; It is not an input interrupt. So what was it?
          ldd    SCDR        ; If it was an input interrupt, get the character
          andb   #7Fh        ; Strip it to 7 bits
          stab   0,y         ; Store in temporary location (inchar)
                             ; That takes care of the input. Now see if there
                             ;  was a simultaneous output interrupt
          ldd    SCSR        ; Check SCI status register for TDRE
          bita   #TDRE
          beq    noout       ; TDRE not set
          ldd    SCCR1       ; If TDRE is set, see if SCCR1 has TIE set
          bitb   #TIE
          beq    noout       ; If not, this cannot be an output interrupt
          ldd    #RIE+RE+TE  ; If so, this is a transmitter interrupt, turn
                             ;  TIE off now that the character is out
          std    SCCR1       ; Update SCCR1
          pshsema SCIOSEMA   ; Signal SCI Output Semaphore

noout:    ldaa   #SCIISEMA   ; Now signal the input semaphore
          jmp    isrrtn

notin:    clra               ; This wasn't a recognizable SCI interrupt
          jmp    isrrtn

          .PAGE "SCIDRV"
;���������������������������������������������������������������������������Ŀ
;� SCI VECTOR                                                                �
;�����������������������������������������������������������������������������

          .PSECT   _text
          .ADDR    sciisr

;���������������������������������������������������������������������������Ŀ
;� SCI DRIVER DATA VARIABLES                                                 �
;�����������������������������������������������������������������������������

          .PSECT _data ; 003FDh

inchar:   .BYTE     1
DQ4dest:  .BYTE     1
EQ3src:   .BYTE     1

.END

SCIDRV.ASM

******************************************************************************
*                       S C I   D R I V E R   M O D U L E                     *
*                                                                             *
*******************************************************************************

isrrtn    equ    $360        ; Address of Common Interrupt Exit routine

SCIINTLV  equ    5           ; SCI Interrupt Level
SCIINTV   equ    $3A         ; SCI Interrupt Vector

QMCR      equ    $FC00
QILR      equ    $FC04       ; QSM Interrupt Levels Register
QIVR      equ    $FC05       ; QSM Interrupt Vector Register

SCCR0     equ    $FC08       ; SCI Control Register 0
SCCR1     equ    $FC0A       ; SCI Control Register 1
SCSR      equ    $FC0C       ; SCI Status Register
SCDR      equ    $FC0E       ; SCI Data Register

*******************************************************************************
*  SCCR1 REGISTER FIELDS                                                      *
*******************************************************************************

SRK       equ    $01         ; Send Break
RWU       equ    $02         ; Receiver Wakeup
RE        equ    $04         ; Receiver Enable
TE        equ    $08         ; Transmitter Enable
RIE       equ    $20         ; Receiver Interrupt Enable
TIE       equ    $80         ; Transmitter Interrupt Enable

*******************************************************************************
*  SCI STATUS REGISTER FIELDS                                                 *
*******************************************************************************

RDRF      equ    $40         ; Receive Data Register Full
TDRE      equ    $01         ; Transmit Data Register Empty (high byte of $0100)

*******************************************************************************
*  SCI DRIVER EQUATES                                                         *
*******************************************************************************

INTS_OFF  equ    $00E0       ; Disable interrupts
SCIINTON  equ    (SCIINTLV<<5+$FF1F) ; Enable interrupts at SCIINTLV (2)
BR9600    equ    $37         ; SCCR0(0-12) setting for 9600 Baud

          PAGE
*******************************************************************************
*                                                                             *
*                       S C I   I N P U T   D R I V E R                       *
*                                                                             *
*******************************************************************************

sciidrv:  orp    #INTS_OFF   ; Turn off interrupts while enabling SCI
          ldab   #$F
          tbek               ; EK = F (K=$Fxxx)

          ldd    #$008A
          std    QMCR        ; Set IARB=10 for intermodule bus arbitration

          ldd    QILR        ; Get content of QSM Interrupt Levels Register
          anda   #$E8        ; Clear out ILSCI field
          oraa   #SCIINTLV   ; Set SCI interrupt level in ILSCI field
          ldab   #SCIINTV     ; Load SCI Interrupt Vector #
          std    QILR        ; Update QILR

          ldd    #RIE+RE+TE  ; Receiver enabled with interrupts active,
                             ; Transmitter enabled without interrupts,
                             ; 1 Start Bit, 1 Stop Bit, 8 Data Bits
          std    SCCR1       ; Set up SCI operating conditions
          ldd    #BR9600     ; Set up 9600 baud rate
          std    SCCR0

rdclr:    ldd    SCSR        ; Get current status of SCI
          bitb   #RDRF       ; See if receive data ready
          beq    scirdy      ; if not SCI is a
          ldab   SCDR        ; Read input data
          bra    rdclr       ; Loop until clear
scirdy:   andp   #$FF1F      ; Turn interrupts on again

inloop:   ldab   #1          ; bank 1
          tbek               ; EK = 1
          tbxk               ; XK = 1 (K=$11xx)
          ldab   #SCIISEMA
          ldaa   #MCX_WAIT   ; Wait for input character
          swi

          ldaa   inchar      ; Get input character captured by isr
          ldx    #EQ3src     ; Move it to safe place
          staa   0,x
          ldab   #SCIIQ      ; Then move the character into SCIIQ
          ldaa   #MCX_ENQUEUE_W
          swi

          bra    inloop      ; Loop forever

          PAGE
*******************************************************************************
*                                                                             *
*                     S C I   O U T P U T   D R I V E R                       *
*                                                                             *
*******************************************************************************

sciodrv:  ldab   #$F
          tbek               ; EK=F  (K=$Fxxx)
          ldab   #1
          tbxk               ; XK=1  (K=$F1xx)

scioloop: ldx    #DQ4dest
          ldab   #SCIOQ      ; Get next character from SCIOQ and put it into
          ldaa   #MCX_DEQUEUE_W  ; DQ4dest as temporary location
          swi

          ldab   0,x         ; Get the character
          cmpb   #$0A        ; New Line?
          bne    notnl       ; Branch if not "\n"
          ldd    SCSR        ; Get SCI status
          ldaa   #$0D
          staa   SCDR+1      ; Output a "\r"
          ldd    #RIE+RE+TE+TIE
          std    SCCR1       ; Enable transmitter interrupts
;         ldab   #RIE+RE+TE+TIE
;         stab   SCCR1+1     ; Enable transmitter interrupts

          ldab   #SCIOSEMA   ; Wait for it to be output completely
          ldaa   #MCX_WAIT
          swi

notnl:    ldd    SCSR        ; Read status
          ldaa   0,x         ; Get character to output
          staa   SCDR+1      ; Output it
          ldd    #RIE+RE+TE+TIE
          std    SCCR1       ; Enable transmitter interrupts
;         ldab   #RIE+RE+TE+TIE
;         stab   SCCR1+1     ; Enable transmitter interrupts

          ldab   #SCIOSEMA   ; Wait for it to be output completely
          ldaa   #MCX_WAIT
          swi

          bra    scioloop    ; Loop forever

          PAGE
*******************************************************************************
*                                                                             *
*           S C I   I N T E R R U P T   S E R V I C E   R O U T I N E         *
*                                                                             *
*******************************************************************************

pshsema   macro
          ldab   #\1
          orp    #INTS_OFF
          lde    $06,x
          stab   e,z
          incw   $06,x
          andp   #SCIINTON
          endm

sciisr:   orp    #INTS_OFF   ; Save the interrupt context
          pshm   d,e,x,y,z,k
          ldab   #1
          tbek               ; EK=1  (K=$1xxx)
          tbyk               ; YK=1  (K=$1x1x)
          tbzk               ; ZK=1  (K=$1x11)
          clrb
          tbxk               ; XK=0  (K=$1011)
          ldx    $0000       ; x = [$10000]
          tst    $000A
          bne    notlvl0
          ldy    $0004       ; y = [$10004]
          sts    8,y         ; [y+8] = SP
          lds    $14,x       ; SP = [X+20]
notlvl0:  inc    $000A       ; [$1000A] = [$1000A]+1
          andp   #SCIINTON   ; Interrupts back on
          ldz    $12,x

          ldab   #$F         ; EK = F  (K=$Fx11)
          tbek
          ldab   #1
          tbxk               ; XK = 1  (K=$F111)
          ldx    #$0000      ;
          ldy    #inchar     ; y = &inchar

          ldd    SCCR1       ; If TDRE is set, see if SCCR1 has TIE set
          bitb   #TIE
          beq    notout      ; If not, this is not an output interrupt
          ldd    SCSR        ; Check SCI status register for TDRE
          bita   #TDRE
          beq    chkrd       ; TDRE not set
          ldd    #RIE+RE+TE  ; If so, this is a transmitter interrupt, turn
                             ;  TIE off now that the character is out
          std    SCCR1       ; Update SCCR1. That takes care of the output side

          ldd    SCSR        ; Now treat a possible input interrupt that is
                             ;  simultaneous with the output. Reread the status
          bitb   #RDRF       ; Check for RDRF set
          beq    noin        ; Branch if no input occurred
          ldd    SCDR        ; Yes it did. Read the input character
          andb   #$7F        ; Strip it to 7 bits
          stab   0,y         ; Store in temporary location (inchar)
          pshsema SCIISEMA   ; Put SCIISEMA into Signal List
noin:     ldaa   #SCIOSEMA   ; Now signal the SCI output semaphore
          jmp    isrrtn

notout:   ldd    SCSR        ; Read status again
chkrd:    bitb   #RDRF       ; See if this is an input interrupt. Check RDRF
          beq    notin       ; It is not an input interrupt. So what was it?
          ldd    SCDR        ; If it was an input interrupt, get the character
          andb   #$7F        ; Strip it to 7 bits
          stab   0,y         ; Store in temporary location (inchar)
                             ; That takes care of the input. Now see if there
                             ;  was a simultaneous output interrupt
          ldd    SCSR        ; Check SCI status register for TDRE
          bita   #TDRE
          beq    noout       ; TDRE not set
          ldd    SCCR1       ; If TDRE is set, see if SCCR1 has TIE set
          bitb   #TIE
          beq    noout       ; If not, this cannot be an output interrupt
          ldd    #RIE+RE+TE  ; If so, this is a transmitter interrupt, turn
                             ;  TIE off now that the character is out
          std    SCCR1       ; Update SCCR1
          pshsema SCIOSEMA   ; Signal SCI Output Semaphore

noout:    ldaa   #SCIISEMA   ; Now signal the input semaphore
          jmp    isrrtn

notin:    clra               ; This wasn't a recognizable SCI interrupt
          jmp    isrrtn

          PAGE
*******************************************************************************
*  SCI VECTOR                                                                 *
*******************************************************************************

          ORG    SCIINTV*2

          dc.w   sciisr

*******************************************************************************
*  SCI DRIVER DATA VARIABLES                                                  *
*******************************************************************************

          ORG    $003FD

inchar:   ds     1
DQ4dest:  ds     1
EQ3src:   ds     1

*******************************************************************************
*                                                                             *
*                       S C I   D R I V E R   M O D U L E                     *
*

STARTUP.S

;����������������������������������������������������������������������������ͻ
;�                                                                            �
;�                SYSTEM STARTUP FOR 68HC16-BASED DATA-LOGGER                 �
;�                                                                            �
;�                    Copyright (c) 1995 by M. Lutfi                          �
;�                                                                            �
;����������������������������������������������������������������������������ͼ

    .PROCESSOR  M68HC16

    .external _main, __memory,__pdata
    .external ._main, .__pdata
    .external .__text__, .__data__, .__bss__
    .public    _exit, __stext

    .include "hc16regs.mac"
    .include "mcx16.mac"
    .include "lgrset.mac"

    .psect  _text
__stext:
;*********** MCU INIT ******************
; These procedures handled by MCX-16
; Rewritten for clarity only
;**********************************
;    ldab    #0Fh
;    tbek                    ; point EK to bank F for register access
;    ldab    #00H
;    tbxk                    ; point XK to bank 0
;    tbyk                    ; point YK to bank 0
;    tbzk                    ; point ZK to bank 0
;
;    ldaa    #007Fh          ; w=0, x=1, y=111111
;    staa    SYNCR           ; set system clock to 16.78 mhz
;
;    clr     SYPCR           ; turn cop (software watchdog) off,
;                            ; since cop is on after reset
;    ldab    #7FH
;    stab    SYNCR
;    clr     SYPCR
;
;****** init SRAM ******
;    ldab    #1
;    std     RAMBAH
;    clrd
;    std     RAMBAL
;    clr     RAMMCR          ;SRAM addr start from 0x10000 to 0x103FF

;****** init external RAM *******
    ldd     #00003          ; at reset, the csboot block size is 512k.
    std     CSBARBT         ; this line sets the block size to 64k since
                            ;  that is what physically comes with the evb16
    ldd     #00303h
    std     CSBAR0          ;set U1 ram base addr to 0x30000: bank 3, 64k
    std     CSBAR1          ;set U3 ram base addr to 0x30000: bank 3, 64k
    ldd     #05030h         ;no wait states
    std     CSOR0           ;set chip select 0, upper byte, write only
    ldd     #03030h
    std     CSOR1           ;set chip select 1, lower byte, write only
    ldd     #00303h
    std     CSBAR2          ;set chip select 2 to fire at base addr 0x30000
    ldd     #07830h
    std     CSOR2           ;set chip select 2, both bytes, read and write
    ldd     #03FFFh
    std     CSPAR0          ;set chip selects 0,1,2 to 16-bit ports

;�����������������������������������������������������������������������������͸
;�                          ADC INITIALIZATION                                 �
;�   Summary:                                                                  �
;�   The ADC module is mapped into 32 words of address space. Five words are   �
;�   control/status registers, one word is digital port data, and 24 words     �
;�   provide access to the results of ADC conversion (eight addresses for each �
;�   type of converted data). Two words are reserved for expansion.            �
;�   The ADC module base address is determined by the value of the MODMAP bit  �
;�   int the system integration module configuration register (SIMMCR).        �
;�   The base address is normaly $FFF700 in the MC68HC16Z1.                    �
;�       Internally, the ADC has both a differential data bus and a buffered   �
;�   IMB data bus. Registers not directly associated with AD conversion        �
;�   functions, such as the MCR, the MTR, and the PDR, reside on the bufferd   �
;�   bus, while conversion registers and result registers reside on the        �
;�   differential bus.                                                         �
;�                                                                             �
;�   Registers that must be set prior operation:                               �
;�     ADMCR:                                                                  �
;�       STOP = 0 (normal operation)                                           �
;�       FRZ  = 0                                                              �
;�       SUPV = 1 (supervisory mode)                                           �
;�     ADCTL0:                                                                 �
;�       PRS   = 1 (ADC clock = system clock/4 = 16.667 MHz/4)                 �
;�       STS   = 0 (4 A/D clock periods in the sample time)                    �
;�       RES10 = 1 (10-bit conversion)                                         �
;�     ADCTL1:                                                                 �
;�       SCAN  = 1 (continuous conversion)                                     �
;�       MULT  = 1 (sequential conversion of four or eight channels            �
;�                  selected by [CD:CA])                                       �
;�       S8CM  = 1 (eight-conversion sequence)                                 �
;�       CD    = 0 (measured data at each channel stored into his register)    �
;�                                                                             �
;�����������������������������������������������������������������������������;
    ldd     #0000h
    std     ADCMCR         ;turn on ADC
    ldd     #0001h
    std     ADCTL0         ;10-bit, set sample period


;�����������������������������������������������������������������������������͸
;�                                                                             �
;�                     SCI DRIVER INITIALIZATION                               �
;�                                                                             �
;� 1. Sets up the SCI and starts an infinite loop of receive transmit          �
;� 2. QSM configuration summary:                                               �
;�  * After reset, the QSM remains in an idle state, requiring initialization  �
;�    of several registers before any serial operations may begin execution.   �
;�  * The type of serial frame (8 or 9 bit) and the use of partiy must be      �
;�    determined by M. PE and PT.                                              �
;�  * For receive operation, WAKE, RWU, ILT, ILIE must be considered.          �
;�    The receiver must be enabled (RE) and, usually, RIE should be set.       �
;�  * For transmit operation, the transmitter must be enabled (TE) and,        �
;�    usually, TIE should be set. The use of wired-OR mode (WOMS) must also    �
;�    be decided. Once the transmitter is configured, data is not sent         �
;�    until TDRE and TC are cleared. To clear TDRE and TC, the SCSR read       �
;�    must be followed by a write to SCDR (either the lower byte or the        �
;�    entire word).                                                            �
;�  * QIVR should be programmed to one of the user-defined vectors ($40-$FF)   �
;�    during initialization of the QSM.                                        �
;�    After reset, QIVR determines which two vectors in the exception vector   �
;�    table are to be used for QSM interrupts. The QSPI and SCI submodules     �
;�    have separate interrupt vectors adjacent to each other.                  �
;�    Both submodules use the same interrupt vector which LSB:                 �
;�       1: interrupt generated by QSPI                                        �
;�       0: interrupt generated by QSCI                                        �
;�> Detail Configurations in QSM:                                              �
;�  * QMCR:                                                                    �
;�       STOP = 0 (Normal QSM clock operation)                                 �
;�       FRZ1 = 0 (Ignore the FREEZE signal on the IMB)                        �
;�       SUPV = 1 (supervisor access)                                          �
;�       IARB = $A (priority = 10; $F = highest priority, used by timer)       �
;�  * QILR:                                                                    �
;�       ILQSPI = 1 (lowest priority)                                          �
;�       ILSCI  = 7 (highest priority)                                         �
;�       QIVR   = set to SCI interrupt handler's address                       �
;�                                                                             �
;�����������������������������������������������������������������������������;
    orp    #INTS_OFF   ; Turn off interrupts while enabling SCI
    ldab   #0Fh
    tbek               ; EK = F (K=$Fxxx)

    ldd    #008Ah
    std    QMCR        ; Set IARB=10 for intermodule bus arbitration

    ldd    QILR        ; Get content of QSM Interrupt Levels Register
    anda   #0E8h       ; Clear out ILSCI field
    oraa   #SCIINTLV   ; Set SCI interrupt level in ILSCI field
    ldab   #SCIINTV    ; Load SCI Interrupt Vector #
    std    QILR        ; Update QILR

    ldd    #RIE+RE+TE  ; Receiver enabled with interrupts active,
                       ; Transmitter enabled without interrupts,
                       ; 1 Start Bit, 1 Stop Bit, 8 Data Bits
    std    SCCR1       ; Set up SCI operating conditions
    ldd    #BR9600     ; Set up 9600 baud rate
    std    SCCR0

;����������������������������������������������������������������������������͸
;�                           STACK ALLOCATION                                 �
;�                                                                            �
;�   I M P O R T A N T   S Y S T E M   C O N F I G U R A T I O N   N O T E:   �
;�                                                                            �
;�  MCX-16 Requires locations $10000 through $1002F for internal operations.  �
;�  Begin the allocation of MCX-16 System Tables at an address equal to or    �
;�  greater than $10030.                                                      �
;����������������������������������������������������������������������������;
    ldk     #.__pdata       ; select memory bank of _data
    tbxk
    tbyk
    ldk     #.__data__
    tbzk
    ldx     #__pdata        ; start of data descriptor
    ldy     0,x             ; start of data images
    aix     #2              ; next word
ibcl:
    ldab    0,x             ; flag
    beq     zbss            ; nul, next step
    bpl     idad            ; if segment
    aix     #2              ; move to it
    ldab    0,x             ; load it
    tbzk                    ; in data pointer extension
idad:
    ldz     1,x             ; data address
ircl:
    ldd     0,y             ; transfert by word
    std     0,z             ; size must be even
    aiy     #2              ; next word
    aiz     #2
    cpy     3,x             ; end of block ?
    blo     ircl            ; no, loop
    aix     #5              ; descriptor size
    bra     ibcl            ; next block
zbss:
    ldk     #.__bss__
    tbxk
    tbek
    tbyk
    tbzk
    tbsk
    ldx     #sbss       ; start of bss
    clrd                ; to be zeroed
    bra     mtest       ; start loop
bcl:
    std     0,x         ; clear memory
    aix     #2          ; next word
mtest:
    cpx     #__memory   ; end of memory ?
    blo     bcl         ; no, continue
;   aix     #4000H      ; you can set-up a 4K stack
;   txs                 ; above the BSS
    lds     #3FEh       ; or directly initialize ptr
    jsr     _main,#._main
                        ; call main routine of application
_exit:
    bra     _exit       ; loop here if return
;
    .end

MCXEVB.S

;   C STARTUP FOR 68HC16 UNDER MCX-16 REAL-TIME KERNEL
;   ==================================================
;   Copyright (c) 1995
;   Designed and programmed by Muhammad Lutfi
;   for Final Project (TA)
;   Thesis Advisors:
;     Dr. Ir. Farida Idealistina Muchtadi
;        and Ir. Sutanto Hadisupadmo, M.T.
;
;   Instrumentation and Controls Lab.
;   Engineering Physics Dept.
;   Institut Teknologi Bandung
;   Jl. Ganesha 10
;   Bandung 40132
;   Phone: (022) 2504424 ext 759
;   FACS:  (022)2504424
;
;
;
;   Platform : Microcontroller 68HC16Z1 on Evaluation Board (EVB)
;
;   Summary:
;   > Other initialization, except for QSM and ADC module, not necessarily
;     done
;   > Take care with heap an pre-initialized RAM initialization
;
    .include "lgrset.mac"

    .external _main, __memory,__pdata
    .external ._main, .__pdata
    .external .__text__, .__data__, .__bss__
    .public    _exit, __stext

.DEFINE STACK_SIZE = 1000H

    .psect _bss         ; stack section
sbss:

    .psect _text        ; program section

__stext:

;*********** MCU INIT ******************
; These procedures handled by MCX-16
; Rewritten for clarity only
; Still used in HARRAT version.
;***************************************
;
; ROM Start address: 0x00000 (program starts from 0x400 instead)
;
;                           BITS
; +--------------+--------------------------------+
; !              ! 2222 1111 1111 11              !
; ! ADDR PINS    ! 3210 9876 5432 1098 7654 3210  !
; +--------------+--------------------------------+----------+
; ! ADDR[23..0]  ! 0000 0000 0000 01?? ???? ????B != 0x00400 !
; ! ADDR[23..11] ! 0000 0000 0000 0xxx xxxx xxxxB != 0x00000 !
; +--------------+--------------------------------+----------+
;
; BLKSZ = 64 KB => address lines compared: ADDR[23..16]
;
; Frequency:
;      FQ_SYSTEM = FQ_REF*(4^(y+1)*(2^((2*W) + x)))
;      FQ_VCO    = F_SYSTEM^(2-X)
;
.DEFINE BLKSZ = 011B
.DEFINE ADDR  = 0000h
.SET CSBARBT_CFG = ((BLKSZ) | (ADDR << 3))
.DEFINE FQ_REF = 16780000   ; MHz
.DEFINE SW = 00B
.DEFINE SX = 01B
.DEFINE SY = 0111111B
.DEFINE
    SEDIV = (0<<7),
    SLIMP = (1<<4),
    SLOCK = (1<<3),
    RSTEN = (1<<2),
    STSIM = (1<<1),
    STEXT = 1

.SET SYNCR_CFG = ((SW<<7)|(SX<<6)|SY)

    ldab    #0Fh
    tbek                    ; point EK to bank F for register access
    ldab    #00H
    tbxk                    ; point XK to bank 0
    tbyk                    ; point YK to bank 0
    tbzk                    ; point ZK to bank 0
    ldd     #CSBARBT_CFG    ; at reset, the csboot block size is 512k, so
    std     CSBARBT         ; this line sets the block size to 64k since
                            ; that is what physically comes with the EVB16
                            ; Boot ROM starts from 0x400 to 0xFFFF
    ldab    #SYNCR_CFG
    stab    SYNCR           ; set system clock to 16.78 mhz

NOT_L:
    brclr   SYNCR+1,#SLOCK,NOT_L   ;wait until synthesizer lock bit is set

;
; SYPCR:
; �����������������������������������������������������������Ŀ
; � SWE = 0� SWP = 0� SWT = 11 � HME = 1 � BME = 0 � BMT = 00 �
; �������������������������������������������������������������
; SWE=0  : Watchdog disabled
; SWP=0  : Software watchdog clock not prescaled
; SWT[1:0]=11 : software watchdog timing
; HME=1  : enable halt monitor function
; BME=0  : disable bus monitor function for an internal to external bus cycle
; BMT=00 : 64 system clocks for bus monitor timing
;
.DEFINE
    SWE = 0,
    SWP = 0,
    SWT = 011B,
    HME=1,
    BME=0,
    BMT=0
.DEFINE SET_SYPCR = (BMT|(BME<<2)|(HME<<3)|(SWT<<4)|(SWP<<6)|(SWE<<7))

    ldab    #SET_SYPCR      ;#38H
    stab    SYPCR           ; turn cop (software watchdog) off,
                            ; since cop is on after reset

.IF TOROM
    ldd     CSORBT
    andd    #0E7FFh         ; R/W* = 00B, means that
    ord     #(01B<<11)      ; ROM is read only
    std     CSORBT
.ENDIF


;************* Stack Allocation *************
.IF USE_EXT_RAM
    ldk     #2
    tbsk                ; set SK to bank 2 for system stack
    lds     #3FEh        ; put SP at top of 1k internal SRAM (0x203FE)
.ELSE
    ldk     #1
    tbsk                ; set SK to bank 1 for system stack
    lds     #3FEh       ; directly initialize ptr to use 0x103FE (SRAM)
.ENDIF                  ; and below as system stack


;�����������������������������������������������������������������������������Ŀ
;�                          ADC INITIALIZATION                                 �
;�   Summary:                                                                  �
;�   The ADC module is mapped into 32 words of address space. Five words are   �
;�   control/status registers, one word is digital port data, and 24 words     �
;�   provide access to the results of ADC conversion (eight addresses for each �
;�   type of converted data). Two words are reserved for expansion.            �
;�   The ADC module base address is determined by the value of the MODMAP bit  �
;�   int the system integration module configuration register (SIMMCR).        �
;�   The base address is normaly $FFF700 in the MC68HC16Z1.                    �
;�       Internally, the ADC has both a differential data bus and a buffered   �
;�   IMB data bus. Registers not directly associated with AD conversion        �
;�   functions, such as the MCR, the MTR, and the PDR, reside on the bufferd   �
;�   bus, while conversion registers and result registers reside on the        �
;�   differential bus.                                                         �
;�                                                                             �
;�   Registers that must be set prior operation:                               �
;�     ADMCR:                                                                  �
;�       STOP = 0 (normal operation)                                           �
;�       FRZ  = 0                                                              �
;�       SUPV = 1 (supervisory mode)                                           �
;�     ADCTL0:                                                                 �
;�       PRS   = 00011B (ADC clock = system clock/8 = 2.1 MHz (Max ADC freq)   �
;�       STS   = 00 (4 A/D clock periods in the sample time)                   �
;�       RES10 = 01 (10-bit conversion)                                        �
;�     ADCTL1:                                                                 �
;�       SCAN  = 1 (continuous conversion)                                     �
;�       MULT  = 1 (sequential conversion of four or eight channels            �
;�                  selected by [CD:CA])                                       �
;�       S8CM  = 1 (eight-conversion sequence)                                 �
;�       CDCA  = 0xxx (measured data at each channel stored into his register) �
;�                                                                             �
;�������������������������������������������������������������������������������
.DEFINE MY_PRS   = 11B,
        MY_STS   = 00B,
        MY_RES10 = 1
.DEFINE MY_CDCA  = 1000B,
        MY_S8CM  = 1,
        MY_MULT  = 1,
        MY_SCAN  = 1

    ldab    #0Fh
    tbek                ; EK = F (K=$Fxxx)
    ADCMCR_SET 0, 0, 0
    ADCTL0_SET MY_PRS, MY_STS, MY_RES10
    ADCTL1_SET MY_CDCA, MY_S8CM, MY_MULT, MY_SCAN


;�����������������������������������������������������������������������������Ŀ
;�                                                                             �
;�                     SCI DRIVER INITIALIZATION                               �
;�                                                                             �
;� 1. Sets up the SCI and starts an infinite loop of receive transmit          �
;� 2. QSM configuration summary:                                               �
;�  * After reset, the QSM remains in an idle state, requiring initialization  �
;�    of several registers before any serial operations may begin execution.   �
;�  * The type of serial frame (8 or 9 bit) and the use of partiy must be      �
;�    determined by M. PE and PT.                                              �
;�  * For receive operation, WAKE, RWU, ILT, ILIE must be considered.          �
;�    The receiver must be enabled (RE) and, usually, RIE should be set.       �
;�  * For transmit operation, the transmitter must be enabled (TE) and,        �
;�    usually, TIE should be set. The use of wired-OR mode (WOMS) must also    �
;�    be decided. Once the transmitter is configured, data is not sent         �
;�    until TDRE and TC are cleared. To clear TDRE and TC, the SCSR read       �
;�    must be followed by a write to SCDR (either the lower byte or the        �
;�    entire word).                                                            �
;�  * QIVR should be programmed to one of the user-defined vectors ($40-$FF)   �
;�    during initialization of the QSM.                                        �
;�    After reset, QIVR determines which two vectors in the exception vector   �
;�    table are to be used for QSM interrupts. The QSPI and SCI submodules     �
;�    have separate interrupt vectors adjacent to each other.                  �
;�    Both submodules use the same interrupt vector which LSB:                 �
;�       1: interrupt generated by QSPI                                        �
;�       0: interrupt generated by QSCI                                        �
;�> Detail Configurations in QSM:                                              �
;�  * QMCR:                                                                    �
;�       STOP = 0 (Normal QSM clock operation)                                 �
;�       FRZ1 = 1 (Halt the QSM on a transfer boundary)                        �
;�       FRZ0 = 0                                                              �
;�       SUPV = 1 (supervisor access)                                          �
;�       IARB = $A (priority = A; $F = highest priority, used by timer)        �
;�  * QILR:                                                                    �
;�       ILQSPI = 0 (disabled)                                                 �
;�       ILSCI  = 7 (highest priority)                                         �
;�       QIVR   = set to SCI interrupt handler's address                       �
;�                                                                             �
;�������������������������������������������������������������������������������
    disable             ; Turn off interrupts while enabling SCI

    ldd    #(0080h+QSMIARB)
    std    QMCR         ; Set IARB=10 for intermodule bus arbitration

    ldd    #MY_QILR     ; our QILR configuration
    std    QILR         ;

    ldd    #BR9600      ; Set up 9600 baud rate
    std    SCCR0
    ldd    #RIE+RE+TE   ; Receiver enabled with interrupts active,
                        ; Transmitter enabled without interrupts,
                        ; 1 Start Bit, 1 Stop Bit, 8 Data Bits
    std    SCCR1        ; Set up SCI operating conditions

rdclr:
    ldd    SCSR         ; Get current status of SCI
    bitb   #RDRF        ; Read  receive data ready (RDR) until RDR reset
    beq    scirdy       ; ZF=1 (RDRF=0), so no RDR is empty
    ldab   SCDR         ; Read input data (a mechanism to reset RDRF)
    bra    rdclr        ; Loop until clear

scirdy:
    enable              ; Turn interrupts back on



;*************** BEGIN **************
    ldk     #.__bss__   ; load extended address of stack
    tbek
    tbxk
    tbyk
    tbzk
    ldx     #sbss       ; start of bss
    clrd                ; to be zeroed
    bra     mtest       ; start loop
bcl:
    std     0,x         ; clear memory
    aix     #2          ; next word
mtest:
    cpx     #__memory   ; end of memory ?
    blo     bcl         ; no, continue
    jsr     _main       ; call application
_exit:
    bgnd                ; loop here if return
1$:
    bra    1$
;
.end