www.pudn.com > avrepp.zip > avrepp.asm
;**** A P P L I C A T I O N N O T E A V R 3 2 5 ************************
;*
;* Title: High-speed Interface to Host EPP Parallel Port
;* Version: 1.0
;* Last updated: 2001.12.20
;* Target: All AVR Devices with 12 I/O pins or more
;*
;* Support E-mail: avr@atmel.com
;*
;* DESCRIPTION
;* This Application Note describes a method for high-speed bidirectional data
;* transfer between an AVR microcontroller and an off-the-shelf Intel x86
;* desktop computer.
;*
;* The code contains the EPP library and ISR, along with a sample application
;* which merely echoes to the host any data sent to it.
;*
;***************************************************************************
.include "8515def.inc"
; Handy application registers. EPP library registers are below.
.def tmp = R17 ; Ubiquitous temporary
.def par0 = R16 ; First function parameter
; Point of terminology:
; Tx and Rx are used throughout from the host's point of view
; (Tx, e.g. goes out from the host).
; The AVR program, however, has the notion of putting
; and getting data to/from a peer, where put corresponds
; to a host Rx operation.
; The terminology conversion (as it were) takes place in
; epp_getc/epp_putc.
;-----------------------------------------------------------
; Reset and interrupt vectors
.cseg
.org 0 ; Reset vector
rjmp start
.org INT0addr ; INT0 vector
rjmp epp_int0
;-----------------------------------------------------------
;
; start() - Come here after reset
;
; This is a sample main program, which just echoes
; characters sent from the host with a little bit
; of decoration.
.equ PROMPT = '>' ; prompt character
.equ CR = 0x0d ; Carriage Return
.equ LF = 0x0a ; Line Feed
start:
ldi tmp,low(RAMEND) ; Set up stack pointer
out SPL,tmp ; SP low half
ldi tmp,high(RAMEND)
out SPH,tmp ; SP high half
; Initialize the EPP - epp_init assumes interrupts are disabled.
rcall epp_init ; Initialization
sei ; Now we can enable interrupts
; This is a sample application which echoes (forever)
; what the host sends it over the EPP.
; The only modifications it does to the data stream are
; (1) a linefeed is inserted following any carriage return and
; (2) a prompt at the beginning of each line.
newline: ; beginning of new line
ldi par0,PROMPT ; prompt
rcall epp_putc ; send it
; Forever:
; Get character from host
loop:
rcall epp_getc
; Echo the character back to the host
echo:
rcall epp_putc ; echo
; To make it pretty, add a linefeed after any CR
cpi par0,CR ; after a CR,
brne loop
ldi par0,LF ; add a linefeed for niceness
rcall epp_putc
rjmp newline ; back to the top (prompt)
; End of sample application
;-----------------------------------------------------------
; This is the EPP library.
; Private definitions are here for data-hiding
; (and easy copying).
; Registers:
; The library uses 5 registers. Three provide
; the buffering mechanism, and the other two are
; dedicated to the ISR for performance/stack.
; The following dedicated registers (could be in SRAM)
; provide a one-element queue in each direction.
;
.def epprxbuf = R25 ; one-element queue to host
.def epptxbuf = R24 ; one-element queue from host
.def eppflag = R23 ; control bits (see below)
; Flags (bit numbers) in "eppflag"
.equ EPPC_OBUFFULL = 0 ; obuf (epprxbuf) is full
.equ EPPC_IBUFFULL = 1 ; ibuf (epptxbuf) is full
.equ EPPC_IOVERRUN = 2 ; Tx has overrun
; These two registers are dedicated to the ISR, and aren't saved.
; In an 8MHz AVR, these could probably be pushed/popped and still
; meet the deadline.
.def SAVE_SREG = R1 ; used to save SREG
.def itmp = r22 ; ISR work register
; These are the port pins used by the EPP.
; The four control lines use pins 2 and 4-6 of port D
.equ eppctlddr = DDRD ; control lines data direction
.equ eppctlin = PIND ; input
.equ eppctlout = PORTD ; output
; The control line assignments in PORTD are mostly conveniences,
; in that they sidestep the UART and INT1 lines.
; The only assignment we depend on is nDATASTR, assigned to INT0
.equ nDATASTR = PD2 ; Data Strobe (from host) [pin 14]
.equ nWRITE = PD4 ; Read/Write (from host) [pin 1]
.equ nINTR = PD5 ; Interrupt (to host) [pin 10]
.equ nWAIT = PD6 ; Device ready (to host) [pin 11]
; The eight data lines [pins 2-9] use (all of) port C
.equ eppdataddr = DDRC ; Data lines Data Direction
.equ eppdatain = PINC ; Data lines Input
.equ eppdataout = PORTC ; Data lines Output
; Use PORTB (LEDs) for debug
.equ debugddr = DDRB ; Data Direction for LEDs
.equ debugout = PORTB ; Port for LEDs
; If you don't want LED debugging, empty these two macros or remove them and
; the references to them
.macro LEDDEBUGINIT
ser itmp ; 0xFF
out debugddr,itmp ; output
out debugout,itmp ; off initially
.endmacro
.macro LEDDEBUG
mov itmp,@0
com itmp
out debugout,itmp
.endmacro
;------------------------------------------------------------------
;
; epp_init() - One-time initialization for the EPP unit.
; Input: none
; Output: none
; Notes: Assumes interrupts are disabled.
epp_init:
ldi eppflag,(0< EOI
sbr itmp,(0<