About the Datalink
What is it?
Download Protocol
Display Segments
Memory Map
150 vs 150s
EEProms

Wristapp Programming
Reference
Creating Wristapps
Wristapp Format
The State Table
Wristapp Routines
Wristapps

Wristapp Programming
Tutorials
1 - Hello World
2 - Getting Input
3 - Better Input
4 - Showing Selection
5 - PassWord
6 - Day Find
7 - Playing with Sound
[This Page] 8 - Using Callbacks
9 - Hex Dump
10 - EEPROM Dumper
11 - Spend Watch
12 - Sound Schemes
13 - Random Numbers
14 - Hourly Chimes
15 - Lottery Picker

Sound Schemes
Sound Hardware
Sound Scheme Format

Home Send Mail

Using Callbacks - Endoff example

Here is another pretty simple program that shows off a couple of useful features of a wristapp.  This one stems from a request several people have had (including myself) to turn off the alarms on the weekend.  That's really all this does.  To make it a little more fun, I decided that I wanted to call it " WEEK " "ENDOFF", with the problem that there is no letter K in the character set for the top line on the display.  So, I figured out how to make a reasonably ok looking letter.  You will notice that this program seems to do very little...

;Name: Week End Off
;Version: ENDOFF
;Description: Week End Off - by John A. Toebes, VIII
;This application turns off all alarms on the weekend.
;
;TIP:  Download your watch faster:  Download a WristApp once, then do not send it again.  It stays in the watch!
;HelpFile: watchapp.hlp
;HelpTopic: 106
            INCLUDE "WRISTAPP.I"
;
; (1) Program specific constants
;
START     EQU	*
;
; (2) System entry point vectors
;
L0110:  jmp     MAIN	; The main entry point - WRIST_MAIN
L0113:  rts             ; Called when we are suspended for any reason - WRIST_SUSPEND
        nop
        nop
L0116:  jmp     CHECKSTATE      ; Called to handle any timers or time events - WRIST_DOTIC
L0119:  jmp     ENABLE_ALL      ; Called when the COMM app starts and we have timers pending - WRIST_INCOMM
L011c:  jmp     CHECKSTATE      ; Called when the COMM app loads new data - WRIST_NEWDATA

L011f:  lda     STATETAB,X ; The state table get routine - WRIST_GETSTATE
        rts

L0123:  jmp     HANDLE_STATE0
        db      STATETAB-STATETAB
;
; (3) Program strings
;
S6_WEEK:        timex6  " WEEH "
S6_ENDOFF:      timex6  "ENDOFF"
S8_TOEBES:      timex   "J.TOEBES"
;
; (4) State Table
;
STATETAB:
        db      0
        db      EVT_ENTER,TIM_LONG,0    ; Initial state
        db      EVT_RESUME,TIM_ONCE,0   ; Resume from a nested app
        db      EVT_MODE,TIM_ONCE,$FF   ; Mode button
        db      EVT_END
;
; (5) State Table 0 Handler
; This is called to process the state events.
; We see ENTER and RESUME events
;        
HANDLE_STATE0:
        bset    1,APP_FLAGS             ; Allow us to be suspended
        jsr	CLEARALL                ; Clear the display
        lda	#S6_WEEK-START          ; Put ' WEEK ' on the top line
        jsr	PUT6TOP
        lda	#S6_ENDOFF-START        ; Put 'ENDOFF' on the second line
        jsr	PUT6MID
;
; (6) Faking a letter K
;
;
; We have    We want it to look like:
; |     |    |      
; |     |    |  |   
; |     |    |  |   
; |=====|    |===== 
; |     |    |     |
; |     |    |     |
; |     |    |     |
; This means turning off T5B and turning on T5H
        lda     #ROW_T5B
        sta     DISP_ROW
        bclr    COL_T5B,DISP_COL
        lda     #ROW_T5H
        sta     DISP_ROW
        bset    COL_T5H,DISP_COL
        jsr     CHECKSTATE              ; Just for fun, check the alarm state
        lda     #S8_TOEBES-START
        jmp     BANNER8
;
; (7) This is the main initialization routine which is called when we first get the app into memory
;
MAIN:
        bset    7,WRISTAPP_FLAGS        ; Tell them that we are a live application
        lda     #$C8    ; Bit3 = wristapp wants a call once a day when it changes (WRIST_DOTIC) (SET=CALL)
                        ; Bit6 = Uses system rules for button beep decisions (SET=SYSTEM RULES)
                        ; Bit7 = Wristapp has been loaded (SET=LOADED)
        sta     WRISTAPP_FLAGS
        ; Fall into CHECKSTATE
