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
[This Page] 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 3 States - HexDump example

Ok, so you have a computer on your wrist.  What better way to show it off than by having a hex dump utility to trapes through memory.  This is a major overhaul of a previous version of the hexdump application that I have posted.  I have turned it into a real application instead of a simple test program.  It also uses the .ZSM file format to allow you to use it with ASM6805.  You can download it here


;Name: Hex Dump

;Version: HEXDUMP

;Description: Hex Dumper - by John A. Toebes, VIII

;This Hex dump routine is a simple thing to test out dumping hex bytes...

;

; Press the NEXT/PREV buttons to advance/backup by 6 bytes of memory at a time

; Press the SET button to change the location in memory where you are dumping.

;

;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

;

FLAGBYTE        EQU     $61

;   Bit 0 indicates the direction of the last button

;   The other bits are not used

CURRENT_DIGIT   EQU     $62

DIGIT0          EQU     $63

DIGIT1          EQU     $64

DIGIT2          EQU     $65

DIGIT3          EQU     $66

;

;

; (2) System entry point vectors

;

START   EQU     *

L0110:  jmp     MAIN    ; The main entry point - WRIST_MAIN

L0113:  rts             ; Called when we are suspended for any reason - WRIST_SUSPEND

        nop

        nop

L0116:  rts             ; Called to handle any timers or time events - WRIST_DOTIC

        nop

        nop

L0119:  rts             ; Called when the COMM app starts and we have timers pending - WRIST_INCOMM

        nop

        nop

L011c:  rts             ; Called when the COMM app loads new data - WRIST_NEWDATA

        nop

        nop



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

        rts



L0123:  jmp     HANDLE_STATE0

        db      STATETAB0-STATETAB0

L0127:  jmp     HANDLE_STATE1

        db      STATETAB1-STATETAB0

L012b:  jmp     HANDLE_STATE2

        db      STATETAB2-STATETAB0

;

; (3) Program strings

;

S6_BYTE:        timex6   " BYTE "

S6_DUMPER:      timex6  "DUMPER"

S8_LOCATION     timex   "aaaa    "

;

; (4) State Table

;

STATETAB0:

        db      0

        db      EVT_ENTER,TIM2_12TIC,0          ; Initial state

        db      EVT_RESUME,TIM_ONCE,0           ; Resume from a nested app

        db      EVT_TIMER2,TIM_ONCE,0           ; This is the timer

        db      EVT_DNNEXT,TIM2_8TIC,1          ; Next button

        db      EVT_DNPREV,TIM2_8TIC,1          ; Prev button

        db      EVT_MODE,TIM_ONCE,$FF           ; Mode button

        db      EVT_SET,TIM_ONCE,2              ; Set button

        db      EVT_USER0,TIM_ONCE,$FF          ; Return to system

        db      EVT_END

        

STATETAB1:

        db      0

        db      EVT_UPANY,TIM_ONCE,0            ; Releasing the prev or next button

        db      EVT_TIMER2,TIM2_TIC,1           ; Repeat operation with a timer

        db      EVT_END                         ; End of table



STATETAB2:

        db      2

        db      EVT_RESUME,TIM_ONCE,2           ; Resume from a nested app

        db      EVT_DNANY4,TIM_ONCE,2           ; NEXT, PREV, SET, MODE button pressed

        db      EVT_UPANY4,TIM_ONCE,2           ; NEXT, PREV, SET, MODE button released

        db      EVT_USER2,TIM_ONCE,0            ; Return to state 0

        db      EVT_END                         ; End of table



;

; (5) State Table 0 Handler

; This is called to process the state events.

; We see ENTER, TIMER2, and RESUME events

;

HANDLE_STATE0:

        bset    1,APP_FLAGS                     ; Indicate that we can be suspended

        lda     BTNSTATE                        ; Get the event

        cmp     #EVT_ENTER                      ; Is this the initial state?

        bne     SHOWDATA                        ; no, just clean up the screen

;

; (6) Put up the initial banner screen

;

        jsr     CLEARALL                        ; Clear the display

        lda     #S6_BYTE-START                  ; Put ' BYTE ' on the top line

        jsr     PUT6TOP

        lda     #S6_DUMPER-START                ; Put 'DUMPER' on the second line

        jsr     PUT6MID

        lda     #SYS8_MODE                      ; Put MODE on the bottom line

        jmp     PUTMSGBOT

; (7) FMTHEX is a routine similar to FMTX, but it handles hex values instead

;=======================================================================

; Routine: FMTHEX

; Purpose:

;   Format a byte into the buffer

; Parameters:

;   A - Byte to be formatted

;   X - Offset into Message buffer to put the byte

