Created
November 29, 2014 03:58
-
-
Save BobBurns/8d678db70d83f0c1f34b to your computer and use it in GitHub Desktop.
reaction timer program from AVR Programming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; | |
;reaction timer program from AVR programming | |
;button on PD2 // leds on PORTB | |
; | |
.equ UBBRvalue = 12 | |
.equ UCSR0C = 0xc2 ;SRAM address of UCSR0C | |
.def temp = r16 | |
.def count = r17 | |
.def temp2 = r18 | |
.def xL = r26 ;x reg used as global counter | |
.def xH = r27 | |
.def zL = r30 | |
.def zH = r31 | |
.device atmega168 | |
;---- global variables ---- | |
.cseg | |
.org 0 | |
jmp reset | |
;----- Main ----- | |
.org 0x0034 | |
reset: | |
;inittialize Stack | |
ldi temp,low(RAMEND) | |
out SPL,temp | |
ldi temp,high(RAMEND) | |
out SPH,temp | |
;initialize USART | |
ldi temp,high(UBBRvalue) ;baud rate param | |
sts UBRR0H,temp | |
ldi temp,low(UBBRvalue) | |
sts UBRR0L,temp | |
lds temp,UCSR0A | |
ori temp,(1 << U2X0) ;set use 2x because %error actual baud > .5 | |
sts UCSR0A,temp | |
;--- USART register values | |
ldi temp,(1 << TXEN0) | (1 << RXEN0) ;enable transmit and receive | |
sts UCSR0B,temp | |
ldi temp,(1 << UCSZ01) | (1 << UCSZ00) ;8 data bits, 1 stop bit | |
sts UCSR0C,temp | |
;--- init Timer ---- | |
lds temp,TCCR1B | |
sbr temp,(1 << CS11) | (1 << CS10) ;set clock speed 1/64 011 | |
sts TCCR1B,temp | |
;--- Init LEDs and Button port --- | |
ldi temp,0xff | |
out DDRB,temp | |
sbi PORTD,PD2 ;enable pullup on PD2 | |
;--- send a message | |
ldi zH, high(hello_str * 2) | |
ldi zL, low(hello_str * 2) | |
rcall print_s | |
ldi zH,high(h2_str * 2) | |
ldi zL,low(h2_str * 2) | |
rcall print_s | |
ldi zH,high(press_str * 2) | |
ldi zL,low(press_str *2) | |
rcall print_s | |
;--- main event loop --- | |
; | |
;--- get a character | |
lp: rcall receive | |
brcc lp | |
;--- random delay? | |
.equ d_cnt = 50000 | |
lds count,TCNT1L ;get psuedo random number from timer | |
ldi temp,0x05 ; >> 5 // use lower 3 bits for outer loop | |
rs_lp: lsr count | |
dec temp | |
brne rs_lp | |
inc count ;has to be at least one | |
outer: ldi r24,low(d_cnt) | |
ldi r25,high(d_cnt) | |
delay: sbiw r25:r24,1 | |
nop ;this makes four clock cycles = 200,000 us | |
brne delay | |
dec count | |
brne outer | |
;--- go! | |
ldi zH,high(go_str *2) | |
ldi zL,low(go_str * 2) | |
rcall print_s | |
ldi temp,0xff | |
out PORTB,temp ;light leds | |
ldi temp,0x00 | |
sts TCNT1L,temp ;reset counter | |
sts TCNT1H,temp | |
;--- check one --- | |
sbis PIND,PD2 | |
rjmp press1 | |
p_lp: sbic PIND,PD2 | |
rjmp p_lp | |
;bit shift divide timer value 1/16 | |
lds temp,TCNT1L ;always load low byte first! | |
lds temp2,TCNT1H | |
clc | |
ldi count,4 | |
sft_l: clc | |
ror temp2 | |
ror temp | |
dec count | |
brne sft_l | |
mov r24,temp2 | |
rcall t_htoa | |
mov r24,temp | |
rcall t_htoa | |
rjmp again | |
press1: | |
ldi zH,high(ch_str * 2) | |
ldi zL,low(ch_str * 2) | |
rcall print_s ;print cheat message | |
again: | |
ldi temp,0x00 | |
out PORTB,temp | |
LDI zH,high(a_str * 2) | |
ldi zL,low(a_str * 2) | |
rcall print_s | |
rjmp lp | |
;--- Subroutines --- | |
;print string function | |
;takes Z loaded with pointer to string with first byte being length | |
;uses r16,r17,r24 | |
.def byte_tx = r24 | |
print_s: | |
lpm count,Z+ | |
for1: lpm byte_tx,Z+ | |
wait: lds temp,UCSR0A | |
sbrs temp,UDRE0 ;wait for Tx buffer to be empty | |
rjmp wait ;not ready | |
sts UDR0,byte_tx; | |
dec count | |
brne for1 | |
ret | |
;send ascii representation of one byte | |
;takes byte in r24. then | |
;uses r24 as low nibble to send and r25 for high nibble | |
t_htoa: | |
lds temp,UCSR0A | |
sbrs temp,UDRE0 | |
rjmp t_htoa | |
ldi temp,0x30 ;ascii offset | |
mov r25,r24 | |
lsr r25 | |
lsr r25 | |
lsr r25 | |
lsr r25 | |
cpi r25,0x0A | |
brlt no_e | |
ldi temp,0x37 ;extended hex | |
no_e: add r25,temp | |
sts UDR0,r25 | |
t_2: lds temp,UCSR0A | |
sbrs temp,UDRE0 | |
rjmp t_2 | |
ldi temp,0x30 ;ascii offset | |
andi r24,0x0f ;low nibble | |
cpi r24,0x0a | |
brlt no_e2 | |
ldi temp,0x37 | |
no_e2: add r24,temp ;add 0x30 to get ascii representation | |
sts UDR0,r24 | |
ret | |
receive: | |
clc | |
lds temp,UCSR0A | |
sbrs temp,RXC0 ;is byte in rx buffer? | |
ret ;not yet | |
lds byte_tx,UDR0; | |
sec ;to indicate a byte was received | |
ret | |
transmit: | |
lds temp,UCSR0A | |
sbrs temp,UDRE0 | |
rjmp transmit | |
sts UDR0,r24 | |
ret | |
hello_str: .db 22,"** Reaction Timer **",0x0d,0x0a,0x00 | |
h2_str: .db 22,"--------------------",0x0d,0x0a,0x00 | |
press_str: .db 26," Press any key to start.",0x0d,0x0a,0x00 | |
rdy_str: .db 14,"Get ready...",0x0d,0x0a,0x00 | |
go_str: .db 10,"** GO **",0x0d,0x0a,0x00 | |
ch_str: .db 32,"You're only cheating yourself.",0x0d,0x0a,0x00 | |
a_str: .db 30, " Press any key to try again.",0x0d,0x0a,0x00 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment