Shop OBEX P1 Docs P2 Docs Learn Events
Need help optimizing playstation controller code — Parallax Forums

Need help optimizing playstation controller code

bulkheadbulkhead Posts: 405
edited 2007-11-03 16:09 in Propeller 1
I've been trying to get this code to work with a wireless playstation 2 video game controller. I timed the getPacket() routine at roughly 5.6ms, and I tested it with a regular wired controller and it works fine. However, it does not seem to work with a wireless controller. I used viewport's 20MHz prop scope function to monitor the signals going from a playstation to the controller, and the data is sent exactly the same way for both wired and wireless controllers. The only difference I can think of is that the wireless controllers actually require that the packet be sent faster. The actual playstation console transfers the whole packet in roughly 0.5 ms.

What I need is a way to make this routine more efficient somehow by converting it into assembly or through some other manner. My target is to get this running at 10x the speed, but any improvement would help (perhaps the threshold speed for wireless controllers is somewhere in between what the playstation does and what my code currently does). Anhy suggestions on improving the runtime speed of this program would be appreciated, thanks.

EDIT 8/20: Here is the info I got from running ViewPort's 20MHz scope program and connecting pins 0-3 to a playstation (original, not ps2) and 1 wired/2 different wireless controllers. Note that the data bytes appear to be exactly the same for both wired and wireless controllers.




EDIT 8/20: updated version down a few posts (runs twice as fast as this version)
'Translated from BS2 version of playstation controller code
VAR
  long attPin
  long cmdPin
  long clkPin
  long datPin

  long idx   'loop counter
  long psxOut 'byte to controller
  long psxIn 'byte from controller

  long ID, ThumbL, ThumbR, Status, JoyRX, JoyRY, JoyLX, JoyLY
  
  long timer
CON
    _xinfreq = 5_000_000                     ' 5 MHz external crystal 
    _clkmode = xtal1 + pll16x                ' 5 MHz crystal multiplied → 80 MHz
    
    start = %00000001  '0x01
    getDat = %01000010  '0x42
    Inverted=1
    Direct=0
    clockMode=Direct

PUB startUp(ddat, cmd, att, clk)

    clkPin:=clk
    attPin:=att
    cmdPin :=cmd  
    datPin:=ddat
    
    'INIT
    dira[noparse][[/noparse]attPin]~~
    dira[noparse][[/noparse]cmdPin]~~
    dira[noparse][[/noparse]clkPin]~~
    dira[noparse][[/noparse]datPin]~
    outa[noparse][[/noparse]attPin]~~ 'deselect PSX controller
    outa[noparse][[/noparse]cmdPin]~
    outa[noparse][[/noparse]clkPin]:=!clockMode 'release clock   

PUB Get_PSX_Packet
  outa[noparse][[/noparse]attPin]~ 'select controller
  psxOut:=start  'send "start"
  PSX_TxRx
  psxOut:=getDat    'send "get data"
  PSX_TxRx
  ID:=psxIn       'save controller type
  psxOut := 0
  PSX_TxRx
  Status:= psxIn   'should be $5A ("ready")
  PSX_TxRx
  ThumbL := psxIn      'get PSX data
  PSX_TxRx
  ThumbR := psxIn
  PSX_TxRx
  JoyRX := psxIn
  PSX_TxRx
  JoyRY := psxIn
  PSX_TxRx
  JoyLX := psxIn
  PSX_TxRx
  JoyLY := psxIn
  outa[noparse][[/noparse]attPin] ~~ 'deselect controller
 
PUB PSX_TxRx
  repeat idx from 0 to 7
    outa[noparse][[/noparse]cmdPin]:= (((psxOut>>idx)&1)==1)
    outa[noparse][[/noparse]clkPin]:=clockMode
    psxIn&= !(1<<idx)
    if(ina[noparse][[/noparse]datPin])
      psxIn |= (1<<idx)
    outa[noparse][[/noparse]clkPin]:= !clockMode    

      


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
I'm new to the propeller!

Post Edited (bulkhead) : 8/21/2007 2:08:02 AM GMT

