https://github.com/virtualagc/virtualagc
Tip revision: a8d66c8ae3c4d967053e2bfb4298e90182cbeff2 authored by Ron Burkey on 06 March 2024, 12:40:55 UTC
Minor tweaks associated with supporting Skylark 48.
Minor tweaks associated with supporting Skylark 48.
Tip revision: a8d66c8
piPeripheral.agc
# Copyright: Public domain
# Filename: piPeripheral.agc
# Purpose: Code for the short tutorial on AGC bare-metal programming
# from http://www.ibiblio.org/apollo/DIY.html.
# Mod History: 2017-12-07 RSB Wrote.
# 2017-12-09 RSB Added displaying the current time and date
# from input channels 040-042 supplied by the
# template peripheral program (piPeriperal.py)
# when it's used with its --time=1 cli switch.
# 2017-12-24 RSB Added the stuff for supporting --imu and --gps.
# 2017-12-25 RSB Added higher-resolution lat,lon data. Deleted
# the toggling of COMP ACTY on keystroke. Replaced
# use of PRO key for cycling through modes with
# + (for cycling forward) and - (for cycling
# backward).
#
# It extends the simple template program described in the tutorial by
# receiving and displaying various data on input channels for a fake
# peripheral device defined by the program piPeripheral.py, and
# sometimes spitting the unpacked data back out on similarly-defined
# output channels 043-050. The input data supported is
# 1's-complement. Here are the channels, all inputs unless
# explicitly stated otherwise:
# Second Least-significant 6 bits of channel 040
# Minute Next higher 6 bits of channel 040
# (Most-significant 3 bits of channel 040 unused)
# Hour Least-significant 5 bits of channel 041
# Day Next higher 5 bits of channel 041
# Month Next higher 4 bits of channel 041
# (Most-significant bit of channel 041 unused)
# Year Channel 042.
# Mode or year Output channel 043. If the value is <100,
# it is the current display mode, otherwise the
# mode is 0 and it is the year.
# (TBD) Output channels 044-050 contain data that's
# dependent on the display mode, but generally
# reflects what is actually being displayed
# on the DSKY. At present, though, it always
# reflects mode 0 evem for other modes, namely,
# 044 is the month, 045 is the day, 046 is
# the hour, 047 is the minute, and 050 is the
# second. In other modes, they will be something
# else.
# X acceleration Channel 051, mm/sec/sec
# Y acceleration Channel 052, mm/sec/sec
# Z acceleration Channel 053, mm/sec/sec
# X mag field Channel 054, in units of 0.0001 gauss
# Y mag field Channel 055, in units of 0.0001 gauss
# Z mag field Channel 056, in units of 0.0001 gauss
# X gyro Channel 057, in units of 0.1 dps
# Y gyro Channel 060, in units of 0.1 dps
# Y gyro Channel 061, in units of 0.1 dps
# baro pressure Channel 062, in units of 0.1 hPa
# temperature Channel 063, in units of 0.01 degrees C
# latitude10 Channel 064. int(latitude*10)
# longitude10 Channel 065. int(longitude*10)
# altitude Channel 066, meters
# ground speed Channel 067, kph
# bearing Channel 070, 0.1 degrees from true North.
# latitudeFrac Channel 071, int(10000*(fractional part of latitude*10))
# longitudeFrac Channel 072, int(10000*(fractional part of longitude*10))
# ... though actually, for channels 051-063 & 066-072, the values from the input
# ports are simply displayed (after conversion to decimal) as-is, so
# the their interpretations and units aren't enforced by the AGC.
# Note that the X, Y, and Z axes mentioned above are relative to
# the sensor board, and I don't know how that relates to DSKY axes.
# On the DSKY, what is displayed depends on the selected
# display-mode, which you can cycle through with the PRO key. The
# mode is always shown in the PROG area, and is:
# 00 time-display mode
# 01 acceleration-display mode
# 02 magnetometer-display mode
# 03 gyro-display mode
# 04 weather-sensor-display mode
# 05 GPS-location-display mode
# 06 GPS-track-display mode
# 07 High-res latitude display mode
# 08 High-res longitude display mode
# Specifically, here's what's shown on the display in the
# various display modes. For the time-display mode:
# PROG 00
# VERB blank
# NOUN seconds
# R1 hour, minute, separated by a blank
# R2 month, day, separated by a blank
# R3 year, prefixed by a blank
# For the acceleration-display mode:
# PROG 01
# VERB blank
# NOUN blank
# R1 X acceleration mm/sec/sec
# R2 Y acceleration mm/sec/sec
# R3 Z acceleration mm/sec/sec
# For the magnetometer-display mode:
# PROG 02
# VERB blank
# NOUN blank
# R1 X magnetometer 0.0001 gauss
# R2 Y magnetometer 0.0001 gauss
# R3 Z magnetometer 0.0001 gauss
# For the gyro-display mode:
# PROG 03
# VERB blank
# NOUN blank
# R1 X gyro 0.1 dps
# R2 Y gyro 0.1 dps
# R3 Z gyro 0.1 dps
# For the weather-sensor-display mode:
# PROG 04
# VERB blank
# NOUN blank
# R1 pressure 0.1 hPa
# R2 temperature 0.01 degrees C
# R3 blank
# For the GPS-location-display mode:
# PROG 05
# VERB blank
# NOUN blank
# R1 latitude, XX.XX
# R2 longitude, XXX.XX
# R3 altitude, meters
# For the GPS-track-display mode:
# PROG 06
# VERB blank
# NOUN blank
# R1 ground speed, kph
# R2 direction, 0.1 degrees from true North
# R3 blank
# For the hi-res-latitude-display mode:
# PROG 07
# VERB blank
# NOUN blank
# R1 latitude, XX
# R2 latitude, .XXXXX
# R3 longitude, XXX.XX
# For the hi-res-longitude-display mode:
# PROG 08
# VERB blank
# NOUN blank
# R1 latitude, XX.XXX
# R2 latitude, XXX
# R3 longitude, .XXXXX
# The output channels used are:
# Year Channel 043
# Month Channel 044
# Day Channel 045
# Hour Channel 046
# Minute Channel 047
# Second Channel 050
# The piPeripheral.py template for peripheral programs provides and interprets
# this additional data if its --time=1 command-line switch is used.
# Special registers.
A EQUALS 0
L EQUALS 1 # L AND Q ARE BOTH CHANNELS AND REGISTERS.
Q EQUALS 2
EBANK EQUALS 3
FBANK EQUALS 4
Z EQUALS 5 # ADJACENT TO FBANK AND BBANK FOR DXCH Z
BBANK EQUALS 6 # (DTCB) AND DXCH FBANK (DTCF).
# REGISTER 7 IS A ZERO-SOURCE, USED BY ZL.
ARUPT EQUALS 10 # INTERRUPT STORAGE.
LRUPT EQUALS 11
QRUPT EQUALS 12
SAMPTIME EQUALS 13 # SAMPLED TIME 1 & 2.
ZRUPT EQUALS 15 # (13 AND 14 ARE SPARES.)
BANKRUPT EQUALS 16 # USUALLY HOLDS FBANK OR BBANK.
BRUPT EQUALS 17 # RESUME ADDRESS AS WELL.
CYR EQUALS 20
SR EQUALS 21
CYL EQUALS 22
EDOP EQUALS 23 # EDITS INTERPRETIVE OPERATION CODE PAIRS.
TIME2 EQUALS 24
TIME1 EQUALS 25
TIME3 EQUALS 26
TIME4 EQUALS 27
TIME5 EQUALS 30
TIME6 EQUALS 31
SETLOC 67
NEWJOB ERASE # Allocate a variable at the location checked by the Night Watchman.
# More variables.
KEYBUF ERASE # 040 when empty, 0-037 when holding a keycode
LAST040 ERASE # Most recent value from input channel 040.
SECOND ERASE # Storage for components of time
MINUTE ERASE
HOUR ERASE
DAY ERASE
MONTH ERASE
YEAR ERASE
SIGN ERASE # For buffering sign+digits in conversion of integer to decimal string.
DIGIT1 ERASE
DIGIT2 ERASE
DIGIT3 ERASE
DIGIT4 ERASE
DIGIT5 ERASE
SIGNA ERASE # For buffering sign+digits in conversion of integer to decimal string.
DIGIT1A ERASE
DIGIT2A ERASE
DIGIT3A ERASE
DIGIT4A ERASE
DIGIT5A ERASE
DSPR ERASE # Return address for DSPxxxx functions.
DIGIT25 ERASE
DIGIT31 ERASE
DIVISOR ERASE # A dummy variable used to store divisors.
DSPMODE ERASE # display-mode: 0 time, 1 acceleration, 2 magnetometer, etc.
LLLOW ERASE # LS word of lat or lon
LLHIGH ERASE # MS word of lat or lon.
LLRET ERASE # Return address for LL2.
SETLOC 4000 # The interrupt-vector table.
# Come here at power-up or GOJAM
INHINT # Disable interrupts for a moment.
# Set up the TIME3 interrupt, T3RUPT. TIME3 is a 15-bit
# register at address 026, which automatically increments every
# 10 ms, and a T3RUPT interrupt occurs when the timer
# overflows. Thus if it is initially loaded with 037774,
# and overflows when it hits 040000, then it will
# interrupt after 40 ms.
CA O37774
TS TIME3
TCF STARTUP # Go to your "real" code.
RESUME # T6RUPT
NOOP
NOOP
NOOP
RESUME # T5RUPT
NOOP
NOOP
NOOP
DXCH ARUPT # T3RUPT
EXTEND # Back up A, L, and Q registers
QXCH QRUPT
TCF T3RUPT
RESUME # T4RUPT
NOOP
NOOP
NOOP
DXCH ARUPT # KEYRUPT1
EXTEND # Back up A, L, and Q registers
QXCH QRUPT
TCF KEYRUPT
DXCH ARUPT # KEYRUPT2
EXTEND # Back up A, L, and Q registers
QXCH QRUPT
TCF KEYRUPT
RESUME # UPRUPT
NOOP
NOOP
NOOP
RESUME # DOWNRUPT
NOOP
NOOP
NOOP
RESUME # RADAR RUPT
NOOP
NOOP
NOOP
RESUME # RUPT10
NOOP
NOOP
NOOP
# The interrupt-service routine for the TIME3 interrupt every 40 ms.
T3RUPT CAF O37774 # Schedule another TIME3 interrupt in 40 ms.
TS TIME3
# And resume the main program
DXCH ARUPT # Restore A, L, and Q, and exit the interrupt
EXTEND
QXCH QRUPT
RESUME
# Interrupt-service code for DSKY keycode
KEYRUPT EXTEND
READ 15 # Read the DSKY keycode input channel
MASK O37 # Get rid of all but lowest 5 bits.
TS KEYBUF # Save the keycode for later.
CA ZERO # Clear the input channel.
EXTEND
WRITE 15
DXCH ARUPT # Restore A, L, and Q, and exit the interrupt
EXTEND
QXCH QRUPT
RESUME
STARTUP RELINT # Reenable interrupts.
# Initialization
CA NOKEY # Clear the keypad buffer variable
TS KEYBUF # to initially hold an illegal keycode.
CA ZERO
TS DSPMODE # Display mode.
# Prepare the display in mode 0
TC BLANKALL # Completely blank the display
CA DSPMODE # Write the display mode to PROG.
TC DSPPROG
EXTEND
READ 40
TS LAST040
MAINLOOP CS NEWJOB # Tickle the Night Watchman.
#----------------------------------------------------------------------
# Check if there's a keycode ready, and process the keycode
# if there is.
CA NOKEY
XCH KEYBUF # Mark keycode buffer as empty and get keycode into A.
INDEX A
TCF KEYTABL
KEYTABL TCF ENDKYCK # unused
TCF ENDKYCK # 1
TCF ENDKYCK # 2
TCF ENDKYCK # 3
TCF ENDKYCK # 4
TCF ENDKYCK # 5
TCF ENDKYCK # 6
TCF ENDKYCK # 7
TCF ENDKYCK # 8
TCF ENDKYCK # 9
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # 0
TCF ENDKYCK # VERB
TCF ENDKYCK # RSET
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # unused
TCF ENDKYCK # KEY REL
TCF DSPMODE+ # +
TCF DSPMODE- # -
TCF ENDKYCK # ENTR
TCF ENDKYCK # unused
TCF ENDKYCK # CLR
TCF ENDKYCK # NOUN
TCF ENDKYCK # NOKEY
DSPMODE+ CA DSPMODE # Increment display mode.
AD ONE
TS DSPMODE
AD MINUS8 # Check for wraparound
EXTEND
BZMF RETRIG # No wraparound
CA ZERO # Wraparound to 0.
TS DSPMODE
TCF RETRIG
DSPMODE- CA DSPMODE # Decrement display mode.
EXTEND # but pre-check for wraparound.
BZF WILLWRAP
AD MINUS1
TS DSPMODE
TCF RETRIG
WILLWRAP CA EIGHT
TS DSPMODE
TCF RETRIG
RETRIG CA MINUS1 # Trigger immediate redisplay.
TS LAST040
TCR BLANKALL
ENDKYCK NOOP
#----------------------------------------------------------------------
# We've now handled the keystrokes, so we need to update the display.
# However, we only do that when data is changed. We are guaranteed
# by our bogus piPeripheral device that all of the input channels we're
# interested in just change once per second, and that the LAST channel
# written is 040. So we only do something when we see that 040 has
# changed, and we know at that point that we have an entire second
# to handle our business.
CA LAST040
EXTEND
RXOR 40 # XOR last reading of channel 040 with current value.
EXTEND
BZF MAINLOOP # Hasn't changed, so just keep looping.
EXTEND
READ 40
TS LAST040
CA DSPMODE
TCR DSPPROG
# Okay, input-channel 040 has changed, so all other input channels
# are ripe for the plucking. Proceed with displaying.
# But exactly what we need to do along those lines depends on the
# display mode, which we handle with a jump-table. Note that
# 0 <= DSPMODE <= 8.
INDEX DSPMODE # JUMP!
TCF MODETABL
MODETABL TCF MODE0
TCF MODE1
TCF MODE2
TCF MODE3
TCF MODE4
TCF MODE5
TCF MODE6
TCF MODE7
TCF MODE8
#----------------------------------------------------------------------
# Display-mode 0.
# We now know that the time has changed. Unpack the time
# data to get and save year/month/day/hour/minute/second.
# Division is tricky. The dividend is double precision (2 words)
# and the divisor is single-precision (1 word). Put the MSW
# of the dividend (in our case always 0) in A and the LSW
# into L. Moreover, the divisor must be in erasable memory
# (and not just that, but the 10 address-bit subset of erasable
# memory).
MODE0 CA LAST040
TS L # Minutes,seconds are quotient,remainder of (channel 040)/64.
CA D64
TS DIVISOR
CA ZERO
EXTEND
DV DIVISOR
TS MINUTE
CA L
TS SECOND
EXTEND
READ 41 # Get months,days,hours from (channel 041).
TS L
CA D1024
TS DIVISOR
CA ZERO
EXTEND
DV DIVISOR # A is now months and L is days,hours
TS MONTH
CA D32
TS DIVISOR
CA ZERO
EXTEND
DV DIVISOR
TS DAY
CA L
TS HOUR
EXTEND
READ 42 # Get year
TS YEAR
# Now display date&time on DSKY. Also, at least for
# testing purposes, spit it back on output
# channels 043-050.
CA YEAR
EXTEND
WRITE 43
TCR DSPR3Y # Display digits for year.
CA MONTH
EXTEND
WRITE 44
CA DAY
EXTEND
WRITE 45
TCR DSPR2MD # Display digits for month, day.
CA HOUR
EXTEND
WRITE 46
CA MINUTE
EXTEND
WRITE 47
TCR DSPR1HM # Display digits for hour, minute
CA SECOND
EXTEND
WRITE 50
TCR DSPNOUN
ENDTMCK NOOP
TCF MAINLOOP
#----------------------------------------------------------------------
# Display-mode 1.
MODE1 EXTEND
READ 051
TC DSPR1
EXTEND
READ 052
TC DSPR2
EXTEND
READ 053
TC DSPR3
TCF MAINLOOP
#----------------------------------------------------------------------
# Display-mode 2.
MODE2 EXTEND
READ 054
TC DSPR1
EXTEND
READ 055
TC DSPR2
EXTEND
READ 056
TC DSPR3
TCF MAINLOOP
#----------------------------------------------------------------------
# Display-mode 3.
MODE3 EXTEND
READ 057
TC DSPR1
EXTEND
READ 060
TC DSPR2
EXTEND
READ 061
TC DSPR3
TCF MAINLOOP
#----------------------------------------------------------------------
# Display-mode 4.
MODE4 EXTEND
READ 062
TC DSPR1
EXTEND
READ 063
TC DSPR2
TCF MAINLOOP
#----------------------------------------------------------------------
# Display-mode 5.
MODE5 EXTEND # Process latitude.
READ 064
TS LLHIGH
EXTEND
READ 071
TS LLLOW
TCR LL2
TCR DIG2R1 # Display in R1.
EXTEND # Process longitude.
READ 065
TS LLHIGH
EXTEND
READ 072
TS LLLOW
TCR LL2
TCR DIG2R2 # Display in R2.
EXTEND # Process altitude
READ 066
TC DSPR3
TCF MAINLOOP
#----------------------------------------------------------------------
# Display-mode 6.
MODE6 EXTEND
READ 067
TC DSPR1
EXTEND
READ 070
TC DSPR2
TCF MAINLOOP
#----------------------------------------------------------------------
# Display-mode 7.
MODE7 EXTEND # Process latitude.
READ 064
TS LLHIGH
EXTEND
READ 071
TS LLLOW
TCR LL5
TCR DIG2R1 # Display in R1.
TCR A2DIG
TCR DIG2R2
EXTEND # Process longitude.
READ 065
TS LLHIGH
EXTEND
READ 072
TS LLLOW
TCR LL2
TCR DIG2R3 # Display in R2.
TCF MAINLOOP
#----------------------------------------------------------------------
# Display-mode 8.
MODE8 EXTEND # Process latitude.
READ 064
TS LLHIGH
EXTEND
READ 071
TS LLLOW
TCR LL2
TCR DIG2R1 # Display in R1.
EXTEND # Process longitude.
READ 065
TS LLHIGH
EXTEND
READ 072
TS LLLOW
TCR LL5
TCR DIG2R2 # Display in R2.
TCR A2DIG
TCR DIG2R3
TCF MAINLOOP
#######################################################################################################################################
# This ends the main loop, which continues forever, so we can put other functions
# below this point.
# Blank all of the numerical displays.
BLANKALL CA OPCODEP
EXTEND
WRITE 10
CA OPCODEV
EXTEND
WRITE 10
CA OPCODEN
EXTEND
WRITE 10
CA OPCODR11
EXTEND
WRITE 10
CA OPCDR123
EXTEND
WRITE 10
CA OPCDR145
EXTEND
WRITE 10
CA OPCDR212
EXTEND
WRITE 10
CA OPCDR234
EXTEND
WRITE 10
CA OPR25R31
EXTEND
WRITE 10
CA OPCDR323
EXTEND
WRITE 10
CA OPCDR345
EXTEND
WRITE 10
CA ZERO
TS DIGIT31
TS DIGIT25
RETURN
# Convert an integer in the accumulator to SIGN/DIGIT1/.../DIGIT5. At the end, all 5 DIGITx
# variables will have values from 0-9, and SIGN will be 0 for + or 1 for -. Note: calls no
# other routines.
CONV10 TS L # Save the argument
EXTEND
BZF CONV10Z # Argument is 0.
EXTEND
BZMF CONV10M # Argument is negative, we'll need to invert
CONV10Z CA ZERO # Record the sign as positive (0 -> SIGN).
TS SIGN
CONV10P CA TEN
TS DIVISOR
CA ZERO # Note that L still contains the original argument.
EXTEND
DV DIVISOR
LXCH A # Save remainder as digit 5 and put quotient into L.
TS DIGIT5
CA ZERO
EXTEND
DV DIVISOR
LXCH A
TS DIGIT4
CA ZERO
EXTEND
DV DIVISOR
LXCH A
TS DIGIT3
CA ZERO
EXTEND
DV DIVISOR
LXCH A
TS DIGIT2
CA ZERO
EXTEND
DV DIVISOR
LXCH A
TS DIGIT1
RETURN
# Lat an lon are each input on two input channels, a more-significant one containing the integer part of
# the value times 10, and a less-significant on containing the fractional part of the value times 10, times
# 10000. The LL2 function assumes that those values have been stored in variables called LLHIGH and LLLOW,
# respectively, and create SIGN, DIGIT1, ..., DIGIT5 containing the value in the form +/- XXX.XX.
LL2 EXTEND
QXCH LLRET
CA LLLOW # Process LS word
TCR CONV10 # Convert to (SIGN, DIGIT1, ..., DIGIT5)
TCR PATT5DIG
TCR DIG2A # Move SIGN/DIGITx to SIGNA/DIGITxA
CA LLHIGH # Process MS word
TCR CONV10 # Convert to SIGN/DIGITx
TCR PATT5DIG
CA DIGIT2 # Rearrange the DIGITx values somewhat. (Multiply by 10.)
TS DIGIT1
CA DIGIT3
TS DIGIT2
CA DIGIT4
TS DIGIT3
CA DIGIT5
TS DIGIT4
CA DIGIT2A
TS DIGIT5
EXTEND
QXCH LLRET
RETURN
# Similarly, the LL5 function puts the integral lat or lon in SIGN,DIGITx and 5 decimal places in SIGNA,DIGITxA.
LL5 EXTEND
QXCH LLRET
CA LLLOW # Process LS word
TCR CONV10 # Convert to (SIGN, DIGIT1, ..., DIGIT5)
TCR PATT5DIG
TCR DIG2A # Move SIGN/DIGITx to SIGNA/DIGITxA
CA LLHIGH # Process MS word
TCR CONV10 # Convert to SIGN/DIGITx
TCR PATT5DIG
CA DIGIT5 # Rearrange the DIGITx values somewhat. (Divide by 10.)
TS DIGIT1A
CA DIGIT4
TS DIGIT5
CA DIGIT3
TS DIGIT4
CA DIGIT2
TS DIGIT3
CA DIGIT1
TS DIGIT2
EXTEND
QXCH LLRET
RETURN
# Transfer set of SIGN/DIGITx to SIGNA/DIGITxA
DIG2A CA SIGN
TS SIGNA
CA DIGIT1
TS DIGIT1A
CA DIGIT2
TS DIGIT2A
CA DIGIT3
TS DIGIT3A
CA DIGIT4
TS DIGIT4A
CA DIGIT5
TS DIGIT5A
RETURN
# ... and vice-versa.
A2DIG CA SIGNA
TS SIGN
CA DIGIT1A
TS DIGIT1
CA DIGIT2A
TS DIGIT2
CA DIGIT3A
TS DIGIT3
CA DIGIT4A
TS DIGIT4
CA DIGIT5A
TS DIGIT5
RETURN
# The argument was negative. Must invert.
CONV10M CA ONE # Record the sign as negative (1 -> SIGN).
TS SIGN
CA L # Invert the argument to make it positive.
COM
TS L
TCF CONV10P # Go back to the processing for positive numbers.
# Packs two digits previously formed by CONV10 into a suitable
# form for output. The channel 10 opcode has to be added in afterward.
# Suitable for PROG, VERB, and NOUN areas. Result returned in A.
# Note: calls no other routines.
PACK2DIG CA DIGIT5
INDEX A
CA DIGPATTS
TS DIGIT5
CA DIGIT4
INDEX A
CA DIGPATTS
TS DIGIT4
EXTEND
MP D32 # Shift by 5 places.
CA DIGIT5
AD L
RETURN
# Convert DIGIT1 ... DIGIT5 to their DSKY patterns. Note: calls no other
# routines.
PATT5DIG CA DIGIT1
INDEX A
CA DIGPATTS
TS DIGIT1
CA DIGIT2
INDEX A
CA DIGPATTS
TS DIGIT2
CA DIGIT3
INDEX A
CA DIGPATTS
TS DIGIT3
CA DIGIT4
INDEX A
CA DIGPATTS
TS DIGIT4
CA DIGIT5
INDEX A
CA DIGPATTS
TS DIGIT5
RETURN
# Display the number in the accumulator as decimal in DSKY PROG
DSPPROG EXTEND
QXCH DSPR
TCR CONV10
TCR PACK2DIG
AD OPCODEP
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Display the number in the accumulator as decimal in DSKY VERB
DSPVERB EXTEND
QXCH DSPR
TCR CONV10
TCR PACK2DIG
AD OPCODEV
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Display the number in the accumulator as decimal in DSKY NOUN
DSPNOUN EXTEND
QXCH DSPR
TCR CONV10
TCR PACK2DIG
AD OPCODEN
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Display the number in the accumulator as decimal in DSKY R1.
DSPR1 EXTEND
QXCH DSPR
TCR CONV10
TCR PATT5DIG
EXTEND
QXCH DSPR
# Fall through to DIG2R1.
# Display the number in SIGN/DIGITx in DSKY R1
DIG2R1 EXTEND
QXCH DSPR
CA DIGIT1 # First write DIGIT1
AD OPCODR11
EXTEND
WRITE 10
CA DIGIT2 # Next, DIGIT2 and DIGIT3
EXTEND
MP D32
CA DIGIT3
ADS L
CA OPCDR123
ADS L
CA SIGN
EXTEND
BZF DSPR1POS
TCF DSPR1NPS
DSPR1POS CA SIGNBIT
ADS L
DSPR1NPS CA L
EXTEND
WRITE 10
CA DIGIT4 # And finally, DIGIT4 and DIGIT5
EXTEND
MP D32
CA DIGIT5
ADS L
CA OPCDR145
ADS L
CA SIGN
EXTEND
BZF DSPR1NNG
CA SIGNBIT
ADS L
DSPR1NNG CA L
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Display the number in the accumulator as decimal in DSKY R2
DSPR2 EXTEND
QXCH DSPR
TCR CONV10
TCR PATT5DIG
EXTEND
QXCH DSPR
# Fall through to DIG2R2.
# Display the number in SIGN/DIGITx in DSKY R2
DIG2R2 EXTEND
QXCH DSPR
CA DIGIT5 # Save DIGIT5 for DSPR3 routine.
TS DIGIT25
CA DIGIT1 # First, DIGIT1 and DIGIT2
EXTEND
MP D32
CA DIGIT2
ADS L
CA OPCDR212
ADS L
CA SIGN
EXTEND
BZF DSPR2POS
TCF DSPR2NPS
DSPR2POS CA SIGNBIT
ADS L
DSPR2NPS CA L
EXTEND
WRITE 10
CA DIGIT3 # Next, DIGIT3 and DIGIT4
EXTEND
MP D32
CA DIGIT4
ADS L
CA OPCDR234
ADS L
CA SIGN
EXTEND
BZF DSPR2NNG
CA SIGNBIT
ADS L
DSPR2NNG CA L
EXTEND
WRITE 10
CA DIGIT5 # Finally, DIGIT5 (and R3 DIGIT1)
EXTEND
MP D32
CA DIGIT31
AD L
AD OPR25R31
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Display the number in the accumulator as decimal in DSKY R3
DSPR3 EXTEND
QXCH DSPR
TCR CONV10
TCR PATT5DIG
EXTEND
QXCH DSPR
# Fall through to DIG2R3.
# Display the number in SIGN/DIGITx in DSKY R3
DIG2R3 EXTEND
QXCH DSPR
CA DIGIT1 # Save DIGIT1 for DSPR2 routine.
TS DIGIT31
CA DIGIT25 # First, (R2 DIGIT5 and) DIGIT1
EXTEND
MP D32
CA DIGIT1
AD L
AD OPR25R31
EXTEND
WRITE 10
CA DIGIT2 # Next, DIGIT2 and DIGIT3
EXTEND
MP D32
CA DIGIT3
ADS L
CA OPCDR323
ADS L
CA SIGN
EXTEND
BZF DSPR3POS
TCF DSPR3NPS
DSPR3POS CA SIGNBIT
ADS L
DSPR3NPS CA L
EXTEND
WRITE 10
CA DIGIT4 # And finally, DIGIT4 and DIGIT5
EXTEND
MP D32
CA DIGIT5
ADS L
CA OPCDR345
ADS L
CA SIGN
EXTEND
BZF DSPR3NNG
CA SIGNBIT
ADS L
DSPR3NNG CA L
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Display the number in YEAR as a year in DSKY R3. (Similar to
# DSPR3, except no sign bit, and first digit is blank.)
DSPR3Y EXTEND
QXCH DSPR
CA YEAR
TCR CONV10
TCR PATT5DIG
CA ZERO # Save first digit (a blank) for DSPR2 routine.
TS DIGIT31
CA DIGIT25 # First, (R2 DIGIT5 and) DIGIT1 (blank)
EXTEND
MP D32
CA ZERO
AD L
AD OPR25R31
EXTEND
WRITE 10
CA DIGIT2 # Next, DIGIT2 and DIGIT3
EXTEND
MP D32
CA DIGIT3
AD L
AD OPCDR323
EXTEND
WRITE 10
CA DIGIT4 # And finally, DIGIT4 and DIGIT5
EXTEND
MP D32
CA DIGIT5
AD L
AD OPCDR345
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Display the numbers in MONTH and DAY as two 2-digit fields in DSKY R2.
DSPR2MD EXTEND
QXCH DSPR
CA MONTH
TCR CONV10
TCR PACK2DIG
AD OPCDR212
EXTEND
WRITE 10
CA DAY
TCR CONV10
CA DIGIT5
INDEX A
CA DIGPATTS
TS DIGIT5
CA DIGIT4
INDEX A
CA DIGPATTS
AD OPCDR234
EXTEND
WRITE 10
CA DIGIT5
TS DIGIT25
EXTEND
MP D32
CA L
AD DIGIT31
AD OPR25R31
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Display the numbers in HOUR and MINUTE as two 2-digit fields in DSKY R1.
DSPR1HM EXTEND
QXCH DSPR
CA HOUR
TCR CONV10
CA DIGIT4
INDEX A
CA DIGPATTS
AD OPCODR11
EXTEND
WRITE 10
CA DIGIT5
INDEX A
CA DIGPATTS
EXTEND
MP D32
CA L
AD OPCDR123
EXTEND
WRITE 10
CA MINUTE
TCR CONV10
TCR PACK2DIG
AD OPCDR145
EXTEND
WRITE 10
EXTEND
QXCH DSPR
RETURN
# Define any constants that are needed.
O37774 OCT 37774
ZERO OCT 0
ONE OCT 1
TWO OCT 2
FOUR OCT 4
EIGHT DEC 8
MINUS1 DEC -1
MINUS8 DEC -8
TEN DEC 10
O37 OCT 37 # Mask with lowest 5 bits set.
O77 OCT 77 # Mask with lowest 6 bits set.
NOKEY OCT 40
D32 DEC 32
D64 DEC 64
D1024 DEC 1024
OPCODEP DEC 11 B11
OPCODEV DEC 10 B11
OPCODEN DEC 9 B11
OPCODR11 DEC 8 B11
OPCDR123 DEC 7 B11
OPCDR145 DEC 6 B11
OPCDR212 DEC 5 B11
OPCDR234 DEC 4 B11
OPR25R31 DEC 3 B11
OPCDR323 DEC 2 B11
OPCDR345 DEC 1 B11
SIGNBIT DEC 1 B10
# DSKY digit patterns for the digit 0-9.
DIGPATTS DEC 21
DEC 3
DEC 25
DEC 27
DEC 15
DEC 30
DEC 28
DEC 19
DEC 29
DEC 31