Help implementing SNES Controller + PIC1F887


Closed Thread
Results 1 to 6 of 6
  1. #1
    Join Date
    Sep 2010
    Posts
    3

    Default Help implementing SNES Controller + PIC1F887

    Hello, I am fairly new to programming with PICBASIC Pro and have run into a problem. I am currently using a Snes Controller, a Pic16F887, and a HD44780 compatible display (4 lines, 20 char)

    I'm reading the output of the Snes Controller, and am trying to display what character is pressed on the LCD screen. I have a word variable which stores the button values from a shiftin command. This word is then displayed on the LCD. (I have fixed this portion of the problem, read past the italics)My problem is that the only button that changes anything displayed is the "B" button, and when B is pressed, it reads as all buttons being pressed (The LCD shows 0000000000000000 where 0 means pressed, 1 means unpressed.) When B is not pressed it reads 1111111111111111. When B is pressed it should read 0111111111111111 since the B button's status is the first bit transferred. I fixed the italicized portion to an extent, I cannot read any buttons after "Y" (the second bit sent) because my timing is not exact enough. Sometimes Y registers like it should, sometimes it does not, so I will have to work on the timing.

    I found this information about how the controller passes information:
    The SNES controller has three data pins plus +5V power and ground.*A high on

    the Data Latch pin for 12 us signals the controller to start sending data

    which is clocked by a sequence of 16 pulses (6 us high, 6 us low) on the

    clock pin. Serial data (8 buttons + 4 directions + 4 unused signals) is

    returned on the serial data pin.*The serial data is negative-edge triggered.

    Clock Cycle Button Reported
    =========== ===============
    1 B
    2 Y
    3 Select
    4 Start
    5 Up on joypad
    6 Down on joypad
    7 Left on joypad
    8 Right on joypad
    9 A
    10 X
    11 L
    12 R
    13 none (always high)
    14 none (always high)
    15 none (always high)
    16 none (always high)


    My current code programmed onto the PIC is as follows:

    Code:
    Include "modedefs.bas"
    	
    	OSCCON = %01110000 ' INTRC = 8MHz
    
    	DEFINE OSC 8
    
    
            DEFINE LCD_DREG PORTB       ' Set LCD Data port
            DEFINE LCD_DBIT 0           ' Set starting Data bit (0 or 4) if 4-bit bus i.e, PortD.4-PORTD.7
            DEFINE LCD_RSREG PORTD      ' Set LCD Register Select port
            DEFINE LCD_RSBIT 2          ' Set LCD Register Select bit i.e, PORTC.5
            DEFINE LCD_EREG PORTD       ' Set LCD Enable port
            DEFINE LCD_EBIT 4           ' Set LCD Enable bit i.e, PORTE.4
            DEFINE LCD_BITS 8           ' Set LCD bus size ot 4 bit Upper Nibble (4 or 8 bits)
            DEFINE LCD_LINES 4          ' Set number of lines on LCD to 4 Lines
            DEFINE LCD_COMMANDUS 2000   ' Set command delay time in us
            DEFINE LCD_DATAUS 50        ' dSet data delay time in us
    	DEFINE LCD_RWREG PORTD
    	DEFINE LCD_RWBIT 3
    
    
    
     
    theoutput	var	Word
    
    
    ANSEL = 0
     
    PAUSE 1000                                        ' Wait a second 
    
    OUTPUT PORTC.1         ' configure input/output pins
    OUTPUT PORTC.0
    INPUT PORTC.2
    
     
    LOW PORTC.1                                             ' Initialize LATCH 
    LOW PORTC.0                                             ' Initialize CLK 
     
    Loop:                                                ' Main loop 
     
      PULSOUT PORTC.1, 10                                   ' Latch the data 
    
      SHIFTIN PORTC.2, PORTC.0, LSBPRE,[theoutput \16]             ' Shift in socket 1 data 
    
      LCDOUT $FE, 1, BIN16 dasresult             ' Display values 
    
    pause 50
     
    GOTO Loop
    END                                              ' Repeat main loop
    My guess on what is going on is that the internal oscillator might not be precise enough and is causing timing problems with the shiftin operation, but it could also be due to a complete lack of understanding of the shiftin operation, as this is the first time I've used it.

    Does anyone have any ideas as to what might be going on? I'm not looking for someone to completely spell things out for me as I like t solve these kinds of problems, but a few nudges if anyone has some insight to this problem would be great. If anyone would like me to provide any more information please let me know.

    Edit: Looking at some example code for a PS2 controller, I believe my shiftin code may be wrong, I'm going to mess around with it and see if that helps.
    Edit2: spotted an error with the shiftin statement, 0 should be PORTC.0, will report back in a bit.

    Edit3: It is now working to an extent. There is a timing issue as button Y, the next bit reported, will sometimes register as pressed to the mcrocontroller, and sometimes not, while all bits after it register no presses.
    Last edited by Daguava; - 7th September 2010 at 23:36. Reason: New info

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Welcome to the forum.

    Is that the whole code posted? I do not see how this will work
    Code:
     SHIFTIN PORTC.2, PORTC.0, LSBPRE,[theoutput \16]             ' Shift in socket 1 data 
      LCDOUT $FE, 1, BIN16 dasresult             ' Display values
    I do not see "dasresult " as a VAR or how you are going from "theoutput" to "dasresult".
    Dave
    Always wear safety glasses while programming.

  3. #3
    Join Date
    Sep 2010
    Posts
    3


    Did you find this post helpful? Yes | No

    Default

    Oops, thats a mistake from when I was cleaning it up to post, the revised code is below XD

    Code:
    Include "modedefs.bas"
    	
    	OSCCON = %01110000 ' INTRC = 8MHz
    
    	DEFINE OSC 8
    
    
            DEFINE LCD_DREG PORTB       ' Set LCD Data port
            DEFINE LCD_DBIT 0           ' Set starting Data bit (0 or 4) if 4-bit bus i.e, PortD.4-PORTD.7
            DEFINE LCD_RSREG PORTD      ' Set LCD Register Select port
            DEFINE LCD_RSBIT 2          ' Set LCD Register Select bit i.e, PORTC.5
            DEFINE LCD_EREG PORTD       ' Set LCD Enable port
            DEFINE LCD_EBIT 4           ' Set LCD Enable bit i.e, PORTE.4
            DEFINE LCD_BITS 8           ' Set LCD bus size ot 4 bit Upper Nibble (4 or 8 bits)
            DEFINE LCD_LINES 4          ' Set number of lines on LCD to 4 Lines
            DEFINE LCD_COMMANDUS 2000   ' Set command delay time in us
            DEFINE LCD_DATAUS 50        ' dSet data delay time in us
    	DEFINE LCD_RWREG PORTD
    	DEFINE LCD_RWBIT 3
    
    
    
     
    theoutput	var	Word
    
    ANSEL = 0
     
    PAUSE 1000                                        ' Wait a second 
    
    OUTPUT PORTC.1         ' configure input/output pins
    OUTPUT PORTC.0
    INPUT PORTC.2
    
     
    LOW PORTC.1                                             ' Initialize LATCH 
    LOW PORTC.0                                             ' Initialize CLK 
     
    Loop:                                                ' Main loop 
     
      PULSOUT PORTC.1, 10                                   ' Latch the data 
    
      SHIFTIN PORTC.2, PORTC.0, MSBPRE,[theoutput \16]             ' Shift in socket 1 data 
    	
      LCDOUT $FE, 1, BIN16 theoutput             ' Display values 
    
    
    
    pause 50
     
    GOTO Loop
    END                                              ' Repeat main loop
    The only issue that remains is that my timing is not precise enough and I'm losing a lot of the button press bits. I think the only solution is purchasing a crystal as the internal oscillator is not accurate enough.
    Last edited by Daguava; - 8th September 2010 at 00:23.

  4. #4
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    I have not used one of those controllers..
    The internal OSC should be accurate enough, the speed might be the issue.
    You are pushing buttons while data is being sent to the display or looping for the next call???

    Would be nice to push the data from the controller instead of calling for it. Is there some way to have a signal going to a PORTB interrupt?
    Dave
    Always wear safety glasses while programming.

  5. #5
    Join Date
    Sep 2010
    Posts
    3


    Did you find this post helpful? Yes | No

    Default

    Oh wow, I feel so stupid, but I've just solved my own problem. Undervolting the shift-register inside of the controller by a half volt was enough to cause it to freak out giving me incomplete output, my code now works as expected and everything is working great.

    Thanks for the help, and, if you wouldn't mind, could you elaborate a bit on what you meant by the PortB interrupt, I've done very little with interrupts and don't quite get what you mean.

  6. #6
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Glad it is working.

    PORTB has an interrupt on change. When the state of PORTB.0 changes an interrupt can be triggered.

    An example would be counting parts on a conveyor. The MCU can be off doing something else like sending data to a display while a sensor/switch is activated as a part passes by. Then when the MCU is finished with the display the part count can be increases.
    That is using PBP interrupts. If you go with ASM or Darrel Taylor's instant interrupts then the trigger is instantly. But you still need a certain amount of time for everything to happen.

    Either way, you do not need to loop back and check the state of the pin, it happens for you in the background.
    Dave
    Always wear safety glasses while programming.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts