Also do you have a copy of the schematic for connecting the prop to the PS2?
It's simple enough that I haven't made an actual schematic. You can connect the PS2 controller data pins directly to the prop, they're both 3.3v logic. There are five data pins, which my emulator expects to be connected sequentially to Prop pins:
There are plenty of places on the internet where you can find pinouts for the PS2 controller socket. Connect all of these pins to the prop, (every one of them is necessary) hook up ground, and ignore power (unless you want to power the prop off of the PS2 supply- if you do this, be very careful, as it's easy to blow a hard-to-replace fuse in the PS2).
computer guy said...
I have had a look at your emulator and am not sure how to use it.
Could you please write some short code to configure it to emulate an Analog Controller and then send out that the "Square" button has been pushed.
This should be enough to give me a general idea of how to use it.
I haven't tested this code, so please excuse any bugs, but it'd be something like this... All of the magic numbers for bytes and bits within the controller packet format are defined in my other "psx_remote_port" object, or most of them are available on the internet.
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
CONTROLLER_PIN = 4
OBJ
emulator : "psx_controller_emulator"
VAR
' 18-byte buffer for controller state
word c_buttons
byte c_axes[noparse][[/noparse] 4]
byte c_pressure[noparse][[/noparse]12]
PUB main
' Initialize default controller state.
' Buttons are released (1), axes are centered ($80).
c_buttons := $FFFF
bytefill(@c_axes, $80, 4)
bytefill(@c_pressure, 0, 12)
emulator.start(CONTROLLER_PIN, -1, emulator#CONTROLLER_ANALOG)
emulator.add_state_buffer(@c_buttons)
' Press the left D-pad button.
' Next time the Playstation polls the controller emulator, it will see this change.
c_buttons &= ~$0080
etc..
Good luck!
Post Edited (Micah Dowty) : 7/8/2008 5:25:03 PM GMT
Also to set the position of the left analog stick? and how many bits is it so that I can get the value from an ADC and go direct to output without any maths in between.
I will leave you alone so that you can get on with your own projects now.
Almost... One way to do it is "c_buttons &= ~($0080 | $0020)". If you're still confused, re-read over the Propeller manual's section on operators, and perhaps check out a tutorial on boolean logic.
Also, be warned, I might have misspoke when I said that "1" is released and "0" is pressed. Some of my own notes were inconsistent, and I think it actually might be the other way around- "1" is pressed.
computer guy said...
Also to set the position of the left analog stick? and how many bits is it so that I can get the value from an ADC and go direct to output without any maths in between.
An 8-bit A/D should do exactly what you want. $00 and $FF are the extremes of motion (I forget the polarity- which one is left/top/right/bottom) and $80 is the center. If you're hooking this up to a pot, connect one leg of the pot to ground, one leg to your analog supply, and the wiper to your A/D.
On a serendipitous note... I also recently got asked about my PSX controller emulator by Julian Bleecker, who wanted to use it for his own project which interposes between a PS2 controller and the console in order to modify the analog joystick values. He was successful at using the emulator, and he even wrote a blog post which includes some sample code:
You're forgetting to invert ("~") the bit masks when you turn off a button. Except for that bug (and possibly inverting the one bits and zero bits) this looks like it would work, but it's much more complicated than it needs to be.
The most straightforward way to do this would be to build a bitfield using a local variable, then assign c_buttons once at the end of your main loop. Something like:
repeat
new_buttons := BTN_LEFT
if ina[noparse][[/noparse]GREEN_PIN]
new_buttons |= BTN_L2
if ina[noparse][[/noparse]RED_PIN]
new_buttons |= BTN_L1
...
c_buttons := new_buttons
It doesn't matter what values new_buttons takes on intermediately, as long as you assign to c_buttons only once.
I noticed that in Julian Bleecker's code he is setting the axis values using the same variable as the buttons (in my case "c_buttons").
Is this how it is done?
The whammy bar of a guitar her controller uses the "Left Analog stick's" Y value as the position of the whammy bar.
So this will also need to be set in the repeat loop.
Thank you, your code and assistance is appreciated.
computer guy said...
So new_buttons would be a long.
new_buttons can be a long on the stack, a word in the VAR section, etc. As long as it's at least 16 bits.
computer guy said...
I noticed that in Julian Bleecker's code he is setting the axis values using the same variable as the buttons (in my case "c_buttons").
Is this how it is done?
The emulator object just needs any arbitrary 18 bytes of memory. This can be a byte array of size 18, but it can also be a consecutive sequence of separate values: a word for the buttons, a 4-byte array for the axes, etc. It can be in the var section or the dat section. In my example, I used separate consecutively-allocated variables. In my example, the axes would be a different variable in the VAR section, immediately after c_buttons. That's one way of doing the job, but it isn't the only way.
Er.. not quite. Call add_state_buffer() only once, with @c_buttons. Then modify the values in c_axes. This works because c_axes comes immediately after c_buttons in memory. The emulator object actually treats the address you pass it as a pointer to an 18-byte buffer with the whole controller state.
computer guy said...
Ok so all I have to do is set.
c_axes[noparse][[/noparse]0 to 3] to the value I want and it will do the rest?
Thank you
Yup. Every time the Playstation polls your device, the emulator will read the necessary parts of your state buffer from hub memory- without any direct interaction from your Spin code. Go Propeller [noparse];)[/noparse]
This has nothing to do with the emulator but is there an easy way to set a pin high for 10 seconds and then set it back to low inside of the repeat without it delaying the next repeat for 10 seconds?
computer guy said...
This has nothing to do with the emulator but is there an easy way to set a pin high for 10 seconds and then set it back to low inside of the repeat without it delaying the next repeat for 10 seconds?
Thank you
If you have cogs to burn, you could start a separate Spin cog which sets the pin high, sleeps for 10 seconds, then sets it low. [noparse];)[/noparse]
Otherwise, you'll need to know what this cog is doing 10 seconds into the future. It's impossible to always set the pin low *exactly* 10 seconds into the future if the cog will be doing other things, but if you can periodically poll ("Is it time to set the pin low yet?") while the cog is doing other things, you can approximate this kind of multi-tasking.
In your simple button-polling loop, you could implement this by:
1. When you want to set the pin high...
- Set it high
- Set a flag, to remind yourself that you need to set it low at some point
- Save the current CNT value
2. Then, periodically poll:
- Is the flag set?
- If so, subtract the current CNT value from the one you saved. Has it been 10 seconds yet?
- If so, set the pin low and clear the flag.
Looks basically fine, though that method of comparing 'cnt' won't do what you expect. You can't rely on the CNT register to monotonically increase- it will wrap every minute or so. It's better to do something like this:
You can do this with a variable that is used as a boolean flag
VAR
byte First_Loop
PUB Main
First_Loop := true 'initially it is true
repeat
if First_Loop
First_Loop := false 'first thing to do is to set the flag to false so beginning with second loop the condition is false
outa[noparse][[/noparse]16] := 1
best regards
Stefan
Post Edited (StefanL38) : 7/10/2008 8:28:10 AM GMT
That would only work if I was repeating every 10 seconds.
Check the previous page of this thread for code that I think might work.
I don't need the delay to be exact, I just want an LED to light when a button is pushed and stay lit for aprox 10 seconds after the button is released.
Without the delay having to temporarily stop the repeat.
first of all i want to make a suggestion
this question has moved far away from the PS2-issue
how about starting a new thread ?
timer-programming-techniques are of common interest
but would never be expected in the middle of a thread about PS2-emulation
back to the question
aha i understand,
now this could be done by comparing the actual value of the systemvariable cnt with
a calculated value
'pseudecode
TimeSnapShot := cnt
repeat
...
if cnt > TimeSnapShot + 10 Sec
turn off LED
There has do be done a little bit more because the cnt-variable wraps around from $FFFFFFFF to $0
@the forum: what is the result of +-calculations that exceed the 32-bit limit f.e. $FFFFFFFF + 100 ?
or second possability:
if your speed-requirements allow this
make a short waitcnt (maybe every millisecond) inside your loop and after every ms a variable is incremented.
If it reaches 3600000 = 1h it will be reset to zero
here is still a wrap around to zero but it could be calculated in 32bit
if TimeSnapShot + 10 sec > TimeMax handle wrap around
another concept could be to put the details of the timecomparing in a method ElapsedTime with a parameter TimeSnapShot
here the value of TimeSnapShot is the "relative-zero"-point
the method calculates the elapsed time in Milliseconds
'pseudecode
TimeSnapShot := cnt
repeat
...
if ElapsedTime(TimeSnapShot) > 10 milliseconds
turn off LED
these timerfunctions could be dedicated to its own cog
then your mainloop stays faster
and last but not least there is a timerobject in the obex
pseudo-code
repeat
if Button is pressed
StartTime := rdReg(TMR_SECS) 'make snapshot if the seconds if button is pressed
ActualTime := rdReg(TMR_SECS)
if ActualTime - StartTime > 0
if ActualTime - StartTime > WaitTime
turn LED off
else
if 60 + ActualTime - StartTime > WaitTime
turn LED off
best regards
Stefan
Post Edited (StefanL38) : 7/11/2008 8:00:30 AM GMT
With the PS2 would it be best to power the controller from the normal power out or the power for the vibration (feedback) motors.
Which provides more current and what one will be able to power the prop, sd, i/o expander, 20 leds, and perhaps an xbee unit?
computer guy said...
With the PS2 would it be best to power the controller from the normal power out or the power for the vibration (feedback) motors.
Which provides more current and what one will be able to power the prop, sd, i/o expander, 20 leds, and perhaps an xbee unit?
Thank you
I'd recommend using the motor power supply, and regulating it yourself. The 3.3v power rail actually isn't quite 3.3v: it's more like 3.6v if I remember right. I also don't know how much power it's rated for. Normal controllers only draw maybe 10mA at most from the 3.3v rail, and the Prop could need a good bit more than that.
The motor power supply is basically connected directly to the PS2's power brick, which is at about 7v. It can source plenty of current, but do be careful- i managed to blow the fuses on my PS2 multiple times while developing my Unicone2 device [noparse]:)[/noparse]
If you do blow the fuse, it's not that hard to replace- it's a 0-ohm SMT resistor. You can follow the traces from the controller ports on the PS2 circuit board to find it.
In that case, the code you posted will actually press every button except X!
The 'buttons' word is a bit field, each button is assigned one bit. A '1' means the button is not pressed, a '0' means it's pressed. So the default value of $FFFF means all buttons are up.
The BTN_X constant is a mask, which tells you which bit corresponds with the X button. $4000 has one bit set, and that bit is in the position corresponding with the X button in 'buttons'.
So, to press the 'X' button, you need to set its bit to zero, and to release it you need to set it to one. To set the bit you can bitwise 'or' it with the mask. To clear the bit, you can 'and' it with a mask in which every *other* bit is one, but the bit you want to clear is zero.
So to press the X button, you should be able to do:
c_buttons &= !BTN_X
and to release it:
c_buttons |= BTN_X
Sorry about the "~" syntax earlier- that's how you do a bitwise 'not' operation in C. In spin, it's just '!'.
Comments
It's simple enough that I haven't made an actual schematic. You can connect the PS2 controller data pins directly to the prop, they're both 3.3v logic. There are five data pins, which my emulator expects to be connected sequentially to Prop pins:
PIN_DAT = 0
PIN_CMD = 1
PIN_SEL = 2
PIN_CLK = 3
PIN_ACK = 4
There are plenty of places on the internet where you can find pinouts for the PS2 controller socket. Connect all of these pins to the prop, (every one of them is necessary) hook up ground, and ignore power (unless you want to power the prop off of the PS2 supply- if you do this, be very careful, as it's easy to blow a hard-to-replace fuse in the PS2).
I haven't tested this code, so please excuse any bugs, but it'd be something like this... All of the magic numbers for bytes and bits within the controller packet format are defined in my other "psx_remote_port" object, or most of them are available on the internet.
Good luck!
Post Edited (Micah Dowty) : 7/8/2008 5:25:03 PM GMT
Sorry just one more thing to release the left D-pad button what would I do?
My guess would be
but I am probably wrong.
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
c_buttons is a bitfield- "1" is not-pressed, "0" is pressed. To release the button, you'd bitwise OR it with $0080:
--Micah
release left
release right
Also to set the position of the left analog stick? and how many bits is it so that I can get the value from an ADC and go direct to output without any maths in between.
I will leave you alone so that you can get on with your own projects now.
Thank you so much
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
Post Edited (computer guy) : 7/9/2008 11:06:26 AM GMT
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
Almost... One way to do it is "c_buttons &= ~($0080 | $0020)". If you're still confused, re-read over the Propeller manual's section on operators, and perhaps check out a tutorial on boolean logic.
Also, be warned, I might have misspoke when I said that "1" is released and "0" is pressed. Some of my own notes were inconsistent, and I think it actually might be the other way around- "1" is pressed.
An 8-bit A/D should do exactly what you want. $00 and $FF are the extremes of motion (I forget the polarity- which one is left/top/right/bottom) and $80 is the center. If you're hooking this up to a pot, connect one leg of the pot to ground, one leg to your analog supply, and the wiper to your A/D.
On a serendipitous note... I also recently got asked about my PSX controller emulator by Julian Bleecker, who wanted to use it for his own project which interposes between a PS2 controller and the console in order to modify the analog joystick values. He was successful at using the emulator, and he even wrote a blog post which includes some sample code:
www.nearfuturelaboratory.com/2008/07/09/psx-with-propeller/
--Micah
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
The most straightforward way to do this would be to build a bitfield using a local variable, then assign c_buttons once at the end of your main loop. Something like:
It doesn't matter what values new_buttons takes on intermediately, as long as you assign to c_buttons only once.
I noticed that in Julian Bleecker's code he is setting the axis values using the same variable as the buttons (in my case "c_buttons").
Is this how it is done?
The whammy bar of a guitar her controller uses the "Left Analog stick's" Y value as the position of the whammy bar.
So this will also need to be set in the repeat loop.
Thank you, your code and assistance is appreciated.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
The emulator object just needs any arbitrary 18 bytes of memory. This can be a byte array of size 18, but it can also be a consecutive sequence of separate values: a word for the buttons, a 4-byte array for the axes, etc. It can be in the var section or the dat section. In my example, I used separate consecutively-allocated variables. In my example, the axes would be a different variable in the VAR section, immediately after c_buttons. That's one way of doing the job, but it isn't the only way.
Would this code work?
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
Post Edited (computer guy) : 7/10/2008 3:17:05 AM GMT
Er.. not quite. Call add_state_buffer() only once, with @c_buttons. Then modify the values in c_axes. This works because c_axes comes immediately after c_buttons in memory. The emulator object actually treats the address you pass it as a pointer to an 18-byte buffer with the whole controller state.
c_axes[noparse][[/noparse]0 to 3] to the value I want and it will do the rest?
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
Yup. Every time the Playstation polls your device, the emulator will read the necessary parts of your state buffer from hub memory- without any direct interaction from your Spin code. Go Propeller [noparse];)[/noparse]
--Micah
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
If you have cogs to burn, you could start a separate Spin cog which sets the pin high, sleeps for 10 seconds, then sets it low. [noparse];)[/noparse]
Otherwise, you'll need to know what this cog is doing 10 seconds into the future. It's impossible to always set the pin low *exactly* 10 seconds into the future if the cog will be doing other things, but if you can periodically poll ("Is it time to set the pin low yet?") while the cog is doing other things, you can approximate this kind of multi-tasking.
In your simple button-polling loop, you could implement this by:
1. When you want to set the pin high...
- Set it high
- Set a flag, to remind yourself that you need to set it low at some point
- Save the current CNT value
2. Then, periodically poll:
- Is the flag set?
- If so, subtract the current CNT value from the one you saved. Has it been 10 seconds yet?
- If so, set the pin low and clear the flag.
--Micah
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
Post Edited (computer guy) : 7/10/2008 7:31:59 AM GMT
Looks basically fine, though that method of comparing 'cnt' won't do what you expect. You can't rely on the CNT register to monotonically increase- it will wrap every minute or so. It's better to do something like this:
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
Yes there is.
You can do this with a variable that is used as a boolean flag
best regards
Stefan
Post Edited (StefanL38) : 7/10/2008 8:28:10 AM GMT
That would only work if I was repeating every 10 seconds.
Check the previous page of this thread for code that I think might work.
I don't need the delay to be exact, I just want an LED to light when a button is pushed and stay lit for aprox 10 seconds after the button is released.
Without the delay having to temporarily stop the repeat.
Thank you anyway.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my robot using the propeller RECONAUTOR
If you like my avatar then check this out Propeller Domed Stickers for sale
Building Blocks To The Propeller Chip
Post Edited (computer guy) : 7/11/2008 7:11:18 AM GMT
first of all i want to make a suggestion
this question has moved far away from the PS2-issue
how about starting a new thread ?
timer-programming-techniques are of common interest
but would never be expected in the middle of a thread about PS2-emulation
back to the question
aha i understand,
now this could be done by comparing the actual value of the systemvariable cnt with
a calculated value
There has do be done a little bit more because the cnt-variable wraps around from $FFFFFFFF to $0
@the forum: what is the result of +-calculations that exceed the 32-bit limit f.e. $FFFFFFFF + 100 ?
or second possability:
if your speed-requirements allow this
make a short waitcnt (maybe every millisecond) inside your loop and after every ms a variable is incremented.
If it reaches 3600000 = 1h it will be reset to zero
here is still a wrap around to zero but it could be calculated in 32bit
if TimeSnapShot + 10 sec > TimeMax handle wrap around
another concept could be to put the details of the timecomparing in a method ElapsedTime with a parameter TimeSnapShot
here the value of TimeSnapShot is the "relative-zero"-point
the method calculates the elapsed time in Milliseconds
these timerfunctions could be dedicated to its own cog
then your mainloop stays faster
and last but not least there is a timerobject in the obex
obex.parallax.com/objects/45/
it provides a clock with Milliseconds
best regards
Stefan
Post Edited (StefanL38) : 7/11/2008 8:00:30 AM GMT
Which provides more current and what one will be able to power the prop, sd, i/o expander, 20 leds, and perhaps an xbee unit?
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Building Blocks To The Propeller Chip A web site designed to help people who are new to the propeller chip.
Guitar Hero controller using the prop (WIP) --> HERE
I'd recommend using the motor power supply, and regulating it yourself. The 3.3v power rail actually isn't quite 3.3v: it's more like 3.6v if I remember right. I also don't know how much power it's rated for. Normal controllers only draw maybe 10mA at most from the 3.3v rail, and the Prop could need a good bit more than that.
The motor power supply is basically connected directly to the PS2's power brick, which is at about 7v. It can source plenty of current, but do be careful- i managed to blow the fuses on my PS2 multiple times while developing my Unicone2 device [noparse]:)[/noparse]
If you do blow the fuse, it's not that hard to replace- it's a 0-ohm SMT resistor. You can follow the traces from the controller ports on the PS2 circuit board to find it.
Good luck,
--Micah
Hi again.
I have connected a ps2 cable up to my prop and loaded a test file.
When I turn it on whilst in the ps2 menu it does nothing. The second controller I have plugged in will only let me press "X".
If I change
to
than I can only press triangle.
I have tried
but it does nothing.
If I use
the propeller tool says "expected a variable".
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Building Blocks To The Propeller Chip A web site designed to help people who are new to the propeller chip.
Guitar Hero controller using the prop (WIP) --> HERE
I'm assuming your value of BTN_X is $4000, right?
In that case, the code you posted will actually press every button except X!
The 'buttons' word is a bit field, each button is assigned one bit. A '1' means the button is not pressed, a '0' means it's pressed. So the default value of $FFFF means all buttons are up.
The BTN_X constant is a mask, which tells you which bit corresponds with the X button. $4000 has one bit set, and that bit is in the position corresponding with the X button in 'buttons'.
So, to press the 'X' button, you need to set its bit to zero, and to release it you need to set it to one. To set the bit you can bitwise 'or' it with the mask. To clear the bit, you can 'and' it with a mask in which every *other* bit is one, but the bit you want to clear is zero.
So to press the X button, you should be able to do:
c_buttons &= !BTN_X
and to release it:
c_buttons |= BTN_X
Sorry about the "~" syntax earlier- that's how you do a bitwise 'not' operation in C. In spin, it's just '!'.
--Micah
Works great.
I think I tried every bitwise operation except that.
I even tried
out of frustration.
Thank you
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Building Blocks To The Propeller Chip A web site designed to help people who are new to the propeller chip.
Guitar Hero controller using the prop (WIP) --> HERE