Searching \ for '[PIC] simple NES controller interface' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/microchip/devices.htm?key=pic
Search entire site for: 'simple NES controller interface'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] simple NES controller interface'
2008\01\14@165523 by threewheeler7

picon face

http://www.nabble.com/file/p14815878/timing.jpg
this has been kind of frustrating me, this is just simply to test an nes
controller, and output its state (eg a,b,start,select,up,down,left,right) to
a lcd display, it includes the standard lcd routine i use for all of my
projects.

code:


       LIST        p=16F877a                ;tell assembler what chip we are using
       include "P16F877a.inc"                ;include the defaults for the chip
       ERRORLEVEL        0,        -302        ;suppress bank selection messages
       __config 0x3F39                        ;sets the configuration settings (oscillator type etc.)




                       cblock        0x20                        ;start of general purpose registers
                       count                        ;used in looping routines
                       count1                        ;used in delay routine
                       counta                        ;used in delay routine
                       countb                        ;used in delay routine
                       tmp1                        ;temporary storage
                       tmp2
                       templcd                        ;temp store for 4 bit mode
                       templcd2        
                       nestemp
                       btchk
               endc
NES_clock        Equ        0x00
NES_latch        Equ        0x01
NES_data        Equ        0x02

NESPORT                Equ        PORTD
nestris                Equ        TRISD
LCD_PORT        Equ        PORTB
LCD_TRIS        Equ        TRISB
LCD_RS                Equ        0x04                        ;LCD handshake lines
LCD_RW                Equ        0x05
LCD_E                Equ        0x06
               org        0x0000


Initialise        clrf        count
               clrf        LCD_PORT

SetPorts        bsf        STATUS,                RP0        ;select bank 1
               movlw        0x04
               movwf        nestris
               movlw        0x80                        ;make all But rb7 output
               movwf        LCD_TRIS        
               bcf        STATUS,                RP0        ;select bank 0
               call        Delay100                ;wait for LCD to settle
               call        LCD_Init                ;setup LCD

       goto Go

                                               
Start                movf        count, w                ;put counter value in W
               call        T_start                        ;get a character from the text table
               xorlw        0x00                        ;is it a zero?
               btfsc        STATUS, Z
               return
               call        LCD_Char
               incf        count, f
               goto        Start
Select                movf        count, w                ;put counter value in W
               call        T_select                        ;get a character from the text table
               xorlw        0x00                        ;is it a zero?
               btfsc        STATUS, Z
               return
               call        LCD_Char
               incf        count, f
               goto        Select
               
Up                movf        count, w                ;put counter value in W
               call        T_up                        ;get a character from the text table
               xorlw        0x00                        ;is it a zero?
               btfsc        STATUS, Z
               return
               call        LCD_Char
               incf        count, f
               goto        Up

Down                movf        count, w                ;put counter value in W
               call        T_down                        ;get a character from the text table
               xorlw        0x00                        ;is it a zero?
               btfsc        STATUS, Z
               return
               call        LCD_Char
               incf        count, f
               goto        Down

Left                movf        count, w                ;put counter value in W
               call        T_left                        ;get a character from the text table
               xorlw        0x00                        ;is it a zero?
               btfsc        STATUS, Z
               return
               call        LCD_Char
               incf        count, f
               goto        Left

Right                movf        count, w                ;put counter value in W
               call        T_right                        ;get a character from the text table
               xorlw        0x00                        ;is it a zero?
               btfsc        STATUS, Z
               return
               call        LCD_Char
               incf        count, f
               goto        Right




;LCD routines

;Initialise LCD
LCD_Init        movlw        0x20                        ;Set 4 bit mode
               call        LCD_Cmd
               movlw        0x28                        ;Set display shift
               call        LCD_Cmd
               movlw        0x06                        ;Set display character mode
               call        LCD_Cmd
               movlw        0x0d                        ;Set display on/off and cursor command
               call        LCD_Cmd
               call        LCD_Clr                        ;clear display
               retlw        0x00

Delay255        movlw        0xff                ;delay 255 mS
               goto        d0
Delay100        movlw        d'100'                ;delay 100mS
               goto        d0
Delay50                movlw        d'50'                ;delay 50mS
               goto        d0
Delay20                movlw        d'20'                ;delay 20mS
               goto        d0
Delay10                movlw        d'10'                ;delay 10mS
               goto        d0
Delay01                movlw        d'01'                ;delay 01mS
               goto        d0
Delay5                movlw        0x05                ;delay 5.000 ms (4 MHz clock)
d0                movwf        count1
d1                movlw        0xC7                        ;delay 1mS
               movwf        counta
               movlw        0x01
               movwf        countb
