3 #GoodFET Chipcon CC2500 SPI Client
4 #by Jean-Michel Picod <jean-michel.picod at cassidan.com>
8 from GoodFETCC2500 import GoodFETCC2500
10 if len(sys.argv) == 1:
11 print "Usage: %s verb [objects]\n" % sys.argv[0]
12 print "%s info" % sys.argv[0]
13 # print "%s test" % sys.argv[0]
14 print "%s regs" % sys.argv[0]
15 print "%s pyregs" % sys.argv[0]
17 print "%s tunelelo\n\tTunes to Lelo vibrator configuration." % sys.argv[0]
18 print "%s snifflelo\n\tSniffs Lelo vibrator packets" % sys.argv[0]
19 print "%s setlelo [0-128]\n\tSet Lelo vibrator strength to a given value" % sys.argv[0]
23 #Initialize FET and set baud rate
24 client = GoodFETCC2500()
28 def printconfig(client):
29 print "Encoding %s (with%s Manchester)" % (client.RF_get_modulation(), "out" if client.peek_by_name("MDMCFG2") & 0x8 else "")
30 print "Base Freq %.3f MHz" % (client.RF_get_frequency() / 10**6)
31 print "IF Freq %.3f kHz" % (client.RF_get_IF_freq() / 1000)
32 print "Channel %d" % client.RF_get_channel()
33 print "Chan spacing %.3f kHz" % (client.RF_get_chan_spacing() / 1000)
34 print "Eff Freq %.3f MHz" % (((client.RF_get_channel() * client.RF_get_chan_spacing()) + client.RF_get_frequency()) / 10**6)
35 print "Bandwith %i kHz" % client.RF_getbandwith()
36 print "Rate %d kbps" % round(client.RF_get_datarate() / 1000)
37 l = client.RF_get_pkt_len()
39 print "PacketLen %i bytes (fixed)" % l
41 print "PacketLen %i bytes (variable)" % -l
43 print "PacketLen Infinite"
44 print "Preamble %d bytes" % client.RF_get_preamble_len()
45 print "Sync 0x%04x" % client.RF_get_syncword()
46 print "CRC %s" % ("Enabled" if client.peek_by_name("PKTCTRL0") & 0x4 else "Disabled")
47 print "Whitening %s" % ("Enabled" if client.peek_by_name("PKTCTRL0") & 0x40 else "Disabled")
48 print "Address %d" % client.RF_get_addr()
50 if sys.argv[1] == "info":
53 if sys.argv[1] == "regs":
56 print "%-8s = 0x%02x" % (k, v)
58 if sys.argv[1] == "pyregs":
61 print "client.poke_by_name('%s', 0x%02x)" % (k, v)
63 def leloremote_setup(client):
64 """Based on scanlime blog post: scanlime.org/2012/11/hacking-my-vagina/"""
65 client.CC_strobe_RES()
66 client.poke(0x0B, [0x0A, 0x00]) # FSCTRL
67 client.poke(0x0D, [0x5D, 0x13, 0xB1]) # FREQ
68 client.poke(0x10, [0x2D, 0x3B, 0x73, 0x22, 0xF8]) # MDMCFG
69 client.poke(0x0A, 0x01) # CHANNR
70 client.poke(0x15, 0x00) # DEVIATN
71 client.poke(0x21, [0xB6, 0x10]) # FREND
72 client.poke(0x18, 0x18) # MCSM0
73 client.poke(0x19, 0x1D) # FOCCFG
74 client.poke(0x1A, 0x1C) # BSCFG
75 client.poke(0x1B, [0xC7, 0x00, 0xB0]) # AGCTRL
76 client.poke(0x23, [0xEA, 0x0A, 0x00, 0x11]) # FSCAL3
77 client.poke(0x29, 0x59) # FSTEST
78 client.poke(0x2C, [0x88, 0x31, 0x0B]) # TEST
79 client.poke(0x00, 0x29) # IOCFG2
80 client.poke(0x02, 0x06) # IOCFG0
81 client.poke(0x07, [0x0A, 0x04]) # PKTCTRL
82 client.poke(0x09, 0x01) # ADDR
83 client.poke(0x06, 0x09) # PKTLEN
84 client.poke(0x7E, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) # PATABLE
85 client.CC_strobe_FRX()
86 client.CC_strobe_FTX()
87 client.CC_strobe_IDLE()
89 if sys.argv[1] == "tunelelo":
90 leloremote_setup(client)
92 if sys.argv[1] == "snifflelo":
93 leloremote_setup(client)
95 client.RF_set_rxoff_mode("IDLE")
96 client.CC_strobe_FRX() ## Flush FIFO
97 print "Entering receive mode..."
99 data = client.RF_rxpacket(bytes=9)
100 if data is None or data == "":
102 if isinstance(data, str):
103 data = [ord(x) for x in data]
104 if data[0:2] == [ 0x01, 0x00, 0xA5 ] and data[5:9] == [ 0x00, 0x00, 0x00, 0x05 ]:
105 print "Motor1: %d (0x%02x)" % (data[2], data[2])
106 print "Motor2: %d (0x%02x)" % (data[3], data[3])
108 print "Invalid Lelo packet: %s" % " ".join(["%02X" % x for x in data])
110 if sys.argv[1] == "setlelo":
111 if len(sys.argv) > 2:
112 strength = min(128, max(0, int(sys.argv[2])))
113 print "Setting Lelo vibrator strengh to %d out of 128" % strength
114 client.RF_txpacket([0x01, 0x00, 0xA5, strength, strength, 0x00, 0x00, 0x00, 0x05])
116 print "ERROR: missing motor strength"