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
8 - Using Callbacks
9 - Hex Dump
10 - EEPROM Dumper
11 - Spend Watch
12 - Sound Schemes
13 - Random Numbers
[This Page] 14 - Hourly Chimes
15 - Lottery Picker

Sound Schemes
Sound Hardware
Sound Scheme Format

Home Send Mail

Playing Hourly Chimes - Ships Bells example

Theron E. White, CPA" <twhite@mercury.peganet.com> suggested a wristapp to allow the hourly chimes to play the number of bells past a shift change.  This would be 8 bells at midnight, 8AM, and 4PM, 1 bell at 1AM, 9AM, and 5PM, with one more bell for each hour after that.  This wristapp is a little unique in that it doesn't use the sound playing routines directly, but instead goes straight to the hardware.  This allows you to have whatever sound scheme you want in the watch.  The pattern for the bells and the actual tone is customizable below.  This app is also a good candidate for combining with another wristapp as this one has no real user input operations.

;Name: Ships Bells
;Version: SHIPBELL
;Description: Ships bells - by John A. Toebes, VIII
;This application turns makes the hour chime with nautical bells.
;
;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	*
CHANGE_FLAGS    EQU     $92     ; System Flags
SND_POS         EQU     $61
SND_REMAIN      EQU     $62
SND_NOTE        EQU     $63