Comments

  • deSilvadeSilva Posts: 2,967
    edited 2007-08-19 21:38
    I think you have to change to machine code; to my experience a "basic operation" in SPIN takes around 5 us, so your loop is around 50 to 100 us - just guessing.

    -- SPIN does not optimize constant expressions without the constant(...) directive (otherwise !clockMode is an additional operation).

    -- (xxx&1)==1 seems equivalent to xxx

    -- I should also suggest "loop-unrolling", not because the loop is very expensive, but you than can profit from knowing idx being 0,1,2,3,4,5,6,7

    -- There should also be an minor speed-up using the return value
    JoyLX := PSX_TxRx
     ...
    PUB PSX_TxRx : psxIn
    


    Even if this will not be an improvement with speed it will be an improvement in readability

    Post Edited (deSilva) : 8/19/2007 10:55:08 PM GMT
  • CJCJ Posts: 470
    edited 2007-08-19 21:42
    I have been planning and procrastinating writing an assembly driver for the Playstation controller for some time now(heavy on the procrastination), perhaps now is the time for me to write it. spin is *almost* fast enough, as I can sometimes get a packet from the official wireless controller for PS2 with my code, gotta write it in assembly to make the timings as accurate as possible, a single byte takes a whole 32uS to read at the lower speed that the PS2 uses, typically reads at twice that speed!


    I feel energized, tonight I write!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Parallax Forums - If you're ready to learn, we're ready to help.
  • mike101videomike101video Posts: 43
    edited 2007-08-19 21:49
    Check out http://www.lynxmotion.com/ViewPage.aspx?ContentCode=electronics&CategoryID=70

    I can esily get a wired PS2 controller to work, but never a wireless. Lynxmotuion have their "own" wireless controller that they have working, but the information on their website may help.

    Mike
  • Tom CTom C Posts: 461
    edited 2007-08-20 02:56
    bulkhead,

    I have reviewed the MBasic code for communication with the wireless PS2 controller receiver with the the Atom 28 and have noticed the following difference:

    The MBasic code does not check for the $5A "Ready" response from the controller after receiving the controller type response. It immediately receives the two button bytes from the controller followed by the right and left joystick position values.

    Regards,
    TCIII

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    If you are going to send·a Robot·to save the world, you·better make sure it likes it the way it is!
  • RinksCustomsRinksCustoms Posts: 531
    edited 2007-08-20 04:32
    If IR remotes are desirable, i'm working on a IR Reader for the Sony remotes, ones a TV remote for a broken XBR set I just tossed out, the other remote is the PS2 DVD remote. The interesting thing is the TV remote was made in '98 and the DVD remote was made in '05, both use the same timing for sync,0's, and 1's.

    I'll be following this thread as i'd be interested in how one would accomplish reading a PS2 controller w/the Prop...

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    E3 = Thought

    http://folding.stanford.edu/·- Donating some CPU/GPU downtime just might lead to a cure for cancer! My team stats.
  • bulkheadbulkhead Posts: 405
    edited 2007-08-21 00:23
    Wow, so many responses...

    Well CJ, I look forward to your assembly driver since I don't feel like learning assembly right now just to write the driver.

    deSilva, I will try those changes and see how much faster it is and whether it is fast enough.

    I've had luck getting a Pelican Chameleon wireless controller working on the Javelin stamp running quite slowly . I found out that it returns different Status and ID bytes than normal wired controllers. However, I just got another Pelican Chameleon wireless controller, and this one is slightly different because it has a manual channel selector on the controller and receiver (my other chameleon didn't have that). I used ViewPort's scope to verify that this wireless controller behaves JUST like a wired one (same status and ID bytes). Perhaps the only difference is that it requires fast data transmission whereas the wired controllers are fine with slow transmissions.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I'm new to the propeller!
  • bulkheadbulkhead Posts: 405
    edited 2007-08-21 02:02
    Ok, well I made some of the changes to the code and now it runs twice as fast! The whole packet is now sent/received in just 2.9 ms. However, I tested it with my 2 wireless controllers and apparently, it still isn't fast enough.

    I did forget to mention that with the code I have, I do get some response with the wireless controllers. When I toggle the "analog" button that switches between the analog (joystick+ buttons) and digital (buttons only) mode, I get a change in the ID byte from 224 (dec) to 249 (dec), although I don't know whether the 224 corresponds to the analog or digital mode. The correct values for the ID should be 65 (dec) or 0x41 hex for digital mode and 115 (dec) or 0x73 hex for analog mode.

    Here is a link to some info I had when I worked on ps2 controllers with the Javelin stamp (it's in the Completed Projects section): http://forums.parallax.com/showthread.php?p=573796 The attached file in that post, "WirelessPS2.txt" has a summary of the expected Status/ID/button info bytes.

    Here is the part of the code that I changed that is still non functional with wireless controllers, but works fine with wired ones (now runs 2x as fast, thanks to deSilva's suggestions). Looks like it will need to be converted to assembly.
    PUB Get_PSX_Packet
      outa[noparse][[/noparse]attPin]~    'select controller
       
      PSX_TxRx(constant(start))        'send "start"   
      ID:=PSX_TxRx(constant(getDat))   'send "get data"  and save controller type
      outa[noparse][[/noparse]cmdPin]~    'clear to zero for rest of packet
     
      Status := PSX_Rx   'should be $5A ("ready")
      ThumbL := PSX_Rx    'get PSX data
      ThumbR := PSX_Rx   
      JoyRX  := PSX_Rx   
      JoyRY  := PSX_Rx 
      JoyLX  := PSX_Rx   
      JoyLY  := PSX_Rx
      
      outa[noparse][[/noparse]attPin] ~~ 'deselect controller
    
    PUB PSX_TxRx(psxOut): psxIn
      outa[noparse][[/noparse]cmdPin]:= (psxOut)
      outa[noparse][[/noparse]clkPin]:=constant(clockMode)
      psxIn&=    %1111_1110
      if(ina[noparse][[/noparse]datPin])
        psxIn |= %0000_0001
      outa[noparse][[/noparse]clkPin]:= !constant(clockMode)  
    ...
      outa[noparse][[/noparse]cmdPin]:= (psxOut>>7)
      outa[noparse][[/noparse]clkPin]:=constant(clockMode)
      psxIn&= %01111111
      if(ina[noparse][[/noparse]datPin])
        psxIn |= %10000000
      outa[noparse][[/noparse]clkPin]:= !constant(clockMode)
    
    PUB PSX_Rx: psxIn
      outa[noparse][[/noparse]clkPin]:=constant(clockMode)
      psxIn&=    %1111_1110
      if(ina[noparse][[/noparse]datPin])
        psxIn |= %0000_0001
      outa[noparse][[/noparse]clkPin]:= !constant(clockMode) 
    ...
      outa[noparse][[/noparse]clkPin]:=constant(clockMode)
      psxIn&= %01111111
      if(ina[noparse][[/noparse]datPin])
        psxIn |= %10000000
      outa[noparse][[/noparse]clkPin]:= !constant(clockMode)
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I'm new to the propeller!

    Post Edited (bulkhead) : 8/21/2007 2:17:29 AM GMT
  • CJCJ Posts: 470
    edited 2007-08-21 04:04
    here is just a small snippet of the core for perusal


    txrx            mov counts, #8
                      mov time, cnt
                      add time, us1
    txrxloop      waitcnt time, us1
                      or dira, clkpin
                      waitcnt time, us1
                      test datpin, ina wc
                      waitcnt time, us1
                      andn dira, clkpin
                      rcr result, #1 
                      djnz counts, #txrxloop
    
                      shr result, #24 
    
    
    



    the assembly code should be capable of whatever speed is needed for the wireless controllers

    not really any more lines than the spin version

    don't be afraid of Propasm, it is very easy to use. my first real assembly work EVER was the N64 and GameCube controller code in the object exchange

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Parallax Forums - If you're ready to learn, we're ready to help.
  • HannoHanno Posts: 1,130
    edited 2007-08-22 11:56
    bulkhead,
    Congrats on a very nice use of Viewport! Those measurements look fantastic. Looks like you would like a feature where Viewport decodes data for you automatically? Ie- tell Viewport that one bit trace is the clock signal while another is the data? cj's code looks very appropriate- Propeller assembly is rather fun once you get started!
    Hanno
  • deSilvadeSilva Posts: 2,967
    edited 2007-08-22 15:25
    Just a propos: outa[noparse][[/noparse]clkPin]:= !constant(clockMode) should read: outa[noparse][[/noparse]clkPin]:= constant(!clockMode)
  • RinksCustomsRinksCustoms Posts: 531
    edited 2007-11-03 16:09
    Does anybody think that it's possible for the prop to read the PS3 sixaxis controller? I know it's bluetooth based. I took one apart and noticed what looks like an accelerometer and maybe a small gyro. I'd imagine that you'd need a bluetooth to USB adapter to get data.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    E3 = Thought

    http://folding.stanford.edu/·- Donating some CPU/GPU downtime just might lead to a cure for cancer! My team stats.
Sign In or Register to comment.