Copyright Nick Fisk 2010 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . SYMBOL RS = 2 ; 0 = Command 1 = Data SYMBOL E = 3 ; 0 = Idle 1 = Active SYMBOL DB4 = 4 ; LCD Data Line 4 SYMBOL DB5 = 5 ; LCD Data Line 5 SYMBOL DB6 = 6 ; LCD Data Line 6 SYMBOL DB7 = 7 ; LCD Data Line 7 SYMBOL RSCMDmask = %00000000 ; Select Command register SYMBOL RSDATmask = %00000100 ; Select Data register SYMBOL shotbyte = b0 SYMBOL recievebyte = b1 SYMBOL roundtimer = b2 SYMBOL bullets = b3 SYMBOL Health = b4 SYMBOL PlayerID = b5 SYMBOL TeamID = b6 SYMBOL OutputPower = b7 SYMBOL counter = b11 SYMBOL sendbyte = b12 SYMBOL rsbit = b13 SYMBOL shotmode = b14 SYMBOL clips = b15 SYMBOL mode = b22 SYMBOL sensorcounter = b23 SYMBOL GameID = b24 'Store Data in EEPROM ' Nibble commands - To initialise 4-bit mode on LCD EEPROM 0,( $33 ) ; %0011---- %0011---- 8-bit / 8-bit EEPROM 1,( $32 ) ; %0011---- %0010---- 8-bit / 4-bit 'Byte commands - To configure the LCD EEPROM 2,( $28 ) ; %00101000 %001LNF00 Display Format EEPROM 3,( $0C ) ; %00001100 %00001DCB Display On EEPROM 4,( $06 ) ; %00000110 %000001IS Cursor Move ; L : 0 = 4-bit Mode 1 = 8-bit Mode ; N : 0 = 1 Line 1 = 2 Lines ; F : 0 = 5x7 Pixels 1 = N/A ; D : 0 = Display Off 1 = Display On ; C : 0 = Cursor Off 1 = Cursor On ; B : 0 = Cursor Steady 1 = Cursor Flash ; I : 0 = Dec Cursor 1 = Inc Cursor ; S : 0 = Cursor Move 1 = Display Shift EEPROM 5,( $01 ) ; Clear Screen 'Strings stored in EEPROM EEPROM 6,("Welcome") ;Welcome string EEPROM 13,("T ID Hlth Ammo C") ;Main Status String EEPROM 29,("Plyr") EEPROM 33,("Cfg") EEPROM 36,("Gun") EEPROM 39,("BAT") EEPROM 42,("Team") EEPROM 46,("ID") EEPROM 48,("To Libre Tag") '59 EEPROM 60,("Reloading") '68 EEPROM 69,("V0.93") '73 EEPROM 74,("Check Sensor") '85 EEPROM 86,("Out Pwr") '92 'Game Defaults EEPROM 200,(1) ;PlayerID EEPROM 201,(1) ;TeamID EEPROM 202,(30) ;Ammo per clip EEPROM 203,(100) ;Health EEPROM 204,(100) ;Output Power % EEPROM 205,(2) ;Gun type 1=MGun 2=Gatling PowerOnReset: 'Initialise pins and hardware low portc 4 read 204,OutputPower Select Case OutputPower case 20 pwmout 1 , 20, 42 case 40 pwmout 1 , 21, 44 case 60 pwmout 1 , 23, 48 case 80 pwmout 1 , 24, 50 case 100 pwmout 1 , 25, 53 EndSelect 'pwmout 1 , 25, 53 'pwmout 1 , 19, 40 let b0=85 hsersetup B2400_4,%11 GOSUB InitialiseLcd 'Display welcome string FOR counter = 6 TO 12 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=$8B GOSUB SendInitCmdByte FOR counter = 69 TO 73 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=$C0 GOSUB SendInitCmdByte pause 10 FOR counter = 48 TO 59 READ counter,sendbyte GOSUB SendDataByte NEXT high portc 2 sound 0,(50,30) low portc 2 high portc 3 sound 0,(80,30) high portc 2 sound 0,(110,30) low portc 2 low portc 3 'Read Game variables out of EEPROM read 202,bullets read 203,Health read 201,TeamID read 200,PlayerID read 205,b27 'Read gun type into temp Select Case b27 case 1 'Machine Gun poke 80,30 poke 81,5 poke 82,2 bullets=30 clips=5 case 2 poke 80,200 poke 81,10 poke 82,0 bullets=200 clips=10 EndSelect GameID=170 'clips=5 pause 1000 IF portA pin2 = 1 then sound 0,(120,10) mode=10 pause 1000 GOTO CalculateShotByte endif Gosub DisplayStatus GOTO CalculateShotByte 'END 'LCD Routines InitialiseLcd: FOR counter = 0 TO 5 READ counter,sendbyte GOSUB SendInitCmdByte NEXT RETURN SendInitCmdByte: PAUSE 10 ; Delay 15mS SendCmdByte: 'rsbit = RSCMDmask ; Send to Command register PEEK $30,rsbit rsbit = rsbit & %11 goto sendCmdOrDataByte SendDataByte: PEEK $30,rsbit rsbit = RSDATmask ; Send to Data register next SendCmdOrDataByte: pins = sendbyte & %11110000 | rsbit ; Put MSB out first PULSOUT E,1 ; Give a 10uS pulse on E pins = sendbyte * %00010000 | rsbit ; Put LSB out second PULSOUT E,1 RETURN ; Give a 10uS pulse on E CalculateShotByte: 'No point calculating it every shot, it never changes 'Shift the variables into a byte (PPPPTTxp) P=Player T=Team x=unused p=parity b25=playerid<<4 ;Move playerid 4 bits to the left b26=teamid<<2 ;Move teamid 2 bits to the left shotbyte=b25|b26 ;Add them together 'sertxd (#bit7,#bit6,#bit5,#bit4,#bit3,#bit2,#bit1,#bit0,cr,lf) b25=shotbyte shotbyte=0 'Calculate the Parity 'FOR b27=1 TO 7 ' shotbyte=shotbyte^b25 ' shotbyte=shotbyte<<1 'NEXT bit7=bit6^bit5^bit4^bit3^bit2^bit1^bit0 shotbyte=b25|bit7 ;Add the parity to the byte main: IF portA pin0 = 1 AND mode = 0 then ;Has trigger button been pressed b27=shotmode & %01 b26=shotmode & %10 IF roundtimer=0 AND b27=0 then ;Has the delay between shots expired shotmode=shotmode | %01 IF bullets > 0 then ;Do we have any bullets ;Flash the muzzle 'sertxd (#bit7,#bit6,#bit5,#bit4,#bit3,#bit2,#bit1,#bit0,cr,lf) high portc 4 hserout 0,(GameID,shotbyte,shotbyte) ;Send the byte peek 82,roundtimer ;Delay the next shot bullets=bullets-1 ;Decrement the number of bullets 'sound 0,(140,1,160,1) sound 0,(80,1,250,1) low portc 4 if b26=0 then shotmode=shotmode & %10 endif 'Update remaining ammo on the LCD if roundtimer<>0 then gosub displayammo else shotmode=shotmode | %100 endif else sound 0,(255,1) endif endif endif if portA pin0=0 then b27=shotmode & %100 if b27>0 then shotmode=shotmode & %010 gosub displayammo endif shotmode=shotmode & %10 endif 'Countdown until next shot if roundtimer>0 then roundtimer=roundtimer-1 if roundtimer>=200 then if roundtimer=200 then roundtimer=0 GOSUB DisplayStatus endif if roundtimer>200 then b27=roundtimer-180%3 if b27=0 then sendbyte="#" GOSUB SendDataByte endif pause 120 if roundtimer=201 then sound 0,(120,10) pause 10 sound 0,(120,10) endif endif endif endif 'Anti cheat sensor check CheckSensor: if portc pin7 = 0 AND hserinflag = 0 AND sensorcounter < 100 then sensorcounter=sensorcounter+1 elseif sensorcounter > 0 then sensorcounter=sensorcounter-1 endif if sensorcounter = 100 then sertxd("Check Sensor") sendbyte=$01 GOSUB SendCmdByte sendbyte=$C0 GOSUB SendCmdByte FOR counter = 74 TO 85 READ counter,sendbyte GOSUB SendDataByte NEXT 'Pause 500 if portc pin7 =1 then GOSUB DisplayStatus sensorcounter=0 endif goto CheckSensor endif IF mode<50 AND mode>0 then 'debug b27=mode % 10 IF portA pin2 = 1 then roundtimer=0 sound 0,(120,10) pause 250 if b27=0 then mode=mode+10 else mode=mode+1 endif if mode=13 then mode=10 endif if mode=22 then mode=20 endif if mode=30 then mode=0 write 201,TeamID write 200,PlayerID write 204,OutputPower GOSUB DisplayStatus GOTO CalculateShotByte endif endif IF portA pin1 =1 then roundtimer=0 sound 0,(120,10) pause 250 Select Case Mode case 11 if PlayerID<14 then PlayerID=PlayerID+1 else PlayerID=1 endif case 12 if TeamID<2 then TeamID=TeamID+1 else TeamID=1 endif case 21 if OutputPower<100 then OutputPower=OutputPower+20 else OutputPower=20 endif 'change the pwm frequency Select Case OutputPower case 20 pwmout 1 , 20, 42 case 40 pwmout 1 , 21, 44 case 60 pwmout 1 , 23, 48 case 80 pwmout 1 , 24, 50 case 100 pwmout 1 , 25, 53 EndSelect EndSelect IF b27=0 then mode=mode+1 endif endif if roundtimer = 0 then 'pause 500 sendbyte=$01 GOSUB SendCmdByte pause 10 select case mode case 10 goto menu10 case 11 goto menu11 case 12 goto menu12 case 20 goto menu20 case 21 goto menu21 endselect 'we are in menu mode 'The headers menu10: FOR counter = 29 TO 32 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=" " GOSUB SendDataByte FOR counter = 33 TO 35 READ counter,sendbyte GOSUB SendDataByte NEXT goto battery menu11: 'PlayerID FOR counter = 29 TO 32 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=" " GOSUB SendDataByte FOR counter = 46 TO 47 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=" " GOSUB SendDataByte bintoascii PlayerID,b25,b26,b27 sendbyte=b26 GOSUB SendDataByte sendbyte=b27 GOSUB SendDataByte goto battery menu12: 'TeamID FOR counter = 42 TO 45 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=" " GOSUB SendDataByte FOR counter = 46 TO 47 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=" " GOSUB SendDataByte bintoascii TeamID,b25,b26,b27 sendbyte=b27 GOSUB SendDataByte goto battery menu20: FOR counter = 36 TO 38 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=" " GOSUB SendDataByte FOR counter = 33 TO 35 READ counter,sendbyte GOSUB SendDataByte NEXT goto battery menu21: FOR counter = 86 TO 92 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=" " GOSUB SendDataByte bintoascii OutputPower,b25,b26,b27 sendbyte=b25 GOSUB SendDataByte sendbyte=b26 GOSUB SendDataByte sendbyte=b27 GOSUB SendDataByte sendbyte="%" GOSUB SendDataByte goto battery battery: sendbyte=$C0 GOSUB SendCmdByte FOR counter = 39 TO 41 READ counter,sendbyte GOSUB SendDataByte NEXT readadc10 3,w13 if w13=0 then w13=670 endif b20=w13-650 b20=b20/2 bintoascii b20,b25,b26,b27 sendbyte=":" GOSUB SendDataByte sendbyte=b26 GOSUB SendDataByte sendbyte=b27 GOSUB SendDataByte sendbyte="%" GOSUB SendDataByte readadc10 3,w13 if w13=0 then w13=670 endif w13=w13-650 w13=w13/20 'debug FOR b20=1 to w13 sendbyte="#" GOSUB SendDataByte NEXT roundtimer=50 endif endif if portA pin2 =1 AND mode=0 then b27=shotmode & %01 b26=shotmode & %10 if b26=0 then shotmode=shotmode | %10 else shotmode=shotmode & %00 endif GOSUB displayammo2 pause 500 GOTO CalculateShotByte endif IF portA pin1 =1 AND mode=0 AND clips>0 then sound 0,(220,3) pause 100 sound 0,(250,3) pause 500 sound 0,(250,10) peek 80,bullets roundtimer=230 sendbyte=$01 clips=clips-1 GOSUB SendCmdByte pause 10 FOR counter = 60 TO 68 READ counter,sendbyte GOSUB SendDataByte NEXT sendbyte=$C0 GOSUB SendCmdByte pause 10 endif 'Receiving Code IF hserinflag = 1 then pause 10 hserinflag=0;Reset data waiting flag ptr=0 'Retrieve Bytes b26=0 DO if ptr=2 then if recievebyte <> @ptr then sound 0,(126,8,80,1) goto endrecieve endif endif recievebyte=@ptrinc 'sertxd(#recievebyte,",") if ptr=1 then if recievebyte<>GameID then 'sertxd("Wrg3",cr,lf) goto endrecieve endif endif LOOP UNTIL ptr=3 'sertxd (#bit7,#bit6,#bit5,#bit4,#bit3,#bit2,#bit1,#bit0," ",#bit15,#bit14,#bit13,#bit12,#bit11,#bit10,#bit9,#bit8,cr,lf) 'sertxd(cr,lf) 'b25=recievebyte 'recievebyte=0 'Calculate Parity 'FOR b27=1 to 7 ' recievebyte=recievebyte<<1 ' recievebyte=recievebyte^b25 'NEXT 'bit15=bit14^bit13^bit12^bit11^bit10^bit9^bit8 'b26=b25 & %11111110 ;Remove Parity for to test 'sertxd(#bit15) 'recievebyte=b26|bit15 ;Add the calculated parity on 'if recievebyte=b25 then ;If the calculate byte is the same as the recieved on, we are good to go 'sertxd("Parity Correct ",#bit15,#bit14,#bit13,#bit12,#bit11,#bit10,#bit9,#bit8,cr,lf) b25=recievebyte>>4 ;Shift the data back to its original position b26=recievebyte>>2 b26=b26 & %00000011 if b25!=15 then ;Small check to rule out any obvious false packets - player 16 should never exist 'sertxd(#b25,",",#b26) if b26!=teamID and b25!=playerID then ;Check shooter is not on same team 'sertxd("enemy hit") if health > 4 then ;Turn off hit light health=health-5 if teamID=1 then high portc 2 else high portc 3 endif sound 0,(60,1) else health=0 mode=255 sound 0,(80,30,50,30,5,60) endif gosub displayhealth low portc 2 low portc 3 else 'sertxd("friendly fire") endif else 'sertxd("wrg2",cr,lf) endif 'else 'sertxd("Wrg",cr,lf) ' sound 0,(255,10,80,1) 'endif endrecieve: 'endif hserptr=0 b1=0 endif goto main displayhealth: bintoascii Health,b25,b26,b27 if Health > 85 then sendbyte=$C5 GOSUB SendCmdByte sendbyte=b25 GOSUB SendDataByte else sendbyte=$C6 GOSUB SendCmdByte endif sendbyte=b26 GOSUB SendDataByte sendbyte=b27 GOSUB SendDataByte RETURN displayammo: bintoascii bullets,b25,b26,b27 if roundtimer = 0 then sendbyte=$C9 GOSUB SendCmdByte sendbyte=b25 GOSUB SendDataByte else sendbyte=$CA GOSUB SendCmdByte endif sendbyte=b26 GOSUB SendDataByte sendbyte=b27 GOSUB SendDataByte RETURN displayammo2: 'shotmode and clips sendbyte=$CC GOSUB SendCmdByte b26=shotmode & %10 if b26=2 then sendbyte="S" else sendbyte="B" endif GOSUB SendDataByte sendbyte=$CE GOSUB SendCmdByte bintoascii clips,b25,b26,b27 sendbyte=b26 GOSUB SendDataByte sendbyte=b27 GOSUB SendDataByte RETURN displaystatus: 'Display Status Screen sendbyte=$01 GOSUB SendCmdByte pause 10 'The headers FOR counter = 13 TO 28 READ counter,sendbyte GOSUB SendDataByte NEXT 'And then the data sendbyte=$C0 GOSUB SendCmdByte bintoascii TeamID,b25,b26,b27 sendbyte=b27 GOSUB SendDataByte sendbyte=$C2 GOSUB SendCmdByte bintoascii PlayerID,b25,b26,b27 sendbyte=b26 GOSUB SendDataByte sendbyte=b27 GOSUB SendDataByte GOSUB displayammo2 GOSUB displayhealth GOSUB displayammo RETURN