UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


projects:aerosol_code

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
projects:aerosol_code [2008/03/01 05:17] laurencebprojects:aerosol_code [2008/07/19 23:33] (current) – external edit 127.0.0.1
Line 2: Line 2:
  
  This is in python, you can find a detailed guide on installing python on the NGW100 [[http://www.cibomahto.com/?p=82|here]]. The reed_solomon library can be found on the wiki [[code:python_reedsolomon|here]]  This is in python, you can find a detailed guide on installing python on the NGW100 [[http://www.cibomahto.com/?p=82|here]]. The reed_solomon library can be found on the wiki [[code:python_reedsolomon|here]]
- 
  
  
 <code python> <code python>
 #!/media/mmcblk0p1/install/bin/python #!/media/mmcblk0p1/install/bin/python
 +##!/usr/bin/python
  
 + 
 import reed_solomon import reed_solomon
 import serial import serial
Line 15: Line 16:
 TRUE=1 TRUE=1
 FALSE=0 FALSE=0
-mynumber=#ha you really thought I'post it on here?+DEG2RAD=math.pi/180.0 
 +class updatest: 
 + pass 
 +mynumber="44<really think I'be that silly?>"
 default_target_pressure=40 default_target_pressure=40
-start_altitude=200                 #sampling starts here +limit=[200,10000,20000]                #our altitude ranges for the different samples 
-limit=[10000,20000]                #our altitude ranges for the different samples+max_flight_time=7000
 callsign="AOPP" callsign="AOPP"
 logname="flightlog.txt" logname="flightlog.txt"
-global Jxpoints +Roottwotwomgovercda = (2*9.81*2/0.72)**0.5 #work this out for our payload mass, cda from http://members.aol.com/nakkarocketry/paratest.html 
-global Jypoints +iterations=0 
-global Iterations +Jxpoints=[] 
-global Roottwomgovercda +Jypoints=[] 
- +updatestuff=updatest() 
 +  
 +  
 + 
 def gps_status(): def gps_status():
  print 'Retrieving GPS status'  print 'Retrieving GPS status'
- gpspos_parts[0]='' + gpspos_parts=['']
  while not gpspos_parts[0]=='$GPGGA':  while not gpspos_parts[0]=='$GPGGA':
  gpspos=ser_gr.readline()  gpspos=ser_gr.readline()
 + print "got" , gpspos
  gpspos_parts = gpspos.split(',')  gpspos_parts = gpspos.split(',')
- if ((gpspos_parts[6]=='2') or (gpspos_parts[6]=='3')): #2D or 3D fix+ if ((gpspos_parts[6]=='1') or (gpspos_parts[6]=='2') or (gpspos_parts[6]=='3')): #2D or 3D fix/DGPS fix
  print 'GPS fix' , gpspos_parts[6] , 'ie valid'  print 'GPS fix' , gpspos_parts[6] , 'ie valid'
- gpsstatus=TRUE+ status=TRUE
  else:  else:
  print 'GPS fix' , gpspos_parts[6] , 'ie not valid'  print 'GPS fix' , gpspos_parts[6] , 'ie not valid'
  status=FALSE  status=FALSE
  return status  return status
 + 
 def gps_data(): def gps_data():
 + ser_gr.flushInput()                       #as gps strings will have built up over time
  print 'Retrieving GPS data'  print 'Retrieving GPS data'
- gpspos_parts[0]='' + gpspos_parts=['']
  while not gpspos_parts[0]=='$GPGGA':  while not gpspos_parts[0]=='$GPGGA':
  gpspos=ser_gr.readline()  gpspos=ser_gr.readline()
  gpspos_parts = gpspos.split(',')  gpspos_parts = gpspos.split(',')
  gpstime=3600*float(gpspos_parts[1][0:2])+60*float(gpspos_parts[1][2:4])+float(gpspos_parts[1][4:])  gpstime=3600*float(gpspos_parts[1][0:2])+60*float(gpspos_parts[1][2:4])+float(gpspos_parts[1][4:])
- latitude=float(gpspos_parts[2][0:2])+float(gpspos_parts[1][2:])/60.0 + latitude=float(gpspos_parts[2][0:2])+float(gpspos_parts[2][2:])/60.0 
  if gpspos_parts[3]=="S":  if gpspos_parts[3]=="S":
  latitude=-latitude  latitude=-latitude
Line 54: Line 62:
  if gpspos_parts[5]=="W":  if gpspos_parts[5]=="W":
  longitude=-longitude  longitude=-longitude
 + if gpspos_parts[9]=='':
 + gpspos_parts[9]='0.0'
  altitude=float(gpspos_parts[9])  altitude=float(gpspos_parts[9])
 + #print gpstime,latitude,longitude,altitude
  return gpstime,latitude,longitude,altitude  return gpstime,latitude,longitude,altitude
 + 
 def db_stats(): def db_stats():
 + ser_daughter.flushInput()         #we done want to mess things up with old data in the buffer
  ser_daughter.write("V1\r\n"     #the high voltage values  ser_daughter.write("V1\r\n"     #the high voltage values
  V1=ser_daughter.readline()  V1=ser_daughter.readline()
Line 71: Line 83:
  PD=ser_daughter.readline()  PD=ser_daughter.readline()
  ser_daughter.write("T\r\n"       #new - temperature sensor, to be fitted  ser_daughter.write("T\r\n"       #new - temperature sensor, to be fitted
- TS=ser_daugher.readline() + TS=ser_daughter.readline() 
- return V1,V2,V3,IC,VB,PD,TS + return V1[:len(V1)-2],V2[:len(V2)-2],V3[:len(V3)-2],IC[:len(IC)-2],PD[:len(PD)-2],TS[:len(TS)-2] 
- +  
-def HV_enable(n);+def HV_enable(n):
  stringy='H'+str(n)+"\r\n"  stringy='H'+str(n)+"\r\n"
  ser_daughter.write(stringy)  ser_daughter.write(stringy)
  print ser_daughter.readline()  print ser_daughter.readline()
- +  
-def Set_pressure_target(P);+def Set_pressure_target(P):
  ser_daughter.write('P'+str(P)+"\r\n")  ser_daughter.write('P'+str(P)+"\r\n")
 +  
 +def air_density(alt):    # NASA air temperature/pressure/density model 
 + if (alt < 11000.0): 
 +         # below 11Km - Troposphere 
 + temp = 15.04 - (0.00649 * alt) 
 + pres = 101.29 *(((temp + 273.1) / 288.08)**5.256)  
 + else: 
 + if (alt < 25000.0): 
 +         # between 11Km and 25Km - lower Stratosphere 
 + temp = -56.46 
 + pres = 22.65 * math.exp(1.73 - ( 0.000157 * alt)) 
 + else: 
 +         # above 25Km - upper Stratosphere 
 + temp = -131.21 + (0.00299 * alt) 
 + pres = 2.488 *(((temp + 273.1) / 216.6)**-11.388) 
 + return(pres / (0.2869 * (temp + 273.1))) 
 +  
 + 
 def Updatepredict(Seconds,North,East,Altitude): def Updatepredict(Seconds,North,East,Altitude):
- global Predictedn                                       #means they keep their values + Deltae=East-updatestuff.Oldeast 
- global Predictede  + Deltan=North-updatestuff.Oldnorth 
- global Oldeast + Deltaa=Altitude-updatestuff.Oldaltitude 
- global Oldnorth + Deltat=Seconds-updatestuff.Oldseconds 
- global Oldseconds + Averagealt=(updatestuff.Oldaltitude+Altitude)/2
- global Oldaltitude +
- if Iterations==0: +
- Predictedn=North +
- Predictede=East +
- Oldeast=East                                            #start +
- Oldnorth=North +
- Oldaltitude=Altitude +
- Oldseconds=Seconds +
- Deltae=East-Oldeast +
- Deltan=North-Oldnorth +
- Deltaa=Altitude-Oldaltitude +
- Deltat=Seconds-Oldseconds +
- Averagealt=(Oldaltitude+Altitude)/2 +
- Oldeast=East +
- Oldnorth=North +
- Oldaltitude=Altitude +
- Oldseconds=Seconds+
  if Deltaa>0:  if Deltaa>0:
- K=Roottwomgovercda*0.90909*math.exp(Averagealt/16000)  #we now have the velocity of decent+ K=Roottwotwomgovercda*(air_density(Averagealt)**-0.5)  #we now have the velocity of decent
  print "Descent velocity=",K  print "Descent velocity=",K
  K=Deltaa/                                           #time of decent for this layer  K=Deltaa/                                           #time of decent for this layer
Line 112: Line 124:
  K=K/Deltat                                            #weighting for this layer  K=K/Deltat                                            #weighting for this layer
  print "Layer weighting=",K  print "Layer weighting=",K
- K=K+1                                                 #need to account for ascent drift + updatestuff.Predictedn+=(K+1)*Deltan                #need to account for ascent drift 
- Predictedn+=K*Deltan + updatestuff.Predictede+=Deltae*( (K*math.cos(((North updatestuff.Oldnorth)/2)*DEG2RAD)/math.cos(updatestuff.Predictedn*DEG2RAD)) +1) 
- Predictede+=K*Deltae + updatestuff.Oldeast=East 
- print "predicted north=",Predictedn + updatestuff.Oldnorth=North 
- print "predicted east=",Predictede + updatestuff.Oldaltitude=Altitude 
- return Predictedn,Predictede + updatestuff.Oldseconds=Seconds 
- + print "predicted north=",updatestuff.Predictedn 
 + print "predicted east=",updatestuff.Predictede 
 + return updatestuff.Predictedn,updatestuff.Predictede 
 +  
 + 
 def are_we_inside(gpstime,Xpos,Ypos,altitude): def are_we_inside(gpstime,Xpos,Ypos,altitude):
  count=False  count=False
- for g in range(len(Jxpoints)-1):+ print "checking",Xpos,Ypos 
 + for g in range(len(Jxpoints)):
  if g==len(Jxpoints)-1:  if g==len(Jxpoints)-1:
  gplus=0  gplus=0
  else:  else:
  gplus=g+1  gplus=g+1
- if ((Jypoints[g]>Ypos and Jypoints[gplus]<Ypos) or (Jypoints[g]<Ypos and Jypoints[gplus]>Ypos))and((Jxpoints[g]-Xpos)+(Ypos-Jypoints[g])*(Jxpoints[gplus]-Jxpoints[g])/(Jypoints[gplus]-Jypoints[g])>0):+ if ((Jypoints[g]>Ypos and Jypoints[gplus]<Ypos) or (Jypoints[g]<Ypos and Jypoints[gplus]>Ypos))and(((Jxpoints[g]-Xpos)+((Ypos-Jypoints[g])*(Jxpoints[gplus]-Jxpoints[g])/(Jypoints[gplus]-Jypoints[g])))>0):
  count=not count  count=not count
 + print "intercept",g
  print 'we are inside=',count  print 'we are inside=',count
  return count  return count
 + 
 def load_kml(filepath): def load_kml(filepath):
  xpoints=[]  xpoints=[]
Line 147: Line 164:
  ypoints+=[float(line_split[1])]  ypoints+=[float(line_split[1])]
  return xpoints,ypoints  return xpoints,ypoints
- +  
-def send_sms(s,target,smscen):+def send_sms(s,target):
  target=str(target)  target=str(target)
- smscen=str(smscen) + if not len(target)==12: 
- if not (len(target)==12 and len(smscen)==12)+ print "phone number incorrect lenght"
- print "phone numbers incorrect lenght"+
  return -1  return -1
  if len(s)>160:  if len(s)>160:
Line 173: Line 189:
  Bitstring.append(0)  Bitstring.append(0)
  print "SMS"  print "SMS"
- stringy="AT+CMGS="+str(14+(int(len(s)*7/8)+1)) + stringy="AT+CMGS="+str(14+(int(len(s)*7/8)+1))+"\r\n" #total lenght 
- print stringy + #print stringy 
- #ser_phone.write(stringy) + ser_phone.write(stringy) 
- #print ser_phone.readline() + print ser_phone.readline()       #echo the command 
- stringy="0791" + ser_phone.readline() 
- for g in range(6): + print ser_phone.readline()       # the "> " is recieved 
- stringy+=(smscen[2*g+1]+ stringy="0011000C91              # SMS submit, 12 digit international
- stringy+=(smscen[2*g]) +
- stringy+="11000C91"+
  for g in range(6):  for g in range(6):
  stringy+=(target[2*g+1])  stringy+=(target[2*g+1])
  stringy+=(target[2*g])  stringy+=(target[2*g])
- stringy+="0000AA"             #PDU string to Mobile + stringy+="0000AA"             #PDU string to Mobile, 4 day validity 
- stringy+="%.2X" % len(s)+ stringy+="%.2X" % len(s)      #datalenght
  for G in Bitstring:  for G in Bitstring:
- stringy+="%.2X" % G + stringy+="%.2X" % G   #a load of HEX 
- stringy+=chr(026) + stringy+=chr(26            #send it 
- #ser_phone.write(stringy) + ser_phone.write(stringy) 
- #print ser_phone.readline() + for n in range(4): 
- print stringy+  print ser_phone.readline() 
 +# print stringy
  return 0  return 0
 + 
 def get_smscen(): def get_smscen():
- ser_phone.write("AT+CSCA?")+ ser_phone.write("AT+CSCA?\r\n"
 + ser_phone.readline()
  s=ser_phone.readline()  s=ser_phone.readline()
  s=s.split('"')  s=s.split('"')
- return s[1:] + return str(s[1:2])[3:15
 + 
 def cutdown(): def cutdown():
  ser_gr.write("Cutdown...   ")  ser_gr.write("Cutdown...   ")
  shutdown()  shutdown()
- os.system("echo 0 > /config/gpio/cutterone/enabled"     #payload release+ os.system("echo 0 > /config/gpio/cuttertwo/enabled"     #payload release
  time.sleep(6)  time.sleep(6)
- os.system("echo 1 > /config/gpio/cutterone/enabled"     #and we are on the way down+ os.system("echo 1 > /config/gpio/cuttertwo/enabled"     #and we are on the way down
  print "released"  print "released"
 + 
 def shutdown(): def shutdown():
  HV_enable(0)             #all off  HV_enable(0)             #all off
  Set_pressure_target(0) #pump off  Set_pressure_target(0) #pump off
  time.sleep(1)            #wait, to avoid smoke contamination  time.sleep(1)            #wait, to avoid smoke contamination
- os.system("echo 0 > /config/gpio/cuttertwo/enabled"     #cut plunger + os.system("echo 0 > /config/gpio/cutterone/enabled"     #cut plunger 
  time.sleep(3)  time.sleep(3)
- os.system("echo 1 > /config/gpio/cuttertwo/enabled") + os.system("echo 1 > /config/gpio/cutterone/enabled")
  print "plunger cut"  print "plunger cut"
  ser_gr.write("Shutdown\r\n")  ser_gr.write("Shutdown\r\n")
- +  
-finally: +try
- log.close() + print 'AOPP aerosol experiment running' 
- + #log=open("/media/mmcblk0p1/"+logname,"a+"
- + log=open("./"+logname,"a+") 
-print 'AOPP aerosol experiment running' + ser_gr=serial.Serial('/dev/ttyS2',4800, timeout=2, rtscts=1)    #we have a CTS line from the radio 
-ser_gr=serial.Serial('/dev/ttyS2',4800, timeout=2, rtscts=1)    #we have a CTS line from the radio + #ser_gr=open("radio.txt","r") 
-ser_daughter=serial.Serial('/dev/ttyS1',19200, timeout=2) + ser_daughter=serial.Serial('/dev/ttyS1',19200, timeout=2
-ser_phone=serial.Serial('/dev/ttyS0',9600,timeout=4) + #ser_daughter=open("daughter.txt","a+")  
-print 'serial is open to gps,radio, and daughterboard' + ser_phone=serial.Serial('/dev/ttyS0',9600,timeout=4
-ser_gr.write("Hello world"+ #ser_phone=open("phone.txt","a+"
-reed_solomon.setup_rs() + print 'serial is open to gps,radio, and daughterboard' 
-ser_gr.write(reed_solomon.encode_string("Hello, I am a reed solomon encoded string :P")) + ser_gr.write("Hello world"
-while not gps_status: + #log.write("Hello world"
- ser_gr.write("waiting for the gps to lock"+ reed_solomon.setup_rs() 
-print 'ok, gps is ready, we are at:' + ser_gr.write(reed_solomon.encode_string("Hello, I am a reed solomon encoded string :P")) 
-ser_gr.write("GPS locked"+ #log.write(reed_solomon.encode_string("Hello, I am a reed solomon encoded string :P")) 
-print gps_data +# while not gps_status()
-print 'now probing daughterboard' +# ser_gr.write("waiting for the gps to lock"
-print db_stats() + #log.write("waiting for the gps to lock"
-print 'DANGER: turning on HV1' + print 'ok, gps is ready, we are at:' 
-HV_enable(1) + ser_gr.write("GPS locked"
-print 'HV1 on, probing board' + #log.write("GPS locked"
-print db_stats() + print gps_data() 
-print 'testing other HV channels' + print 'now probing daughterboard'
-for x in [2,3]: +
- time.sleep(1) +
- HV_enable(x+
- print 'HV channel' + str(x) + 'stats:' + db_stats(+
-HV_enable(0+
-print 'ok, now testing the pump @ 20%' +
-Set_pressure_target(20) +
-for i in range(20):+
  print db_stats()  print db_stats()
 + print 'DANGER: turning on HV1'
 + HV_enable(1)
 + print 'HV1 on, probing board'
  time.sleep(1)  time.sleep(1)
-Set_pressure_target(0) 
-for i in range(6): 
  print db_stats()  print db_stats()
- time.sleep(1) + print 'testing other HV channels' 
-print 'Testing done' + for x in [2,3]: 
-print 'opening KML cutdown file' + HV_enable(x) 
-Jxpoints,Jypoints=load_kml('/media/mmcblk0p1/cutdown.kml'+ time.sleep(1) 
-print Jxpoints,Jypoints + print 'HV channel' + str(x) + 'stats:' + str(db_stats()) 
-print 'testing phone' + HV_enable(0) 
-ser_phone.write("AT"+ print 'ok, now testing the pump @ 20%' 
-print ser_phone.readline() + Set_pressure_target(20) 
-smscen=get_smscen() + for i in range(20): 
-send_sms("hello world",mynumber,smscen+ print db_stats() 
-ser_daughter.flushinput() + time.sleep(1) 
-count=0 + Set_pressure_target(0) 
-iterations=0 + print 'pressure set to zero' 
-layercounter=0 + for i in range(6): 
-cut_down='' + print db_stats() 
-system_vector=gps_data() + time.sleep(1) 
-maxaltitude=system_vector[3] + print 'Testing done' 
-log=open("/media/mmcblk0p1/"+logname,"a+"+ print 'opening KML cutdown file' 
-print 'ok launch the fucking balloon' + Jxpoints,Jypoints=load_kml('./cutdown.kml'
-while 1: + print Jxpoints,Jypoints 
- print 'in loop' + print 'testing phone' 
- iterations+=1+ ser_phone.write("AT\r\n") 
 + print ser_phone.readline() 
 + print ser_phone.readline() 
 + #smscen=get_smscen() 
 + send_sms("hello world",mynumber) 
 + ser_daughter.flushInput() 
 + ser_phone.flushInput()
  system_vector=gps_data()  system_vector=gps_data()
- daughter_board=db_stats() + updatestuff.Predictedn=system_vector[1] 
- datastring=str(system_vector)+str(daughter_board)+cut_down + updatestuff.Predictede=system_vector[2] 
- log.write(datastring+"\r\n"+ updatestuff.Oldeast=system_vector[2]                                            #start 
- ser_gr.write(reed_solomon.encode_string(callsign+datastring)))         #all our telemetery over the radio link + updatestuff.Oldnorth=system_vector[1] 
- if count=2: + updatestuff.Oldaltitude=system_vector[3] 
- send_sms(datastring,mynumber,smscen                 #every third time + updatestuff.Oldseconds=system_vector[0] 
- count=0 + count=0 
- os.system("sync"+ calibrate=0 
- count+=1 + layercounter=0 
- if system_vector[3]/100>layercounter:                                 #100m altitude layers + cut_down='' 
- layercounter+=1                                               #we move up a layer + system_vector=gps_data() 
- if !are_we_inside([0]+Updatepredict(system_vector)+[0]):      #update and check against the polygon + maxaltitude=system_vector[3] 
- print "geofence cutdown" + startuptime=system_vector[0] 
- log.write("geofence cutdown\r\n")  + HV=0 
- cutdown() + pump=FALSE 
- cut_down='CG' + print 'ok launch the balloon' 
- if system_vector[0]-startuptime>max_flight_time: + while 1: 
- print "time cutdown" + print 'in loop' 
- log.write("time cutdown\r\n"+ system_vector=gps_data() 
- cutdown() + daughter_board=db_stats() 
- cut_down='CT' + datastring = ','.join(['%.0f'system_vector[0]]+['%.6f' % system_vector[1]]+['%.6f' % system_vector[2]]+['%.0f' % system_vector[3]]+['%.4f' % updatestuff.Predictedn]+['%.4f' % updatestuff.Predictede]) 
- if daughter_board[4]<battery_limit: + datastring+=str(daughter_board)+cut_down 
- print "voltage cutdown" + print datastring 
- log.write("voltage cutdown\r\n")  + log.write(datastring+"\r\n"
- cutdown() + ser_gr.write(reed_solomon.encode_string(callsign+datastring))         #all our telemetery over the radio link 
- cut_down='CB' + #log.write(reed_solomon.encode_string(callsign+datastring)) 
- if system_vector[3]-maxaltitude<-100: + #t=reed_solomon.encode_string(callsign+datastring) 
- print "balloon popped" + #print t 
- log.write("balloon popped\r\n"+ #print reed_solomon.decode_string(t,[]) 
- shutdown() + if count==2: 
- cut_down='BP' + send_sms(datastring,mynumber)                          #every third time 
- if system_vector[3]>maxaltitude: + count=0 
- maxaltitude=system_vector[3] + os.system("sync"
- if system_vector[3]>start_altitude+ count+=1 
- print 'turning on the pump (setting pressure target)' + if calibrate==30: 
- HV_enable(1) + ser_daughter.write("K\r\n"                           #recalibrates the pressure sensor 
- Set_pressure_target(default_target_pressure) + calibrate=0 
- log.write("HV1 on\r\n"+ calibrate+=1 
- if system_vector[3]>limit[1]:                                #set the right HV channel for the altitude                                 + if cut_down=='': 
- if system_vector[3]<limit[2]:+ if system_vector[3]/100>layercounter:                                 #100m altitude layers 
 + layercounter+=1                                               #we move up a layer 
 + up=Updatepredict(*system_vector) 
 + log.write(str(up)+"\r\n"
 + if not are_we_inside([0],up[1],up[0],[0]):      #update and check against the polygon 
 + print "geofence cutdown" 
 + log.write("geofence cutdown\r\n")  
 + cutdown() 
 + cut_down='CG' 
 + if system_vector[0]-startuptime>max_flight_time: 
 + print "time cutdown" 
 + log.write("time cutdown\r\n"
 + cutdown() 
 + cut_down='CT' 
 + #if daughter_board[4]<battery_limit: 
 + # print "voltage cutdown" 
 + # log.write("voltage cutdown\r\n")  
 + # cutdown() 
 + # cut_down='CB' 
 + if system_vector[3]-maxaltitude<-100: 
 + print "balloon popped" 
 + log.write("balloon popped\r\n"
 + shutdown() 
 + cut_down='BP' 
 + if system_vector[3]>maxaltitude: 
 + maxaltitude=system_vector[3] 
 + if system_vector[3]>limit[0] and pump==FALSE
 + print 'turning on the pump (setting pressure target)' 
 + HV_enable(1) 
 + Set_pressure_target(default_target_pressure) 
 + log.write("HV1 on\r\n"
 + pump=TRUE 
 + HV=1 
 + if system_vector[3]>limit[1] and HV==1                         #set the right HV channel for the altitude                                
  HV_enable(2)  HV_enable(2)
  log.write("HV2 on\r\n")  log.write("HV2 on\r\n")
- else+ HV=2 
 + if system_vector[3]>limit[2] and HV==2:
  HV_enable(3)  HV_enable(3)
- log.write("HV3 on\r\n"+ log.write("HV3 on\r\n")  
- time.sleep(10)                                              #10 seconds sleep + HV=3 
-  + time.sleep(10) 
-  + iterations+=1                                              #10 seconds sleep
- +
-  +
    
- +finally: 
-</code>+ log.close() 
 +# ser_phone.write("AT+CFUN=0\r\n"     #phone off 
 + ser_phone.close() 
 + ser_gr.close() 
 + ser_daughter.close() 
 + print "bye"</code>
projects/aerosol_code.1204348671.txt.gz · Last modified: 2008/07/19 23:31 (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki