home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / hd64180a.lbr / EXCORE.AZM / EXCORE.ASM
Assembly Source File  |  1991-08-04  |  43KB  |  1,984 lines

  1.     title    'Executive Processor Hardware Interface For CORE BOARD'
  2. ;----------------------------------------------------------------
  3. ; This module contains the Console I/O Drivers for the CORE BOARD
  4. ; card.
  5. ;
  6. ; These are meant to be run in conjunction with the EXEC
  7. ; module.
  8. ;
  9. ;
  10. ;    Written     By  Richard Holmes    04-02-86
  11. ;       Last Update By  Richard Holmes    17-10-88
  12. ;
  13. ; Bug fix in cursor address andlatch of 4 X 40 lcd
  14. ; Made 4 by 40 lcd true                        13/08/88
  15. ; Added hrs, min, sec data                17/10/88
  16. ;----------------------------------------------------------------
  17. ;
  18.     maclib    z80
  19.     maclib    core
  20.     maclib    iocmd
  21. ;
  22.     public    sys$ini
  23.     public    con$ini,con$inp,con$out,con$ost,con$ist,con$cmd
  24.     public    aux$ini,aux$inp,aux$out,aux$ost,aux$ist,aux$cmd
  25.     public    lcd$ini,lcd$out,lcd$ost,lcd$cmd
  26.     public    prn$ini,prn$out,prn$ost
  27.     public    ms$delay
  28. ;
  29.     public    set$led,clr$led,tog$led,zro$led
  30.     public    set$bel,clr$bel
  31.     public    clk$rd,clk$wr
  32. ;
  33.     public    clr$wdt
  34. ;
  35.     public    sch$rd
  36.     public    set$bel,clr$bel
  37. ;
  38.     public    hrs, min, sec
  39. ;
  40. ; Communications AUX port routines.
  41.     public    aux$ird,aux$iwr        ; Initialization routines
  42. ;
  43.     extrn    exec
  44. ;
  45. true    equ    0ffffh
  46. false    equ    not true
  47. ;
  48. aux$xonof equ    true            ; Xon/Xoff AUX control
  49. debug    equ    false
  50. ;
  51. numatt    equ    6            ; 6 attributes
  52. cr    equ    0dh            ; Simple video definitions
  53. lf    equ    0ah
  54. bs    equ    8        ; Backspace
  55. esc    equ    01bh        ; Escape
  56. ;
  57. ;----------------------------------------------------------------
  58. ; Delay the number of milliseconds in DE
  59. ;----------------------------------------------------------------
  60. ;
  61. ms$delay:
  62.     mov    a,e
  63.     ora    d
  64.     rz
  65. ;
  66.     push    d            ; save it
  67. delay2:
  68.     call    clr$wdt
  69.     call    delay3
  70.     dcx    d            ; one less millisecond less overhead
  71.     mov    a,d
  72.     ora    e
  73.     jrnz    delay2            ; keep on till DE = 0
  74.     pop    d            ; restore users initial value
  75.     ret                ; back to user
  76. ;
  77. ; Delay 1 millisecond less the overhead involved in the above code.
  78. ;
  79. ; This routine must delay 3957 t-states
  80. ;
  81. delay3:
  82.     push    b            ; 11
  83.     mvi    b,224            ;  7
  84. delay4:    ; This loop does (4 + 13) * 230 - 5 = 3905 t
  85.     nop                ; 4
  86.     djnz    delay4            ; 13
  87. ; Fudge 14 machine cycles
  88.     lxi    b,0            ; 10
  89.     nop                ;  4
  90.     pop    b            ; 10
  91. ;
  92.     ret
  93. ;
  94. ;================================================================
  95. ;
  96. ;        LED Drivers
  97. ;
  98. ;================================================================
  99. ; Initialize the LED drivers by clearing the data byte and hence 
  100. ; the led port
  101. ;----------------------------------------------------------------
  102. ;
  103. zro$led:
  104.     mvi    a,wr$en        ; Memory enable only
  105.     sta    led$byt        ; Save for masks later
  106.     out    @ledd        ; Send to driver
  107.     ret
  108. ;
  109. ;----------------------------------------------------------------
  110. ; Or the specified bit mask in A into the LED Outputs.
  111. ;
  112. ; On Entry
  113. ;    A = led mask
  114. ;
  115. ; On Exit
  116. ;     Set bit leds turned on. Others preserved.
  117. ;----------------------------------------------------------------
  118. ;
  119. ori$led:
  120.     push    b
  121.     ani    0011$1111b        ; Mask off any top bits
  122.     mov    c,a            ; Save
  123.     lda    led$byt            ; Load old data
  124.     ora    c            ; OR in the bit mask
  125. ; Maskin ram enable
  126.     ori    1100$0000b        ; Ensure ram on.
  127.     jr    led$com
  128. ;
  129. ;----------------------------------------------------------------
  130. ; Set the specified bit in A LED on. Leave others alone.
  131. ;
  132. ; On Entry
  133. ;    A = 1..6 for the led number
  134. ; On Exit
  135. ;     Led number turned on. Others preserved.
  136. ;----------------------------------------------------------------
  137. ;
  138. set$led:
  139.     ora    a
  140.     rz                ; Exit if = 0
  141.     cpi    7
  142.     rnc                ; NC and > 6 hence in error
  143.     push    b
  144.     call    led$msk
  145.     lda    led$byt            ; Load old data
  146.     ora    c            ; OR in the new bit mask
  147. led$com:
  148.     ori    wr$en            ; Force write enable high
  149.     sta    led$byt
  150.     out    @ledd            ; Write out again
  151.     pop    b
  152.     ret
  153. ;
  154. ;----------------------------------------------------------------
  155. ; Clear the specified bit in A. Leave others alone.
  156. ;
  157. ; On Entry
  158. ;    A = 1..6 for the led number
  159. ; On Exit
  160. ;     Led number cleared. Others preserved.
  161. ;----------------------------------------------------------------
  162. ;
  163. clr$led:
  164.     ora    a
  165.     rz                ; Exit if = 0
  166.     cpi    7
  167.     rnc                ; NC and > 6 hence in error
  168.     push    b
  169.     call    led$msk
  170.     cma    
  171.     mov    c,a            ; Invert and save led mask
  172.     lda    led$byt            ; Load old data
  173.     ana    c            ; And OFF the selected bit
  174.     ori    wr$en            ; Mask in the memory enable bit
  175.     jr    led$com
  176. ;
  177. ;----------------------------------------------------------------
  178. ; Toggle the passed in LED
  179. ;
  180. ;----------------------------------------------------------------
  181. ;
  182. tog$led:
  183.     ora    a
  184.     rz
  185.     cpi    8
  186.     rnc
  187. ;
  188.     push    b
  189.     call    led$msk
  190.     lda    led$byt
  191.     xra    c
  192.     ori    wr$en
  193.     jmp    led$com
  194. ;
  195. ; ---------------------------------------------
  196. ; -- Convert a bit number into an actual Bit --
  197. ; ---------------------------------------------
  198. ;
  199. led$msk:
  200.     mov    b,a            ; load counter
  201.     mvi    a,080h            ; Seed. Must rotate at least once.
  202. led$rot:
  203.     rlc                ; Shift left
  204.     djnz    led$rot
  205.     mov    c,a            ; Save data into C for later
  206.     ret
  207. ;
  208. ;----------------------------------------------------------------
  209. ;           Turn on the system bell
  210. ;----------------------------------------------------------------
  211. ;
  212. set$bel:
  213.     push    psw
  214.     mvi    a,1
  215.     sta    bel$byt
  216.     out    @buz            ; To bell / buzzer
  217.     pop    psw
  218.     ret
  219. ;
  220. ;----------------------------------------------------------------
  221. ;           Turn off the system bell
  222. ;----------------------------------------------------------------
  223. ;
  224. clr$bel:
  225.     push    psw
  226.     xra    a            ; Send a 0
  227.     sta    bel$byt
  228.     out    @buz            ; To bell / buzzer
  229.     pop    psw
  230.     ret
  231. ;
  232. ;----------------------------------------------------------------
  233. ;     Toggle the system bell bit ON/OFF
  234. ;----------------------------------------------------------------
  235. ;
  236. tog$bel:
  237.     push    psw
  238.     lda    bel$byt
  239.     xri    1
  240.     sta    bel$byt
  241.     out    @buz            ; To bell / buzzer
  242.     pop    psw
  243.     ret
  244. ;
  245. ;----------------------------------------------------------------
  246. ; Clear the watchdog timer by writing a 1 then 0 to toggle
  247. ; the port.
  248. ;----------------------------------------------------------------
  249. ;
  250. clr$wdt:
  251.     push    psw
  252.     lda    wdt$flg
  253.     out    @wdt
  254.     xri    1            ; Toggle bit 1
  255.     sta    wdt$flg
  256.     pop    psw
  257.     ret
  258. ;
  259. ;----------------------------------------------------------------
  260. ; Read the dip switch into A for the user
  261. ;----------------------------------------------------------------
  262. ;
  263. schrd:
  264.     in    @sch
  265.     ret
  266. ;
  267. ;----------------------------------------------------------------
  268. ;    Read real time clock to ram at DE
  269. ;
  270. ; Memory is laid out in the following format:
  271. ; seconds
  272. ; minutes
  273. ; hours
  274. ; day of week
  275. ; day of month
  276. ; month
  277. ; Year. Saved in ram in the clock chip at port 01fh
  278. ;
  279. ; Note the bit of code that stops the clock from being read
  280. ; constantly if the chip is faulty. This is the count value
  281. ; in B.
  282. ;----------------------------------------------------------------
  283. ;
  284. clk$rd:
  285.     push    h
  286.     push    b                ; Save
  287.     sded    ?time
  288.     mvi    b,5                ; 5 times maximum read count
  289. ;
  290. read$clock:                ; Repeat here if a rollover
  291.     lhld    ?time
  292.     in    @clk + 2            ; Seconds
  293.     mov    m,a
  294.     inx    h
  295. ;
  296.     in    @clk + 3            ; Minutes
  297.     mov    m,a
  298.     inx    h
  299. ;
  300.     in    @clk + 4            ; hours
  301.     mov    m,a
  302.     inx    h
  303. ;
  304.     in    @clk + 5            ; Day of week
  305.     mov    m,a
  306.     inx    h
  307. ;
  308.     in    @clk + 6            ; Day of month
  309.     mov    m,a
  310.     inx    h
  311. ;
  312.     in    @clk + 7            ; Month
  313.     mov    m,a
  314.     inx    h            ; -> year register in system ram
  315.     in    @clk + 0fh        ; Year ram in clock
  316.     mov    m,a
  317. ;
  318. ; Check rollover status port. Bitset = an internal ripple, re-read required.
  319. ;
  320.     in    @clk+20            ; Status port
  321.     ani    1            ; Status bit is in D0
  322.     jz    read$kend        ; if 00, a good read
  323.     djnz    read$clock        ; Read till a 0 bit.
  324. ;
  325. ; Else the time is valid
  326. ;
  327. read$kend:
  328.     pop    b            ; Restore all
  329.     pop    h
  330.     ret
  331. ;
  332. ;----------------------------------------------------------------
  333. ;
  334. ; Write the real time clock from a ram store. This is expected
  335. ; to be in the same format as that for clock read.
  336. ;
  337. ; On entry
  338. ;  DE -> time buffer
  339. ;----------------------------------------------------------------
  340. ;
  341. clk$wr:
  342. ; Reset clock counters
  343.     mvi    a,0ffh            ; All 1's for a reset counter command
  344.     out    @clk + 18        ; Resets all the counters
  345. ;
  346.     ldax    d
  347.     out    @clk + 2
  348.     inx    d
  349. ;
  350.     ldax    d
  351.     out    @clk + 3            ; Minutes
  352.     inx    d
  353. ;
  354.     ldax    d
  355.     out    @clk + 4            ; hours
  356.     inx    d
  357. ;
  358.     ldax    d
  359.     out    @clk + 5            ; Day of week
  360.     inx    d
  361. ;
  362.     ldax    d
  363.     out    @clk + 6            ; Day of month
  364.     inx    d
  365. ;
  366.     ldax    d
  367.     out    @clk + 7            ; Month
  368.     inx    d
  369. ;
  370.     ldax    d                ; Write year to clock ram
  371.     out    @clk + 0fh            ; Write to year register ram
  372. ;
  373.     ret
  374. ;
  375. ;----------------------------------------------------------------
  376. ;     Hardware system initializations.
  377. ;
  378. ; This is called by the C=0 function in the EXEC processor.
  379. ;----------------------------------------------------------------
  380. ;     Initialize the hardware on the board
  381. ;
  382. ; Initialize the SIO for channel A and channel B 8 bit, 1 stop
  383. ; no parity and 9600 baud each.
  384. ; CTC channels 0 and 1 are for SIO baud rates
  385. ; CTC channel 2 for external interrupts......... (see monitor)
  386. ; CTC channel 3 for real time clock interrupts.. (see monitor)
  387. ;----------------------------------------------------------------
  388. ;
  389. sys$ini:
  390.     call    clr$wdt        ; Reset the watchdog timer. Stop him.
  391. ;
  392. ; Initialize the watchdog timer clear routine that toggles the
  393. ; low order bit each time it is called.
  394. ;
  395.     xra    a
  396.     sta    wdt$flg
  397.     sta    bel$byt
  398.     sta    hrs
  399.     sta    min
  400.     sta    sec
  401. ;
  402.     mvi    a,wr$en
  403.     sta    led$byt        ; Setup the LED outputs
  404. ;
  405.     ret
  406. ;
  407. ;----------------------------------------------------------------
  408. ; This is the console command processor. The channel routines call
  409. ; it with a function number in C and these are then performed.
  410. ;----------------------------------------------------------------
  411. ;
  412. con$cmd:
  413.     push    h
  414.     push    b
  415.     push    d
  416.     mvi    b,0        ; Top offset = 0
  417.     lxi    h,con$cmd$tbl    ; -> table of routine addresses
  418.     dad    b
  419.     dad    b        ; Add twice for 2 byte offsets
  420.     mov    e,m        ; Low address
  421.     inx    h        ; -> High address
  422.     mov    d,m
  423.     xchg            ; HL -> routine
  424.     pop    d        ; Restore DE, it may be a parameter
  425.     pop    b        ;         BC could be someones counter
  426.     xthl            ; top of stack = routine, HL restored also.
  427.     ret
  428. ;
  429. con$cmd$tbl:
  430.     dw    0
  431.     dw    clear
  432.     dw    cleop
  433.     dw    cleol
  434.     dw    cursor
  435.     dw    setatt
  436.     dw    con$null
  437. ;
  438. con$null:
  439.     ret
  440. ;
  441. ; The AUX channel does not have any such thing as a command
  442. ; processor. It is a comms channel, not a screen.
  443. aux$cmd:
  444.     xra    a
  445.     ora    a
  446.     ret
  447. ;
  448.     page
  449. ;----------------------------------------------------------------
  450. ;    L C D    I / O    D R I V E R S
  451. ;----------------------------------------------------------------
  452. ;
  453. ; PB 0 = Enable 1. For controller 1
  454. ;    1 = Enable 2. For controller 2
  455. ;    1 = R/W-.               1 = write to LCD
  456. ;    2 = Register select     1 = Data, 0 = control register
  457. ;----------------------------------------------------------------
  458. ;
  459. lcd$440    equ    true
  460. lcd$216    equ    false
  461. ;
  462. ; ---- Special LCD Equates. Here to make reading easy ----
  463. ;
  464. data    equ    044h        ; LCD data port
  465. cntl    equ    045h        ; Control port of LCD
  466. mode    equ    047h        ; Mode port
  467. ;
  468.     if    lcd$440
  469. ;
  470. idle    equ    0        ; Idle display controllers
  471. wr$cmd2    equ    1        ; Write command 1
  472. wr$cmd1    equ    2        ; Write command 2
  473. ;
  474. wr$dat2    equ    9        ; Write data 1
  475. wr$dat1    equ    0ah        ; Write data 2
  476. ;
  477. rd$st2    equ    5        ; Read status 1
  478. rd$st1    equ    6        ; Read status 2
  479. ;
  480. lcd$line equ    4        ; 4 line screen
  481. lcd$char equ    40        ; 40 chars per line
  482.     endif
  483. ;
  484. ; Or are we a 16 by 2 ??
  485.     if    lcd$216
  486. lcd$line equ    2        ; 2 line screen
  487. lcd$char equ    16        ; 16 chars per line
  488.     endif
  489. ;
  490. ;----------------------------------------------------------------
  491. ;         Initialize the LCD.
  492. ;
  493. ; 1. Data path 8 bits, 4 line display, 40 char.
  494. ; 2. Enable cursor. Blink. Enable display
  495. ; 4. Clear and home cursor.
  496. ; 3. Display stationary, auto increment, right move.
  497. ;
  498. ; On Exit
  499. ;    CARRY Set = ERROR - probably LCD missing / faulty.
  500. ;          Clr = no problem - all ok.
  501. ;----------------------------------------------------------------
  502. ;
  503. lcd$ini:
  504.     if    lcd$440
  505.     push    psw
  506. ;
  507.     mvi    a,1
  508.     sta    err$num
  509. ;
  510. ; Select the first controller, command latching.
  511.     mvi    a,wr$cmd1    ; Command for controller 1
  512.     sta    lc$cmd        ; Save in command port.
  513.     call    ini$cntrlr    ; Initialize the controller
  514.     jrc    ini$err        ; Error exit
  515. ;
  516.     mvi    a,wr$cmd2    ; Controller 2
  517.     sta    lc$cmd
  518.     call    ini$cntrlr
  519.     jrc    ini$err        ; Error exit
  520. ;
  521.     xra    a
  522.     sta    lcd$x
  523.     sta    lcd$y        ; Setup X and Y addresses
  524.     call    cof$lcd        ; Turn off all cursors. Usually 2 actually.
  525.     jrc    ini$err
  526. ;
  527.     call    con$lcd        ; Turn cursor on. Just one ay lcdX, lcdY
  528.     jrc    ini$err
  529. ;
  530.     pop    psw
  531.     ora    a        ; No carry = no error
  532.     ret
  533. ;
  534. ini$err:
  535.     pop    psw
  536.     jmp    gp$err
  537. ;
  538. ;----------------------------------------------------------------
  539. ;     ---- Initialize the contoller. ----
  540. ;----------------------------------------------------------------
  541. ;
  542. ini$cntrlr:
  543. ;
  544. ; 1. Enable 8 bit bus, 2 line display
  545.     mvi    a,038h
  546.     call    lch$lcd        ; Latch 8 bit, 2 line display
  547.     rc            ; Exit on error
  548. ;
  549. ; 2. Enable display on, cursor on, blink
  550.     mvi    a,0eh
  551.     call    lch$lcd
  552.     rc
  553. ;
  554.     mvi    a,08
  555.     call    lch$lcd
  556.     rc
  557. ;
  558. ;
  559. ; 3. Display stationary, Right cursor
  560. ;
  561.     mvi    a,2
  562.     call    lch$lcd
  563.     rc
  564. ;
  565.     mvi    a,1
  566.     call    lch$lcd
  567.     rc
  568.     ora    a            ; No error exit
  569.     ret
  570. ;
  571. ;
  572. gp$err:
  573.     mvi    a,'e'
  574.     call    con$out
  575.     stc
  576.     ret
  577. ;
  578.     endif
  579. ;
  580. ; =====================================
  581. ; ==== 2 line by 16 char interface ====
  582. ; =====================================
  583. ;
  584.     if    lcd$216
  585.     push    psw
  586. ; 1. Enable 8 bit bus, 2 line display
  587.     mvi    a,038h
  588.     call    lch$cmd        ; Latch 8 bit, 2 line display
  589. ; 2. Enable display on, cursor on, blink
  590.     mvi    a,0fh
  591.     call    lch$cmd
  592. ; 3. Display stationary, auto increment, right
  593.     mvi    a,6
  594.     call    lch$cmd
  595. ; 4. Display stationary, Right cursor
  596.     mvi    a,014h
  597.     call    lch$cmd
  598. ; Done.
  599.     call    lcd$clr
  600.     pop    psw
  601.     ret
  602.     endif
  603. ;
  604.     page
  605. ;----------------------------------------------------------------
  606. ;        L C D    C O M M A N D    P R O C E S S O R
  607. ;
  608. ; Impliment the LCD commands so that the channel system can
  609. ; do clearing, cursor addressing etc.
  610. ;----------------------------------------------------------------
  611. ;
  612. lcd$cmd:
  613.     push    h
  614.     push    b
  615.     push    d
  616.     mvi    b,0        ; Top offset = 0
  617.     lxi    h,lc$cmd$tbl    ; -> table of routine addresses
  618.     dad    b
  619.     dad    b        ; Add twice for 2 byte offsets
  620.     mov    e,m        ; Low address
  621.     inx    h        ; -> High address
  622.     mov    d,m
  623.     xchg            ; HL -> routine
  624.     pop    d        ; Restore DE, it may be a parameter
  625.     pop    b        ;         BC could be someones counter
  626.     xthl            ; top of stack = routine, HL restored also.
  627.     ret
  628. ;
  629. lc$cmd$tbl:
  630.     dw    0
  631.     dw    lcd$clr            ; LCD clear page
  632.     dw    lcd$null        ; No clear to end of lcd page yet
  633.     dw    lcd$eol            ; LCD clear to end of line
  634.     dw    lcd$cur            ; LCD cursor address
  635.     dw    lcd$null        ; No such thing as LCD video attributes
  636.     dw    lcd$getxy        ; Fetch current LCD x-y address
  637. ;
  638. lcd$null:
  639.     ret
  640. ;
  641. ; Returns DE = XY address.
  642. ;
  643. lcd$getxy:
  644.     lda    lcd$y
  645.     mov    e,a
  646.     lda    lcd$x
  647.     mov    d,a
  648.     ret
  649. ;
  650. ;----------------------------------------------------------------
  651. ; Return LCD Status. This is tricky as it must re-initialize
  652. ; the LCD control port and read the LCD status flag BF. It
  653. ; will return a 00 if idling or an FF if busy. NOTE the
  654. ; need to re-load the CS2 line to the ram chip and clock
  655. ; and LED return when finished.
  656. ;----------------------------------------------------------------
  657. ;
  658. lcd$ost:    
  659.     if    lcd$440
  660.     push    h        ; Save register to use as a scratch pad
  661. ;
  662. ; Generate the LCD enable signals
  663.     lda    lcd$cmd        ; Command to be used
  664.     ani    0000$0011b    ; Get the controller bits
  665.     ori    0000$0100b    ; Or in the status reading function
  666.     mov    l,a        ; L = device image.
  667. ;
  668.     di            ; STOP interrupts when checking LCD status
  669.     mvi    a,090h        ; Port A inputs
  670.     out    @ledmd        ; LED mode port
  671.     mvi    a,0c0h
  672.     out    @ledd        ; Re-assert ram as soon as possible
  673. ;
  674.     nop
  675.     nop
  676.     nop
  677.     nop            ; Settling time
  678. ;
  679. ;       OK, Port A inputs, B and C outputs. 
  680. ; Note the need to set R/W pin high for a time before the E pin (bit 0).
  681. ;
  682.     mvi    a,0000$0100b    ; Send the Read bit out.
  683.     out    cntl        ; To the control port
  684.     mov    a,l
  685.     out    cntl        ; Send "E" bits also
  686. ;
  687. ; This requires a 40uS delay as per the data sheet
  688. ;
  689.     mvi    a,15        ; Plenty of time 
  690. st$dly:
  691.     dcr    a
  692.     jnz    st$dly
  693. ;
  694.     in    data        ; Read the LCD data
  695.     mov    l,a        ; Save here. Can't see stack can we....
  696. ;
  697. ; Restore 8255 mode
  698.     mvi    a,080h        ; ALL outputs
  699.     out    @ledmd        ; LED mode port
  700. ; Re-load ram control signals
  701.     mvi    a,0C0h        ; Bit 6 and 7 for ram and clock on
  702.     out    @ledd        ; Sends to led port to turn on ram again.
  703. ;
  704.     nop
  705.     nop
  706.     nop
  707.     nop
  708.     xra    a
  709.     out    cntl        ; Clear the port
  710. ;
  711.     ei            ; Restore interrupts after LCD write
  712. ;
  713.     call    ori$led        ; Restore previous LED status
  714. ;
  715.     mov    a,l        ; Restore data
  716.     pop    h        ; Restore register
  717. ;Now. Determine basic state of 00 = idle or FF = busy.
  718.     ani    1000$0000b    ; Leave busy flag
  719.     rz
  720.     mvi    a,0ffh        ; Else load an FF for very busy still.
  721.     ret
  722. ;
  723.     endif
  724. ;
  725. ; ==== 2 line by 16 char interface ====
  726. ;
  727.     if    lcd$216
  728.     di            ; STOP interrupts when checking LCD status
  729.     push    h        ; Save a register to use as a scratch pad
  730.     mvi    a,090h        ; Port A inputs
  731.     out    @ledmd        ; LED mode port
  732.     mvi    a,0c0h
  733.     out    @ledd        ; Re-assert ram as soon as possible
  734. ;
  735. ; OK, Port A inputs, B and C outputs. Dangerous. No RAM now.
  736. ; Note the need to set R/W pin high for a time before the E pin (bit 0).
  737. ;
  738.     mvi    a,0000$0010b    ; Read status. E = 0, R/W- = 1, RS = 0
  739.     out    @lcdc        ; LCD Control sent.
  740.     mvi    a,0000$0011b    ; Enable high now
  741.     out    @lcdc        ; LCD now ready to be read.
  742.     nop
  743.     nop            ; 2uS settling time
  744.     in    @lcdd        ; Read the LCD data
  745.     mov    l,a        ; Save here. Can't see stack can we....
  746. ; Restore 8255 mode
  747.     mvi    a,080h        ; ALL outputs
  748.     out    @ledmd        ; LED mode port
  749. ; Re-load ram control signals
  750.     mvi    a,0C0h        ; Bit 6 and 7 for ram and clock on
  751.     out    @ledd        ; Sends to led port to turn on ram again.
  752. ;
  753.     nop
  754.     nop
  755.     nop
  756.     nop
  757.     xra    a        ; Load a null so that ORI will work
  758. ;
  759.     ei            ; Restore interrupts after LCD write
  760. ;
  761.     call    ori$led        ; Restore previous LED status
  762.     mov    a,l        ; Restore data
  763.     pop    h        ; Restore register
  764. ;Now. Determine basic state of 00 = idle or FF = busy.
  765.     ani    1000$0000b    ; Leave busy flag
  766.     rz
  767.     mvi    a,0ffh        ; Else load an FF for very busy still.
  768.     ret
  769.     endif
  770. ;
  771. ;------------------------------------------------
  772. ; Latch the command in lc$cmd  and the
  773. ; data in lcd$dat into the LCD.
  774. ;
  775. ; On Exit
  776. ;    CARRY Set = error. LCD did not respond.
  777. ;          Clr = no error.
  778. ;------------------------------------------------
  779. ;
  780. lch$lcd:
  781.     if    lcd$440
  782.     push    h
  783.     push    psw        ; Save registers
  784. ;
  785. ; Now setup timeout counter in HL and look for LCD idle
  786.     lxi    h,400        ; Big delay
  787. lch$cmd$loop:
  788.     call    clr$wdt
  789.     call    clr$wdt
  790.     call    lcd$ost        ; Get LCD status
  791.     ora    a
  792.     jrz    lch$cmd$ok
  793.     dcx    h
  794.     mov    a,l
  795.     ora    h        ; Done ?
  796.     jrnz    lch$cmd$loop    ; Loop on till IDLE (busy flag = 0)
  797. ; ERROR here
  798. ;
  799.     mvi    a,'L'
  800.     call    con$out
  801.     mvi    a,'E'
  802.     call    con$out
  803. ;
  804.     pop    psw
  805.     pop    h
  806.     stc            ; Carry flag = error
  807.     ret
  808. ;
  809. ; Restore registers and do job
  810. ;
  811. lch$cmd$ok:
  812.     pop    psw
  813.     push    psw
  814. ;
  815.     out    data
  816.     lda    lc$cmd
  817.     out    cntl
  818.     xra    a
  819.     out    cntl
  820. ;
  821.     pop    psw
  822.     pop    h
  823.     ora    a            ; Clear carry for all ok.
  824.     ret
  825. ;
  826.     endif
  827. ;
  828. ; ==== 2 line by 16 char interface ====
  829. ;
  830.     if    lcd$216
  831. ;
  832. lch$dat:
  833.     push    h
  834.     push    psw        ; Save registers
  835. ; Now setup timeout counter in HL and look for LCD idle
  836.     lxi    h,200        ; Big delay
  837. lch$dat$loop:
  838.     call    clrwdt
  839.     call    lcd$ost        ; Get LCD status
  840.     ora    a
  841.     jrz    lch$dat$ok
  842.     dcx    h
  843.     mov    a,l
  844.     ora    h        ; Done ?
  845.     jrnz    lch$dat$loop    ; Loop on till IDLE (busy flag = 0)
  846. ; ERROR here
  847.     pop    psw
  848.     pop    h
  849.     stc            ; Carry flag = error
  850.     ret
  851. ;
  852. ; Restore registers and do job
  853. ;
  854. lch$dat$ok:
  855.     pop    psw
  856.     pop    h
  857. ;
  858.     out    data
  859.     push    psw
  860.     mvi    a,5        ; Data selector
  861.     jr    lch$comm    ; Note the use of command common code
  862. ;
  863. ;
  864. lch$cmd:
  865.     push    h
  866.     push    psw        ; Save registers
  867. ; Now setup timeout counter in HL and look for LCD idle
  868.     lxi    h,200        ; Big delay
  869. lch$cmd$loop:
  870.     call    clrwdt
  871.     call    lcd$ost        ; Get LCD status
  872.     ora    a
  873.     jrz    lch$cmd$ok
  874.     dcx    h
  875.     mov    a,l
  876.     ora    h        ; Done ?
  877.     jrnz    lch$cmd$loop    ; Loop on till IDLE (busy flag = 0)
  878. ; ERROR here
  879.     pop    psw
  880.     pop    h
  881.     stc            ; Carry flag = error
  882.     ret
  883. ;
  884. ; Restore registers and do job
  885. ;
  886. lch$cmd$ok:
  887.     pop    psw
  888.     pop    h
  889. ;
  890. fast$lch$cmd:    ; Here to latch a command W/O busy checking
  891.     out    data
  892.     push    psw
  893.     mvi    a,1
  894. lch$comm:    ; Common latching code for both command and data
  895.     out    cntl
  896.     xra    a
  897.     out    cntl        ; Latch HIGH then low
  898.     pop    psw
  899.     ora    a        ; Clear carry
  900.     ret
  901. ;
  902.     endif
  903. ;
  904.     page
  905. ;----------------------------------------------------------------
  906. ;             Clear LCD and home cursor.
  907. ;
  908. ; On Exit
  909. ;    CARRY Set = ERROR - probably LCD missing / faulty.
  910. ;          Clr = no problem - all ok.
  911. ;----------------------------------------------------------------
  912. ;
  913. lcd$clr:
  914.     if    lcd$440
  915.     push    psw
  916. ;
  917.     mvi    a,2
  918.     sta    err$num
  919. ; Clear controller 1
  920.     mvi    a,wr$cmd1
  921.     sta    lc$cmd            ; Select a clear command controller 1
  922.     mvi    a,1            ; Clear display totally
  923.     call    lch$lcd
  924.     jrc    clr$err
  925. ;
  926. ; Clear controller 2
  927.     mvi    a,wr$cmd2
  928.     sta    lc$cmd            ; Select a clear command controller 1
  929.     mvi    a,1            ; Clear display totally
  930.     call    lch$lcd
  931.     jrc    clr$err
  932. ;
  933.     xra    a            ; Clear cursor address
  934.     sta    lcd$x
  935.     sta    lcd$y
  936.     call    hom$lcd
  937.     jrc    clr$err
  938. ;
  939.     pop    psw
  940.     ora    a            ; Clear carry - no error.
  941.     ret
  942. ;
  943. clr$err:
  944.     pop    psw
  945.     jmp    gp$err
  946. ;
  947.     endif
  948. ;
  949. ; ==== 2 line by 16 interface ====
  950. ;
  951.     if    lcd$216
  952.     push    psw
  953.     mvi    a,1            ; Clear display totally
  954.     call    lch$cmd
  955. ;
  956.     xra    a            ; Clear cursor address
  957.     sta    lcd$x
  958.     sta    lcd$y
  959.     pop    psw
  960.     ret
  961.     endif
  962. ;
  963. ;----------------------------------------------------------------
  964. ;         Home the cursor
  965. ;
  966. ; On Exit
  967. ;    CARRY Set = ERROR - probably LCD missing / faulty.
  968. ;          Clr = no problem - all ok.
  969. ;----------------------------------------------------------------
  970. ;
  971. hom$lcd:
  972.     if    lcd$440
  973.     push    d
  974.     push    psw
  975. ;
  976.     mvi    a,3
  977.     sta    err$num
  978. ;
  979.     lxi    d,0            ; Top left hand corner of screen
  980.     call    lcd$cur            ; Home to the top lh lcd corner
  981.     jrc    hom$err
  982. ;
  983.     pop    psw
  984.     pop    d
  985.     ora    a
  986.     ret
  987. ;
  988. hom$err:
  989.     pop    psw
  990.     pop    d
  991.     jmp    gp$err
  992. ;
  993.     else
  994.     ret
  995.     endif
  996. ;
  997. ;
  998. ;----------------------------------------------------------------
  999. ;     Turn all cursors off.
  1000. ;
  1001. ; On Exit
  1002. ;    CARRY Set = ERROR - probably LCD missing / faulty.
  1003. ;          Clr = no problem - all ok.
  1004. ;----------------------------------------------------------------
  1005. ;
  1006. cof$lcd:
  1007.     if    lcd$440
  1008.     push    psw
  1009.     mvi    a,wr$cmd1
  1010.     sta    lc$cmd
  1011.     mvi    a,0000$1100b    ; Display on, cursor off
  1012.     call    lch$lcd        ; Latch the command and data in.
  1013.     jrc    cof$err
  1014. ;
  1015.     mvi    a,wr$cmd2
  1016.     sta    lc$cmd
  1017.     mvi    a,0000$1100b    ; Display on, cursor off
  1018.     call    lch$lcd        ; Latch the command and data in.
  1019.     jrc    cof$err
  1020.     pop    psw
  1021.     ora    a
  1022.     ret
  1023. ;
  1024. cof$err:
  1025.     pop    psw
  1026.     stc
  1027.     endif
  1028. ;
  1029.     ret
  1030. ;
  1031. ;----------------------------------------------------------------
  1032. ;     Turn the current cursor at lcd$x and lcd$y on.
  1033. ;
  1034. ; This is decided by the current cursor address of the lcd.
  1035. ;----------------------------------------------------------------
  1036. ;
  1037. con$lcd:
  1038.     if    lcd$440
  1039.     push    b
  1040.     push    psw
  1041. ;
  1042. ; Select the controller and load the write command control word
  1043.     mvi    c,wr$cmd1    ; Default to controller 1
  1044.     lda    lcd$y        ; Line number
  1045.     cpi    2
  1046.     jrc    con$do        ; Line 0 and 1 user controller 1
  1047. ;
  1048.     mvi    c,wr$cmd2    ; Controller 2 if line 2 or 3
  1049. con$do:
  1050.     mov    a,c        ; get
  1051.     sta    lc$cmd        ; Load the command
  1052.     mvi    a,0fh        ; cursor on
  1053.     call    lch$lcd        ; And do it.
  1054.     jrc    lcd$con$err
  1055. ;
  1056.     pop    psw
  1057.     pop    b
  1058.     ora    a
  1059.     ret
  1060. ;
  1061. lcd$con$err:
  1062.     pop    psw
  1063.     pop    b
  1064.     stc
  1065.     endif
  1066. ;
  1067.     ret
  1068. ;
  1069.     page
  1070. ;----------------------------------------------------------------
  1071. ;     Cursor address the lcd.
  1072. ;
  1073. ; On Entry D = X in the range 0..38  (characters per line)
  1074. ;          E = Y in the range 0..3   (lines)
  1075. ;
  1076. ; If out of range, no change is made.
  1077. ; All registers preserved
  1078. ;----------------------------------------------------------------
  1079. ;
  1080. lcd$cur:
  1081.     if    lcd$440
  1082.     push    b
  1083.     push    psw
  1084. ;
  1085. ; Check if X > possible range.
  1086.     mvi    b,1        ; Error location pointer
  1087.     mov    a,d
  1088.     cpi    40        ; Error if > 16
  1089.     jrnc    cur$err
  1090. ;
  1091. ; Check Line number in range
  1092.     mvi    b,2
  1093.     mov    a,e
  1094.     cpi    4
  1095.     jrnc    cur$err        ; Error if > 3
  1096. ;
  1097.     mvi    b,3
  1098.     call    cof$lcd
  1099.     jrc    cur$err
  1100. ;
  1101. ; Calculate the LCD command
  1102.     mov    a,e            ; New 'y' address
  1103.     sta    lcd$y            ; Save it also.
  1104. ;
  1105.     mvi    c,wr$cmd1        ; Default to controller 1
  1106.     cpi    2
  1107.     jrc    cur$lc$cmd
  1108.     mvi    c,wr$cmd2
  1109. ;
  1110. cur$lc$cmd:
  1111.     mov    a,c
  1112.     sta    lc$cmd
  1113. ;
  1114. ; Now generate the ram address for the LCD
  1115.     mvi    c,080h        ; Top bit = cursor address
  1116.     mov    a,e        ; Get the line number back
  1117.     ani    0000$0001b    ; Do a modulus 2
  1118.     jrz    cur$not$1    ; Top row is address 80h..A7h
  1119.     mvi    c,0C0h        ; If second row the offset is 0C0h
  1120. ;
  1121. cur$not$1:
  1122.     mov    a,c        ; Address
  1123.     add    d        ; Add in the X address
  1124. ;
  1125.     call    lch$lcd        ; Command in A built up, latch to LCD
  1126.     mvi    b,4        ; Flag any error locations.
  1127.     jrc    cur$err
  1128. ; Save the X address also
  1129.     mov    a,d        ; X
  1130.     sta    lcd$x
  1131. ; Finally, turn on the cusor
  1132.     mvi    a,0000$1111b    ; Turn on cursor, display, blink.
  1133.     call    lch$lcd
  1134.     mvi    b,5
  1135.     jrc    cur$err
  1136. ;
  1137.     pop    psw
  1138.     pop    b
  1139.     ora    a
  1140.     ret
  1141. ;
  1142. cur$err:
  1143. ; Signal the cursor addressing error
  1144.     mvi    a,'C'
  1145.     call    con$out
  1146.     mvi    a,'E'
  1147.     call    con$out
  1148.     mvi    a,'0'
  1149.     add    b
  1150.     call    con$out
  1151. ;
  1152.     pop    psw
  1153.     pop    b
  1154.     stc
  1155.     ret
  1156. ;
  1157.     endif
  1158. ;
  1159. ; ==== 2 line by 16 LCD interface ====
  1160. ;
  1161.     if    lcd$216
  1162.     push    psw
  1163. ; Check if X > possible range.
  1164.     mov    a,d
  1165.     cpi    16        ; Error if > 16
  1166.     jrnc    cur$err
  1167. ; Check Line number
  1168.     mov    a,e
  1169.     cpi    2
  1170.     jrnc    cur$err        ; Error if > 1
  1171. ; Now do the addressing
  1172.     sta    lcd$y        ; Save LCD address
  1173. ;
  1174.     push    b        ; Save all registers always, makes easy later.
  1175.     mvi    c,080h        ; Top bit = cursor address
  1176.     ora    a        ; At top row (A = 0 ?)
  1177.     jrz    cur$not$1    ; Top row is address 80h..8fh
  1178.     mvi    c,0C0h        ; If second row the offset if 0C0h
  1179. ;
  1180. cur$not$1:
  1181.     mov    a,c        ; Address
  1182.     add    d        ; Add in the X address
  1183.     call    lch$cmd        ; Command in A built up
  1184. ; Save the X address also
  1185.     mov    a,d        ; X
  1186.     sta    lcd$x
  1187. ;
  1188.     pop    b
  1189. cur$err:
  1190.     pop    psw
  1191.     ret
  1192. ;
  1193.     endif
  1194. ;
  1195. ;----------------------------------------------------------------
  1196. ;         Clear to end of line.
  1197. ;----------------------------------------------------------------
  1198. ;
  1199. lcd$eol:
  1200.     push    h
  1201.     push    b
  1202.     push    d
  1203.     push    psw
  1204. ; Get the current cursor address.
  1205.     lda    lcd$y
  1206.     mov    e,a
  1207.     lda    lcd$x
  1208.     mov    d,a        ; Save X
  1209. ;
  1210. ; Generate a counter in B for the number of spaces to be sent
  1211.     mov    b,a        ; A counter also
  1212.     mvi    a,39
  1213.     sub    b        ; A = 39 - column.
  1214.     jrz    eol$done
  1215.     jrc    eol$done
  1216.     mov    b,a        ; B = the number of spaces
  1217. ;
  1218. ; B = column number. Send spaces to end of line now.
  1219. ;
  1220. eol$loop:
  1221.     mvi    a,' '        ; Erase with a space.
  1222.     call    lcd$out        ; Send the character to the LCD
  1223.     jrc    eol$err
  1224.     djnz    eol$loop
  1225. ;
  1226. eol$done:
  1227.     call    lcd$cur        ; Cursor address to previous row/col position
  1228. ;
  1229.     pop    psw
  1230.     pop    d
  1231.     pop    b
  1232.     pop    h
  1233.     ora    a        ; No error
  1234.     ret
  1235. ;
  1236. eol$err:
  1237.     pop    psw
  1238.     pop    d
  1239.     pop    b
  1240.     pop    h
  1241.     stc            ; Error flag
  1242.     ret
  1243. ;
  1244.     page
  1245. ;----------------------------------------------------------------
  1246. ;
  1247. ;          Send character in A to the LCD
  1248. ;
  1249. ; We must decide which controller by checking the lcd$y address
  1250. ; and use Y = 0,1 for controller 1, and 2,3 for controller 2.
  1251. ;
  1252. ; Note that the cursor is not moved.
  1253. ;----------------------------------------------------------------
  1254. ;
  1255. lcd$out:
  1256.     push    psw
  1257.     push    b
  1258. ;
  1259. ; Carriage return ?
  1260.     cpi    0dh
  1261.     jz    put$cr
  1262.     cpi    lf
  1263.     jz    put$lf
  1264.     cpi    bs            ; Back space ?
  1265.     jz    put$bs
  1266. ;
  1267. ; None of these. Bump the column number.
  1268.     lda    lcd$x
  1269.     inr    a
  1270.     sta    lcd$x
  1271.     cpi    lcd$char + 1        ; End of line ?
  1272.     jc    put$lcd1        ; If not, continue.
  1273.     xra    a            ; Start of next line
  1274.     sta    lcd$x
  1275. ;
  1276. ; Bump the row now. We must also cusor position.
  1277. ; This is used as the line feed entry point so that the
  1278. ; line number is advaced without advancing any columns.
  1279. ;
  1280.     lda    lcd$y
  1281.     inr    a
  1282.     sta    lcd$y
  1283.     cpi    lcd$line        ; Past last line ? 
  1284.     jrc    put$lcd$xy        ; Not last row and all ok
  1285. ;
  1286. ; Past last row. Start at top again.
  1287.     xra    a
  1288.     sta    lcd$y
  1289. ;
  1290. put$lcd$xy:
  1291.     push    d
  1292.     lda    lcd$x
  1293.     mov    d,a
  1294.     lda    lcd$y
  1295.     mov    e,a
  1296.     call    lcd$cur            ; Setup cursor at end of line to "wrap"
  1297.     pop    d
  1298. ;
  1299. ; Now select the controller to be used (written to).
  1300. ;
  1301. put$lcd1:
  1302.     if    lcd$440
  1303.     mvi    c,wr$dat1        ; Default to controller 1
  1304.     lda    lcd$y
  1305.     cpi    2
  1306.     jrc    put$lcd$do
  1307.     mvi    c,wr$dat2
  1308. ;
  1309. put$lcd$do:
  1310.     mov    a,c
  1311.     sta    lc$cmd
  1312. ;
  1313.     pop    b
  1314.     pop    psw
  1315.     jmp    lch$lcd
  1316.     endif
  1317. ;
  1318. ; ---- Else merely latch in data when a 16 char by 2 line display ----
  1319. ;
  1320.     if    lcd$216
  1321.     pop    b
  1322.     pop    psw
  1323.     jmp    lch$dat
  1324.     endif
  1325. ;
  1326. ;
  1327. ; Carriage return = home cursor to left hand column
  1328. ;
  1329. put$cr:
  1330.     xra    a
  1331.     sta    lcd$x
  1332. ;
  1333. ; Cursor address now - Also used by the CR handler
  1334. ;
  1335. put$lf$cur:
  1336.     push    d
  1337.     lda    lcd$x
  1338.     mov    d,a            ; D = X
  1339.     lda    lcd$y
  1340.     mov    e,a            ; E = Y
  1341.     call    lcd$cur
  1342.     pop    d
  1343. ;
  1344. ;
  1345. put$end:
  1346.     pop    b            ; Saved at routine start.
  1347.     pop    psw
  1348.     ora    a            ; No error
  1349.     ret
  1350. ;
  1351. ; Process a line feed by incrementing the line number by 1
  1352. ;
  1353. put$lf:
  1354.     lda    lcd$y            ; Line number
  1355.     inr    a
  1356.     sta    lcd$y
  1357.     cpi    lcd$line        ; Last line ?
  1358.     jc    put$lf$cur        ; Carry = not past end line
  1359.     xra    a
  1360.     sta    lcd$y
  1361.     jmp    put$lf$cur
  1362. ;
  1363. ; Send a backspace to the LCD by decrementing the current column by 
  1364. ; one. NOTE that the backspacing will stop at left hand margin.
  1365. ;
  1366. put$bs:
  1367.     lda    lcd$x
  1368.     ora    a            ; At zero ?
  1369.     jrz    put$end
  1370.     dcr    a
  1371.     sta    lcd$x            ; Save the new decremented column
  1372.     jmp    put$lf$cur        ; Cursor address now.
  1373. ;
  1374.     page
  1375. ;----------------------------------------------------------------
  1376. ;    P R I N T E R    I / O    D R I V E R S
  1377. ;----------------------------------------------------------------
  1378. ;
  1379. prn$ini:    
  1380. prn$ost:
  1381. prn$cmd:
  1382. prn$out:
  1383.     ret
  1384. ;
  1385.     page
  1386. ;----------------------------------------------------------------
  1387. ;        A U X    P O R T    R O U T I N E S
  1388. ;
  1389. ; Initialize the AUX Port hardware
  1390. ;
  1391. ; Setup AUX comms port to be
  1392. ;     1200 baud
  1393. ;          8 bit
  1394. ;          1 stop
  1395. ;         NO parity
  1396. ;----------------------------------------------------------------
  1397. ;
  1398. aux$ini:
  1399.     lxi    h,aux$initbl
  1400. aux$initlp:
  1401.     mov    b,m            ; get counter
  1402.     inx    h
  1403.     mov    c,m            ; get port    
  1404.     mov    a,b
  1405.     ora    a            ; check for zero
  1406.     jrz    aux$inictc        ; exit if count=0
  1407.     inx    h
  1408.     outir                ; send all out
  1409.     jr    aux$initlp
  1410. ;
  1411. aux$inictc:
  1412.     mvi    a,02h            ; Reset channel
  1413.     out    @ctc1
  1414. ;
  1415.     nop
  1416.     nop
  1417. ;
  1418. ;
  1419.     mvi    a,045h            ; Time constant follows
  1420.     out    @ctc1
  1421.     nop
  1422.     mvi    a,104            ; For 1200 baud
  1423.     out    @ctc1
  1424. ;
  1425.     ret
  1426. ;
  1427. ;----------------------------------------------------------------
  1428. ;         Aux output
  1429. ;
  1430. ; Xon/Xoff handshaking done here. Check on entry for a code back
  1431. ; from printer and if so, wait for another to re-start. Also, for
  1432. ; safety, have a timeout.
  1433. ;----------------------------------------------------------------
  1434. ;
  1435. aux$out:
  1436.     push    psw
  1437. ;
  1438.     if    aux$xonof        ; Allowed to Xon/Xoff are we??
  1439.     call    aux$ist            ; Character there ?
  1440.     jrz    aux$wait        ; Nothing = no bother
  1441. ;
  1442. ; We have a character
  1443.     call    aux$inp
  1444.     cpi    'S' and 01fh
  1445.     jrnz    aux$wait
  1446. ; We have an Xoff. Wait for Xon.
  1447. ;
  1448.     push    h
  1449.     lxi    h,4000h
  1450. aux$xon:
  1451.     call    clr$wdt            ; Stop watchdog.
  1452.     call    aux$ist
  1453.     jz    xon$wait
  1454.     call    aux$inp
  1455.     jr    aux$xof
  1456. ;
  1457. xon$wait:
  1458.     dcx    h
  1459.     mov    a,h
  1460.     ora    l            ; HL = 0 ?
  1461.     jnz    aux$xon
  1462. aux$xof:
  1463.     pop    h            ; Restore HL/stack
  1464. ;
  1465.     endif
  1466. ;
  1467. ; -- Send character to aux port --
  1468. ;
  1469. aux$wait:
  1470.     call    clr$wdt
  1471.     in    @stat1
  1472.     ani    txmsk            ; See if transmitter empty.
  1473.     jrz    aux$wait
  1474. ; Ok, send the data out.
  1475.     pop    psw
  1476.     out    @data1
  1477.     ret
  1478. ;
  1479. ;----------------------------------------------------------------
  1480. ;         Aux input
  1481. ;----------------------------------------------------------------
  1482. ;
  1483. aux$inp:
  1484.     call    clr$wdt
  1485.     in    @stat1
  1486.     ani    rxmsk
  1487.     jrz    aux$inp
  1488.     in    @data1
  1489.     ret                ; Done
  1490. ;
  1491. ;----------------------------------------------------------------
  1492. ;         Console status
  1493. ;----------------------------------------------------------------
  1494. ;
  1495. aux$ist:
  1496.     call    clr$wdt            ; Clear the dog
  1497.     in    @stat1
  1498.     ani    rxmsk
  1499.     rz
  1500.     mvi    a,0ffh
  1501.     ret
  1502. ;
  1503. ; Return the aux output status.
  1504. ;
  1505. aux$ost:
  1506.     call    clr$wdt
  1507.     in    @stat1
  1508.     ani    txmsk
  1509.     rz
  1510.     mvi    a,0ffh
  1511.     ret
  1512. ;
  1513. aux$iwr:
  1514. aux$ird:
  1515.     ret
  1516. ;
  1517. ;----------------------------------------------------------------
  1518. ;         Hardware setups for the AUX port chips.
  1519. ;----------------------------------------------------------------
  1520. ;
  1521. aux$initbl:
  1522. ; Setup the dart B channel
  1523.     db    01,@stat1,018h        ; Channel reset
  1524.     db    02,@stat1,04,044h    ; X1 clock, 1 stop bit, parity OFF
  1525.     db    02,@stat1,01,000h    ; Clear internal status
  1526.     db    02,@stat1,03,0c1h    ; Rx 8 bit. Rx enable, auto enables OFF
  1527.     db    02,@stat1,05,0eah    ; DTR, Tx 8 bit, Tx enable, RTS, DTR of
  1528.     db    00
  1529. ;
  1530.     page
  1531. ;----------------------------------------------------------------
  1532. ;    C O N S O L E    R O U T I N E S
  1533. ;
  1534. ;         Initialize the console hardware
  1535. ;
  1536. ; Setup console serial port to be
  1537. ;     9600 baud
  1538. ;          8 bit
  1539. ;          1 stop
  1540. ;         NO parity
  1541. ;----------------------------------------------------------------
  1542. ;
  1543. con$ini:
  1544.     lxi    h,con$initbl
  1545. con$initlp:
  1546.     mov    b,m            ; get counter
  1547.     inx    h
  1548.     mov    c,m            ; get port    
  1549.     mov    a,b
  1550.     ora    a            ; check for zero
  1551.     jrz    con$inictc        ; exit if count=0
  1552.     inx    h
  1553.     outir                ; send all out
  1554.     jr    con$initlp
  1555. ;
  1556. con$inictc:
  1557.     mvi    a,02h            ; Reset channel
  1558.     out    @ctc0
  1559. ;
  1560.     nop
  1561.     nop
  1562. ;
  1563. ;
  1564.     mvi    a,045h            ; Time constant follows
  1565.     out    @ctc0
  1566.     mvi    a,13
  1567.     out    @ctc0
  1568.     ret
  1569. ;
  1570. ;----------------------------------------------------------------
  1571. ;      Hardware setups for the console system chips.
  1572. ;----------------------------------------------------------------
  1573. ;
  1574. con$initbl:
  1575. ; Setup the dart A channel
  1576.     db    01,@stat0,018h        ; Channel reset
  1577.     db    02,@stat0,04,044h    ; X1 clock, 1 stop bit, parity OFF
  1578.     db    02,@stat0,01,000h    ; Clear internal status
  1579.     db    02,@stat0,03,0c1h    ; Rx 8 bit. Rx enable, auto enables OFF
  1580.     db    02,@stat0,05,0eah    ; DTR, Tx 8 bit, Tx enable, RTS, DTR of
  1581.     db    00
  1582. ;
  1583. ;----------------------------------------------------------------
  1584. ;     Read the console serial port error bits.
  1585. ;
  1586. ; On Entry
  1587. ;    nothing required
  1588. ;
  1589. ; On Exit
  1590. ;    A = 0 for no errors
  1591. ;        else same errors as noted in data book.
  1592. ;----------------------------------------------------------------
  1593. ;
  1594. con$err:
  1595.     xra    a
  1596.     ora    a
  1597.     ret
  1598. ;
  1599. ;----------------------------------------------------------------
  1600. ;         Return the console input status.
  1601. ;
  1602. ; The console is the first ASCI serial channel, channel 0
  1603. ;
  1604. ; On Entry
  1605. ;    nothing required
  1606. ;
  1607. ; On Exit
  1608. ;    A = 00 for nothing there
  1609. ;    A = 01 for a character waiting to be read.
  1610. ;----------------------------------------------------------------
  1611. ;
  1612. con$ist:
  1613.     call    clr$wdt            ; Clear the dog
  1614.     in    @stat0
  1615.     ani    rxmsk
  1616.     rz
  1617.     mvi    a,0ffh
  1618.     ret
  1619. ;
  1620. ;----------------------------------------------------------------
  1621. ;         Return the console output status.
  1622. ;
  1623. ; The console is the first ASCI serial channel, channel 0
  1624. ;
  1625. ; On Entry
  1626. ;    nothing required
  1627. ;
  1628. ; On Exit
  1629. ;    A = 00 for transmitter busy
  1630. ;    A = 01 for a character can be sent to transmitter
  1631. ;----------------------------------------------------------------
  1632. ;
  1633. con$ost:
  1634.     in    @stat0
  1635.     ani    txmsk            ; See if transmitter empty.
  1636.     rz
  1637.     mvi    a,0ffh
  1638.     ret
  1639. ;
  1640.     page
  1641. ;----------------------------------------------------------------
  1642. ;         Read a byte from the Console port
  1643. ;
  1644. ; The console is the first ASCI serial channel, channel 0
  1645. ;
  1646. ; On Entry
  1647. ;    nothing required
  1648. ;
  1649. ; On Exit
  1650. ;    A = char for a character waiting to be read.
  1651. ;
  1652. ; note that NO WATCHDOG clears will be done. Careful.
  1653. ;----------------------------------------------------------------
  1654. ;
  1655. con$inp:
  1656.     call    clr$wdt
  1657.     in    @stat0
  1658.     ani    rxmsk
  1659.     jrz    con$inp
  1660.     in    @data0
  1661.     ret                ; Done
  1662. ;
  1663. ;----------------------------------------------------------------
  1664. ; Send the byte in A to the output port. Wait if necessary.
  1665. ;
  1666. ; On Entry
  1667. ;    A = data byte to send
  1668. ;
  1669. ; On Exit
  1670. ;    No changes
  1671. ;
  1672. ;----------------------------------------------------------------
  1673. ;
  1674. con$out:
  1675.     push    psw
  1676. coe$wait:
  1677.     call    clr$wdt
  1678.     in    @stat0
  1679.     ani    txmsk            ; See if transmitter empty.
  1680.     jrz    coe$wait
  1681. ; Ok, send the data out.
  1682.     pop    psw
  1683.     out    @data0
  1684.     ret
  1685. ;
  1686.     page
  1687. ;================================================================
  1688. ;    V I D E O      D R I V E R      R O U T I N E S
  1689. ;================================================================
  1690. ;
  1691. ;     Initializations.
  1692. ;
  1693. ini$vid:
  1694.     xra    a
  1695.     sta    curatt            ; Select attribute 0
  1696.     sta    curvid
  1697.     ret
  1698. ;
  1699. ;================================================================
  1700. ;        Terminal Function Codes
  1701. ;================================================================
  1702. ;
  1703. ; General purpose function codes
  1704. ;
  1705. xyfn:    db    02,01bh,'=',00,00    ; xy addressing
  1706. ;
  1707. rowcol:    db    00            ; 00 means row first
  1708. xoff:    db    32            ; X offset
  1709. yoff:    db    32            ; Y offset
  1710. cdly:    db    01            ; Cursor positioning delay qty
  1711. ;
  1712. cpfn    db    02,01bh,'*',00,00    ; erase whole page
  1713. clfn    db    02,01bh,'T',00,00    ; erase to end of line
  1714. epfn    db    02,01bh,'Y',00,00    ; erase to end of page
  1715. ecfn    db    03,01bh,'.','1',0    ; enable cursor function
  1716. dcfn    db    03,01bh,'.','0',0    ; disable cursor function
  1717. ;
  1718. attset:
  1719.     db    2,01bh,029h,00,00    ; Start half intensity
  1720.     db    2,01bh,05eh,00,00    ; Start blinking
  1721.     db    2,01bh,06ah,00,00    ; Start reverse video
  1722.     db    2,01bh,06ch,00,00    ; Start underline
  1723.     db    4,01bh,029h,01bh,05eh    ; Start half-blinking
  1724.     db    4,01bh,06ah,01bh,05eh    ; Start reverse-blinking
  1725.     db    0,00,00,00,00        ; Start underline
  1726. ;
  1727. attclr:
  1728.     db    02,01bh,028h,00,00    ; End half intensity
  1729.     db    02,01bh,071h,00,00    ; End blinking
  1730.     db    02,01bh,06bh,00,00    ; End reverse video
  1731.     db    02,01bh,06dh,00,00    ; End underline
  1732.     db    4,01bh,071h,01bh,028h    ; End half-blinking
  1733.     db    4,01bh,071h,01bh,06bh    ; End reverse-blinking
  1734.     db    0,00,00,00,00        ; end
  1735. ;
  1736. ;
  1737. ;-----------------
  1738. ; Clear the screen
  1739. ;-----------------
  1740. ;
  1741. clear:
  1742.     push    b
  1743.     push    h            ; save
  1744.     push    psw
  1745.     lxi    h,cpfn            ; clear page function
  1746.     jmp    do$fn            ; send the function and return
  1747. ;
  1748. ;----------------------------------------------------------------
  1749. ; Clear the screen till the end of the line. This is highly
  1750. ; terminal dependant and is table driven to suit.
  1751. ;----------------------------------------------------------------
  1752. ;
  1753. cleol:
  1754.     push    b
  1755.     push    h            ; save
  1756.     push    psw
  1757.     lxi    h,clfn            ; clear page function
  1758.     jr    do$fn            ; send the function and return
  1759. ;
  1760. ;----------------------------------------------------------------
  1761. ; Clear to the end of the page. Same comments as the above fn.
  1762. ;----------------------------------------------------------------
  1763. ;
  1764. cleop:
  1765.     push    b
  1766.     push    h            ; save
  1767.     push    psw
  1768.     lxi    h,epfn            ; clear page function
  1769.     jr    do$fn            ; end of job
  1770. ;
  1771. ;-----------------------------------------------
  1772. ; Set a visual attribute onto the video terminal
  1773. ;         Attribute in register A
  1774. ;-----------------------------------------------
  1775. ;
  1776. setatt:
  1777.     cpi    numatt + 1    ; In range ??
  1778.     rnc            ; Return tail B/N legs if too big
  1779.     push    d
  1780.     push    b
  1781.     push    h
  1782.     push    psw        ; Save the users attribute
  1783.     mov    c,a        ; Save locally also
  1784.     lda    curatt        ; Get the current attribute
  1785.     cmp    c
  1786.     jz    set$fin        ; Terminate if THE SAME
  1787.     ora    a
  1788.     jrz    doatt        ; If 00, no need to clear old one, already 0
  1789. ;
  1790. ; See if the current attribute is an illegal value. This may be because of
  1791. ; rom based software first time through and a silly ram value. 
  1792. ;
  1793.     cpi    numatt + 1
  1794.     jrnc    doatt        ; Silly old attribute, then set new one now.
  1795. ;
  1796. ; Here we must clear the old attribute before proceeding.
  1797. ;
  1798. clr$start:
  1799.     dcr    a        ; Make the attribute in range
  1800.     lxi    h,attclr    ; Point to the table of clear atts.
  1801.     call    index
  1802.     call    att$send    ; Send the attributes -> by HL
  1803. doatt:
  1804.     pop    psw        ; Get users attribute
  1805.     sta    curatt        ; Save in ram.
  1806.     ora    a        ; Is it attribute 00 ?
  1807.     jrz    set$end        ; Ignore if so
  1808.     dcr    a        ; Make in the correct range then
  1809. ; Now index into the table of attribute setting bytes to get the req'd code.
  1810.     lxi    h,attset    ; Point to start
  1811.     call    index        ; Get hl -> start
  1812.     call    att$send    ; Send attributes -> by HL
  1813. ;
  1814. ; Re-load registers and return.
  1815. ;
  1816. set$end:
  1817.     pop    h
  1818.     pop    b
  1819.     pop    d
  1820.     ret
  1821. ;
  1822. ; Restore registers when terminated
  1823. ;
  1824. set$fin:
  1825.     pop    psw
  1826.     jr    set$end
  1827. ;
  1828. ; This routine must use HL -> a counter byte to send
  1829. ; the proceeeding bytes to the console.
  1830. ;
  1831. att$send:    
  1832.     mov    a,m
  1833.     ora    a        ; See if a null length ?
  1834.     rz            ; Return if a null string
  1835.     mov    b,a        ; Else load the length
  1836. sloop:
  1837.     inx    h        ; Point to next character
  1838.     mov    a,m
  1839.     call    con$out        ; Send
  1840.     djnz    sloop
  1841.     ret
  1842. ;
  1843. ;----------------------------------------------------------------
  1844. ; This routine that follows simply indexes into the table 
  1845. ; of bytes. Each table entry is assumed to be 5 bytes long.
  1846. ;
  1847. ; On entry hl -> start of table, on exit hl -> first element 
  1848. ; in line (a)
  1849. ;----------------------------------------------------------------
  1850. ;
  1851. index:    
  1852.     ora    a
  1853.     rz            ; Return if no loops needed
  1854.     mvi    d,0        ; Clear upper register
  1855.     mov    e,a        ; Load counter
  1856. ; Multiply A by 5 then add to HL
  1857.     add    a        ; * 2 (double original)
  1858.     add    a        ; * 4
  1859.     add    e        ; * 5 (add original)
  1860.     mov    e,a        ; load into indexing register
  1861.     dad    d        ; now HL -> start of this entry
  1862.     ret            ; hl -> start of a line
  1863. ;
  1864. ; This routine uses HL to send the function to the screen.
  1865. ;
  1866. send$fn:
  1867.     mov    a,m            ; test if this is not supported
  1868.     ora    a
  1869.     rz                ; not supported if no bytes to send
  1870.     mov    b,a            ; load a counter
  1871. send$fn2:
  1872.     inx    h            ; get next byte
  1873.     mov    a,m
  1874.     call    con$out
  1875.     djnz    send$fn2
  1876.     ret
  1877. ;
  1878. ;----------------------------------------------------------------
  1879. ; Send the function pointed to by HL to the terminal then exit
  1880. ;----------------------------------------------------------------
  1881. ;
  1882. do$fn:
  1883.     call    send$fn            ; send it.
  1884. ; Fall through to the exit routine
  1885. end$fn:
  1886.     pop    psw
  1887.     pop    h
  1888.     pop    b
  1889.     ret
  1890. ;
  1891. ;----------------------------------------------------------------
  1892. ; Position the cursor to the value in DE. D = X, E = Y.
  1893. ;----------------------------------------------------------------
  1894. ;
  1895. cursor:
  1896.     push    b
  1897.     push    h
  1898.     push    psw            ; save registers
  1899.     push    d            ; save the original
  1900. ; Send the lead in string
  1901.     lxi    h,xyfn            ; XY addressing lead in string
  1902.     call    send$fn
  1903. ; Now we must add the offsets to be applied to the X and Y values
  1904.     lda    xoff
  1905.     add    e            ; Y value
  1906.     mov    e,a            ; save it
  1907. ;
  1908.     lda    yoff
  1909.     add    d            ; X value
  1910.     mov    d,a            ; save it also
  1911. ; Now decode the row or column sent first decision
  1912.     lda    rowcol            ; 00 = row first
  1913.     ora    a
  1914.     jrz    row$first
  1915. ; Here and we are sending the column first (X value first)
  1916.     mov    a,d            ; X value
  1917.     call    con$out
  1918.     mov    a,e            ; Y next
  1919.     jr    row$first2
  1920. ; Here and we send the row first for cursor addressing
  1921. row$first:
  1922.     mov    a,e            ; Y value
  1923.     call    con$out
  1924.     mov    a,d            ; X value next
  1925. row$first2:
  1926.     call    con$out
  1927.     pop    d            ; restore original cursor address
  1928. ; Now do any delays required
  1929.     lda    cdly
  1930. cursor$delay:
  1931.     ora    a
  1932.     jrz    end$fn            ; End of job
  1933.     push    psw
  1934.     mvi    a,0ffh            ; Loop counter
  1935. cd$loop:
  1936.     nop                ; Extra waits
  1937.     dcr    a
  1938.     jrnz    cd$loop            ; Loop till A = 0
  1939.     pop    psw
  1940.     dcr    a            ; One done.
  1941.     jr    cursor$delay
  1942. ;
  1943. ;----------------------------------------------------------------
  1944. ;            Write bytes at mDE till a null
  1945. ;----------------------------------------------------------------
  1946. ;
  1947. wrt$vid:
  1948.     ldax    d
  1949.     ora    a
  1950.     rz
  1951.     call    con$out
  1952.     inx    d
  1953.     jr    wrt$vid
  1954. ;
  1955.     dseg
  1956. ;
  1957. curatt    db    00
  1958. curvid    db    00
  1959. ;
  1960. ; -- LCD Data bytes --
  1961. lc$cmd: ds    1        ; Command to write to LCD
  1962. ;
  1963. ;
  1964. err$num ds    1
  1965. lcd$x:    ds    1
  1966. lcd$y:    ds    1
  1967. ;
  1968. bel$byt    db    00            ; Last bell port write
  1969. led$byt    db    00            ; Last LED output byte
  1970. wdt$flg    db    00            ; Dog flag bit 0
  1971. ;
  1972. hrs    ds    1
  1973. min    ds    1
  1974. sec    ds    1
  1975. ;
  1976. ?time:    ds    8            ; Time buffer address
  1977. ;
  1978.     end
  1979. ;
  1980. ;
  1981.