;
; (8) Determining the day of the week
;
CHECKSTATE
        jsr     ACQUIRE                 ; Lock so that it doesn't change under us
        lda     TZ1_DOW                 ; Assume that we are using the first timezone
        jsr     CHECK_TZ                ; See which one we are really using
        bcc     GOT_TZ1                 ; If we were right, just skip on to do the work
        lda     TZ2_DOW                 ; Wrong guess, just load up the second time zone
GOT_TZ1
        jsr     RELEASE                 ; Unlock so the rest of the system is happy
        cmp     #5                      ; Time zone day of week is 0=Monday...6=Sunday
        bhs     DISABLE_ALL             ; Saturday, Sunday - disable them all
        ; Fall into ENABLE_ALL
;---------------------------------------------------------------
; Routine:
;   (9) ENABLE_ALL/DISABLE_ALL
; Parameters:
;   NONE
; Purpose:
;   These routines enable/disable all of the alarms.  It hides the disabled status of
;   the alarm by storing it in bit 3 of the alarm flags.
;      Bit0 = Alarm is enabled (SET=ENABLED)
;      Bit1 = Alarm is masked (SET=MASKED)
;      Bit2 = Current alarm is in 12 hour mode and is in the afternoon (SET=AFTERNOON)
;      Bit3 = Alarm was enabled, but we are hiding it (SET=HIDDEN)
;   It is safe to call these routine multiple times.
;---------------------------------------------------------------
ENABLE_ALL
        ldx     #4                      ; We have 5 alarms to go through
ENABLE_NEXT
        lda     ALARM_STATUS,X          ; Get the flags for this alarm
        lsra                            ; Shift right 3 to get our hidden bit into place
        lsra
        lsra
        and     #1                      ; Mask out everything except the hidden bit (now in the enabled position
        ora     ALARM_STATUS,X          ; Or it back into the flags
        and     #7                      ; and clear out our hidden bit
        sta     ALARM_STATUS,X          ; then save it out again.
        decx                            ; Count down the number of alarms
        bpl     ENABLE_NEXT             ; And go back for the next one
        rts

DISABLE_ALL
        ldx     #4                      ; We have 5 alarms to go through
DISABLE_NEXT
        lda     ALARM_STATUS,X          ; Get the flags for this alarm
        and     #1                      ; And extract our enabled bit
        lsla                            ; Shift left 3 to save as our hidden bit
        lsla
        lsla
        ora     ALARM_STATUS,X          ; Or it back into the flags
        and     #$0e                    ; and clear out the enabled bit
        sta     ALARM_STATUS,X          ; then save it out again.
        decx                            ; Count down the number of alarms
        bpl     DISABLE_NEXT            ; And go back for the next one
        rts

This code has a few notable sections.

  1. Program specific constants - We don't have any
  2. System entry point vectors - This is where we have a lot of fun. We are using three of the entry points which we have never used before. The WRIST_DOTIC entry is enabled by us setting bit 3 in the Wristapp_flags which causes us to get called once a day. While we could enable it to call us hourly, by the minute, or even faster, it really doesn't make sense to waste processing time. The WRIST_INCOMM entry point gives us a chance to undo our hiding of the alarms just in case the downloaded data wants to mess with it. Lastly, the WRIST_NEWDATA entry is called after the data has been loaded into the watch.
  3. Program strings - Of course we changed the strings once again. Note that the one string says WEEH and not WEEK since K is not a valid letter in the TIMEX6 alphabet. Don't worry, we will fix it up at runtime.
  4. State Table(s) - We are back to only one state table. In fact, you will see that this state table is even less fancy than the hello world example. We really don't have any input functions, so we pretty much ignore everything.
  5. State Table Handler0 - For state0, we only really need to handle the initial enter or resume where we put up the banner.
  6. Faking the letter K - All we need to do is turn off one segment and turn on another to turn the H into a K.
  7. Main Initialization routine - Nothing really significant here. This is called once when the wristapp is first loaded.  We need to make sure that we set the appropriate bits in WRISTAPP_FLAGS. The new bit that we set here is to enable the callback once a day.
  8. Determining the Current Day - This really is pretty simple, we figure out the current time zone and grab the day of the week from the right spot.
  9. ENABLE_ALL/DISABLE_ALL - These routines are pretty simple also, all they have to do is hide the state of the enabled bit in the third bit of the alarm status flags. These routines had to be constructed so that you can call them many times in a row and not lose the original sense of the enabled bit for each alarm. We are able to do that by making sure that we always OR together the bits before clearing out the other.