;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