Delay_0
               decfsz        counta, f
               goto        $+2
               decfsz        countb, f
               goto        Delay_0

               decfsz        count1        ,f
               goto        d1
               retlw        0x00

; command set routine
LCD_Cmd                movwf        templcd
               swapf        templcd,        w        ;send upper nibble
               andlw        0x0f                        ;clear upper 4 bits of W
               movwf        LCD_PORT
               bcf        LCD_PORT, LCD_RS        ;RS line to 0
               call        Pulse_e                        ;Pulse the E line high

               movf        templcd,        w        ;send lower nibble
               andlw        0x0f                        ;clear upper 4 bits of W
               movwf        LCD_PORT
               bcf        LCD_PORT, LCD_RS        ;RS line to 0
               call        Pulse_e                        ;Pulse the E line high
               call        LCD_Busy
               retlw        0x00

LCD_CharD        addlw        0x30
LCD_Char        movwf        templcd
               swapf        templcd,        w        ;send upper nibble
               andlw        0x0f                        ;clear upper 4 bits of W
               movwf        LCD_PORT
               bsf        LCD_PORT, LCD_RS        ;RS line to 1
               call        Pulse_e                        ;Pulse the E line high

               movf        templcd,        w        ;send lower nibble
               andlw        0x0f                        ;clear upper 4 bits of W
               movwf        LCD_PORT
               bsf        LCD_PORT, LCD_RS        ;RS line to 1
               call        Pulse_e                        ;Pulse the E line high
               call        LCD_Busy
               retlw        0x00

LCD_Line1        movlw        0x80                        ;move to 1st row, first column
               call        LCD_Cmd
               retlw        0x00

LCD_Line2        movlw        0xc0                        ;move to 2nd row, first column
               call        LCD_Cmd
               retlw        0x00

LCD_Line1W        addlw        0x80                        ;move to 1st row, column W
               call        LCD_Cmd
               retlw        0x00

LCD_Line2W        addlw        0xc0                        ;move to 2nd row, column W
               call        LCD_Cmd
               retlw        0x00

LCD_CurOn        movlw        0x0d                        ;Set display on/off and cursor command
               call        LCD_Cmd
               retlw        0x00

LCD_CurOff        movlw        0x0c                        ;Set display on/off and cursor command
               call        LCD_Cmd
               retlw        0x00

LCD_Clr                movlw        0x01                        ;Clear display
               call        LCD_Cmd
               retlw        0x00
               
LCD_Space        movlw        0x14
               call        LCD_Cmd
               retlw        0x00
Pulse_e                bsf        LCD_PORT, LCD_E
               nop
               bcf        LCD_PORT, LCD_E
               retlw        0x00
LCD_Busy
               bsf        STATUS,        RP0                ;set bank 1
               movlw        0x0f                        ;set Port for input
               movwf        LCD_TRIS
               bcf        STATUS,        RP0                ;set bank 0
               bcf        LCD_PORT, LCD_RS        ;set LCD for command mode
               bsf        LCD_PORT, LCD_RW        ;setup to read busy flag
               bsf        LCD_PORT, LCD_E
               swapf        LCD_PORT, w                ;read upper nibble (busy flag)
               bcf        LCD_PORT, LCD_E                
               movwf        templcd2
               bsf        LCD_PORT, LCD_E                ;dummy read of lower nibble
               bcf        LCD_PORT, LCD_E
               btfsc        templcd2, 7                ;check busy flag, high = busy
               goto        LCD_Busy                ;if busy check again
               bcf        LCD_PORT, LCD_RW
               bsf        STATUS,        RP0                ;set bank 1
               movlw        0x00                        ;set Port for output
               movwf        LCD_TRIS
               bcf        STATUS,        RP0                ;set bank 0
               return


;end of LCD routines

T_select        addwf        PCL, f
               retlw        'S'
               retlw        'e'
               retlw        'l'
               retlw        'e'
               retlw        'c'
               retlw        't'
               retlw        0x00
       
T_start                addwf        PCL, f
               retlw        'S'
               retlw        't'
               retlw        'a'
               retlw        'r'
               retlw        't'
               retlw        0x00

T_up                addwf        PCL, f
               retlw        'U'
               retlw        'p'
               retlw        0x00

T_down                addwf        PCL, f
               retlw        'D'
               retlw        'o'
               retlw        'w'
               retlw        'n'
               retlw        0x00

T_left                addwf        PCL, f
               retlw        'L'
               retlw        'e'
               retlw        'f'
               retlw        't'
               retlw        0x00

T_right                addwf        PCL, f
               retlw        'R'
               retlw        'i'
               retlw        'g'
               retlw        'h'
               retlw        't'
               retlw        0x00
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<MANE
PROGRAM>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Go                bcf        NESPORT,NES_latch
               bsf        NESPORT,NES_clock
Loop        call        Getbyte
       
       call        Delay20
       call        LCD_Clr
       btfsc nestemp,0
       call        a
       btfsc nestemp,1
       call        bb
       btfsc nestemp,2
       call        Start
       btfsc nestemp,3
       call        Select
       btfsc nestemp,4        
       call        Up
       btfsc nestemp,5
       call        Down
       btfsc nestemp,6
       call        Left
       btfsc nestemp,7
       call        Right
       goto        Loop


a        movlw        'A'
       call        LCD_Char
       return
bb        movlw        'B'
       call        LCD_Char
       return


Getbyte        clrf        nestemp
Latch        bsf                NESPORT,NES_latch        ;bring "latch" high
       call        del6                                ;6ms
       call        del6                                ;6ms
       bcf                NESPORT,NES_latch        ;bring "latch" low
       nop
       movlw        0x08
       movwf        btchk
       bcf                NESPORT_clock
Dat        
       decfsz        btchk                        ;see if 8 bits have been read        
       goto d1
       return
D1        btfss        NESPORT,NES_data                ;bit is clear(buttons are active low)
       bsf                nestemp,7                ;if it is set bit 7 of temp
       rrf        nestemp,F                                ;shift right
       call        del6                                ;6us
       bsf                NESPORT,NES_clock        ;bring "clock" high
       call        del6                                ;6ms
       bcf                NESPORT,NES_clock        ;bring "clock" low
       goto        Dat
       
del6
       goto        $+1
       return
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        
               end  
--
View this message in context: www.nabble.com/simple-NES-controller-interface-tp14815878p14815878.html
Sent from the PIC - [PIC] mailing list archive at Nabble.com.

2008\01\15@074633 by Rikard Bosnjakovic

picon face
On 14/01/2008, threewheeler7 <spam_OUTthreewheeler7TakeThisOuTspamhotmail.com> wrote:

> this has been kind of frustrating me, this is just simply to test an nes
> controller
[...]

And the problem is what?


--
- Rikard - http://bos.hack.org/cv/

2008\01\15@152006 by threewheeler7

picon face



On 14/01/2008, threewheeler7 <.....threewheeler7KILLspamspam@spam@hotmail.com> wrote:

> this has been kind of frustrating me, this is just simply to test an nes
> controller
[...]

And the problem is what?

im sorry. i can only get it to display when "a" is pressed. btw all the
controller is is a CD4021 - 8 Bit shift register.


--
View this message in context: www.nabble.com/simple-NES-controller-interface-tp14815878p14845580.html
Sent from the PIC - [PIC] mailing list archive at Nabble.com.

2008\01\15@234835 by Christopher Head

picon face
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!
I don't know NES, but I have interfaced SNES controllers which according
to various Web pages are exactly the same but with 16 bits instead of 8.
The timing diagram you linked to looks exactly like what I did, modulo
perhaps having one or the other signal at the wrong polarity or perhaps
wrong wires connected.

One thing comes to mind: it looks like A is the very first button
transmitted, and you say A can be detected but the others can't. Are you
sure you don't have latch and clock swapped? If you did, each clock
cycle would end up firing latch instead which would mean you'd be
reading the value of button A for every clock cycle instead of stepping
through the buttons.

Good luck,
Chris

threewheeler7 wrote:
|
|
| On 14/01/2008, threewheeler7 <threewheeler7spamKILLspamhotmail.com> wrote:
|
|> this has been kind of frustrating me, this is just simply to test an nes
|> controller
| [...]
|
| And the problem is what?
|
| im sorry. i can only get it to display when "a" is pressed. btw all the
| controller is is a CD4021 - 8 Bit shift register.
|
|

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (MingW32)
Comment: GnuPT 2.7.2
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHjYyfiD2svb/jCb4RAqZxAJwO7e7dTwlRtP/VTOcQxXBDCUGCcgCglY94
FlWhRUeZcCpY3tfoVfm+47I=
=88OB
-----END PGP SIGNATURE-----

2008\01\16@002035 by Eric w

picon face
yes they basically are the same i would be interested in seeing your code, if you dont mind. yes it does send "a" first though unlike the snes but the protocol is still the same just 12 instead of 8 bits. and no the clock and latch are not switched, unfortunately i already checked that.



{Quote hidden}