NOTE_PAUSE      EQU     (TONE_PAUSE/16)
NOTE_BELL       EQU     (TONE_MID_C/16)
;
; (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     STOPIT          ; Called when the COMM app starts and we have timers pending - WRIST_INCOMM
L011c:  rts
        nop
        nop                     ; 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_SHIPS:       timex6  "SHIPS"
S6_BELLS:       timex6  " BELLS"
S8_TOEBES:      timex   "J.TOEBES"
;
; Here is the pattern for the ships bells.  We want to have a short bell followed by a very short silence
; followed by a longer bell.  We use 3 tics for the short bell, 1 tic for the silence and 6 tics for the longer
; bell.  The last bell is 7 ticks.
; We then have to byte swap each of these because the BRSET instruction numbers from bottom to top.
;
; The string looks like:
;   111 0 111111 000000 111 0 111111 000000 111 0 111111 000000 111 0 111111 000000
; Taking this into clumps of 4 bytes, we get
;   1110 1111  1100 0000  1110 1111  1100 0000  1110 1111  1100 0000  1110 1111  1100 0000  1111 1110
;
Pattern DB      $F7     ;1110 1111  ; 8 start here
        DB      $03     ;1100 0000
P67     DB      $F7     ;1110 1111  ; 6, 7 start here
        DB      $03     ;1100 0000
P45     DB      $F7     ;1110 1111  ; 4, 5 start here
        DB      $03     ;1100 0000
P23     DB      $F7     ;1110 1111  ; 2, 3 start here
        DB      $03     ;1100 0000
P1      DB      $7F     ;1111 1110  ; 1 starts here
;
; This table indexes where we start playing the tone from
;
STARTS  
        DB      (Pattern-Pattern)*8     ; 0 (8 AM,  4PM, Midnight)
        DB      (P1-Pattern)*8          ; 1 (1 AM,  9AM,  5PM)
        DB      (P23-Pattern)*8         ; 2 (2 AM, 10AM,  6PM)
        DB      (P23-Pattern)*8         ; 3 (3 AM, 11AM,  7PM)
        DB      (P45-Pattern)*8         ; 4 (4 AM, NOON,  8PM)
        DB      (P45-Pattern)*8         ; 5 (5 AM,  1PM,  9PM)
        DB      (P67-Pattern)*8         ; 6 (6 AM,  2PM, 10PM)
        DB      (P67-Pattern)*8         ; 7 (7 AM,  3PM, 11PM)
;
; (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_SHIPS-START         ; Put 'SHIPS ' on the top line
        jsr	PUT6TOP
        lda	#S6_BELLS-START         ; Put ' BELLS' on the second line
        jsr	PUT6MID
        bsr     FORCESTATE              ; Just for fun, check the alarm state
        lda     #S8_TOEBES-START
        jmp     BANNER8
;
; (6) This is the main initialization routine which is called when we first get the app into memory
;
MAIN:
        lda     #$C4    ; Bit2 = wristapp wants a call once an hour 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
        bclr    2,MODE_FLAGS    ; Turn off the hourly chimes
        clr     SND_REMAIN
;
; (7) Determining the current hour
;
CHECKSTATE
        brclr   5,CHANGE_FLAGS,NO_HOUR  ; Have we hit the hour mark?
FORCESTATE
        bclr    3,MAIN_FLAGS            ; Make sure we don't play the system hourly chimes
        jsr     ACQUIRE                 ; Lock so that it doesn't change under us
        lda     TZ1_HOUR                ; 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_HOUR                ; Wrong guess, just load up the second time zone
GOT_TZ1
;
;        12  1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9 10 11 12
;        00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18
; deca   FF 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17
; anda   07 00 01 02 03 04 05 06 07 00 01 02 03 04 05 06 07 00 01 02 03 04 05 06 07
        and     #7                      ; Convert the hour to the number of bells
        tax                             ; Save away as an index into the start position table
        bne     NOTEIGHT                ; Is it midnight (or a multiple of 8)
        lda     #8                      ; Yes, so that is 8 bells, not zero
NOTEIGHT
        lsla                            ; Multiple the number of bells by 8 to get the length
        lsla
        lsla
        sta     SND_REMAIN              ; Save away the number of bells left to play
        lda     STARTS,X                ; Point to the pattern of the first bell
        sta     SND_POS                 
        bset    1,BTNFLAGS              ; Turn on the tic timer
        JMP     RELEASE                 ; And release our lock on the time
;
; (8) Playing the next note piece
;
NO_HOUR
        lda     SND_REMAIN              ; Do we have any more notes to play?
        bne     DO_SOUND                ; No, skip out
STOPIT
        lda     #TONE_PAUSE             ; End of the line, shut up the sound hardware
        sta     $28
        clr     SND_REMAIN              ; Force us to quit looking at sound
        bclr    1,BTNFLAGS              ; and turn off the tic timer
        rts

DO_SOUND
        deca                            ; Yes, note that we used one up
        sta     SND_REMAIN
        lda     SND_POS                 ; See where we are in the sound
        lsra                            ; Divide by 8 to get the byte pointer
        lsra
        lsra
        tax                             ; and make it an index
        lda     Pattern,X               ; Get the current pattern byte
        sta     SND_NOTE                ; And save it where we can test it
        lda     SND_POS                 ; Get the pointer to where we are in the sound
        inc     SND_POS                 ; Advance to the next byte
        and     #7                      ; and hack off the high bytes to leave the bit index
        lsla                            ; Convert that to a BRSET instruction
        sta     TSTNOTE                 ; And self modify our code so we can play
TSTNOTE brset   0,SND_NOTE,PLAYIT       ; If the note is not set, skip out
        lda     #TONE_PAUSE             ; Not playing, we want to have silence
        brskip2
PLAYIT  lda     #NOTE_BELL              ; Playing, select the bell tone
        sta     $28                     ; And make it play
NO_SOUND
        rts
  1. Program specific constants - We define the CHANGE_FLAGS because it is not currently in Wristapp.i.  This allows us to turn off the system attempts at playing hourly chimes.  We also select the tone that we want to play the bells with.  This seems to work as the best one to be heard as bells.
  2. System entry point vectors - The only interesting thing here is that we use the WRIST_INCOMM entry to disable any bell playing that might have started.
  3. Program strings - The pattern and starts tables are used to describe when we will be playing notes and when we will be pausing.
  4. State Table - Pretty boring here.
  5. State Table 0 Handler - Also amazingly boring.  The only interesting thing that we do here is to force the current bells to play when you enter the app.
  6. Main initialization routine - Nothing spectactular here, other than the fact that we save 1 byte by falling into the code to determine if we have passed an hour.
  7. Determining the current hour - This code looks to see if the hour has changed and if so, it latches in the time based on the selected timezone.  It also calculates the number of bells and the length of the sequence necessary to play for that number of bells.
  8. Playing the next note piece - The really tricky part here is that we have self modifying code that generates a BRSET instruction to test the next bit in the currently selected byte.  Once we have done so, we load up a tone and stuff it into the hardware.
1