;=======================================================================

FMTHEX:

        sta     S8_LOCATION,X   ; Save the byte

        and     #$0f            ; Extract the bottom nibble

        sta     S8_LOCATION+1,X ; Save the hex value of the nibble

        lda     S8_LOCATION,X   ; Get the value once again

        lsra                    ; Shift right by 4 to get the high order nibble

        lsra

        lsra

        lsra



        sta     S8_LOCATION,X   ; And put it back into the buffer

        rts

;

; (8) This is called when we press the prev/next button or when the timer fires during that event

;

HANDLE_STATE1:

        lda     BTNSTATE

        cmp     #EVT_TIMER2                     ; Is this a repeat/timer event?

        beq     REPEATBTN                       ; yes, do as they asked



        bclr    0,FLAGBYTE                      ; Assume that they hit the prev button

        cmp     #EVT_DNPREV                     ; Did they hit the prev button

        bne     REPEATBTN                       ; Yes, we guessed right

        bset    0,FLAGBYTE                      ; No, they hit next.  Mark the direction.

REPEATBTN:

        brclr   0,FLAGBYTE,NEXTLOC              ; If they hit the next button, go do that operation

;

; They pressed the prev button, let's go to the previous location

;

PREVLOC:

        lda     CURRENT_LOC+1

        sub     #6

        sta     CURRENT_LOC+1

        lda     CURRENT_LOC

        sbc     #0

        sta     CURRENT_LOC

        bra     SHOWDATA

NEXTLOC:

        lda     #6

        add     CURRENT_LOC+1

        sta     CURRENT_LOC+1

        lda     CURRENT_LOC

        adc     #0

        sta     CURRENT_LOC

;

; (9) This is the main screen update routine.

; It dumps the current memory bytes based on the current address.  Note that since it updates the entire

; display, it doesn't have to clear anything

;

SHOWDATA:

        jsr     CLEARSYM



        clrx

        bsr     GETBYTE

        jsr     PUTTOP12



        ldx     #1

        bsr     GETBYTE

        jsr     PUTTOP34



        ldx     #2

        bsr     GETBYTE

        jsr     PUTTOP56



        ldx     #3

        bsr     GETBYTE

        jsr     PUTMID12



        ldx     #4

        bsr     GETBYTE

        jsr     PUTMID34



        ldx     #5

        bsr     GETBYTE

        jsr     PUTMID56



        lda     CURRENT_LOC             ; Get the high order byte of the address

        clrx

        bsr     FMTHEX          ; Put that at the start of the buffer

        lda     CURRENT_LOC+1           ; Get the low order byte of the address

        ldx     #2

        bsr     FMTHEX          ; Put that next in the buffer



        lda     #S8_LOCATION-START

        jmp     BANNER8

; (10) GETBYTE gets a byte from memory and formats it as a hex value

;=======================================================================

; Routine: GETBYTE

; Purpose:

;   Read a byte from memory and put it into DATDIGIT1/DATDIGIT2 as hex values

; Parameters:

;   X - Offset from location to read byte

;   CURRENT_LOC - Base location to read from

;=======================================================================

GETBYTE

CURRENT_LOC     EQU     *+1                     ; Self modifying code... Point to what we want to modify

        lda     $4000,X                         ; Get the current byte

        sta     DATDIGIT2                       ; And save it away

        lsra                                    ; Extract the high nibble

        lsra

        lsra

        lsra



        sta     DATDIGIT1                       ; And save it

        lda     DATDIGIT2                       ; Get the byte again

        and     #$0f                            ; Extract the low nibble

        sta     DATDIGIT2                       ; And save it

        rts

;

; (11) State Table 2 Handler

; This is called to process the state events.

; We see SET, RESUME, DNANY4, and UPANY4 events

;

HANDLE_STATE2:

        bset    1,APP_FLAGS	                ; Indicate that we can be suspended

        lda     BTNSTATE                        ; Get the event

        cmp     #EVT_UPANY4

        beq     REFRESH2

        cmp     #EVT_DNANY4                     ; Is this our initial entry?

        bne     FORCEFRESH

        lda     BTN_PRESSED                     ; Let's see what the button they pressed was

        cmp     #EVT_PREV                       ; How about the PREV button

        beq     DO_PREV                         ; handle it

        cmp     #EVT_NEXT                       ; Maybe the NEXT button?

        beq     DO_NEXT                         ; Deal with it!

        cmp     #EVT_MODE                       ; Perhaps the MODE button

        beq     DO_MODE                         ; If so, handle it

        ; It must be the set button, so take us out of this state

        bsr     SHOWDATA

        lda     #EVT_USER2

        jmp     POSTEVENT

;

