* ============================================================= *
*  Thomas C. Penick   ID# 452 80 6040              Program   6  *
*  EE319K Microprocessor Programming               due  4/3/98  *
*  Instructor: Laurence                            Section   B  *
*  MC6811 Program Source Code  PA6.asm             Roster#  32  *
*  Numerical Integration                                        *
* ============================================================= *

      org  0
      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]
PartA:
      ldx  #PA          \ output problem number          [4 cycles]
      jsr  OutString    /                                [5 cycles]
      ldaa #4           dx = h = 4                       [3 cycles]
      ldab #12          n = number of elements           [3 cycles]
      ldx  #yeqx4       load the address                 [4 cycles]
      jsr  S3INTEG      call the subroutine              [5 cycles]
      jsr  Report       call subroutine to report results [5 cycles]
PartB:
      ldx  #PB          \ output problem number          [4 cycles]
      jsr  OutString    /                                [5 cycles]
      ldaa #2           dx = h = 2                       [3 cycles]
      ldab #24          n = number of elements           [3 cycles]
      ldx  #yeqx2       load the address                 [4 cycles]
      jsr  S3INTEG      call the subroutine              [5 cycles]
      jsr  Report       call subroutine to report results [5 cycles]
PartC:
      ldx  #PC          \ output problem number          [4 cycles]
      jsr  OutString    /                                [5 cycles]
      ldaa #2           dx = h = 2                       [3 cycles]
      ldab #18          n = number of elements           [3 cycles]
      ldx  #yeqxsq      load the address                 [4 cycles]
      jsr  S3INTEG      call the subroutine              [5 cycles]
      jsr  Report       call subroutine to report results [5 cycles]
PartD:
      ldx  #PD          \ output problem number          [4 cycles]
      jsr  OutString    /                                [5 cycles]
      ldaa #2           dx = h = 2                       [3 cycles]
      ldab #8           n = number of elements           [3 cycles]
      ldx  #yeqxcu      load the address                 [4 cycles]
      jsr  S3INTEG      call the subroutine              [5 cycles]
      jsr  Report       call subroutine to report results [5 cycles]
PartE:
      ldx  #PE          \ output problem number          [4 cycles]
      jsr  OutString    /                                [5 cycles]
      ldaa #2           dx = h = 2                       [3 cycles]
      ldab #12          n = number of elements           [3 cycles]
      ldx  #yeqxcu      load the address                 [4 cycles]
      jsr  S3INTEG      call the subroutine              [5 cycles]
      jsr  Report       call subroutine to report results [5 cycles]
AllDone:
      stop
      jmp  main         repeat the program

***  Subroutine S3INTEG  ******************************************
*                                                                 *
*  Demonstrate Parameter Passing by Registers                     *
*  Given vector of 2-byte unsigned integers, returns              *
*  Inputs: X = base address of vector                             *
*          A = integration interval, dx (h)                       *
*          B = number of elements  n = (b - x)/dx                 *
*  Outputs: D = integral                                          *
*           CCR, C = 1 unsigned overflow, D not valid             *
*  Limitations:  B must be greater than 0                         *
*  Destroyed: CCR                                                 *
*                                                                 *
*******************************************************************
; 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.  If the remainder of this last division is 2, then
; increment by one and add this to the grand total.
S3INTEG:
                        ; odd/even counter           9,x
                        ; division remainder         8,x
      pshx              local variables              8,x [4 cycles]
      pshx              local variable, accumulator  6,x [4 cycles]
      pshy              save the Y register              [5 cycles]
      pshx              base address of vector       2,x [4 cycles]
      pshb              B = n  (number of elements)  1,x [3 cycles]
      psha              A = h                        0,x [3 cycles]
      tsx               X points to stack                [4 cycles]
      ldy  2,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  6,x          store value in accumulator       [5 cycles]
      ldaa 1,x          retrieve n                       [4 cycles]
      lsra              divide n by 2  (# of odd's)      [2 cycles]
      staa 9,x          store the odd/even counter       [4 cycles]
LoopOdd:                ; beginning with element [3] ([1] already summed)
      dec  9,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 6,x          add data to accumulator          [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]**

      std  6,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  6,x          store new data total             [5 cycles]
DoneOdd:

SumEven:
      ldaa 1,x          retrieve n                       [4 cycles]
      suba #1           n - 1                            [3 cycles]
      lsra              divide n by 2  (# of even's)     [2 cycles]
      staa 9,x          store the odd/even counter       [4 cycles]
      ldy  2,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 6,x          add data to accumulator          [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  6,x          store new data total             [5 cycles]
      dec  9,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  6,x          store new data total             [5 cycles]
DoneEven:

SumLastTwo:
      ldy  2,x          y points to base address         [6 cycles]
      ldd  0,y          retrieve the [0] data element    [6 cycles]
      addd 6,x          add data to accumulator          [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  6,x          store new data total             [5 cycles]
      ldab 1,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 6,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 8,y          store remainder  (r < 3)         [5 cycles]
      xgdx              move quotient in X to D          [3 cycles]
      std  6,y          store quotient                   [6 cycles]
MultiplyByh:            ;16-bit x 8-bit multiply
      tsx               X points to stack                [4 cycles]
      ldaa 0,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 6,x          load 8 most significant bits of quotient [4cycles]
      ldab 0,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  6,x          store product2                   [5 cycles]
      xgdy              move product1 into D             [4 cycles]
      addd 6,x          add product1 and product 2       [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      std  6,x          store product of 16-bit x 8-bit multiply [5 cycles]
Remainder:
      ldaa 8,x          retrieve the remainder           [4 cycles]
      beq  SkipRound2   do nothing if zero               [3 cycles]
      ldab 0,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]
      addd 6,x          sum total                        [6 cycles]
      bcs  Err          branch on 16-bit overflow        [3 cycles]
      bra  Done                                          [3 cycles]
SkipRound2:
      ldd  6,x          load result into D               [5 cycles]
Done:
      pulx              \                                [5 cycles]
      pulx               \                               [5 cycles]
      puly                > restore the stack & Y        [6 cycles]
      pulx               /                               [5 cycles]
      pulx              /                                [5 cycles]
      rts
***  End S3INTEG Subroutine  **************************************


***  Subroutine Report  *******************************************
*                                                                 *
*  Check the CCR for error and report result of error or          *
*  integration to the SCI window.                                 *
*  Inputs: D = integral                                           *
*          CCR = error information                                *
*  Outputs: sent to SCI window                                    *
*  Limitations:                                                   *
*  Destroyed: CCR, A                                              *
*                                                                 *
*******************************************************************
Report:
      pshx              save register X                  [4 cycles]
      bcs  Error        branch if C-bit set
      ldx  #DoneMsg     \ output message
      jsr  OutString    /
      jsr  OutDec       output value
      bra  SkipErr      finish
Error:
      ldx  #ErrMsg
      jsr  OutString
SkipErr:
      pulx              restore register X               [5 cycles]
      rts
***  End Report Subroutine  ***************************************

WelcomeMsg fcc "Numerical Integration"
	fcb  CR
	fcc  "Written by Tom Penick"
	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
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
