;******************************************************************************* ;N64 ASM Joseph Weaver, jew17@cornell.edu ;Atmel 90S1200 code to poll a nintendo 64 controller ;and report the response in 4 selectable words on port B ;April, 2002 ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ; ; ;****************************************************************************** ;******************************** .nolist .include "AT90S1200def.inc" .list ;******************************** ;define registers .def Temp =r16 ;temporary register .def Temp2 =r23 ;second temporary register .def WordRq =r17 ;Word Requested .def Word0 =r18 ;first 8 bits .def Word1 =r19 ;second .def Word2 =r20 ;3rd .def Word3 =r21 ;4th .def PollEn =r24 ;Poll sheduling .def Save =r25 ;SREG saving .def Reload =r26 ;******************************** ;set up macros here .MACRO __DELAY_USB ldi R27,LOW(@0) __DELAY_USB_LOOP: dec R27 brne __DELAY_USB_LOOP .ENDM ;********************************* ;set up the interrupt vectors ;Vector Address Source Interrupt Definition ;1 $000 RESET Hardware Pin and Watchdog Reset ;2 $001 INT0 External Interrupt Request 0 ;4 $002 TIMER0,OVF0 Timer/Counter0 Overflow ;5 $003 ANA_COMP Analog Comparator ;intialize the code .cseg .org $0000 rjmp RESET ;reset entry vector reti RJMP Timer reti RESET: ;clear all the registers clr Temp ;initialize variables clr Temp2 clr Word0 clr Word1 clr Word2 clr Word3 clr WordRq clr PollEn clr Save clr Reload ;set up the PORTS ldi Temp, 0b1000001 out DDRD, Temp ;PORTD 0,6 is output, 1-5 input ser Temp out DDRB, Temp ;PORTB is an output ;set up timer 0 for 1 mSec ticks ldi Temp, 0b00000010 out TIMSK, Temp ;enable interrupt ldi Temp, 0b00000100 out TCCR0, Temp ;prescale at CK/256 ldi Reload,55 out TCNT0, Reload ;timer overflows every 200 ticks = 2.56 ms ;start with polling disabled clr PollEn cbi PORTD,6 ;enable watchdog at 16ms ldi Temp,0b00001000 out WDTCR,Temp ;Start the clock ticking sei ;enable all interrupts ;infinite loop ILOOP: wdr ;reset the watchdog timer ;******************* ;Word transfer block ;******************* ;get the current word request off PORTD.2 and PORTD.3 clr WordRq sbic PIND,3 ori WordRq, 0b00000001 lsl WordRq sbic PIND,2 ori WordRq, 0b00000001 ;assert the proper word on PortB CPI WordRq, 0 BRNE SHOWW1 OUT PORTB, Word0 SHOWW1: CPI WordRq, 1 BRNE SHOWW2 OUT PORTB, Word1 SHOWW2: CPI WordRq, 2 BRNE SHOWW3 OUT PORTB, Word2 SHOWW3: CPI WordRq, 3 brne ENDRQ OUT PORTB, Word3 ENDRQ: ; ldi Temp2, 0b10110100 ; out PORTB, Temp2 ; out PORTB, Word0 TST PollEn BREQ ILOOP ;don't poll, unless enabled ;******************* ;Polling block ;******************* clr Temp2 clr PollEn ;reset poll enable for next interrupt ;assert 7 nintendo logic 0's to the pulldown circuit OUT0: sbi PORTD, 0 __DELAY_USB 18 cbi PORTD, 0 __DELAY_USB 7 inc Temp2 cpi Temp2, 7 brne OUT0 clr Temp2 clr Temp ;assert 2 nintendo logic 1's to pulldown circuit ;note that it takes less to do this explicitly twice than loop ;also final delay is not needed, line will float high OUT1: sbi PORTD, 0 __DELAY_USB 7 cbi PORTD, 0 __DELAY_USB 18 sbi PORTD, 0 __DELAY_USB 7 cbi PORTD, 0 ;slurp data ;note: we don't think there's enough time between bits to select which word we write to, so we do 4 explicit loops ; it should still fit in ram. ;TODO if time, test to see if we can fit it clr Temp clr Temp2 __DELAY_USB 13 ;wait a bit for response sbi PORTD,6 LISTEN: sbic PIND,1 ;wait for bit rjmp LISTEN __DELAY_USB 13 ;figure out bit value sbis PIND,1 rjmp ZDETCT0 ori Temp,0b00000001 rjmp ZD0 ZDETCT0: andi Temp,0b11111110 ZD0: cpi Temp2, 7 ;load value into temp breq LP lsl Temp LP: sbis PIND,1 rjmp LP inc Temp2 cpi Temp2, 8 ;read 8 bits of data brne LISTEN mov Word0, Temp ;put bits into correct register clr Temp2 ;we do the above for the nex 3 registers. perhaps we could fit them into a loop, but we ;don't want to mess with timing, and it fits, and there's 3 hours left in lab LISTEN1: sbic PIND,1 rjmp LISTEN1 __DELAY_USB 13 sbis PIND,1 rjmp ZDETCT1 ori Temp,0b00000001 rjmp ZD1 ZDETCT1: andi Temp,0b11111110 ZD1: cpi Temp2, 7 breq LP1 lsl Temp LP1: sbis PIND,1 rjmp LP1 inc Temp2 cpi Temp2, 8 brne LISTEN1 mov Word1, Temp clr Temp2 LISTEN2: sbic PIND,1 rjmp LISTEN2 __DELAY_USB 13 sbis PIND,1 rjmp ZDETCT2 ori Temp,0b00000001 rjmp ZD2 ZDETCT2: andi Temp,0b11111110 ZD2: cpi Temp2, 7 breq LP2 lsl Temp LP2: sbis PIND,1 rjmp LP2 inc Temp2 cpi Temp2, 8 brne LISTEN2 mov Word2, Temp clr Temp2 LISTEN3: sbic PIND,1 rjmp LISTEN3 __DELAY_USB 13 sbis PIND,1 rjmp ZDETCT3 ori Temp,0b00000001 rjmp ZD3 ZDETCT3: andi Temp,0b11111110 ZD3: cpi Temp2, 7 breq LP3 lsl Temp LP3: sbis PIND,1 rjmp LP3 inc Temp2 cpi Temp2, 8 brne LISTEN3 mov Word3, Temp ;out PORTB, Temp clr Temp2 cbi PORTD,6 wdr rjmp ILOOP ;loop forever ;timer 0 ISR (timer-zero overflow) ;Enters every 1.0 mSec TIMER: in Save, SREG out TCNT0, Reload ;save state and reaload counter ; ldi Temp, 0b11110000 ; out PORTB, Temp ser PollEn ;enable poll out SREG, save ;restore state reti ;back to backgound