; (12) This handles the update routine to change a digit...

;

DO_NEXT

        bset    0,SYSFLAGS                      ; Mark our update direction as up

        bra     DO_UPD

DO_PREV

        bclr    0,SYSFLAGS                      ; Mark our update direction as down

DO_UPD

        clra

        sta     UPDATE_MIN                      ; Our low end is 0

        lda     #$F

        sta     UPDATE_MAX                      ; and the high end is 15 (the hes digits 0-F)

        bsr     GET_DISP_PARM

        lda     #UPD_DIGIT

        jsr     START_UPDATEP                   ; And prepare the update routine   

        bset    4,BTNFLAGS                      ; Mark that the update is now pending

        rts

;

; (13) This is where we switch which digit we are changing...

;

DO_MODE

        lda     CURRENT_DIGIT

        inca

        and     #3

        sta     CURRENT_DIGIT

;

; (14) Refresh the screen and start blinking the current digit...

;

REFRESH2

        lda     DIGIT0                          ; Get the first digit

        lsla                                    ; *16

        lsla

        lsla

        lsla

        add     DIGIT1                          ; Plus the second digit

        sta     CURRENT_LOC                     ; To make the high byte of the address

        lda     DIGIT2                          ; Get the third digit

        lsla                                    ; *16 

        lsla

        lsla

        lsla

        add     DIGIT3                          ; Plus the fourth digit

        sta     CURRENT_LOC+1                   ; To make the low byte of the address

FORCEFRESH

        bclr    7,BTNFLAGS                      ; Turn off any update routine that might be pending

        jsr     SHOWDATA                        ; Format the screen

        ldx     #4                              ; We need to copy over 4 bytes from the buffer

COPYIT

        decx                                    ; This will be one down.

        lda     S8_LOCATION,X                   ; Get the formatted byte

        sta     DIGIT0,X                        ; And store it for the update routine

        tstx                                    ; Did we copy enough bytes?

        bne     COPYIT                          ; No, go back for more

        bsr     GET_DISP_PARM                   ; Get the parm for the blink routine

        lda     #BLINK_DIGIT                    ; Request to blink a digit

        jsr     START_BLINKP                    ; And do it

        bset    2,BTNFLAGS                      ; Mark a blink routine as pending

        rts

;

; (15) This gets the parameters for an UPDATE/BLINK routine

;

GET_DISP_PARM

        lda     CURRENT_DIGIT                   ; Figure out what digit we are dumping

        sta     UPDATE_POS                      ; Store it for the BLINK/UPDATE routine

        add     #DIGIT0                         ; Point to the byte to be updated

        tax                                     ; And put it into X as needed for the parameter

        rts

;

; (16) 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

        clr     CURRENT_DIGIT                   ; Start out on the first digit

        rts

This code has a few notable sections.

  1. Program specific constants - We only really need special storage for the 4 digits which the update/blink routines will handle.
  2. System entry point vectors - We only have a main.  However, we also have 3 state tables.
  3. Program strings - Nothing special here.  We have two strings for the banner and one string that we show the current location with.
  4. State Tables - We have three state tables now.  State table0 does very little other than handle getting into states 1 and 2.  State table 1 is for when you are pressing the prev/next buttons while in the main state to allow you to advance/backup by 6 bytes at a time.  State Table 2 handles all of the setting of the digits.  Note that it would be possible to combine these two states, but it would make the code much more complicated than it needs to be.
  5. State Table 0 Handler - This is actually one of the simplest.  All it has to do is put up the startup banner and then show the current data once that times out.
  6. Initial banner screen - Very simple code to display the name of the application.
  7. FMTHEX is a routine similar to FMTX, but it handles hex values instead.  It is up here in order to allow several of the other BSR instructions to be able to reach the main update routine.  Sometimes moving a subroutine can save you quite a few bytes.
  8. PREV/NEXT Handling This is called when we press the prev/next button or when the timer fires during that event.
  9. Main Update This is the main screen update routine.  Note that we don't have to refresh anything since the entire screen is writen.
  10. GETBYTE gets a byte from memory and formats it as a hex value
  11. State Table 2 Handler - This is very similar to the state handling in the passwd sample.
  12. Changing Digits This handles the update routine to change a digit...
  13. Switching Digits This is where we switch which digit we are changing...
  14. Blinking DigitsRefresh the screen and start blinking the current digit...
  15. GET_DISP_PARM This gets the parameters for an UPDATE/BLINK routine.  We made this a subroutine in order to ensure that everything is kept in sync.  It also saves a few bytes.
  16. Main Initialization This is the main initialization routine which is called when we first get the app into memory.  As usual, there is not a lot that we have to do.