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
[This Page] 13 - Random Numbers
14 - Hourly Chimes
15 - Lottery Picker

Sound Schemes
Sound Hardware
Sound Scheme Format

Home Send Mail

Random Numbers and Marquis - 3Ball example

Wayne Buttles contributed the first version of this Wristapp which gives you a simple decision maker. It inspired me to make a few adjustments to it and add a real random number generator that you can use. I've also included a little busy wait Marquis while it is selecting a number to show off a use of the time. This Wristap also illustrates that you don't always have to put a JMP or RTS instruction in the entry point vectors.

;Name: 3BALL
;Version: 3BALL
;Description: An executive decision maker that will give a yes/no/maybe answer.  Pressing Next will generate another answer and beep (since it will be the same answer sometimes).
;
;(c) 1997 Wayne Buttles (timex@fdisk.com). Compiled using tools and knowledge published by John A. Toebes, VIII and Michael Polymenakos (mpoly@panix.com).
; Some enhancements by John Toebes...
;
;HelpFile: watchapp.hlp
;HelpTopic: 100
;
; (1) Program specific constants
;
            INCLUDE "WRISTAPP.I"
;
; Program specific constants
;
CURRENT_TIC     EQU     $27     ; Current system clock tic (Timer)
LAST_ANS        EQU     $61
RAND_SEED       EQU     $60
MARQ_POS        EQU     $62
START	        EQU   *
;
; (2) System entry point vectors
;
L0110:  jmp     MAIN	; The main entry point - WRIST_MAIN
L0113:  bclr    1,BTNFLAGS      ; Called when we are suspended for any reason - WRIST_SUSPEND
        rts
L0116:  jmp     FLASH   ; Called to handle any timers or time events - WRIST_DOTIC
L0119:  bclr    1,BTNFLAGS      ; Called when the COMM app starts and we have timers pending - WRIST_INCOMM
        rts
L011c:  rts             ; Called when the COMM app loads new data - WRIST_NEWDATA
        nop
        nop

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

L0123:  jmp   HANDLE_STATE0
        db    STATETAB-STATETAB
;
; (3) Program strings
;
S6_MSG  timex6  "3 BALL"
S6_MAYBE timex6 "MAYBE"
S6_YES  timex6  " YES"
S6_NO   timex6  "  NO"
S6_MARQ timex6  "   +O+   "

MARQ_SEL
        DB      S6_MARQ+2-START
        DB      S6_MARQ+3-START
        DB      S6_MARQ+2-START
        DB      S6_MARQ+1-START
        DB      S6_MARQ-START
        DB      S6_MARQ+1-START

MSG_SEL DB      S6_YES-START
        DB      S6_NO-START
        DB      S6_MAYBE-START
        DB      S6_YES-START
;
; (4) State Table
;
STATETAB:
        db  	0
        db	EVT_ENTER,TIM2_16TIC,0 	; Initial state
        db      EVT_RESUME,TIM_ONCE,0   ; Resume from a nested app
        db  	EVT_DNNEXT,TIM2_16TIC,0	; Next button
        db      EVT_TIMER2,TIM_ONCE,0   ; Timer
        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, RESUME, TIMER2 and NEXT events
;        
HANDLE_STATE0:
        bset    1,APP_FLAGS             ; Indicate that we can be suspended
        bclr    1,BTNFLAGS              ; Turn off the MARQUIS tic event
        lda     BTNSTATE
        cmp     #EVT_DNNEXT             ; Did they press the next button?
        beq     DOITAGAIN
        cmp     #EVT_ENTER              ; Or did we start out
        beq     DOITAGAIN
        cmp     #EVT_RESUME             
	beq     REFRESH
;
; (6) Select a random answer
;
SHOWIT
        bsr     RAND
        and     #3              ; go to a 1 in 4 chance
        sta     LAST_ANS
;
; (7) Display the currently selected random number
;
REFRESH
        ldx     LAST_ANS        ; Get the last answer we had, and use it as an index
        lda     MSG_SEL,X       ; And get the message to display
        jsr	PUT6TOP         ; Put that on the top
BANNER
        lda     #S6_MSG-START   
        jsr     PUT6MID
        lda	#SYS8_MODE      ; And show the mode on the bottom
        jmp	PUTMSGBOT
;
; (8) This flashes the text on the screen
;
FLASH
        lda     CURRENT_APP     ; See which app is currently running
        cmp     #APP_WRIST      ; Is it us?
        bne     L0113           ; No, so just turn off the tic timer since we don't need it
        ldx     #5
        lda     MARQ_POS
        jsr     INCA_WRAPX
        sta     MARQ_POS
        tax
        lda     MARQ_SEL,X
        jmp     PUT6TOP
;
; (9) They want us to do it again
;
DOITAGAIN	                ; Tell them we are going to do it again
        clr     MARQ_POS
        bset    1,BTNFLAGS
        bra     BANNER
;
; (10) Here is a simple random number generator
;
RAND
        lda     RAND_SEED
        ldx     #85
        mul
        add     #25
        sta     RAND_SEED
        rola
        rola
        rola
        rts     
;
; (11) This is the main initialization routine which is called when we first get the app into memory
;
MAIN:
        lda     #$c0            ; We want button beeps and to indicate that we have been loaded
	sta	WRISTAPP_FLAGS
        lda     CURRENT_TIC
        sta     RAND_SEED
	rts
  1. Program specific constants - We have two variables - RAND_SEED and CURRENT_TIC which we use for the random number routine.  RAND_SEED is used to keep track of the last random number returned so that we continue to deliver random numbers.  CURRENT_TIC is what is set by the system when it reads the clock to keep the watch time up to date.  We use it once to provide a seed for the random number generator.
  2. System entry point vectors - This one gets to be a little fun.  Notice for the WRIST_SUSPEND and WRIST_INCOMM routines that we don't have a JMP instruction, but instead put the actual code in line.  This saves use a couple of bytes.
  3. Program strings - We are pretty fruegal here in reusing blanks at the end of the string very liberally.  Also note the S6_MARQ string which has blanks at the start and end so that it can shuffle left and right on the display but always have blanks visible.  The MARQ_SEL and MSG_SEL tables are simply offsets that allow us to select the message with a simple load instruction instead of having to caluclate the offset.
  4. State Table - This is pretty vanilla here except for the fact that we have a very long time interval after the DNNEXT and ENTER events.  It is during this time that the Marquis runss.  We could make it even longer, but this seems to be a good compromise between seeing something happen and actually getting a result in a resonable time.
  5. State Table 0 Handler - Extremely simple, there are only four events that we want to see and this is the typical test and branch one.  THe only unique thing here is that we turn off the Marquis timer as soon as we get any event.
  6. Select a random answer - As if life weren't complicated enough.  This is where we go when it is time to make a decision.  For this we get a random number and limit it to 1 in four.
  7. Display the currently selected random number - Given a random number, we just get the message for it and put it on the display.
  8. This flashes the text on the screen - This is the cheap way to do a Marquis.  Just have a string wider than the display and change the offset from the start at which you start to display.  For this one, there are only 6 states and we select the starting offset from the table based on our current cycle.  Note that this routine is called by the TIC timer which is enabled when they want a new random number.  Eventually the timer for the main event will run out and they will simply stop calling us.
  9. They want us to do it again - Whenever we want to do a new random number, we just start the Marquis tic timer and set up the display.
  10. Here is a simple random number generator - This is a random number generator that you might want to use.  It is a derivative of the typical calculation rand = (seed*25173 + 13849) MOD 65536 which I have chopped down to fit in the 8 bit world as rand = (seed * 85 + 25) MOD 256.  Because the low order bits do produce a pattern cycle which is fairly predictable, we rotate through to get a few of the more randomly occuring bits.
  11. This is the main initialization routine which is called when we first get the app into memory - Very boring stuff here, but we do take a moment to initialize the random number seed with the current tic count just to make it a little more variable.