;Dick Cappels' project pages projects@cappels.org - you should be able to copy and paste this text into an assembler file.
;©2002 Richard Cappels All Rights Reserved. Email projects@cappels.org
;No restriction on republishing rights provided proper attribution is given.
;HOME
;
;*********************************
;2313 based DS port test tool
;*********************************
.include "2313def.inc"
.equ setltime1 = $08 ; ;How long to wait for data and I/O lines to settle first part
.equ setletime2 = $80 ;How long to wait for I/O on DS port to settle 2nd part
.equ clock = 4000000 ;clock frequency
.equ baudrate = 9600 ;choose a baudrate
.equ baudconstant = (clock/(16*baudrate))-1
.equ dataline = 0 ;B0 Data line
.equ attline = 1 ;B1 Attention line
.equ dout = 2 ;B2 Data output pin for test purposes
.def rxtxbyte = r2 ;byte to be sent
.def secondelay = r3
.def index = r4 ;used to index commands while sending sequence
.def delayreg1 = r5
.def delayreg2 = r6
.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
.def delayc = r22 ;counter used for timing delay
.def bitcount = r23 ;counter for number of bits transfered
; Note: flagsreg bit 0 true indicates that DS receiver to be disconnected
.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
ldi currentadd,$02
ldi temp,$04
out DDRB,temp
ldi temp,$03 ;Set B0 and B1 weak pullups high.
out PORTB,temp
;Read contents of EEPROM for dealy1 and 2 data
wratzA: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wratzA
ldi temp,$01
out eear,temp ;Move to EEPROM address register
sbi eecr,eere ;Trigger the read
in delayreg1,eedr ;Get the data into temp
wratzB: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wratzB
ldi temp,$02
out eear,temp ;Move to EEPROM address register
sbi eecr,eere ;Trigger the read
in delayreg2,eedr ;Get the data into temp
cbi PORTB,dout
rcall shortdelay
rcall DoMenu
rjmp loop ;Get started
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
sendicset:
sec
rcall SendSByte
ldi ZH,high(2*Commandsentmessage);Load high part of byte address into ZH
ldi ZL,low(2*Commandsentmessage);Load low part of byte address into ZL
rcall sendstring
rjmp loop
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
waitforinput:
sbic PINB,attline ;in spare time check for Attention line to go low
rjmp noinput2
rcall ReceiveSByte ;get byte from DS port
ldi currentadd,$02 ;set current address to DS data register
rjmp readdata ;output data at current address
noinput2:
sbi ucr,rxen ;set reciver bit...
sbis usr,rxc ;wait for a byte
rjmp waitforinput
in inchar,udr ;read variable
cbi ucr,rxen ;clear register
;//////check for input from temrminal and get data if present
cpi inchar,$2F ;If / then send contents of r2 via SS port with carry set
breq sendicset
cpi inchar,$3F ;If ? then type greeting
breq domenu
cpi inchar,$20 ;If space bar,get input data
breq writedata
cpi inchar,$0D ;If carriage return, send last value to terminal
breq readdata
cpi inchar,$21 ;If ! then use watchdog timer to reset the
breq pull_the_plug
;////// UPPER-CASE the character//////
andi inchar,$DF ;Make upper-case ascii
cpi inchar,$44 ;If D or d, read registers from 0 through B (commands $20 through $2B sent)
breq sendsequence
cpi inchar,$4D ;If M or m, send data at r2 as data to DS port
breq senditit
cpi inchar,$54 ;If T or t, set DS port delay
breq writedelayreg
cpi inchar,$53 ;If S or s, get data from keyboard and send it to DS device
breq getnandsendata
rjmp loop ;keep going
writedelayreg:
rcall showdelay
mov inbytel,delayreg2 ;Get contents of (delayreg[x]) into inbytel
rcall sendbyte ;Send that byte to terminal
ldi outchar,$20 ;Send space char to terminal
rcall rs_send
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
rcall recbyte ;Get byte from terminal to bytel
mov delayreg1,inbytel
ldi outchar,$20
rcall rs_send
rcall recbyte ;Get byte from terminal to bytel
mov delayreg2,inbytel
ldi temp,$01
wrat1: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wrat1
out eear,temp
out eedr,delayreg1 ;Set up the write data
cli ;Inhibit interrupts -**** INTERRUPTS NOT RE-ENABLED CAUTION!
sbi eecr,eemwe
sbi eecr,eewe
ldi temp,$02
wrat2: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wrat2
out eear,temp
out eedr,delayreg2 ;Set up the write data
cli ;Inhibit interrupts -**** INTERRUPTS NOT RE-ENABLED CAUTION!
sbi eecr,eemwe
sbi eecr,eewe
rcall crlf
rjmp loop
sendsequence:
rjmp sendsequenceit
senditit:
clc
rcall SendSByte
ldi ZH,high(2*Datasentmessage) ;Load high part of byte address into ZH
ldi ZL,low(2*Datasentmessage) ;Load low part of byte address into ZL
rcall sendstring
rjmp loop
domenu:
rcall TypeGreeting
rcall showdelay
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
getnandsendata:
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 data to enter
rcall recbyte
ldi ZH,$00
mov ZL,currentadd
st Z,inbytel
; rcall typeaddressdata
; 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
clc
rcall SendSByte ;Send that data as data
;Ask for register to send it to
ldi ZH,high(2*whatregistermessage) ;Load high part of byte address into ZH
ldi ZL,low(2*whatregistermessage) ;Load low part of byte address into ZL
rcall sendstring
ldi inbyteh,$31 ;Fist character is $31 because its a send command
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
ldi ZH,$00
mov ZL,currentadd
st Z,inbytel
sec
rcall SendSByte
;Confirm data sent
ldi ZH,high(2*Datasentmessage) ;Load high part of byte address into ZH
ldi ZL,low(2*Datasentmessage) ;Load low part of byte address into ZL
rcall sendstring
rjmp loop
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
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
hellomessage:
.db "DS Interface test tool 03 November 2002 Dick Cappels"
.db $0A,$0D,$0A,$0D
.db "Space bar = Enter value "
.db $0A,$0D
.db "M or m = Send value as data "
.db $0A,$0D
.db "/ = Send value as command"
.db $0A,$0D
.db "S = Send value from keyboard to register "
.db $0A,$0D
.db "D = Dump registers 0..F"
.db $0A,$0D
.db "<RETURN> = Print last value buffer"
.db $0A,$0D
.db "T or t = Set DS port delay parameter"
.db $0A,$0D
.db "! = reset chip"
.db $0A,$0D
.db "? = Display menu"
.db $0A,$0D
.db "All address and 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
delaymessage:
.db $0A,$0D
.db "Current delay value = $"
.db $00,$00
newdatamessage:
.db "Enter Value: $"
.db $00,$00
resetmessage:
.db "Hardware reset via watchdog initiated."
.db $00,$00
Datasentmessage:
.db " Data Sent."
.db $0A,$0D
.db $00,$00
Commandsentmessage:
.db "Command Sent. "
.db $0A,$0D
.db $00,$00
whatregistermessage:
.db "Enter register to send data to ($0..$F):"
.db $00,$00
; DS send and receive a byte using DS protocol.
; Two I/O pins are used, one for data/signaling and one only for signaling.
; The pins are bidirectional with weak pullups (or optionally, exernal pullups)
; Protocol is byte based via the rxtxbyte register.
; A 9th bit is transferred through the carry bit. When a 1, data is being transferred.
; When the 9th bit is a 0, an instruction is being transferred.
;//////////SEND A BYTE
; Send carry bit as first bit, then send rxtxbyte bit-by-bit. rxtxbyte destroyed.
SendSByte:
ldi bitcount,$09
S1:
sbis PINB,attline ;Wait for Attention line to go high
rjmp S1
sbis PINB,dataline ;Wait for Data line to go high = possible improvement
rjmp S1
sbi PORTB,dataline ;Put data on data line
cbi DDRB,dataline
brcs R1
cbi PORTB,dataline
sbi DDRB,dataline
R1:
cbi PORTB,attline ;Set Attention line low
sbi DDRB, attline
rcall shortdelay ;Wait a short time so other chip can see Attnetion line is low
cbi DDRB,attline ;Release Attention line for a peek
sbi PORTB,attline
rcall shortdelay ;Short delay to allow settling of lines
sbic PINB,attline ;If Attention line isn't low, go back and put it low again, else continue
rjmp R1
brcs szero ;Invert data line
sbi PORTB,dataline
cbi DDRB,dataline
rjmp R3
szero: cbi PORTB,dataline
sbi DDRB,dataline
R3:
sbis PINB,attline ;Wait for Attention line to go high
rjmp R3
cbi DDRB,dataline ;Let data line float
sbi PORTB,dataline
;-finished sending a bit
rol rxtxbyte ;Shift rxtxbyte through carry
dec bitcount
brne S1 ;Continue until all bits sent
ret
ReceiveSByte: ;Get a byte into rxtxbyte, and "start bit" into carry bit.
ldi bitcount,$09
W3: ;Get a bit from the input into the carry
sbic PINB,attline ;Wait for Attention line to go low
rjmp w3
clc ;Latch dataline into carry bit
sbis PINB,dataline
rjmp NotaOne
sec
cbi PORTB,attline ;ACK by pulling attention line low
sbi DDRB, attline
W1: ;Wait for data line to go low
sbic PINB,dataline
rjmp W1
rjmp RelesaseAttLineAndGo
NotaOne:
cbi PORTB,attline ;ACK by pulling attention line low
sbi DDRB, attline
W2: ;Wait for data line to go high
sbis PINB,dataline
rjmp W2
RelesaseAttLineAndGo: ;Release attention line
cbi DDRB, attline
sbi PORTB,attline ;DONE RECEIVING BIT
rol rxtxbyte ;Shift rxtxbyte through carry
dec bitcount
brne W3 ;Continue until all bits sent
ret
shortdelay:
mov delayc,delayreg1
outerloop:
mov secondelay,delayreg2
innerloop:
dec secondelay
brne innerloop
dec delayc
brne outerloop
ret
sendsequenceit:
rcall crlf
rcall crlf
ldi temp,$20
mov index,temp
continuetosend:
mov inbytel,index
rcall byte_to_asciihex ;convert byte in inbytel to ascii in inbyteh,nbytel
mov outchar,inbytel
rcall rs_send
ldi outchar,$20 ;send space char to terminal
rcall rs_send
mov rxtxbyte,index
sec
rcall SendSByte
rcall ReceiveSByte
mov inbytel,rxtxbyte
rcall sendbyte ;send that byte to terminal
rcall crlf
inc index
ldi temp,$30
cp index,temp
brne continuetosend
rcall crlf
rjmp loop
showdelay:
ldi ZH,high(2*delaymessage) ;Load high part of byte address into ZH
ldi ZL,low(2*delaymessage) ;Load low part of byte address into ZL
rcall sendstring
mov inbytel,delayreg1 ;Get contents of (delayreg[x]) into inbytel
rcall sendbyte ;Send that byte to terminal
ldi outchar,$20 ;Send space char to terminal
rcall rs_send
mov inbytel,delayreg2 ;Get contents of (delayreg[x]) into inbytel
rcall sendbyte ;Send that byte to terminal
ldi outchar,$0A ;Send space char to terminal
rcall rs_send
ldi outchar,$0D ;Send space char to terminal
rcall rs_send
ldi outchar,$0A ;Send space char to terminal
rcall rs_send
ldi outchar,$0D ;Send space char to terminal
rcall rs_send
ret
;http://projects.cappels.org/
;HOME