' =============================================================================== ' ' File....... DemoDerby.BS2 ' Purpose.... Prototype This: Anger Management Demolition Derby ' Author..... Joe Grand ' ' {$STAMP BS2sx} ' {$PBASIC 2.5} ' ' =============================================================================== ' -----[ Program Description ]--------------------------------------------- ' This code is for the Anger Management Demolition Derby interface board ' that reads in data from the Thrustmaster Ferrari GT 2-in-1 Racing Wheel, ' controls the Electric Shockerator, handles the On-Screen Display for each ' player's POV monitor, and communicates with Zoz via the Lantronix XPORT ' in a UDP broadcast packet. ' ' Network configuration: ' ' Joe, 169.254.1.69 port 31337 ' Zoz, 169.254.1.70 port 31338 ' North, 169.254.1.71 port 31339 ' Terry, 169.254.1.72 port 31340 ' Main host, 169.254.1.202 ' ' The Sony PlayStation 2 interface and portions of code are based on ' previous work by Aaron Dahlen and Jon Williams. ' ' -----[ I/O Definitions ]------------------------------------------------- XPORT_TX PIN 2 ' Serial data input to Xport FROM BS2 XPORT_RX PIN 3 ' Serial data output from XPort TO BS2 PsxAtt PIN 14 ' PSX joystick interface PsxClk PIN 15 PsxCmd PIN 13 PsxDat PIN 12 Bob_SOUT PIN 5 ' BOB-4-H Video On-Screen Display, INPUT from BOB Bob_SIN PIN 11 ' OUTPUT to BOB SysReady PIN 1 ShockEnable PIN 4 ' Shockerator enable (active HIGH) ' -----[ Constants ]------------------------------------------------------- #SELECT $STAMP #CASE BS2, BS2E, BS2PE T1200 CON 813 T2400 CON 396 T4800 CON 188 T9600 CON 84 T19K2 CON 32 T38K4 CON 6 #CASE BS2SX, BS2P T1200 CON 2063 T2400 CON 1021 T4800 CON 500 T9600 CON 240 T19K2 CON 110 T38K4 CON 45 #ENDSELECT XPORT_Baud CON T19K2 BOB_Baud CON T19K2 Inverted CON 1 ' inverted clock signal Direct CON 0 ' no inverter in clock line ClockMode CON Inverted ' PlayerNum nameZoz CON 0 nameJoe CON 1 nameNorth CON 2 nameTerry CON 3 ' Gears gearPark CON 0 gearFwd CON 1 gearNeutral CON 2 gearRev CON 3 ' -----[ Variables ]------------------------------------------------------- cnt VAR Nib ' counter for on-screen display update idx VAR Nib ' loop counter psxOut VAR Byte ' byte to controller psxIn VAR Byte ' byte from controller ' joystick packet ' psxThumbL = Dpad L : Dpad D : Dpad R : Dpad U : ST : R3 : L3 : SE ' psxThumbR = Square : X : Circle : Triangle : R1 : L1 : Up Shift : Down Shift ' psxJoyLX = Steering wheel, 128 center, 0 left, 255 right ' psxJoyLY = Unused ' PsxJoyRX = Brake, 0 unpressed, 255 max press ' PsxJoyRY = Acceleration, 0 unpressed, 255 max press psxID VAR Byte ' controller ID psxStatus VAR Byte ' status ($5A) psxThumbL VAR Byte ' left thumb buttons psxThumbR VAR Byte ' right thumb buttons psxJoyLX VAR Byte ' l joystick - X axis psxJoyLY VAR Byte ' l joystick - Y axis psxJoyRX VAR Byte ' r joystick - X axis psxJoyRY VAR Byte ' r joystick - Y axis ' BOB-4-H OSD csi VAR Byte(2) 'Control Sequence Introducer = ESC,[ ' player status information (received from zoz) playerNum VAR Byte name1 VAR Byte ' xport didn't like the byte array for some reason, so have to define discrete bytes for name string name2 VAR Byte name3 VAR Byte name4 VAR Byte name5 VAR Byte name6 VAR Byte gear VAR Byte maxAcc VAR Byte gsrOK VAR Byte heartVal VAR Byte emotivOK VAR Byte ' -----[ Initialization ]-------------------------------------------------- Setup: PAUSE 1000 HIGH PsxAtt ' deselect PSX controller OUTPUT PsxCmd PsxClk = ~ClockMode ' release clock OUTPUT PsxClk ' make clock an output csi(0) = 27 'esc csi(1) = 91 '[ cnt = 0 LOW ShockEnable HIGH SysReady ' the system's ready to go ' -----[ Program Code ]---------------------------------------------------- Main: DEBUG CLS, "Anger Management Demolition Derby", CR DEBUG "---------------------------------", CR, CR ' setup on-screen display parameters SEROUT Bob_SIN, BOB_Baud, [STR csi\2,"20;3v"] 'set display to 480 x 288 SEROUT Bob_SIN, BOB_Baud, [STR csi\2,"0m"] 'clear display settings SEROUT Bob_SIN, BOB_Baud, [STR csi\2,"2J"] 'clear screen SEROUT Bob_SIN, BOB_Baud, [STR csi\2,"0z"] 'select font 0 to 7 SEROUT Bob_SIN, BOB_Baud, [STR csi\2,"7m"] 'set inverse text ' draw filled white square for background SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "0;182.r"] SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "480;182+r"] SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "480;288+r"] SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "0;288+r"] SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "!r"] SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "#r"] DO cnt = cnt + 1 ' increment counter GOSUB Get_PSX_Packet_Fast IF (psxStatus = $5A AND psxId <> $41) THEN 'DEBUG "Type = ", IHEX2 psxId, " (Status = ", IHEX2 psxStatus, ") " 'DEBUG BIN8 psxThumbL, " ", BIN8 psxThumbR, " " 'DEBUG DEC3 psxJoyLX, " ", DEC3 psxJoyLY, " ", DEC3 psxJoyRX, " ", DEC3 psxJoyRY ' shockerator (for testing/demo only - won't be used for finale) 'IF (psxThumbL.BIT0 = 0) THEN ' enable with the SE button ' DEBUG " SHOCK!" ' HIGH ShockEnable 'ELSE ' LOW ShockEnable 'ENDIF 'DEBUG CR DEBUG "." ' ps2 controller debug information ' SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;1H"] ' SEROUT Bob_SIN, BOB_Baud, [$C4, $88] ' clock symbol - it looks like a steering wheel (unicode) ' SEROUT Bob_SIN, BOB_Baud, [" ", DEC3 psxJoyLX] ' steering wheel ' SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;8H"] ' SEROUT Bob_SIN, BOB_Baud, [$C4, $81] ' symbol (unicode) ' SEROUT Bob_SIN, BOB_Baud, [" ", DEC3 psxJoyRX] ' brake ' SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;15H"] ' SEROUT Bob_SIN, BOB_Baud, [$C4, $82] ' symbol (unicode) ' SEROUT Bob_SIN, BOB_Baud, [" ", DEC3 psxJoyRY] ' acceleration ' SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;21H"] ' SELECT (psxThumbL) ' CASE %01111111 ' SEROUT Bob_SIN, BOB_Baud, [$C3, $BF] ' Dpad L ' CASE %10111111 ' SEROUT Bob_SIN, BOB_Baud, [$C4, $81] ' Dpad D ' CASE %11011111 ' SEROUT Bob_SIN, BOB_Baud, [$C4, $80] ' Dpad R ' CASE %11101111 ' SEROUT Bob_SIN, BOB_Baud, [$C4, $82] ' Dpad U ' CASE %11110111 ' SEROUT Bob_SIN, BOB_Baud, [$C2, $89] ' ST ' CASE %11111011 ' SEROUT Bob_SIN, BOB_Baud, ["7"] ' R3 ' CASE %11111101 ' SEROUT Bob_SIN, BOB_Baud, ["5"] ' L3 ' CASE %11111110 ' SEROUT Bob_SIN, BOB_Baud, [$C2, $8A] ' SE ' CASE ELSE ' SEROUT Bob_SIN, BOB_Baud, [" "] ' ENDSELECT ' SELECT (psxThumbR) ' CASE %01111111 ' SEROUT Bob_SIN, BOB_Baud, ["2"] ' Square ' CASE %10111111 ' SEROUT Bob_SIN, BOB_Baud, ["1"] ' X ' CASE %11011111 ' SEROUT Bob_SIN, BOB_Baud, ["3"] ' Circle ' CASE %11101111 ' SEROUT Bob_SIN, BOB_Baud, ["4"] ' Triangle ' CASE %11110111 ' SEROUT Bob_SIN, BOB_Baud, ["8"] ' R1 ' CASE %11111011 ' SEROUT Bob_SIN, BOB_Baud, ["6"] ' L1 ' CASE %11111101 ' SEROUT Bob_SIN, BOB_Baud, ["+"] ' Up Shift ' CASE %11111110 ' SEROUT Bob_SIN, BOB_Baud, ["-"] ' Down Shift ' CASE ELSE ' SEROUT Bob_SIN, BOB_Baud, [" "] ' ENDSELECT ' send packet to zoz SEROUT XPORT_TX, XPORT_Baud, [psxThumbL, psxThumbR, psxJoyLX, psxJoyLY, psxJoyRX, psxJoyRY] IF (cnt = 10) THEN cnt = 0 ' get packet from zoz, if available (timeout if nothing received in 100mS) SERIN XPORT_RX, XPORT_Baud, 100, NoZozData, [WAIT("!"), playerNum, name1, name2, name3, name4, name5, name6, gear, maxAcc, gsrOK, heartVal, emotivOK] 'DEBUG "playerNum = ", DEC playerNum, ", name = ", STR name1\1, STR name2\1, STR name3\1, STR name4\1, STR name5\1, STR name6\1, ", gear = ", DEC gear, ", maxAcc = ", DEC maxAcc, ", gsrOK = ", DEC gsrOK, ", heartVal = ", DEC heartVal, ", emotivOK = ", DEC emotivOK, CR ' draw status to screen ' line 1 SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "14;1H"] 'position cursor, row;column ' player name SELECT (playerNum) 'add special character (unicode) before the name CASE nameJoe SEROUT Bob_SIN, BOB_Baud, [$C2, $9F] ' cat CASE nameZoz SEROUT Bob_SIN, BOB_Baud, [$C3, $9A] ' z CASE nameNorth SEROUT Bob_SIN, BOB_Baud, [$C2, $8C] ' boat CASE nameTerry SEROUT Bob_SIN, BOB_Baud, [$C2, $9D] ' duck thing ENDSELECT SEROUT Bob_SIN, BOB_Baud, [" ", STR name1\1, STR name2\1, STR name3\1, STR name4\1, STR name5\1, STR name6\1] ' send the name received from zoz ' what gear is the car currently in? SEROUT Bob_SIN, BOB_Baud, [" ", $C2, $8D] SELECT (gear) CASE gearPark SEROUT Bob_SIN, BOB_Baud, [" Park"] CASE gearFwd SEROUT Bob_SIN, BOB_Baud, [" Fwd "] CASE gearRev SEROUT Bob_SIN, BOB_Baud, [" Rev "] CASE gearNeutral SEROUT Bob_SIN, BOB_Baud, [" Neut"] ENDSELECT ' maximum acceleration (in %) SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "14;19H"] 'position cursor, row;column SEROUT Bob_SIN, BOB_Baud, ["Max Accel: ", DEC3 maxAcc, "%"] ' line 2 ' heart rate SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;1H"] 'position cursor, row;column SEROUT Bob_SIN, BOB_Baud, [$C4, $84] ' heart symbol (unicode) SEROUT Bob_SIN, BOB_Baud, [" ", DEC3 heartVal] SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;8H"] SEROUT Bob_SIN, BOB_Baud, ["GSR: "] ' galvanic skin response IF (gsrOK = 0) THEN SEROUT Bob_SIN, BOB_Baud, ["Calm "] ELSE SEROUT Bob_SIN, BOB_Baud, ["Aggro"] ENDIF SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;19H"] SEROUT Bob_SIN, BOB_Baud, ["Emotiv: "] ' emotiv IF (emotivOK = 0) THEN SEROUT Bob_SIN, BOB_Baud, ["Calm "] ELSE SEROUT Bob_SIN, BOB_Baud, ["Aggro"] ENDIF GOTO Done NoZozData: DEBUG "No Zoz Data!", CR SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "14;1H"] 'position cursor SEROUT Bob_SIN, BOB_Baud, ["NO ZOZ DATA! "] SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;1H"] 'position cursor SEROUT Bob_SIN, BOB_Baud, [" "] Done: ENDIF ' end of on screen display update ELSE DEBUG "Controller not responding!", CR ' SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "14;1H"] 'position cursor ' SEROUT Bob_SIN, BOB_Baud, ["CONTROLLER NOT RESPONDING! "] ' SEROUT Bob_SIN, BOB_Baud, [STR csi\2, "15;1H"] 'position cursor ' SEROUT Bob_SIN, BOB_Baud, [" "] ' END ' stop the program so we can figure out what's wrong. this will force us to restart after we fix the problem. ENDIF LOOP END ' -----[ Subroutines ]----------------------------------------------------- ' This routine combines manual and built-in shifting ' routines to get the best speed and all valid data. ' ' Execution time on BS2 is ~40 ms. Get_PSX_Packet_Fast: LOW PsxAtt ' select controller SHIFTOUT PsxCmd, PsxClk, LSBFIRST, [$01] ' send "start" psxOut = $42 : GOSUB PSX_TxRx ' send "get data" psxId = psxIn ' save controller type SHIFTIN PsxDat, PsxClk, LSBPRE, [psxStatus] ' should be $5A ("ready") SHIFTIN PsxDat, PsxClk, LSBPRE, [psxThumbL] SHIFTIN PsxDat, PsxClk, LSBPRE, [psxThumbR] SHIFTIN PsxDat, PsxClk, LSBPRE, [psxJoyRX] SHIFTIN PsxDat, PsxClk, LSBPRE, [psxJoyRY] SHIFTIN PsxDat, PsxClk, LSBPRE, [psxJoyLX] GOSUB PSX_TxRx : psxJoyLY = psxIn HIGH PsxAtt ' deselect controller RETURN ' Transmit psxOut to, and receive psxIn from the ' PSX controller PSX_TxRx: FOR idx = 0 TO 7 PsxCmd = psxOut.LOWBIT(idx) ' setup command bit PsxClk = ClockMode ' clock the bit psxIn.LOWBIT(idx) = PsxDat ' get data bit PsxClk = ~ClockMode ' release clock NEXT RETURN ' -----[ END OF FILE ]-----------------------------------------------------