HP Forums
Alarm (Relative) Timer Manager - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (/forum-10.html)
+--- Forum: HP-41C Software Library (/forum-11.html)
+--- Thread: Alarm (Relative) Timer Manager (/thread-9831.html)



Alarm (Relative) Timer Manager - Bill Duncan - 01-01-2018 08:09 PM

Background

A few years ago I was approached by Kevin Viney to help in designing a better
way to manage timer alarms. He wanted a system that could set relative timer
alarms and manage them. He'd seen my previous "Time Manager" program and
thought that a similar arrangement for local label keys would work.

Time Manager

We collaborated in designing the following system.

Features
Uses local label keys and can manage 10 relative alarm timers. They can be
individually started when entered, or can be set up ahead of time and started
simultaneously. There are display functions that show time remaining on each,
or a short form display that shows which timers are active with the time
remaining to the next one.

User Keys
Code:

  A-J   Set or Display information on individual timers
  a     Toggle start at once mode, default is to ask
  b     Start timers which are set up but not running yet
  c     Short form display active timers and remaining time to next
  d     Display information on all active timers
  e     Erase all active timers

Flags
Code:

  00   Start immediate if set (don't ask, just start running)
  01   Set if you want original relative time set for display
  02   Enter minutes instead of HMS mode
  04   Used to initiate clearing function, timer came due and need to clear
  10   Internal use in several places
  11   Autoexecute before turning off, by pressing [R/S] when title showing.

Registers
Code:

  00     Set epoch date that we use for all relative time calculations
  01-10  Relative time set, negative if timer set but inactive
  11-20  Alpha labels
  21-30
  31     index to R01-R10
  32     index to alpha names in R11-R20
  33     index, store HR since epoch in R21-R30

Usage
Before setting any timers, be sure to use the "e" function to erase registers
and set the epoch date in R00.

To set a timer, press any of the "A" through "J" keys to set the corresponding
timer. If flag 00 is clear (default), it will ask if you want to start the
timer right away, just press R/S to do so. If you don't, it will save the
information and you can start it later by pressing the key again, or by pressing
the "b" key to start all timers that have been set up but not activated.

By default, timers are named "T1" through "T10", but you can change the names
in alpha mode when setting them up.

The "c" routine will give you a short form display of timer numbers that have
been set up. If they have a period after the number they are active. This
display routine will also show the next timer name that is due and the time
remaining.

The "d" display routine is a long form displaying information about all active
timers. Timers that are set up but not activated will have "N/A" for remaining
time.

The "e" routine should be used before prior to setting any timers and resets
all.

Pressing R/S from anywhere should get you to the top of the loop and show
the "MULTI-TIMER" display. Pressing R/S once more will set auto execute
and turn the calculator off.

Bugz and Warts
This will currently work with the HP-41CX as the CLRALMS function isn't availble
with the timer module. Perhaps there might be a way to simulate that instruction
with some synthetic program subroutine?

Cancelling individual alarms by using "XEQ" and "A" through "J" (01-10) sorta
works, but leaves the program timer activated. This timer is set simply to
set flag 04 to do cleanup work when a timer goes off. Not optimal. This also
has the side effect of sometimes showing "//MTIM" as the next available alarm
with the "c" display.

Side effect is that statistics register is left at R34. Don't forget to reset
if you want it left pointing to another register.

There may be other bugz that I haven't discovered yet.. Wink

Please let me know if you find any or have suggestions for improvements!

Code

Code:

# ------------------------------------------------------------------------------
# Start
# ------------------------------------------------------------------------------

LBL "MTIM6"                # main program start
  CF 21
  "V0.6"                    # identification, executed once on autostart
  AVIEW                     # if loaded from tape, cards or file
  MDY
  CLK24
  ΣREG 34               # make sure these registers do not interfere!!
LBL 99                    # everything loops back here
  FS?C 04                 # was FS? 04
    XEQ 90
  AOFF
  CF 21                   # we don't want aview to stop
  CF 22                   # clear data entry
  CF 25
  SF 27                   # set user mode
  SF 29                   # show dot on fix 0
  FIX 4                   # normal, or fix 4
  "MULTI-TIMER"           # display prompt -or- alternate "ON THE CLOCK"
  PROMPT                  # just press R/S to turn off
  SF 11
  OFF              # set for auto execute and turn off
GTO 99

# ------------------------------------------------------------------------------
# Jump here for the time critical timer toggle keys
# The forward search should take minimal time, since we're stopped
# just above.
# ------------------------------------------------------------------------------

LBL "A" 1 GTO 11
LBL "B" 2 GTO 11
LBL "C" 3 GTO 11
LBL "D" 4 GTO 11
LBL "E" 5 GTO 11
LBL "F" 6 GTO 11
LBL "G" 7 GTO 11
LBL "H" 8 GTO 11
LBL "I" 9 GTO 11
LBL "J" 10              # GTO 11 not needed here.  fall through...

# ------------------------------------------------------------------------------
# All timer toggle keys A-J funnel through here...
# ------------------------------------------------------------------------------
LBL 11
  XEQ 23        # stash numbers
  RCL IND X
  X<0?          # if data entered but not running
    GTO 00      # jump to ask to START
  X#0?          # test if X not equal to zero
    GTO 12      # Just display what's there
  RDN           # get rid of zero, timer num in X
  "TIM/NAM? R/S"
  AVIEW
  FIX 0
  CF 29
  "T"
  ARCL 31
  FIX 4          # put normal back for data entry
  SF 29
  STOP
  FC?C 22        # test for data entry
    GTO 11       # go back if nothing entered
  # we have a number
  FS? 02         # if minute mode
    XEQ 61       #   change to hh.mmss
  FC? 00
    CHS          # store negative number if in default mode
  STO IND 31
  ASTO IND 32
LBL 00
  "START? R/S"   # prompt
  FC? 00
    AVIEW          # display if default mode, otherwise skip
  CLA
  ARCL IND 32    # get alpha name back before setting alarm
  FC? 00         # default is to pause
    STOP
  ABS            # if we get here, we are going through with it
  STO IND 31     # store positive value
  XEQ 60         # set the alarm, now returns with HR since Epoch
  RCL 31
  20
  +
  X<>Y
  STO IND Y     # store HR since epoch in R21-R30
GTO 99          # back to top

LBL 23          # stash timer number and indirect register with name
  STO 31
  STO 32
  STO 33
  10
  ST+ 32
  ST+ 33
  ST+ 33
  RDN
RTN

# Display Routine
LBL 12    # Y=timernum X=timerval
  XEQ 41
GTO 99

# Display routine
#   Y=timernum X=timerval
#   Entering here we know that X not 0
LBL 41
  X<>Y
  FIX 0
  CF 29
  CLA
  ARCL X
  "|- "   # append space
  ARCL IND 32
  "|- "   # append space
  X<>Y
  X>0?
    GTO 00      # -v  forward reference, skip 3
  "|-N/A
  AVIEW
  RTN
LBL 00
  FIX 4
  ABS
  FC? 01         # Show Time remaining
    XEQ 00       # Time remaining subroutine below
  ATIME
  AVIEW
  PSE
RTN

LBL 00
  RDN            # throw away the timerval, get timernum
  DATE           #
  TIME           # push to Z, Y=date, X=time
  XEQ 50         # Y=timer, X=current
  RCL IND 33
  X<>Y
  -
  HMS
RTN

# ------------------------------------------------------------------------------
# Clearing Routines
# ------------------------------------------------------------------------------
LBL 01 1 GTO 14
LBL 02 2 GTO 14
LBL 03 3 GTO 14
LBL 04 4 GTO 14
LBL 05 5 GTO 14
LBL 06 6 GTO 14
LBL 07 7 GTO 14
LBL 08 8 GTO 14
LBL 09 9 GTO 14
LBL 10 10

LBL 14
  XEQ 23
  CLA
  ARCL IND 32     # get alpha name
  SF 25           # ignore error
  CLALMA          # clear alarm
  FC?C 25         # if there was an error
    "|- N/A"      # append N/A to name
  AVIEW
  CLX
  STO IND 31
  STO IND 32
  STO IND 33
GTO 99

# ------------------------------------------------------------------------------
#   - This routine loops through and clears any expired alarms
#   - sets a loop and checks whether the time (IND 33) is less than now
#   - assumes that the alarm has already gone off (so does not try clearing)
# ------------------------------------------------------------------------------
LBL 90
  10
  XEQ 23
  CF 29
  FIX 0
  LBL 13
    VIEW 31
    RCL IND 31
    X=0?
      GTO 00      # fast skip over, do next --v
    DATE
    TIME
    XEQ 50        # translate to epoch time
    RCL IND 33
    -
    X<0?          # if it is still in the future
      GTO 00      # do next, skip over

    # clear expired timers
    "CLR "
    ARCL 31
    AVIEW
    CLX
    STO IND 31
    STO IND 32
    STO IND 33
LBL 00
    DSE 33
      ENTER   # NOOP, do nothing
    DSE 32
      ENTER   # NOOP, do nothing
    DSE 31
      GTO 13
RTN

# ------------------------------------------------------------------------------
# Display routine
# ------------------------------------------------------------------------------
LBL "d"
  1.01          # set index

LBL 40
  RCL IND X     # get timer value
  X=0?          # if not active
    GTO 00      #   skip loop body
  X<>Y          # timer number in X and stash val in Y
  XEQ 23        # store indexes
  X<>Y          # set up for 41, Y=timenum X=val
  XEQ 41        # display
LBL 00
  RDN           # discard timer value
  ISG X         # next timer
    GTO 40      #   loop back

GTO 99          # back to main on finish

# ------------------------------------------------------------------------------
# Erase all, (reset)
# ------------------------------------------------------------------------------
LBL "e"
  "SURE?"
  PROMPT
  .033
  CLRGX
  # also clear all alarms
  CLRALMS
  # Store Epoch Date and set time/date modes
  DATE
  STO 00
  MDY
  CLK24
GTO 99

# ------------------------------------------------------------------------------
# LBL "c"  --  display list of active timers
# ------------------------------------------------------------------------------
LBL "c"
  CF 10         # temporary flag set if any active timers
  1.01          # index counter
  FIX 0         # set for integer display
  CLA           # clear alpha

LBL 30          # loop
  RCL IND X     # get current timer value
  X=0?          # if clear
    GTO 00      #   then skip loop body

  SF 10         # flag that we have at least one
  "|- "         # append a space
  X>0?          # flag running timers with a dot
    SF 29
  X<0?
    CF 29
  ARCL Y        # recall timer number

LBL 00
  RDN           # discard timer value or zero
  ISG X         # loop if more to do
    GTO 30

                # loop exit
  FS? 10        # was FS?C 10        # if we had at least one active timer
    AVIEW       # then display the list
  FS?C 10
    PSE
  XEQ 62        # Display next timer and time remaining
GTO 99          # back to main

# ------------------------------------------------------------------------------
# toggle entry mode
# ------------------------------------------------------------------------------

LBL "a"
  FC?C 00
  SF 00
  "IMMED O"
  FS? 00
    "|-N"
  FC? 00
    "|-FF"
  AVIEW
  PSE
GTO 99

# ------------------------------------------------------------------------------
LBL 60         # set up relative alarm
               # enter:  alpha=name X=relative time, HMS
  TIME
  HMS+
  ENTER
  ENTER
  24
  /
  INT
  DATE
  X<>Y
  DATE+
  LASTX
  24
  *
  ST- Z
  CLX
  STO T
  RDN
  X<>Y
  XYZALM
  "^^MTIM"      # note that these are up-arrows, shift [ENTER] in alpha mode
  XYZALM
  # TODO - store in R21-30 after conversion
  # but we need to know the timer number, just return with conversion
  XEQ 50
RTN

# ------------------------------------------------------------------------------
LBL 61
  # convert minutes to hh.mmss
  60
  /
  HMS
RTN

# ------------------------------------------------------------------------------
# Display next timer and time remaining
LBL 62
  CF 10
  SF 25
  1
  RCLALM     # which also recalls alpha register
  FC?C 25
    SF 10
  FS? 10
    "N/A"    # replace alpha if non-existant alarm
  ASTO T     # either way, we store it in T
  "NEXT: "
  ARCL T     # recall either the timer name or N/A
  AVIEW
  PSE
  # Calculate time if valid
  FS?C 10
    RTN

  XEQ 51
  FIX 4
  "REM: "
  ATIME
  AVIEW
  PSE
RTN

# ------------------------------------------------------------------------------
# Start all inactive but entered timers
# ------------------------------------------------------------------------------
LBL "b"
  1.01          # index counter
  FIX 0         # set for integer display

LBL 31          # loop
  RCL IND X     # get current timer value
  X#0?          # X>=0? does not exist, this is a good substitue
  X>0?          # if already running or not entered
    GTO 00      #   skip the following..
  ABS           # ABS value, strip neg flag
  STO IND Y     # unflag it
  X<>Y          # X=timernum Y=abs(timerval)
  XEQ 23        # stash timer indexes (to get alpha)
  "START "
  ARCL X        # recall timer number
  AVIEW
  CLA
  ARCL IND 32
  X<>Y          # get timer value back
  XEQ 60        # set alarm, now returns with HR since Epoch
  RCL 31        # recall index back  # TODO, this is the loop counter
  20
  +
  X<>Y
  STO IND Y     # store in R21-30
  RCL 31
  ENTER
LBL 00
  RDN           # discard timer value or zero, timer num counter back
  ISG X         # loop if more to do
    GTO 31
                # loop exit
GTO 99          # back to main

# ------------------------------------------------------------------------------
# Epoch time translations
# ------------------------------------------------------------------------------

# translate to epoch time.  enter with date in Y, time in X
# returns epoch time fractional hours
LBL 50
  X<>Y
  RCL 00
  X<>Y
  DDAYS
  24
  *
  X<>Y
  HR
  +
RTN

# time remaining, enter with Y=Date, X=Time
#   returns HMS relative to current time
LBL 51
  XEQ 50
  DATE
  TIME
  XEQ 50
  -
  HMS
RTN

# additionally come here for timer and set flag
LBL MTIM
  SF 04
RTN
  GTO 99