Full Version : The DS Protocol by Dick Cappel (ASM)
avr >>ASSMBLER ROUTINES >>The DS Protocol by Dick Cappel (ASM)


AVR_Admin- 04-28-2006
About the DS protocol

The DS protocol was designed to provide firmware-based bidirectional host-to-slave inter processor communications for situations in which no hardware solution is available and the host and/or the slave in incapable of tending the interface in real time. The only specialized hardware required is two bidirectional I/O ports on each chip (alternatively two input ports and two output ports that can be put into an high impedance state may be used).

Link to Site: http://cappels.org/dproj/dspage/ds.htm

Firmware based protocol for low priority data transfer between a host and a busy slave processor with limited resources:
DS Protocol (Data transfer via handshake)

Distinguishing characteristics:

• Compact code and minimal hardware requirements -only two bidirectional I/O lines required

• Bidirectional byte-oriented protocol

• Designed for communication with slave processors that cannot guarantee response time or sampling frequency

• Low pin count


Overview

The DS protocol was designed to provide firmware-based bidirectional host-to-slave inter processor communications for situations in which no hardware solution is available and the host and/or the slave in incapable of tending the interface in real time. The only specialized hardware required is two bidirectional I/O ports on each chip (alternatively two input ports and two tri-statable output ports may be used).


Programmer's model:

When read, DS slaves conforming to the interface protocol appear as byte-wide two locations -one register for temporary storage of incoming data and one location for instructions.

Instructions and data are send one byte at a time with each byte preceded by a control bit, which when set, indicates and instructions. A cleared control bit indicates the following byte is data to be held in the Incoming Data Register until a later instruction byte tells the slave what to do with the data byte.

Minimum command set for full implementation

1R Write data to register R
2R Read data from register R
4A Write EEPROM data to memory location A within *current page, for devices with EEPROM.
5A Read EEPROM data from memory location A within *current page, for devices with EEPROM.
80 Read firmware version number in two bytes as [Version],[revision].

*Note: Assumes a 16 byte page. If there is more than one page of EEPROM, a page addressing mechanism must be defined for the target device.

The use of R and A above indicate register numbers and EEPROM addresses, respectively. F or example, command $1C would write the contents of the Incoming Data Register to register $C in the register set and command $2C would read the contents of that register back to the host. Similarly commands $48 and $58 would write and read EEPROM location 8 in devices that have EEPROM.

Memory other than EEPROM or I/O may be used with the 4A and 5A commands.


Description of protocol

DS messages are sent 9 bits at a time as one byte preceded by a control bit that indicates whether the byte following is meant to be stored in the Incoming Data Register or sent to the Instruction Interpreter. In the flowcharts below, the control bit is located in the carry bit in both the sending and receiving routines. The flowcharts and code on this page were written with the Atmel AVR processors in mind, but should be easily ported to other processors. The communications routines were coded directly from these flow charts.

Sending a byte and control bit via DS.

Receiving a byte and control bit via DS.

The byte-level protocol is, if anything, simple compared to a lot of other protocols. It is included here for completeness.


Bit level Protocol:

A single DS bit transaction is shown in the illustration below. The two signal lines involved, Attention and Data, are roughly similar in function to I2C 's SCL and SDA lines respectively. Also similar to I2C , there are passive pull-ups on each line and each chip drives the lines with the equivalent of open-drain outputs. Some microcontrollers have the ability to provide so-called weak pull-ups on their I/O pins, and with these, discreet pull-up resistors may not be needed. Take note that with high resistance pull-up devices or some very "weak" pull-ups, capacitance on the bus might make to too slow, and in some cases, even probing the bus with a high resistance probe might place enough capacitance across it to disturb bus activity.


Data Transfer
At the start of a bit transfer, the sender puts the data bit on the data line. After the data line has been given a chance to settle, the sender pulls the attention line low for some period of time. Periodically, it releases the attention line, waits for the line to settle, then peeks at the line to see if it is being held low by the receiver. If the receiver is holding the line low, to indicate that it has received the data bit, the sender inverts the data line to acknowledge the receiver holding the attention line low. The receive, upon seeing the data line reverse, releases the attention line, and the sender, seeing the attention line being released, releases the data line. That process concludes on bit transfer.

While it is a little bit cumbersome, it is robust in that there is handshaking on each bit that is sent.

Each message is composed of a byte preceded by a flag bit. The purpose of the control bit is to indicate to the slave whether a command or data is being sent. When the flag bit is a logic 1 a command is being sent. When the control bit is a logic 0 data is being sent. This signaling system allows simple register-based interface and command structure to be used. Additional details of the data format are shown in the Data Format section of this document.
DS does not allow more than two devices to be connected to the same interface: one host and one slave. Since there is no mechanism defined for detecting and resolving collisions, the slave may only transmit when requested by the host.

Because of the sampling of the attention line by the sender, there is some uncertainty in the data transfer rate. Without delving into the theory, suffice it to say that some combinations host and slave timing will result in particularly slow data transfer rates -on the order of minutes per byte have been observed. At very high speeds on some hardware data transmission may be unreliable or fail completely. It is therefore a good idea to experiment a little bit and determine a transfer speed that proves reliable. It might be necessary to increase pull-up current in order to achieve high enough data transfer rates. Remember that this interface is intended for applications where transfer speed in not particularly important.

The details of juggling the data direction control bits on bidirectional data ports has been omitted from the flow charts to improve readability.



Data Transfer

At the start of a bit transfer, the sender puts the data bit on the data line. After the data line has been given a chance to settle, the sender pulls the attention line low for some period of time. Periodically, it releases the attention line, waits for the line to settle, then peeks at the line to see if it is being held low by the receiver. If the receiver is holding the line low, to indicate that it has received the data bit, the sender inverts the data line to acknowledge the receiver holding the attention line low. The receive, upon seeing the data line reverse, releases the attention line, and the sender, seeing the attention line being released, releases the data line. That process concludes on bit transfer.

