import numpy,os import waveforms as w # sync used in Task #5 sync = [0,0,1,1,1,1,1,0,1,0] # parameters that control the encoding sample_rate = 4e6 channel_bw = 20000 # ensure spectral plots make sense def quantize_frequency(f,fs,N): #assert N&1,"N must be odd!" f1 = float(fs)/float(N) return int(f/f1)*f1 def samples_per_bit(sample_rate,bits_per_second): bps = int(sample_rate/bits_per_second) if (bps & 1) == 0: bps += 1 return bps # Convert message bits into samples, then use samples # to modulate the amplitude of sinusoidal carrier. # Limit the bandwidth of the transmitted signal to # bw Hz. def am_transmit(bits,samples_per_bit,sample_rate,fc,bw): # use helper function to create a sampled_waveform by # converting each bit into samples_per_bit samples samples = w.symbols_to_samples(bits,samples_per_bit, sample_rate) bandlimited_samples = samples.filter('low-pass', cutoff=bw) # now multiply by sine wave of specified frequency return bandlimited_samples.modulate(hz=fc) def verify_task2(f): print "***** Testing Task 2 with 5 transmission channels *****" size = 30 spb = samples_per_bit(sample_rate,20000) N = size*spb fc = quantize_frequency(100e3,sample_rate,N) # start channels at 100 kHz fsep = quantize_frequency(2*channel_bw,sample_rate,N) # separation between center freqs # build a 5-transmitter RF spectrum messages = [] freqs = [] rf = 0 for i in xrange(5): # a random binary message msg = numpy.random.randint(2,size=size) # modulate, add to rf rf += w.symbols_to_samples(msg,spb,sample_rate).filter('low-pass',cutoff=channel_bw).modulate(hz=fc) # remember message and freq for this channel messages.append(msg) freqs.append(fc) # onto next channel fc += fsep #plot spectrum of transmitted message rf.spectrum(title='spectrum of received samples') #w.show() # try receiving all the messages for i in xrange(5): received = f(rf,freqs[i],spb,channel_bw) if not numpy.array_equal(messages[i],received): print "Error when listening to channel",i print 'message: ',messages[i] print 'received:',received return None else: print "Message received correctly on channel",i return 2 def verify_task5(f): am_receive = f # a random binary message with zeros at both ends to ensure periodicity message_size = 31 # must be odd! message = numpy.zeros(message_size+2,dtype=numpy.int) message[1:-1] = numpy.random.randint(2,size=message_size) # message with sync message = sync + list(message) # send it through transmitter, modulate to legal freq near 125 kHz bits_per_second = 20000 spb = samples_per_bit(sample_rate,bits_per_second) fc = quantize_frequency(500e3,sample_rate, len(message)*spb) xmit_out = am_transmit(message,spb,sample_rate, fc,channel_bw) error = False for delay in xrange(8): print "%d-sample delay:" % delay delayed_xmit_out = xmit_out.delay(nsamples=delay) delayed_xmit_out.noise(amplitude=0.1) # run receiver received = am_receive(delayed_xmit_out,fc,spb,channel_bw) # report results if not numpy.array_equal(message,received): print ' => differences' print ' message: ',message print ' received:',received error = True return None if error else 4 ################################################## ## ## Code to submit task to server. Do not change. ## Task-specific code is in verify(), defined above. ## ################################################## import Tkinter class Dialog(Tkinter.Toplevel): def __init__(self, parent, title = None): Tkinter.Toplevel.__init__(self, parent) self.transient(parent) if title: self.title(title) self.parent = parent body = Tkinter.Frame(self) self.initial_focus = self.body(body) body.pack(padx=5, pady=5) self.buttonbox() self.grab_set() if not self.initial_focus: self.initial_focus = self self.protocol("WM_DELETE_WINDOW", self.cancel) self.geometry("+%d+%d" % (parent.winfo_rootx()+50,parent.winfo_rooty()+50)) self.initial_focus.focus_set() self.wait_window(self) def body(self, master): return None # add standard button box def buttonbox(self): box = Tkinter.Frame(self) w = Tkinter.Button(box, text="Ok", width=10, command=self.ok, default=Tkinter.ACTIVE) w.pack(side=Tkinter.LEFT, padx=5, pady=5) box.pack() # standard button semantics def ok(self, event=None): if not self.validate(): self.initial_focus.focus_set() # put focus back return self.withdraw() self.update_idletasks() self.apply() self.cancel() def cancel(self, event=None): # put focus back to the parent window self.parent.focus_set() self.destroy() # command hooks def validate(self): return 1 # override def apply(self): pass # override # ask user for Athena username and MIT ID class SubmitDialog(Dialog): def __init__(self,parent,error=None,title = None): self.error = error self.athena_name = None self.mit_id = None Dialog.__init__(self,parent,title=title) def body(self, master): row = 0 if self.error: l = Tkinter.Label(master,text=self.error, anchor=Tkinter.W,justify=Tkinter.LEFT,fg="red") l.grid(row=row,sticky=Tkinter.W,columnspan=2) row += 1 Tkinter.Label(master, text="Athena username:").grid(row=row,sticky=Tkinter.E) self.e1 = Tkinter.Entry(master) self.e1.grid(row=row, column=1) row += 1 Tkinter.Label(master, text="MIT ID:").grid(row=row,sticky=Tkinter.E) self.e2 = Tkinter.Entry(master) self.e2.grid(row=row, column=1) return self.e1 # initial focus # add standard button box def buttonbox(self): box = Tkinter.Frame(self) w = Tkinter.Button(box, text="Submit", width=10, command=self.ok, default=Tkinter.ACTIVE) w.pack(side=Tkinter.LEFT, padx=5, pady=5) w = Tkinter.Button(box, text="Cancel", width=10, command=self.cancel) w.pack(side=Tkinter.LEFT, padx=5, pady=5) box.pack() def apply(self): self.athena_name = self.e1.get() self.mit_id = self.e2.get() # Let user know what server said class MessageDialog(Dialog): def __init__(self, parent,message = '',title = None): self.message = message Dialog.__init__(self,parent,title=title) def body(self, master): l = Tkinter.Label(master, text=self.message,anchor=Tkinter.W,justify=Tkinter.LEFT) l.grid(row=0) # return contents of file as a string def file_contents(fname): # use universal mode to ensure cross-platform consistency in hash f = open(fname,'U') result = f.read() f.close() return result import hashlib def digest(s): m = hashlib.md5() m.update(s) return m.hexdigest() # if verify(f) indicates points have been earned, submit results # to server if requested to do so import inspect,os,urllib,urllib2 def checkoff(f,task='???',submit=True): if task == 'L7_2': points = verify_task2(f) elif task == 'L7_5': points = verify_task5(f) else: raise ValueError,"task must be L7_2 or L7_5" if submit and points: root = Tkinter.Tk(); #root.withdraw() error = None while submit: sd = SubmitDialog(root,error=error,title="Submit Task %s?"%task) if sd.athena_name: if isinstance(f,str): fname = os.path.abspath(f) else: fname = os.path.abspath(inspect.getsourcefile(f)) post = { 'user': sd.athena_name, 'id': sd.mit_id, 'task': task, 'digest': digest(file_contents(os.path.abspath(inspect.getsourcefile(checkoff)))), 'points': points, 'filename': fname, 'file': file_contents(fname) } try: response = urllib2.urlopen('http://scripts.mit.edu/~6.02/currentsemester/submit_task.cgi', urllib.urlencode(post)).read() except Exception,e: response = 'Error\n'+str(e) if response.startswith('Error\n'): error = response[6:] else: MessageDialog(root,message=response,title='Submission response') break else: break root.destroy()