* ============================================================= *
*  Thomas C. Penick   ID# 452 80 6040              Program   7  *
*  EE319K Microprocessor Programming               due 4/10/98  *
*  Instructor: Laurence                            Section   B  *
*  MC6811 Program Source Code  PA7.asm             Roster#  32  *
*  Numerical Integration and Passing Values on the Stack        *
* ============================================================= *

Num   equ  5            number of problems to solve
      org  $E000
main:
      lds  #$00FF       load stack pointer               [4 cycles]
      jsr  InitSCI      initialize the serial port       [5 cycles]
      ldx  #WelcomeMsg  get address of message           [4 cycles]
      jsr  OutString    display the message              [5 cycles]
      ldaa #Num         \ counter goes on bottom of      [3 cycles]
      psha              /   stack                        [3 cycles]
      ldy  #InData      Y points to the input data       [5 cycles]
      pshx              space on the stack for output    [4 cycles]
; The loop takes data from an array called InData and sends it to
; the subroutine SINTEG which performs an integration using Simpson's
; 1/3 rule.  There are five problems.  A counter is used to keep
; track of how many problems are left to be done.  The counter is
; stored at the bottom of the stack.  The loop sends 3 data for
; each problem by placing them on the stack.  These are 1) the base
; address of a seperate data vector, 2) the width of the intervals
; h, and 3) the number of intervals n.  The result is returned on
; the stack.  A second subroutine, Report, is called which checks
; for an error (C-bit set) and either sends an error message to
; the screen or sends the result of the integration to the screen.
; The counter is then incremented and tested and the loop starts
; over or the program ends.
Loop:
      ldx  0,y          \ send problem number to screen  [5 cycles]
      jsr  OutString    /                                [5 cycles]
      ldx  4,y          \ put the base address of data   [4 cycles]
      pshx              /   onto the stack               [4 cycles]
      ldaa 2,y          \ dx = h,  goes on stack         [5 cycles]
      psha              /                                [3 cycles]
      ldab 3,y          \ n = number of elements,        [3 cycles]
      pshb              /   goes on stack                [3 cycles]
      jsr  SINTEG       call the subroutine              [5 cycles]
      pulx              \ deallocate 4 bytes, leaving    [5 cycles]
      pulx              /   output on top of stack       [5 cycles]
      jsr  Report       call subroutine to report results [5 cycles]
      tsx               X points to stack                [4 cycles]
      ldaa 2,x          retrieve counter from bottom of stack [4 cycles]
      deca              decrement the counter            [2 cycles]
      beq  AllDone      branch is counter is zero        [3 cycles]
      staa 2,x          store counter                    [4 cycles]
      ldab #6           \ increment Y by 6 to access     [3 cycles]
      aby               /   next set of data             [4 cycles]
      bra  Loop                                          [3 cycles]
AllDone:
      pulx              deallocate 2 bytes used for output [5 cycles]
      ins               deallocate 1 byte used for counter [3 cycles]
      stop              end of program                   [2 cycles]
      jmp  main         repeat the program               [3 cycles]

***  Subroutine SINTEG  *******************************************
*                                                                 *
*  Demonstrate Parameter Passing on the Stack                     *
*  Given vector of 2-byte unsigned integers, returns Simpson's    *
*    one-third rule integral                                      *
*  Inputs:  base address of vector, first on stack                *
*           integration interval, dx (h), second on stack         *
*           number of elements  n = (b - x)/dx, third on stack    *
*  Outputs: Integral, returned on stack allocated by caller       *
*           CCR, C = 1 unsigned overflow, D not valid             *
*  Limitations:  n must be greater than 0                         *
*  Destroyed: CCR                                                 *
*                                                                 *
*  Displaclements of Inputs and Outputs  **************************
r     equ   0           ; displacement of division remainder on stack
OE    equ   1           ; displacement of odd/even counter on stack
n     equ  10           ; displacement of number n on stack
h     equ  11           ; displacement of interval h or dx on stack
Adr   equ  12           ; displacement of base address on stack
Out   equ  14           ; displacement of output/accumulator on stack