Each message is composed of a byte preceded by a flag bit. The purpose of the control bit is to indicate to the slave whether a command or data is being sent. When the flag bit is a logic 1 a command is being sent. When the control bit is a logic 0 data is being sent. This signaling system allows simple register-based interface and command structure to be used. Additional details of the data format are shown in the Data Format section of this document.

DS does not allow more than two devices to be connected to the same interface: one host and one slave. Since there is no mechanism defined for detecting and resolving collisions, the slave may only transmit when requested by the host.

Because of the sampling of the attention line by the sender, there is some uncertainty in the data transfer rate. Without delving into the theory, suffice it to say that some combinations host and slave timing will result in particularly slow data transfer rates -on the order of minutes per byte have been observed. At very high speeds on some hardware data transmission may be unreliable or fail completely. It is therefore a good idea to experiment a little bit and determine a transfer speed that proves reliable. It might be necessary to increase pull-up current in order to achieve high enough data transfer rates. Remember that this interface is intended for applications where transfer speed in not particularly important.

Below are flow charts illustrating the coding for bit and byte transmit and receive routines. The details of juggling the data direction control bits on bidirectional data ports has been omitted to improve readability.

Sample send and receive routines for ATMs AVR90S2313 and similar processors is included here . This file is also listed at the top of this page under "Downloads".


Routine to send a bit. The code in the listing referenced on this page contains a wait loop to prevent the sending of a bit before the data line is high. That wait loop follows the loop that waits for the Attention line to be high and is not shown on this flow chart.


Routine to receive a bit.


Settling and sampling delays

A delay time is used in the bit level protocol to allow for settling of the attention and data lines and provide adequate time for the attention line to be sampled by the receiving device. Too short of a delay will result in the interface locking up. Too long of a delay will slow things down a lot. There are theoretically some "magic" delays, that depend on the clock rates of the master and salve devices that will result in very long transmission times -these are analogous to beats between harmonics of the sampling rates. The delay values are not critical. Select the delay numbers that provide the fastest robust performance.



Avoiding hang-ups

The DS protocol was designed as a means of communications between two integrated circuits on the same circuit board and it can lock up if the attention line is momentarily shorted to ground since both the host and the slave will see this as an attention signal by the other and will each hold the attention line low, each waiting in vain for the other change the state of the data bit. The capacitance of an oscilloscope or logic analyzer probe or even a high resistance voltmeter may be enough to trigger this situation. The chances of this situation developing may be minimized by one of the following precautions:

1. Do not probe the Attention line.

2. Insert a sufficiently large resistor in series with test points for the Attention and Data lines. (it might have to be several megohms).

3. Use sufficiently low resistance pull-up resistors, particularly on the Attention line.

4. Make the receive routines able to time out if the word transmission does not complete within a reasonable time.

In some applications it is impossible to completely protect the attention line from being affected unintentionally. In one such case, I found the solution was to maintain a counter during timed interrupts and limit the amount of time the DS routines had to wait for transitions on the Attention and Data lines.

AVR_Admin- 04-28-2006
CODE

; DS send and receive a byte.
; 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.
 
 
;.include "tn12def.inc"
 
.include "2313def.inc"; REMEMBER TO INITIALIZE THE STACK POINTER
 
.def rxtxbyte = r2;byte to be sent
.def temp  = r16;scratch
.def delayc = r17;counter used for timing delay
.def bitcount= r18;counter for number of bits transfered
 
.equ dataline= 0;B0 Data line
.equ attline = 1;B1 Attention line
.equ dout = 2;B2 Data output pin for test purposes
 
.equ setltime= $01;How long to wait for data and I/O lines to settle
 
.ORG $0000
 
ldi     temp,low(ramend)
out     spl,temp     ;set the 8 bit stack pointer to the top of ram FOR AT90S2313
ldi temp,$04
out  DDRB,temp
ldi temp,$03;Set B0 and B1 weak pullups high.
out PORTB,temp
 
cbi PORTB,dout
rcall shortdelay
 
 

main:
ldi temp,$00
mov rxtxbyte,temp
clc
rcall SendByte
rjmp  main
 
 
 
;//////////SEND A BYTE
; Send carry bit as first bit, then send rxtxbyte bit-by-bit. rxtxbyte destroyed.
SendByte:
 
ldi bitcount,$09
 
S1:

sbis PINB,attline ;Wait for Attention line to go high =--SEND A BIT
rjmp S1
sbis     PINB,dataline          ;! This instruction not in flow chart and not extensively tested
rjmp S1                     ;but is included because it covers a theoretical risk.
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 peak
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
 
 
 
 
ReceiveByte:;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:
ldi delayc,setltime  
D1: dec delayc
brne D1
ret


AVR_Admin- 04-28-2006
DS interface test tool
(Data transfer via handshake test tool)

The DS protocol was designed to provide firmware-based bidirectional host-to-slave inter processor communications for situations in which no hardware solution is available and the host and/or the slave in incapable of tending the interface in real time. The only specialized hardware required is two bidirectional I/O ports on each chip (alternatively two input ports and two tri-statable output ports may be used. In other words, it provides some of the functionalit of the Two-Wire-Interface (TWI, or I2C as named by Philips) where an actual TWI is not feasible in either hardware or firmware.


Link: http://cappels.org/dproj/DS%20tool/dsptt.htm

CODE

;©2002 Richard Cappels All Rights Reserved. Email projects@cappels.org
;No restriction on republishing rights provided proper attribution is given.
;*********************************
;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



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.