#!/usr/bin/python """ play a rtttl file by sending the tone lengths to the arduino """ from __future__ import division import re import serial import struct import sys import time BAUDRATE = 9600 PAUSE = .001 _rtttl_re = re.compile('^\s*([0-9]+)?([a-hp]#?)(\.?)([0-9]?)\s*$') _rtttl_prefix_re = re.compile('d=([0-9]+),\s?o=([1-5]),\s?b=([0-9]+)') freqs = { 'c': 261.626, 'c#': 277.183, 'd': 293.665, 'd#': 311.127, 'e': 329.628, 'f': 349.228, 'f#': 369.994, 'g': 391.995, 'g#': 415.305, 'a': 440.000, 'a#': 466.164, 'b': 493.883, 'h': 493.883, 'p': 0, } def parse(s): name, prefix, music = s.split(':') pm = _rtttl_prefix_re.match(prefix) d, o, b = pm.groups() defaultlength = int(d) defaultoctave = int(o) timefactor = int(b)/60 # for m in _rtttl_re.finditer(music): for tone in music.split(","): m = _rtttl_re.match(tone) if not m: print("Didn't match:",music) continue l, t, ld, o = m.groups() if l: length = 1/int(l) else: length = 1/defaultlength if ld: length = length * 1.5 length = length*timefactor tone = freqs[t.lower()] if o: octave = o else: octave = defaultoctave tone = tone * 2**(int(octave) - 4) yield (length, tone) def send(sounds, device): with serial.Serial(device, BAUDRATE) as ser: for length, freq in sounds: sys.stderr.write('len: %.3f, ton: %9.3f, send: %d' % (length, freq, freq2t(freq))) ser.write(struct.pack('>H', freq2t(freq))) time.sleep(length) sys.stderr.write('\n') ser.write('\0\0') time.sleep(PAUSE) ser.write('\0\0') def freq2t(freq): if freq == 0: return 0 return 2000000/freq if __name__ == '__main__': if len(sys.argv) > 1: if sys.argv[1] == '-d': for length, freq in parse(sys.stdin.read()): print 'len: %.3f, ton: %9.3f' % (length, freq) else: send(parse(sys.stdin.read()), sys.argv[1]) else: print >>sys.stderr, "Usage: %s -d|/dev/ttyUSBx" % sys.argv[0]