; The plan is to add the odd terms first then multiply their sum
; by 2.  Then add the even terms to this subtotal and multiply the
; result by 2 to achieve 4x odd + 2x even.  Then add the first and
; last terms and divide by 3 and multiply by h.  Doing the division
; first prevents a premature overflow for some values.  The remainder
; from the division is saved and later multiplied by h and divided
; by three and added to the total.  If the remainder of this last 
; division is 2, then increment by one and add this to the grand 
; total.

SINTEG:
      pshy              \                                [5 cycles]
      pshx               \ save registers                [4 cycles]
      pshb               /                               [3 cycles]
      psha              /                                [3 cycles]
      pshx              local variables                  [4 cycles]
      tsx               X points to stack                [4 cycles]
      ldy  Adr,x        y points to base address         [6 cycles]
SumOdd:
      ldab #2           \ Y points to first odd data     [3 cycles]
      aby               /                                [4 cycles]
      ldd  0,y          load first odd data              [6 cycles]
      std  Out,x        store value in accumulator       [5 cycles]
      ldaa n,x          retrieve n                       [4 cycles]
      lsra              divide n by 2  (# of odd's)      [2 cycles]
      staa OE,x         store the odd/even counter       [4 cycles]
LoopOdd:                ; beginning with element [3] ([1] already summed)
      dec  OE,x         decrement the element counter    [6 cycles]
      beq  MultOdd      branch on zero  (done)           [3 cycles]
      ldab #4           \ increment Y by 4               [3 cycles]
      aby               /                                [4 cycles]
      ldd  0,y          retrieve the next data           [6 cycles]
      addd Out,x        add data to accumulator          [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  Out,x        store new data total             [5 cycles]
      bra  LoopOdd                                       [3 cycles]
MultOdd:
      lsld              multiply 2x total of odd's       [3 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  Out,x        store new data total             [5 cycles]
DoneOdd:

SumEven:
      ldaa n,x          retrieve n                       [4 cycles]
      suba #1           n - 1                            [3 cycles]
      lsra              divide n by 2  (# of even's)     [2 cycles]
      staa OE,x         store the odd/even counter       [4 cycles]
      ldy  Adr,x        y points to base address         [6 cycles]
LoopEven:               ; beginning with element [2]
      ldab #4           \ Y points to next even data     [3 cycles]
      aby               /                                [4 cycles]
      ldd  0,y          retrieve the next data           [6 cycles]
      addd Out,x        add data to accumulator          [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  Out,x        store new data total             [5 cycles]
      dec  OE,x         decrement the element counter    [6 cycles]
      beq  MultEven     branch on zero  (done)           [3 cycles]
      bra  LoopEven                                      [3 cycles]
MultEven:
      lsld              2x total of even's & odd's       [3 cycles]
      bcc  NoErr        branch on no 16-bit overflow     [3 cycles]
Err   sec               some situations require setting C-bit [2 cycles]
      bra  Done         leap frog to prevent out-of-range error [3 cycles]
NoErr std  Out,x        store new data total             [5 cycles]
DoneEven:

SumLastTwo:
      ldy  Adr,x        y points to base address         [6 cycles]
      ldd  0,y          retrieve the [0] data element    [6 cycles]
      addd Out,x        add data to accumulator          [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  Out,x        store new data total             [5 cycles]
      ldab n,x          retrieve n                       [4 cycles]
      lslb              2x n                             [2 cycles]
      aby               Y points to last data element    [4 cycles]
      ldd  0,y          retrieve the [n] data element    [6 cycles]
      addd Out,x        add data to accumulator          [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
DivideBy3:              ; data total is in D
      ldx  #3           load denominator into X          [4 cycles]
      idiv              divide sum by 3 (result in X)    [4 cycles]
      tsy               Y points to stack                [5 cycles]
      stab r,y          store remainder  (r < 3)         [5 cycles]
      xgdx              move quotient in X to D          [3 cycles]
      std  Out,y        store quotient                   [6 cycles]
MultiplyByh:            ; 16-bit x 8-bit multiply
      tsx               X points to stack                [4 cycles]
      ldaa h,x          load h                           [4 cycles]
      mul               multiply h by 8 least significant
;                       bits in quotient                 [3-10 cycles]
      xgdy              move product1 to Y               [4 cycles]
      ldaa Out,x        load 8 most significant bits of quotient [4 cycles]
      ldab h,x          load h                           [4 cycles]
      mul               multiply h by 8 most significant [3-10 cycles]
      tsta              \ If A is not 0 we will have an  [2 cycles]
      bne  Err          / overflow.                      [3 cycles]
      tba               \ left shift 8 times             [2 cycles]
      clrb              /                                [2 cycles]
      std  Out,x        store product2                   [5 cycles]
      xgdy              move product1 into D             [4 cycles]
      addd Out,x        add product1 and product 2       [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  Out,x        store product of 16-bit x 8-bit multiply [5 cycles]
Remainder:
      ldaa r,x          retrieve the remainder           [4 cycles]
      beq  Done         do nothing if zero               [3 cycles]
      ldab h,x          retrieve h                       [4 cycles]
      mul               remainder × h                    [3-10 cycles]
      ldx  #3           load denominator into X          [4 cycles]
      idiv              divide product by 3 (result in X)[4 cycles]
      cmpb #2           \ round only if remainder is 2   [3 cycles]
      bne  SkipRound1   /                                [3 cycles]
      inx               round up                         [3 cycles]
SkipRound1:
      xgdx              move result into D               [4 cycles]
      tsx               X points to stack                [4 cycles]
      addd Out,x        sum total                        [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  Out,x        store result in accumulator      [5 cycles]
      bra  Done                                          [3 cycles]
Done:
      pulx              deallocate local variables       [5 cycles]
      pula              \                                [4 cycles]
      pulb               \ restore registers             [4 cycles]
      pulx               /                               [5 cycles]
      puly              /                                [6 cycles]
      rts                                                [5 cycles]
***  End SINTEG Subroutine  ***************************************


***  Subroutine Report  *******************************************
*                                                                 *
*  Check the CCR for error and report result of error or          *
*  integration to the SCI window.                                 *
*  Inputs:  Integral, on top of stack                             *
*           CCR = error information                               *
*  Outputs: sent to SCI window                                    *
*  Limitations:                                                   *
*  Destroyed: CCR                                                 *
*                                                                 *
*  Displacement of Input  *****************************************
Int   equ   6           ; displacement of Integral on stack

Report:
      pshx              \                                [4 cycles]
      pshb               > save registers                [3 cycles]
      psha              /                                [3 cycles]
      bcs  Error        branch if C-bit set              [3 cycles]
      ldx  #DoneMsg     \ output message                 [4 cycles]
      jsr  OutString    /                                [5 cycles]
      tsx               X points to stack                [4 cycles]
      ldd  Int,x        \ output the integral value      [5 cycles]
      jsr  OutDec       /                                [5 cycles]
      bra  SkipErr      finish                           [3 cycles]
Error:
      ldx  #ErrMsg      \ error message                  [4 cycles]
      jsr  OutString    /                                [5 cycles]
SkipErr:
      pula              \                                [4 cycles]
      pulb               > restore registers             [4 cycles]
      pulx              /                                [5 cycles]
      rts                                                [5 cycles]
***  End Report Subroutine  ***************************************

WelcomeMsg fcc "PA7: Numerical Integration"
	fcb  CR
	fcc  "and Passing Values on the Stack"
	fcb  CR,EOT
DoneMsg fcc  ": The result is  "
	fcb  EOT
ErrMsg fcc  ": An overflow error has occurred."
      fcb  CR,EOT
PA    fcb  CR,'A,EOT
PB    fcb  CR,'B,EOT
PC    fcb  CR,'C,EOT
PD    fcb  CR,'D,EOT
PE    fcb  CR,'E,EOT
InData fdb #PA,$040C,#yeqx4,#PB,$0218,#yeqx2,#PC,$0212,#yeqxsq,#PD,$0208,#yeqxcu,#PE,$020C,#yeqxcu
yeqx4 fdb  0,4,8,12,16,20,24,28,32,36,40,44,48
yeqx2 fdb  0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48
yeqxsq fdb 0,4,16,36,64,100,144,196,256,324,400,484,576,676,784,900,1024,1156,1296
yeqxcu fdb 0,8,64,216,512,1000,1728,2744,4096,5832,8000,10648,13824
	org  $FFFE
	fdb  main
