;Dick Cappels' project pages ........You should be able to copy and paste this into an assembler file.
;©2002 Richard Cappels All Rights Reserved email projects@cappels.org
;HOME
;*********************************
;2313 monitor program; should work on any AVR with UART
;*********************************
.include "2313def.inc"
.equ clock = 4000000 ;clock frequency
.equ baudrate = 9600 ;choose a baudrate
.equ baudconstant = (clock/(16*baudrate))-1
.def temp = r16 ;general purpose variable
.def inchar = r17 ;char destined to go out the uart
.def outchar = r18 ;char coming in from the uart
.def inbytel = r19 ;lower byte for asci-hex conversion
.def inbyteh = r20 ;higher byte for asci-hex conversion
.def currentadd = r21 ;pointer to write address for first page of memory
.org $00
rjmp reset ;reset handle
reset: rjmp init ;start init
init:
ldi temp,low(ramend)
out spl,temp ;set spl
ldi temp,baudconstant
out ubrr,temp ;load baudrate
rcall TypeGreeting
ldi currentadd,$00
; rcall establish_address_send_data ;estsablish current address
loop: ;*****command interpretation loop****
ldi outchar,$3A ;send prompt (colon char) to terminal
rcall rs_send
ldi outchar,$20
rcall rs_send
ldi outchar,$20
rcall rs_send
rcall rs_rec ;get char from terminal and
;interpret char
cpi inchar,$2F ;if / decrement current address and display
breq decrementanddisplay
cpi inchar,$3F ;if ? then display meny
breq domenu
cpi inchar,$20 ;if <space>, increment current address and dispaly
breq incaddress
cpi inchar,$0D ;if carriage return, read data at current address
breq readdata
cpi inchar,$21 ;if ! then use watchdog timer to reset the
breq pull_the_plug
cpi inchar,$25 ;if % (percent sign) monitor memory in binary
breq monitorbinary
andi inchar,$DF ;make upper-case ascii
cpi inchar,$52 ;if R or r, read data at current address
breq readdata
cpi inchar,$57 ;if W or w, write data at current address
breq writedata
cpi inchar,$41 ;if A or a, set new current address
breq setaddress
cpi inchar,$51 ;if Q or q, restart monitor
breq reset
cpi inchar,$4D ;if M or m, monitor memory location
breq monitormemory
rjmp loop ;keep going
decrementanddisplay: ;decrement current address and display current memory contens
dec currentadd
rcall typeaddressdata
rjmp loop
monitorbinary: ;send contents of memory as binary until char received from terminal
rcall crlf
rcall sendaddress ; write adress and a space char
ldi ZH,0 ; set Z register pair to point to current address
mov ZL,currentadd
ld inbytel,Z ; get contents of (correntadd) into inbytel
rcall sendbinarybyte ;send that byte to terminal
ldi outchar,$20 ;send space char to terminal
rcall rs_send
sbi ucr,rxen ;set reciver bit.
sbis usr,rxc ;repeat until char
rjmp monitorbinary
rjmp loop ;exit when char received
domenu:
rcall TypeGreeting
rjmp loop
pull_the_plug: ;enable watchdog timer and wait for hardware reset
ldi ZH,high(2*resetmessage) ; Load high part of byte address into ZH
ldi ZL,low(2*resetmessage) ; Load low part of byte address into ZL
rcall sendstring
wdr
ldi temp,$08
out wdtcr,temp
wait_for_reset:
rjmp wait_for_reset
readdata: ;read data from current location to terminal
rcall typeaddressdata
rjmp loop
writedata:
ldi ZH,high(2*newdatamessage) ; Load high part of byte address into ZH
ldi ZL,low(2*newdatamessage) ; Load low part of byte address into ZL
rcall sendstring ;ask for new datat to enter
rcall recbyte
ldi ZH,$00
mov ZL,currentadd
st Z,inbytel
rcall typeaddressdata
rjmp loop
incaddress: ;increment current address and display current memory contens
inc currentadd
rcall typeaddressdata
rjmp loop
setaddress: ;set current address
rcall establish_address_send_data
rjmp loop
monitormemory: ;send contents of memory until char received from terminal
rcall crlf
rcall sendaddress ; write adress and a space char
ldi ZH,0 ; set Z register pair to point to current address
mov ZL,currentadd
ld inbytel,Z ; get contents of (correntadd) into inbytel
rcall sendbyte ;send that byte to terminal
ldi outchar,$20 ;send space char to terminal
rcall rs_send
sbi ucr,rxen ;set reciver bit.
sbis usr,rxc ;repeat until char
rjmp monitormemory
rjmp loop ;exit when char received
rs_send:
sbi ucr,txen ;set sender bit
sbis usr,udre ;wait till register is cleared
rjmp rs_send
out udr,outchar ;send the byte
cbi ucr,txen ;clear sender bit
ret ;go back
rs_rec:
sbi ucr,rxen ;set reciver bit...
sbis usr,rxc ;wait for a byte
rjmp rs_rec
in inchar,udr ;read valuable
cbi ucr,rxen ;clear register
ret ;go back
rs_rec_echo: ;receive and echo char
rcall rs_rec
mov outchar,inchar
rcall rs_send ;send to comX
ret
crlf: ;send carriage return and line feed.
ldi ZH,high(2*crlfmessage) ; Load high part of byte address into ZH
ldi ZL,low(2*crlfmessage) ; Load low part of byte address into ZL
rcall sendstring
ret
sendstring: ;call with location of string in Z
lpm ; Load byte from program memory into r0
tst r0 ; Check if we've reached the end of the message
breq finishsendstering ; If so, return
mov outchar,r0
rcall rs_send
adiw ZL,1 ; Increment Z registers
rjmp sendstring
finishsendstering:
ret
sendline: ;send a string terminated in cariage return and line feed
;call with location of start of string in Z
rcall sendstring
rcall crlf
ret
sendaddress: ;send address followed by space char
mov inbytel,currentadd
rcall sendbyte
ldi outchar,$20
rcall rs_send
ret
TypeGreeting:
rcall crlf
rcall crlf
ldi ZH,high(2*hellomessage) ; Load high part of byte address into ZH
ldi ZL,low(2*hellomessage) ; Load low part of byte address into ZL
rcall sendline ; sent it.
ret
askforaddress:
ldi ZH,high(2*askaddressmessage) ; Load high part of byte address into ZH
ldi ZL,low(2*askaddressmessage) ; Load low part of byte address into ZL
rcall sendstring ; sent it.
ret
byte_to_asciihex: ;convert byte in inbytel to ascii in inbyteh,nbytel
mov inbyteh,inbytel
lsr inbyteh ;convert the high nybble to ascii byte
lsr inbyteh
lsr inbyteh
lsr inbyteh
subi inbyteh,$D0 ;add $30
cpi inbyteh,$3A
brlo PC+2 ;If less than 9 skip next instruction
subi inbyteh,$F9 ;add 8 to ASCII (if data greater than 9)
; byte in inbyteh represents upper nybble that was in inbytel at start
andi inbytel,0b00001111 ;convert the lower nybble to ascii byte
subi inbytel,$D0 ;add $30
cpi inbytel,$3A
brlo PC+2 ;If less than 9 skip next instruction
subi inbytel,$F9 ;add 8 to ASCII (if data greater than 9)
; byte in inbyteh represents upper nybble that was in inbytel at start
ret
asciihex_to_byte: ;convert ascii in inbyteh,inbytel to byte in inbytel
sbrc inbyteh,6 ;convert high byte
subi inbyteh,$f7 ;add inbyte,temp ;if bit 6 is set, add $09
andi inbyteh,$0F
sbrc inbytel,6 ;convert low byte
subi inbytel,$f7 ;add inbyte,temp ;if bit 6 is set, add $09
andi inbytel,$0F
lsl inbyteh ;combine them
lsl inbyteh
lsl inbyteh
lsl inbyteh
or inbytel,inbyteh
ret
sendbyte: ;send byte contained in inbytel to terminal
rcall byte_to_asciihex
mov outchar,inbyteh
rcall rs_send
mov outchar,inbytel
rcall rs_send
ret
sendbinarybyte:
ldi temp,$08
stillsendingbinary:
ldi outchar,$30
rol inbytel
brcc dontsendone
ldi outchar,$31
dontsendone:
rcall rs_send
dec temp
brne stillsendingbinary
ret
recbyte: ; get ascii hex byte from terminal. Result in inbytel
rcall rs_rec_echo ;read from comX
mov inbyteh,inchar ;put 1st char from uart into inbyteh for hex conversion
rcall rs_rec_echo
mov inbytel,inchar ;put 2nd char from uart into inbytel for hex conversion
rcall asciihex_to_byte ;convert ASCII to byte in inbytel
ret
typeaddressdata:
rcall crlf ;send carriage return and life feed
rcall sendaddress ; write adress and a space char
ldi ZH,0 ; set Z register pair to point to current address
mov ZL,currentadd
ld inbytel,Z ; get contents of (correntadd) into inbytel
rcall sendbyte ;send that byte to terminal
ldi outchar,$20 ;send space char to terminal
rcall rs_send
ret
establish_address_send_data:
rcall askforaddress ;ask for memory address
rcall recbyte ;get a byte from terminal
mov currentadd,inbytel ;save received byte as current address
rcall typeaddressdata
ret
hellomessage:
.db "2313 monitor 2002.02.01 V Dick Cappels"
.db $0A,$0D
.db "A = set address "
.db $0A,$0D
.db "W = write "
.db $0A,$0D
.db "R or <CR> = show memory contents at current address "
.db $0A,$0D
.db "<space> = increment current address and display "
.db $0A,$0D
.db "/ = decrement current address and display "
.db $0A,$0D
.db "M = monitor data until key pressed"
.db $0A,$0D
.db "% = monitor data and show in binary "
.db $0A,$0D
.db "? = type opening screen."
.db $0A,$0D
.db "Q = restart firmware"
.db $0A,$0D
.db "! = reset chip"
.db $0A,$0D
.db "All address and data values are hexadecimal and are byte wide."
.db $0A,$0D
.db 00,00
askaddressmessage:
.db "Address: "
.db $00,00
crlfmessage:
.db $0A,$0D
.db 00,00
newdatamessage:
.db "new data: "
.db $00,$00
resetmessage:
.db "Hardware reset via watchdog initiated."
.db $00,$00
;http://www.projects.cappels.org/
; HOME