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.