_________________________________________________________________
Put your friends on the big screen with Windows Vista® + Windows Live™.
http://www.microsoft.com/windows/shop/specialoffers.mspx?ocid=TXT_TAGLM_CPC_MediaCtr_bigscreen_012008

2008\01\16@005536 by Christopher Head

picon face
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

It's thoroughly messy, written in C using Microchip's USB framework, and
is interrupt driven (it was an abandoned work-in-progress; I intend to
start over in assembly Real Soon Now). That said, here are the relevant
pieces of the code (note that, if I remember right, I use some extremely
long delays - on the order of dozens or hundreds of milliseconds - might
this be your problem? Remember that the controller isn't at all intended
to be a high-speed device):

/*
~ * RA2 = latch
~ * RA1 = clock
~ * RA0 = data
~ */
void UserInit(void)
{
       ADCON1 = 0x0F; // ADC disabled.
       PORTA = 0b110;
       TRISA = 0b001;
       phase = 32;
       TMR0H = 0;        
       TMR0L = 0;
       INTCONbits.TMR0IF = 0;
       T0CON = 0b10001000;
       attached = 0;
}


void ProcessIO(void) {
~    // User Application USB tasks
~    if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return;

       if (INTCONbits.TMR0IF) {
               INTCONbits.TMR0IF = 0;
               if (phase == 32) {
                       // Lower latch.
                       PORTAbits.RA2 = 0;
                       phase = 0;
                       T0CONbits.T08BIT = 1;
               } else if (!(phase & 1)) {
                       // Even phase number => CK=1 and will fall.
                       // Falling edge implies read data line NOW.
                       PORTAbits.RA1 = 0;
                       serialindex = phase >> 1;
                       if (map[serialindex].bitindex == 0x0F) {
                               attached = PORTAbits.RA0;
                       } else {
                               mask = 1 << map[serialindex].bitindex;
                               if (PORTAbits.RA0) {
                                       buffer[map[serialindex].byteindex] &= ~mask;
                               } else {
                                       buffer[map[serialindex].byteindex] |= mask;
                               }
                       }
                       phase++;
               } else {
                       // Odd phase number => CK=0 and will rise.
                       // Rising edge implies controller will drive next data bit NOW.
                       PORTAbits.RA1 = 1;
                       phase++;
                       // If we hit phase 32...
                       if (phase == 32) {
                               // Raise the latch and switch to the 16-bit timer.
                               PORTAbits.RA2 = 1;
                               T0CONbits.T08BIT = 0;
                               TMR0H = 0;
                               TMR0L = 0;
                       }
               }
       }

       if (!attached) {
               buffer[0] = buffer[1] = 0;
       }

~    if(!mHIDTxIsBusy())                                        // Check if USB is busy?
~    {
~        HIDTxReport(buffer, DEVICE_RETURNDATA_SIZE);                        // Send USB data.
~    }
}

Eric w wrote:
| yes they basically are the same i would be interested in seeing your
code, if you dont mind. yes it does send "a" first though unlike the
snes but the protocol is still the same just 12 instead of 8 bits. and
no the clock and latch are not switched, unfortunately i already checked
that.
|
|
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (MingW32)
Comment: GnuPT 2.7.2
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHjZwOiD2svb/jCb4RAvwZAJ9+kyC1Di3XsDecw9tgqhnWfxCvbwCdFrBN
Jngf6UgRmf6reVoTH2KU92Q=
=ZF4V
-----END PGP SIGNATURE-----

2008\01\16@113805 by peter green

flavicon
face

>
> It's thoroughly messy, written in C using Microchip's USB framework, and
> is interrupt driven (it was an abandoned work-in-progress; I intend to
> start over in assembly Real Soon Now). That said, here are the relevant
> pieces of the code (note that, if I remember right, I use some extremely
> long delays - on the order of dozens or hundreds of milliseconds - might
> this be your problem?
I remember doing the sums and working out that a fast pic can bit bang
IO faster than the 4000 series shift register in the nes controller is
able to handle.



2008\01\16@150440 by threewheeler7

picon face


this is why i am using the 12 and 6 us delays exactly the same as the
original NES put out, and captured at. the 4000 series chip will handle a
good amount faster thad that.


>(note that, if I remember right, I use some extremely
> long delays - on the order of dozens or hundreds of milliseconds - might
> this be your problem?
>I remember doing the sums and working out that a fast pic can bit bang
>IO faster than the 4000 series shift register in the nes controller is
>able to handle.

--
View this message in context: www.nabble.com/simple-NES-controller-interface-tp14815878p14891809.html
Sent from the PIC - [PIC] mailing list archive at Nabble.com.

More... (looser matching)
- Last day of these posts
- In 2008 , 2009 only
- Today
- New search...