;*****************************************************************************
;* Coin Tosser Program Example (KEH) 8/5/2008 for the CSMB12C128 Module
;* Pushbutton SW on PB1, LED on PB0, PTAD holds nr. Heads, PTT holds nr. Tails
;*****************************************************************************
; export symbols
            	XDEF cointoss        		; export 'Entry' symbol
           		ABSENTRY cointoss    		; for absolute assembly: mark this as application entry point
           		nolist
            	INCLUDE 'mc9s12c128.inc'	; This include file has all the 9S12C32 register EQU's in it!
            	list
PushButton: equ PORTB
LEDDisplay: equ PORTB
ShowNumberOfHeads:   equ PTAD
ShowNumberOfTails:   equ PTT
; variable/data section
            	ORG RAMStart
nr_heads:   	ds.b 1      					;Allocate 1 byte of RAM: Number of head outcomes accumulated  here
nr_tails:   	ds.b 1     				 	  ;Allocate 1 byte of RAM: Number of tail outcomes accumulated  here
; code section
            	ORG ROM_4000Start
cointoss:
   lds   #RAMEnd 	      ; Initialize user stack near top of RAM,
						            ; just below the monitor stack
    bset  DDRAD,$FF  	  ; Port AD will be output port to display (as an 8-bit binary nr) the nr of heads.
    bset  DDRT,$FF	  	; Port T is will be output port to display (as an 8-bit binary nr) the nr of tails.
    bset  DDRB,%00000001 ;PB0 is "Head/Tail" LED output.
    bclr  DDRB,%00000010 ; PB1 is pushbutton "die toss" switch input.
    clr   nr_heads    	; Initialize statistics to 0.
    clr   nr_tails
    clr   PTT				    ; Set all output pins low.
    clr   PORTB
    clr   PTAD		 
Top_of_loop:		        
    clrb    ; Use B as a 1-bit counter that will be stopped when the switch is depressed and 
            ;thereby will contain a random outcome: either 0 or 1.               
SW_wt_press:
    eorb #1     					; Toggle LSB of accumulator B (if high, make it low, and vice versa)
    ldaa  PushButton   		; Load accum A with the SW state (Only Bit #1 matters)
    anda #$02   					; Accum A = $02 if SW not pressed, and $00 if SW pressed
    bne   SW_wt_press 	  ; Hang in this loop until SW is pressed
    jsr   delay_rtn  		  ; Wait for pushbutton switch to stop bouncing
SW_wt_release:                        
    ldaa  PushButton 			; Arrive here when SW is presed, with random outcome in accum B
    anda  #$02 
    beq   SW_wt_release	  ; Hang in this loop until switch is released.
    jsr   delay_rtn       ; Wait for pushbutton switch to stop bouncing by calling delay_rtn subroutine.
    stab  LEDDisplay    	; Send HEAD/TAIL result to LED on Bit 0 of PORTB.
    cmpb  #1    				  ; If HEAD outcome, B = 1.  If TAIL outcome, B = 0.
    beq   heads_outcome
tails_outcome:
    inc   nr_tails			  ; Update nr_tails RAM location
    movb  nr_tails,ShowNumberOfTails   	; Mirror this value on Port T
    bra   Top_of_loop
heads_outcome:
    inc   nr_heads				; Update nr_heads RAM location
    movb  nr_heads,ShowNumberOfHeads  	; Mirror this on Port AD
    bra   Top_of_loop                  
;*********** End of main program*******************       
; Here is a short delay subroutine that delays for about
; 20 ms before returning.  It is used for pushbutton switch debouncing
delay_rtn:  
    ldy   #$ffff
delay_more: dey									  ;
    bne   delay_more 		  ;Count y down from $ffff to 0.           
    rts          				  ;Return addr (pop return addr off stack into PC)
; Here we intialize the RESET vector to point to the 
; start of the cointoss program
    ORG       $FFFE
    dc.w      cointoss              ; Intialize Reset Vector with starting address of coin toss program