/ A second demonstration interrupt driven program.
/
/ This program has to read characters from keyboard,
/  non-digit characters will get discarded, sequences of digits are 
/ interpreted as representing (unsigned) decimal numbers --- a number conversion
/ is performed, the value read is stored in an array and added into a sum
/
/ the program terminates when the sum exceeds one thousand.
/
/ the program has to monitor the clock while doing other work
/
/ the characters read must be stored in a buffer, they get fetched from there
/ when needed by the processing routines. 
/ Since the multiply by shift-and-add is slow, the buffer tends to fill up
/ when digits are being processed; but, its quickly emptied of any non-digit
/ characters
*0
/ save program counter on interrupt
        0
        jmp i pints
pints,  inthnd
accsav, 0
lnksav, 0
/
*20
ticks,  0               / count of clock ticks
intsrd, intary          / array where integer values read are stored
intcnt, 0               / count of integers read
total,  0               / sum of integers read
inbuff, chrbuf          / array that constitutes circular input buffer
pptr,   0               / " pointers " into buffer for producer and
cptr,   0               / consumer
nchar,  0               / character
done,   0               / boolean flag. set when want to terminate
/
/ the following variables belong to the multiplication routines
/
*160
mplr,   0               / multiplier
mpand,  0               / multiplicand
prod,   0               / single length product
temp,   0               / work space used by multiply routine
divsr,  0               / divisor
divdn,  0               / dividend
quot,   0               / quotient
rem,    0               / remainder
kd12,   14              / 12 decimal, the number of bits
kd10,   12              / 10 decimal
kd100,  144             / 100 decimal
kd1000, 1750            / 1000 decimal
cntr,   0               / used when looping as a counter
*200
start,  cla cll
        dca intcnt      / zero out all variables
        dca total
        dca done
        dca ticks
        dca cptr
        dca pptr
        clkt            / start clock
        ion             / enable interrupts
loop,   jms i pnxtch    / get a character
        jms isdig    / check if a digit
        skp             / if it wasn't, discard the character
        jms readnm      / if it was, start the new number
        cla cll
        tad total       / check for termination
        cia
        tad kd1000
        sma cla
        jmp loop
/       have read enough
        iof
        hlt
pnxtch, nxtch
/
/       readnm:
/               entered when have read first digit
/               of a number
/               complete reading characters and combining them
/               in to form a number
readnm, 0
        cla cll
        dca number
lrdnm,  cla cll         / convert character to numeric
        tad czero
        cia
        tad nchar
        dca n
/       now need to multiply current number by 10 decimal
        tad number
        dca mpand
        tad kd10
        dca mplr
        jms i pmult
/       assume that no chance of exceeding numbers allowed!
        tad prod
        tad n
        dca number
/       get next character
        jms i pnxtch
/       check if digit
        jms isdig
        skp             / if it wasn't then quit
        jmp lrdnm       / if it was a digit, continue building number
/       number is finished,
/       store it away
/       have to index into an array
        tad intsrd  / base address
        tad intcnt  / + index value
        dca point   / = required address
        tad number
        dca i point
/       increment count
        isz intcnt
        nop
/       add number into total
        tad number
        tad total
        dca total
        jmp i readnm
number, 0
n,      0
point,  0
pmult,  mult
/
/       isdig:
/               check on character in "char"
/               is it a digit, (i.e. >= '0', <='9'),
/               if so return its numeric value in acc
/                       and MODIFY RETURN address
/
/       so, will be returning to address immediately
/               following call if its not a digit (and acc will be zero)
/           but returning to address subsequent to that if it
/               is a digit
/
isdig,  0
        cla cll
        tad czero
        cia
        tad nchar
        spa cla
        jmp i isdig             / its less than zero character
        tad nchar
        cia
        tad cnine
        spa cla
        jmp i isdig
/       its a digit as in correct range of character values
        isz isdig
        nop
        jmp i isdig
czero,   60              / value representing '0'
cnine,   71              / value representing '9'
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*400
/       Here is the interrupt handler
inthnd,   dca accsav
        rar
        dca lnksav
/       saves completed, now skip chain
        clksf
        skp
        jmp clksrv
        ksf
        skp
        jmp keysrv
        hlt     / unknown interrupt
/       here, have return from interrupt
xit,    cla cll
/       restore registers
        tad lnksav
        ral
        tad accsav
/       re-enable interrupts
        ion
/       do return
        jmp i 0
/
/       clock service routine
clksrv, clkcf   / clear clock flag
        isz ticks
        nop
        jmp xit
/       keyboard service routine
keysrv, krb
        dca temp1
/       need to index into array
        tad inbuff      / base address
        tad pptr        / + index
        dca temp2       / = required address
        tad temp1
        dca i temp2     / character stored in "inbuff[pptr]"
        tad pptr
        iac
/       here we cheat a little, use a masking operation
/       to force pptr to stay in range 0-177 octal
        and m177
        dca pptr
        jmp xit
m177,   0177
temp1,  0
temp2,  0
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*600
nxtch,  0
/       wait till there are characters
nxtl,   cla cll
        tad cptr
        cia
        tad pptr
        sna cla
        jmp nxtl        / if pointers are equal then no characters yet
/       need to index into array
        tad inbuff      / base address
        tad cptr        / + index
        dca ntemp2      / = required address
        tad i ntemp2
        dca nchar
        tad cptr
        iac
/       here we cheat a little, use a masking operation
/       to force pptr to stay in range 0-177 octal
        and nm177
        dca cptr
        jmp i nxtch
nm177,   0177
ntemp2,  0
/       Here we have a "shift and add" multiply routine.
/
/       Several simplifying assumptions:
/       1) its intended only for positive numbers (so not
/               going to worry about two's complement notation
/               for integers).
/       2) its intended only for small numbers (the product
/               of two 12-bit numbers can require 24-bits,
/               that would mean simulating a double length
/               register which is practical but tiresome,
/               so assume that will only be working with
/               small numbers  and that product will be
/               represented in 12-bits; no attempt made
/               to detect overflow).
/       3) note the crude way of passing the arguments (multiplier
/               and multiplicand) via page 0 locations.
mult,   0
        cla cll
/       first, set up a loop that will take us through the
/       12 (decimal) bits of the words to be multiplied.
        tad kd12
        cia
        dca cntr
        tad mpand
        dca temp
/       zero the product
        dca prod
lmult,  cla cll
/       isolate next bit of multiplier
        tad mplr
        rar
        dca mplr
/       test if a 1, for then need to add in another
/       partial product
        snl
        jmp mult1       / that bit was a zero, so ignore
        tad temp
        tad prod
        dca prod
/       to mult1, now  shift temp left as considering next power
/       of 2
mult1,  cla cll
        tad temp
        ral
        dca temp
/       check if have finished the loop
        isz cntr
        jmp lmult
emult,  jmp i mult
/
*1000
chrbuf, 0
*1200
intary, 0
$
