🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
Showing first 21 files as there are too many
  • ■ ■ ■ ■ ■ ■
    etc/udev/rules.d/20-rfcat.rules
     1 +# legacy RfCats and cc1111usb
     2 +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="4715", MODE:="0660", SYMLINK+="RFCAT%n", GROUP="dialout"
     3 + 
     4 +# modern RfCats
     5 +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="6047", MODE:="0660", SYMLINK+="RFCAT%n", GROUP="dialout"
     6 +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="6048", MODE:="0660", SYMLINK+="RFCAT%n", GROUP="dialout"
     7 +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="605b", MODE:="0660", SYMLINK+="RFCAT%n", GROUP="dialout"
     8 +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="ecc1", MODE:="0660", SYMLINK+="RFCAT%n", GROUP="dialout"
     9 + 
     10 +# RfCat bootloader subsystem (uses it's own product id)
     11 +SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="6049", MODE:="0660", SYMLINK+="RFCAT_BL_C", ENV{ID_MM_DEVICE_IGNORE}="1", GROUP="dialout"
     12 +SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="604a", MODE:="0660", SYMLINK+="RFCAT_BL_D", ENV{ID_MM_DEVICE_IGNORE}="1", GROUP="dialout"
     13 +SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="605c", MODE:="0660", SYMLINK+="RFCAT_BL_YS1", ENV{ID_MM_DEVICE_IGNORE}="1", GROUP="dialout"
     14 +SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="ecc0", MODE:="0660", SYMLINK+="RFCAT_BL_SRF", ENV{ID_MM_DEVICE_IGNORE}="1", GROUP="dialout"
     15 + 
  • ■ ■ ■ ■ ■ ■
    etc/udev/rules.d/LICENSE
     1 +Copyright 2012 atlas
     2 + 
     3 +License: BSD
     4 + 
     5 +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
     6 + 
     7 + 1. Redistributions of source code must retain the above copyright
     8 + notice, this list of conditions and the following disclaimer.
     9 + 
     10 + 2. Redistributions in binary form must reproduce the above copyright
     11 + notice, this list of conditions and the following disclaimer in
     12 + the documentation and/or other materials provided with the
     13 + distribution.
     14 + 
     15 + 3. The names of the authors may not be used to endorse or promote
     16 + products derived from this software without specific prior
     17 + written permission.
     18 + 
     19 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     20 +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     21 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     22 + 
     23 + 
     24 + 
  • ■ ■ ■ ■ ■ ■
    rflib/LICENSE
     1 +Copyright 2012 atlas
     2 + 
     3 +License: BSD
     4 + 
     5 +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
     6 + 
     7 + 1. Redistributions of source code must retain the above copyright
     8 + notice, this list of conditions and the following disclaimer.
     9 + 
     10 + 2. Redistributions in binary form must reproduce the above copyright
     11 + notice, this list of conditions and the following disclaimer in
     12 + the documentation and/or other materials provided with the
     13 + distribution.
     14 + 
     15 + 3. The names of the authors may not be used to endorse or promote
     16 + products derived from this software without specific prior
     17 + written permission.
     18 + 
     19 +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     20 +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     21 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     22 + 
     23 + 
     24 + 
  • ■ ■ ■ ■ ■ ■
    rflib/__init__.py
     1 +#!/usr/bin/env ipython3 -i --no-banner
     2 + 
     3 +from __future__ import print_function
     4 +from __future__ import absolute_import
     5 + 
     6 +from builtins import str
     7 +from builtins import range
     8 +from .chipcon_nic import *
     9 +import rflib.bits as rfbits
     10 + 
     11 +RFCAT_START_SPECAN = 0x40
     12 +RFCAT_STOP_SPECAN = 0x41
     13 + 
     14 +MAX_FREQ = 936e6
     15 + 
     16 +class RfCat(FHSSNIC):
     17 + def RFdump(self, msg="Receiving", maxnum=100, timeoutms=1000):
     18 + try:
     19 + for x in range(maxnum):
     20 + y, t = self.RFrecv(timeoutms)
     21 + print("(%5.3f) %s: %s" % (t, msg, hexlify(y)))
     22 + except ChipconUsbTimeoutException:
     23 + pass
     24 + 
     25 + def scan(self, basefreq=902e6, inc=250e3, count=104, delaysec=2, drate=38400, lowball=1):
     26 + '''
     27 + scan for signal over a range of frequencies
     28 + '''
     29 + self.RFdump("Clearing")
     30 + self.lowball(lowball)
     31 + self.setMdmDRate(drate)
     32 + print("Scanning range: ")
     33 + while not keystop():
     34 + try:
     35 + print("(press Enter to quit)")
     36 + for freq in range(int(basefreq), int(basefreq+(inc*count)), int(inc)):
     37 + print("Scanning for frequency %d..." % freq)
     38 + self.setFreq(freq)
     39 + self.RFdump(timeoutms=delaysec*1000)
     40 + if keystop():
     41 + break
     42 + except KeyboardInterrupt:
     43 + print("Please press <enter> to stop")
     44 + 
     45 + sys.stdin.read(1)
     46 + self.lowballRestore()
     47 + 
     48 + def specan(self, centfreq=915e6, inc=250e3, count=104):
     49 + '''
     50 + Enter Spectrum Analyzer mode.
     51 + this sets the mode of the dongle to send data, and brings up the GUI.
     52 + 
     53 + centfreq is the center frequency
     54 + '''
     55 + freq, delta = self._doSpecAn(centfreq, inc, count)
     56 + 
     57 + import rflib.ccspecan as rfspecan
     58 + rfspecan.ensureQapp()
     59 + 
     60 + fhigh = freq + (delta*(count+1))
     61 + 
     62 + window = rfspecan.Window(self, freq, fhigh, delta, 0)
     63 + window.show()
     64 + rfspecan._qt_app.exec_()
     65 + 
     66 + def _doSpecAn(self, centfreq, inc, count):
     67 + '''
     68 + store radio config and start sending spectrum analysis data
     69 + 
     70 + centfreq = Center Frequency
     71 + '''
     72 + if count>255:
     73 + raise Exception("sorry, only 255 samples per pass... (count)")
     74 + 
     75 + spectrum = (count * inc)
     76 + halfspec = spectrum / 2.0
     77 + basefreq = centfreq - halfspec
     78 + if (count * inc) + basefreq > MAX_FREQ:
     79 + raise Exception("Sorry, %1.3f + (%1.3f * %1.3f) is higher than %1.3f" %
     80 + (basefreq, count, inc))
     81 + self.getRadioConfig()
     82 + self._specan_backup_radiocfg = self.radiocfg
     83 + 
     84 + self.setFreq(basefreq)
     85 + self.setMdmChanSpc(inc)
     86 + 
     87 + freq, fbytes = self.getFreq()
     88 + delta = self.getMdmChanSpc()
     89 + 
     90 + self.send(APP_NIC, RFCAT_START_SPECAN, b"%c" % (count) )
     91 + return freq, delta
     92 + 
     93 + def _stopSpecAn(self):
     94 + '''
     95 + stop sending rfdata and return radio to original config
     96 + '''
     97 + self.send(APP_NIC, RFCAT_STOP_SPECAN, '')
     98 + self.radiocfg = self._specan_backup_radiocfg
     99 + self.setRadioConfig()
     100 + 
     101 + 
     102 + def rf_configure(self, *args, **kwargs):
     103 + self.setRFparameters(*args, **kwargs)
     104 + 
     105 + def rf_redirection(self, fdtup, use_rawinput=False, printable=False):
     106 + buf = b''
     107 + 
     108 + if len(fdtup)>1:
     109 + fd0i, fd0o = fdtup
     110 + else:
     111 + fd0i, = fdtup
     112 + fd0o, = fdtup
     113 + 
     114 + fdsock = False # socket or fileio?
     115 + if hasattr(fd0i, 'recv'):
     116 + fdsock = True
     117 + 
     118 + try:
     119 + while True:
     120 + #if self._pause:
     121 + # continue
     122 + 
     123 + try:
     124 + x,y,z = select.select([fd0i ], [], [], .1)
     125 + if fd0i in x:
     126 + # FIXME: make this aware of VLEN/FLEN and the proper length
     127 + if fdsock:
     128 + data = fd0i.recv(self.max_packet_size)
     129 + else:
     130 + data = fd0i.read(self.max_packet_size)
     131 + 
     132 + if not len(data): # terminated socket
     133 + break
     134 + 
     135 + buf += data
     136 + pktlen, vlen = self.getPktLEN()
     137 + if vlen:
     138 + pktlen = ord(buf[0])
     139 + 
     140 + #FIXME: probably want to take in a length struct here and then only send when we have that many bytes...
     141 + data = buf[:pktlen]
     142 + if use_rawinput:
     143 + data = eval('"%s"'%data)
     144 + 
     145 + if len(buf) >= pktlen:
     146 + self.RFxmit(data)
     147 + 
     148 + except ChipconUsbTimeoutException:
     149 + pass
     150 + 
     151 + try:
     152 + data, time = self.RFrecv(1)
     153 + 
     154 + if printable:
     155 + data = "\n"+str(time)+": "+repr(data)
     156 + else:
     157 + data = struct.pack("<fH", time, len(data)) + data
     158 + 
     159 + if fdsock:
     160 + fd0o.sendall(data)
     161 + else:
     162 + fd0o.write(data)
     163 + 
     164 + except ChipconUsbTimeoutException:
     165 + pass
     166 + 
     167 + #special handling of specan dumps... somewhat set in solid jello
     168 + try:
     169 + data, time = self.recv(APP_SPECAN, 1, 1)
     170 + data = struct.pack("<fH", time, len(data)) + data
     171 + if fdsock:
     172 + fd0o.sendall(data)
     173 + else:
     174 + fd0o.write(data)
     175 + 
     176 + except ChipconUsbTimeoutException:
     177 + #print "this is a valid exception, run along... %x"% APP_SPECAN
     178 + pass
     179 + 
     180 + except KeyboardInterrupt:
     181 + self.setModeIDLE()
     182 + 
     183 +class InverseCat(RfCat):
     184 + def setMdmSyncWord(self, word, radiocfg=None):
     185 + FHSSNIC.setMdmSyncWord(self, word ^ 0xffff, radiocfg)
     186 + 
     187 + def RFrecv(self, timeout=1000):
     188 + global data
     189 + data,timestamp = RfCat.RFrecv(self, timeout)
     190 + return rfbits.invertBits(data),timestamp
     191 + 
     192 + def RFxmit(self, data):
     193 + return RfCat.RFxmit(self, rfbits.invertBits(data) )
     194 + 
     195 +def cleanupInteractiveAtExit():
     196 + try:
     197 + if d.getDebugCodes():
     198 + d.setModeIDLE()
     199 + pass
     200 + except:
     201 + pass
     202 + 
     203 +def interactive(idx=0, DongleClass=RfCat, intro=''):
     204 + global d
     205 + import rflib.chipcon_nic as rfnic
     206 + import atexit
     207 + 
     208 + d = DongleClass(idx=idx)
     209 + d.setModeRX() # this puts the dongle into receive mode
     210 + atexit.register(cleanupInteractiveAtExit)
     211 + 
     212 + print(intro)
     213 + gbls = globals()
     214 + lcls = locals()
     215 + interact(lcls, gbls)
     216 + 
     217 +def interact(lcls, gbls):
     218 + shellexception = None
     219 + 
     220 + try:
     221 + from IPython.terminal.interactiveshell import TerminalInteractiveShell
     222 + ipsh = TerminalInteractiveShell()
     223 + ipsh.user_global_ns.update(gbls)
     224 + ipsh.user_global_ns.update(lcls)
     225 + ipsh.autocall = 2 # don't require parenthesis around *everything*. be smart!
     226 + ipsh.mainloop()
     227 + except ImportError as e:
     228 + shellexception = e
     229 + 
     230 + if shellexception:
     231 + try:
     232 + import IPython.Shell
     233 + ipsh = IPython.Shell.IPShell(argv=[''], user_ns=lcls, user_global_ns=gbls)
     234 + ipsh.mainloop()
     235 + 
     236 + except ImportError as e:
     237 + shellexception = e
     238 + 
     239 + if shellexception:
     240 + try:
     241 + from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
     242 + ipsh = TerminalInteractiveShell()
     243 + ipsh.user_global_ns.update(gbls)
     244 + ipsh.user_global_ns.update(lcls)
     245 + ipsh.autocall = 2 # don't require parenthesis around *everything*. be smart!
     246 + 
     247 + ipsh.mainloop()
     248 + except ImportError as e:
     249 + shellexception = e
     250 + 
     251 + if shellexception:
     252 + print("falling back to straight Python... (%r)" % shellexception)
     253 + shell = code.InteractiveConsole(gbls)
     254 + shell.interact()
     255 + 
     256 + 
     257 +if __name__ == "__main__":
     258 + idx = 0
     259 + if len(sys.argv) > 1:
     260 + idx = int(sys.argv.pop())
     261 + 
     262 + interactive(idx)
     263 + 
  • rflib/__pycache__/__init__.cpython-38.pyc
    Binary file.
  • rflib/__pycache__/bits.cpython-38.pyc
    Binary file.
  • rflib/__pycache__/chipcon_nic.cpython-38.pyc
    Binary file.
  • rflib/__pycache__/chipcon_usb.cpython-38.pyc
    Binary file.
  • rflib/__pycache__/chipcondefs.cpython-38.pyc
    Binary file.
  • rflib/__pycache__/const.cpython-38.pyc
    Binary file.
  • rflib/__pycache__/rflib_defs.cpython-38.pyc
    Binary file.
  • rflib/__pycache__/rflib_version.cpython-38.pyc
    Binary file.
  • ■ ■ ■ ■ ■ ■
    rflib/bits.py
     1 +from __future__ import print_function
     2 +from __future__ import division
     3 + 
     4 +from builtins import hex
     5 +from builtins import range
     6 +from builtins import bytes
     7 +from past.utils import old_div
     8 +import sys
     9 +import struct
     10 + 
     11 +fmtsLSB = [None, "B", "<H", "<I", "<I", "<Q", "<Q", "<Q", "<Q"]
     12 +fmtsMSB = [None, "B", ">H", ">I", ">I", ">Q", ">Q", ">Q", ">Q"]
     13 +sizes = [ 0, 1, 2, 4, 4, 8, 8, 8, 8]
     14 +masks = [ (1<<(8*i))-1 for i in range(9) ]
     15 + 
     16 +PYVER = int(sys.version[0])
     17 +def correctbytes(val):
     18 + global PYVER
     19 + 
     20 + if PYVER == 2:
     21 + return chr(val)
     22 + 
     23 + return bytes([val])
     24 + 
     25 +def wtfo(string):
     26 + outstr = []
     27 + bitlen = len(outstr) * 8
     28 + for x in range(8):
     29 + outstr.append(shiftString(string, x))
     30 + 
     31 + string = strBitReverse(string)
     32 + for x in range(8):
     33 + outstr.append(shiftString(string, x))
     34 + 
     35 + return outstr
     36 + 
     37 + 
     38 +def ord23(thing):
     39 + if PYVER == 2:
     40 + return ord(thing)
     41 + return thing
     42 + 
     43 + 
     44 +def strBitReverse(string):
     45 + # FIXME: this is really dependent upon python's number system. large strings will not convert well.
     46 + # FIXME: break up array of 8-bit numbers and bit-swap in the array
     47 + num = 0
     48 + bits = len(string)*8
     49 + # convert to MSB number
     50 + for x in range(len(string)):
     51 + ch = string[x]
     52 + #num |= (ord(ch)<<(8*x)) # this is LSB
     53 + num <<= 8
     54 + num |= ord(ch)
     55 + 
     56 + print(hex(num))
     57 + rnum = bitReverse(num, bits)
     58 + print(hex(rnum))
     59 + 
     60 + # convert back from MSB number to string
     61 + out = []
     62 + for x in range(len(string)):
     63 + out.append(correctbytes(rnum&0xff))
     64 + rnum >>= 8
     65 + out.reverse()
     66 + print(''.join(out).encode('hex'))
     67 + return ''.join(out)
     68 + 
     69 +def strXorMSB(string, xorval, size):
     70 + '''
     71 + lsb
     72 + pads end of string with 00
     73 + '''
     74 + out = []
     75 + strlen = len(string)
     76 + string += "\x00" * sizes[size]
     77 + 
     78 + for idx in range(0, strlen, size):
     79 + tempstr = string[idx:idx+sizes[size]]
     80 + temp, = struct.unpack( fmtsMSB[size], tempstr )
     81 + temp ^= xorval
     82 + temp &= masks[size]
     83 + tempstr = struct.pack( fmtsMSB[size], temp )[-size:]
     84 + out.append(tempstr)
     85 + return ''.join(out)
     86 + 
     87 +
     88 +
     89 + 
     90 +def bitReverse(num, bitcnt):
     91 + newnum = 0
     92 + for idx in range(bitcnt):
     93 + newnum <<= 1
     94 + newnum |= num&1
     95 + num >>= 1
     96 + return newnum
     97 + 
     98 +def shiftString(string, bits):
     99 + carry = 0
     100 + news = []
     101 + for x in range(len(string)-1):
     102 + newc = ((ord(string[x]) << bits) + (ord(string[x+1]) >> (8-bits))) & 0xff
     103 + news.append("%c"%newc)
     104 + newc = (ord(string[-1])<<bits) & 0xff
     105 + news.append("%c"%newc)
     106 + return "".join(news)
     107 + 
     108 +def getNextByte_feedbackRegister7bitsMSB():
     109 + '''
     110 + this returns a byte of a 7-bit feedback register stemming off bits 4 and 7
     111 + the register is 7 bits long, but we return a more usable 8bits (ie.
     112 + '''
     113 + global fbRegister
     114 + 
     115 + retval = 0
     116 + for x in range(8): #MSB,
     117 + retval <<= 1
     118 + retval |= (fbRegister >> 6) # start with bit 7
     119 + nb = ( ( fbRegister>>3) ^ (fbRegister>>6)) &1
     120 + fbRegister = ( ( fbRegister << 1 ) | nb ) & 0x7f # do shifting
     121 + #print("retval: %x fbRegister: %x bit7: %x nb: %x" % (retval, fbRegister, (fbRegister>>6), nb))
     122 + 
     123 + return retval
     124 + 
     125 +def getNextByte_feedbackRegister7bitsLSB():
     126 + '''
     127 + this returns a byte of a 7-bit feedback register stemming off bits 4 and 7
     128 + the register is 7 bits long, but we return a more usable 8bits (ie.
     129 + '''
     130 + global fbRegister
     131 + 
     132 + retval = 0
     133 + for x in range(8): #MSB,
     134 + retval >>= 1
     135 + retval |= ((fbRegister << 1)&0x80) # start with bit 7
     136 + 
     137 + nb = ( ( fbRegister>>3) ^ (fbRegister>>6)) &1
     138 + fbRegister = ( ( fbRegister << 1 ) | nb ) & 0x7f # do shifting
     139 + #print("retval: %x fbRegister: %x bit7: %x nb: %x" % (retval, fbRegister, (fbRegister>>6), nb))
     140 + 
     141 + return retval
     142 + 
     143 + 
     144 +def whitenData(data, seed=0xffff, getNextByte=getNextByte_feedbackRegister7bitsMSB):
     145 + global fbRegister
     146 + fbRegister = seed
     147 + 
     148 + carry = 0
     149 + news = []
     150 + for x in range(len(data)-1):
     151 + newc = ((ord(data[x]) ^ getNextByte() ) & 0xff)
     152 + news.append("%c"%newc)
     153 + return "".join(news)
     154 + 
     155 +def findSyncWord(byts, sensitivity=4, minpreamble=2):
     156 + '''
     157 + seek SyncWords from a raw bitstream.
     158 + assumes we capture at least two (more likely 3 or more) preamble bytes
     159 + '''
     160 + possDwords = []
     161 + # find the preamble (if any)
     162 + while True: # keep searching through string until we don't find any more preamble bits to pick on
     163 + sbyts = byts
     164 + pidx = byts.find("\xaa"*minpreamble)
     165 + if pidx == -1:
     166 + pidx = byts.find("\x55"*minpreamble)
     167 + byts = shiftString(byts, 1)
     168 + 
     169 + if pidx == -1:
     170 + return possDwords
     171 +
     172 + # chop off the nonsense before the preamble
     173 + sbyts = byts[pidx:]
     174 + #print("sbyts: %s" % repr(sbyts))
     175 +
     176 + # find the definite end of the preamble (ie. it may be sooner, but we know this is the end)
     177 + while (sbyts[0] == '\xaa' and len(sbyts)>2):
     178 + sbyts = sbyts[1:]
     179 +
     180 + #print("sbyts: %s" % repr(sbyts))
     181 + # now we look at the next 16 bits to narrow the possibilities to 8
     182 + # at this point we have no hints at bit-alignment aside from 0xaa vs 0x55
     183 + dwbits, = struct.unpack(">H", sbyts[:2])
     184 + #print("sbyts: %s" % repr(sbyts))
     185 + #print("dwbits: %s" % repr(dwbits))
     186 + if len(sbyts)>=3:
     187 + bitcnt = 0
     188 + # bits1 = aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
     189 + # bits2 = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
     190 + bits1, = struct.unpack(">H", sbyts[:2])
     191 + bits1 = bits1 | (ord('\xaa') << 16)
     192 + bits1 = bits1 | (ord('\xaa') << 24)
     193 + bits1 <<= 8
     194 + bits1 |= (ord(sbyts[2]) )
     195 + #print("bits: %x" % (bits1))
     196 + 
     197 + bit = (5 * 8) - 2 # bytes times bits/byte #FIXME: MAGIC NUMBERS!?
     198 + while (bits1 & (3<<bit) == (2<<bit)):
     199 + bit -= 2
     200 + #print("bit = %d" % bit)
     201 + bits1 >>= (bit-16)
     202 + #while (bits1 & 0x30000 != 0x20000): # now we align the end of the 101010 pattern with the beginning of the dword
     203 + # bits1 >>= 2
     204 + #print("bits: %x" % (bits1))
     205 +
     206 + bitcount = min( 2 * sensitivity, 17 )
     207 + for frontbits in range( bitcount ): # with so many bit-inverted systems, let's not assume we know anything about the bit-arrangement. \x55\x55 could be a perfectly reasonable preamble.
     208 + poss = (bits1 >> frontbits) & 0xffff
     209 + if not poss in possDwords:
     210 + possDwords.append(poss)
     211 + byts = byts[pidx+1:]
     212 +
     213 + return possDwords
     214 + 
     215 +def findSyncWordDoubled(byts):
     216 + possDwords = []
     217 + # find the preamble (if any)
     218 + bitoff = 0
     219 + pidx = byts.find("\xaa\xaa")
     220 + if pidx == -1:
     221 + pidx = byts.find("\55\x55")
     222 + bitoff = 1
     223 + if pidx == -1:
     224 + return []
     225 + 
     226 + # chop off the nonsense before the preamble
     227 + byts = byts[pidx:]
     228 + 
     229 + # find the definite end of the preamble (ie. it may be sooner, but we know this is the end)
     230 + while (byts[0] == ('\xaa', '\x55')[bitoff] and len(byts)>2):
     231 + byts = byts[1:]
     232 + 
     233 + # now we look at the next 16 bits to narrow the possibilities to 8
     234 + # at this point we have no hints at bit-alignment
     235 + dwbits, = struct.unpack(">H", byts[:2])
     236 + if len(byts)>=5:
     237 + bitcnt = 0
     238 + # bits1 = aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
     239 + # bits2 = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
     240 + bits1, = struct.unpack(">H", byts[:2])
     241 + bits1 = bits1 | (ord(('\xaa','\x55')[bitoff]) << 16)
     242 + bits1 = bits1 | (ord(('\xaa','\x55')[bitoff]) << 24)
     243 + bits1 <<= 8
     244 + bits1 |= (ord(byts[2]) )
     245 + bits1 >>= bitoff
     246 + 
     247 + bits2, = struct.unpack(">L", byts[:4])
     248 + bits2 <<= 8
     249 + bits2 |= (ord(byts[4]) )
     250 + bits2 >>= bitoff
     251 +
     252 + 
     253 + frontbits = 0
     254 + for frontbits in range(16, 40, 2): #FIXME: if this doesn't work, try 16, then 18+frontbits
     255 + dwb1 = (bits1 >> (frontbits)) & 3
     256 + dwb2 = (bits2 >> (frontbits)) & 3
     257 + print("\tfrontbits: %d \t\t dwb1: %s dwb2: %s" % (frontbits, bin(bits1 >> (frontbits)), bin(bits2 >> (frontbits))))
     258 + if dwb2 != dwb1:
     259 + break
     260 + 
     261 + # frontbits now represents our unknowns... let's go from the other side now
     262 + for tailbits in range(16, -1, -2):
     263 + dwb1 = (bits1 >> (tailbits)) & 3
     264 + dwb2 = (bits2 >> (tailbits)) & 3
     265 + print("\ttailbits: %d\t\t dwb1: %s dwb2: %s" % (tailbits, bin(bits1 >> (tailbits)), bin(bits2 >> (tailbits))))
     266 + if dwb2 != dwb1:
     267 + tailbits += 2
     268 + break
     269 + 
     270 + # now, if we have a double syncword, iinm, tailbits + frontbits >= 16
     271 + print("frontbits: %d\t\t tailbits: %d, bits: %s " % (frontbits, tailbits, bin((bits2>>tailbits & 0xffffffff))))
     272 + if (frontbits + tailbits >= 16):
     273 + tbits = bits2 >> (tailbits&0xffff)
     274 + tbits &= (0xffffffff)
     275 + print("tbits: %x" % tbits)
     276 + 
     277 + poss = tbits&0xffffffff
     278 + if poss not in possDwords:
     279 + possDwords.append(poss)
     280 + else:
     281 + pass
     282 + # FIXME: what if we *don't* have a double-sync word? then we stop at AAblah or 55blah and take the next word?
     283 + 
     284 + possDwords.reverse()
     285 + return possDwords
     286 + 
     287 +#def test():
     288 + 
     289 +def visBits(data):
     290 + pass
     291 + 
     292 + 
     293 + 
     294 +def getBit(data, bit):
     295 + idx = old_div(bit, 8)
     296 + bidx = bit % 8
     297 + char = data[idx]
     298 + return (ord(char)>>(7-bidx)) & 1
     299 + 
     300 + 
     301 + 
     302 +def detectRepeatPatterns(data, size=64, minEntropy=.07):
     303 + #FIXME: convert strings to bit arrays before comparing.
     304 + c1 = 0
     305 + c2 = 0
     306 + d1 = 0
     307 + p1 = 0
     308 + mask = (1<<size) - 1
     309 + bitlen = 8*len(data)
     310 + 
     311 + while p1 < (bitlen-size-8):
     312 + d1 <<= 1
     313 + d1 |= getBit(data, p1)
     314 + d1 &= mask
     315 + #print(bin(d1))
     316 + 
     317 + if c1 < (size):
     318 + p1 += 1
     319 + c1 += 1
     320 + continue
     321 + 
     322 + d2 = 0
     323 + p2 = p1+size
     324 + while p2 < (bitlen):
     325 + d2 <<= 1
     326 + d2 |= getBit(data, p2)
     327 + d2 &= mask
     328 + #print(bin(d2))
     329 + 
     330 + if c2 < (size):
     331 + p2 += 1
     332 + c2 += 1
     333 + continue
     334 + 
     335 + if d1 == d2 and d1 > 0:
     336 + s1 = p1 - size
     337 + s2 = p2 - size
     338 + print("s1: %d\t p1: %d\t " % (s1, p1))
     339 + print("s2: %d\t p2: %d\t " % (s2, p2))
     340 + # complete the pattern until the numbers differ or meet
     341 + while True:
     342 + p1 += 1
     343 + p2 += 1
     344 + #print("s1: %d\t p1: %d\t " % (s1, p1))
     345 + #print("s2: %d\t p2: %d\t " % (s2, p2))
     346 + if p2 >= bitlen:
     347 + break
     348 + 
     349 + b1 = getBit(data,p1)
     350 + b2 = getBit(data,p2)
     351 + 
     352 + if p1 == s2 or b1 != b2:
     353 + break
     354 + 
     355 + length = p1 - s1
     356 + c2 = 0
     357 + p2 -= size
     358 + 
     359 + bitSection, ent = bitSectString(data, s1, s1+length)
     360 + if ent > minEntropy:
     361 + print("success:")
     362 + print(" * bit idx1: %4d (%4d bits) - '%s' %s" % (s1, length, bin(d1), bitSection.encode("hex")))
     363 + print(" * bit idx2: %4d (%4d bits) - '%s'" % (s2, length, bin(d2)))
     364 + #else:
     365 + # print(" * idx1: %d - '%s' * idx2: %d - '%s'" % (p1, d1, p2, d2))
     366 + p2 += 1
     367 + p1 += 1
     368 + 
     369 + 
     370 +def bitSectString(string, startbit, endbit):
     371 + '''
     372 + bitsects a string... ie. chops out the bits from the middle of the string
     373 + returns the new string and the entropy (ratio of 0:1)
     374 + '''
     375 + ones = 0
     376 + zeros = 0
     377 + entropy = [zeros, ones]
     378 + 
     379 + s = ''
     380 + bit = startbit
     381 + 
     382 + Bidx = old_div(bit, 8)
     383 + bidx = (bit % 8)
     384 + 
     385 + while bit < endbit:
     386 + 
     387 + byte1 = ord( string[Bidx] )
     388 + try:
     389 + byte2 = ord( string[Bidx+1] )
     390 + except IndexError:
     391 + byte2 = 0
     392 + 
     393 + byte = (byte1 << bidx) & 0xff
     394 + byte |= (byte2 >> (8-bidx))
     395 + #calculate entropy over the byte
     396 + for bi in range(8):
     397 + b = (byte>>bi) & 1
     398 + entropy[b] += 1
     399 + 
     400 + bit += 8
     401 + Bidx += 1
     402 + 
     403 + if bit > endbit:
     404 + diff = bit-endbit
     405 + mask = ~ ( (1<<diff) - 1 )
     406 + byte &= mask
     407 + 
     408 + s += correctbytes(byte)
     409 +
     410 + ent = old_div((min(entropy)+1.0), (max(entropy)+1))
     411 + #print("entropy: %f" % ent)
     412 + return (s, ent)
     413 + 
     414 + 
     415 +
     416 +def genBitArray(string, startbit, endbit):
     417 + '''
     418 + bitsects a string... ie. chops out the bits from the middle of the string
     419 + returns the new string and the entropy (ratio of 0:1)
     420 + '''
     421 + binStr, ent = bitSectString(string, startbit, endbit)
     422 + 
     423 + s = []
     424 + for byte in binStr:
     425 + byte = ord(byte)
     426 + for bitx in range(7, -1, -1):
     427 + bit = (byte>>bitx) & 1
     428 + s.append(bit)
     429 + 
     430 + return (s, ent)
     431 + 
     432 + 
     433 +chars_top = [
     434 + " ", #000
     435 + " ", #001
     436 + "^", #010
     437 + "/", #011
     438 + " ", #100
     439 + " ", #101
     440 + "\\",#110
     441 + "-", #111
     442 + ]
     443 + 
     444 +chars_mid = [
     445 + " ", #000
     446 + "|", #001
     447 + "#", #010
     448 + " ", #011
     449 + "|", #100
     450 + "#", #101
     451 + " ", #110
     452 + " ", #110
     453 + ]
     454 + 
     455 +chars_bot = [
     456 + "-", #000
     457 + "/", #001
     458 + " ", #010
     459 + " ", #011
     460 + "\\",#100
     461 + "V", #101
     462 + " ", #110
     463 + " ", #110
     464 + ]
     465 + 
     466 + 
     467 +def reprBitArray(bitAry, width=194):
     468 + top = []
     469 + mid = []
     470 + bot = []
     471 + 
     472 + arylen = len(bitAry)
     473 + # top line
     474 + #FIXME: UGGGGLY and kinda broken.
     475 + fraction = 1.0 * arylen/width
     476 + expand = [bitAry[int(x*fraction)] for x in range(width)]
     477 + 
     478 + for bindex in range(width):
     479 + bits = 0
     480 + if bindex>0:
     481 + bits += (expand[bindex-1]) << (2)
     482 + bits += (expand[bindex]) << (1)
     483 + if bindex < width-1:
     484 + bits += (expand[bindex+1])
     485 + 
     486 + top.append( chars_top[ bits ] )
     487 + mid.append( chars_mid[ bits ] )
     488 + bot.append( chars_bot[ bits ] )
     489 + 
     490 + tops = "".join(top)
     491 + mids = "".join(mid)
     492 + bots = "".join(bot)
     493 + return "\n".join([tops, mids, bots])
     494 + 
     495 +def invertBits(data):
     496 + output = []
     497 + ldata = len(data)
     498 + off = 0
     499 + 
     500 + if ldata&1:
     501 + output.append( correctbytes( ord( data[0] ) ^ 0xff) )
     502 + off = 1
     503 + 
     504 + if ldata&2:
     505 + output.append( struct.pack( "<H", struct.unpack( "<H", data[off:off+2] )[0] ^ 0xffff) )
     506 + off += 2
     507 + 
     508 + #method 1
     509 + #for idx in xrange( off, ldata, 4):
     510 + # output.append( struct.pack( "<I", struct.unpack( "<I", data[idx:idx+4] )[0] & 0xffff) )
     511 + 
     512 + #method2
     513 + count = old_div(ldata, 4)
     514 + #print(ldata, count)
     515 + numlist = struct.unpack( "<%dI" % count, data[off:] )
     516 + modlist = [ struct.pack("<L", (x^0xffffffff) ) for x in numlist ]
     517 + output.extend(modlist)
     518 + 
     519 + return ''.join(output)
     520 + 
     521 + 
     522 +def diff_manchester_decode(data, align=False):
     523 + # FIXME: not validated. must find reference to validate against
     524 + '''
     525 + differential manchester encoding/decoding uses 2 symbols per data bit.
     526 + there must always be a transition between the first and second symbol of a bit.
     527 + bit values are determined by the existence/lack of transition between symbol pairs
     528 + 
     529 + set align=True to allow *one* sync of the bits to clock. ie, either the whole
     530 + thing lines up with a transition in the middle of every bit, or shift one, and
     531 + try again. one way *must* have transitions, or failure occurs
     532 + '''
     533 + syncd = False
     534 + 
     535 + out = []
     536 + last = 0
     537 + obyte = 0
     538 + for bidx in range(len(data)):
     539 + byte = ord(data[bidx])
     540 + for y in range(6, -1, -2):
     541 + if not syncd:
     542 + diff = last & 1
     543 + bit0 = (byte >> (y+1)) & 1
     544 + bit1 = (byte >> y) & 1
     545 + else:
     546 + diff = last >> 1
     547 + bit0 = last & 1
     548 + bit1 = (byte >> (y+1)) & 1
     549 + 
     550 + if bit0 == bit1:
     551 + if syncd or not align:
     552 + raise Exception("Differential Manchester Decoder cannot work with this data. Sync fault at index %d,%d" % (bidx, y))
     553 + 
     554 + syncd = 1
     555 + # redo the last stuff with new info
     556 + diff = last >> 1
     557 + bit0 = last & 1
     558 + bit1 = (byte >> (y+1)) & 1
     559 + 
     560 + obyte <<= 1
     561 + if diff != bit0:
     562 + obyte |= 1
     563 + 
     564 + last = (bit0 << 1) | bit1
     565 + if (bidx & 1):
     566 + out.append(correctbytes(obyte))
     567 + obyte = 0
     568 + 
     569 + if not (bidx & 1):
     570 + obyte << 4 # pad 0's on end
     571 + out.append(correctbytes(obyte))
     572 + return ''.join(out)
     573 + 
     574 + 
     575 + 
     576 +def biphase_mark_coding_encode(data):
     577 + # FIXME: broken? this looks more like BMC (biphase mark encoding)
     578 + # FIXME: write encoder as well
     579 + out = []
     580 + last = 0
     581 + for bidx in range(len(data)):
     582 + byte = ord(data[bidx])
     583 + obyte = 0
     584 + for y in range(7, -1, -1):
     585 + bit = (byte >> y) & 1
     586 + obyte <<= 1
     587 + if bit == last:
     588 + obyte |= 1
     589 + 
     590 + last = bit
     591 + if bidx & 1:
     592 + print("%d - write" % bidx)
     593 + out.append(correctbytes(obyte))
     594 + else:
     595 + print("%d - skip" % bidx)
     596 + if not (bidx & 1):
     597 + print("%d - write" % bidx)
     598 + out.append(correctbytes(obyte))
     599 + 
     600 + return ''.join(out)
     601 + 
     602 +def manchester_decode(data, hilo=1):
     603 + out = []
     604 + last = 0
     605 + obyte = 0
     606 + for bidx in range(len(data)):
     607 + byte = ord(data[bidx])
     608 + for y in range(7, -1, -1):
     609 + bit = (byte >> y) & 1
     610 + 
     611 + if not (y & 1): # every other bit counts
     612 + obyte <<= 1
     613 + if bit and not last:
     614 + if not hilo:
     615 + obyte |= 1
     616 + elif last and not bit:
     617 + if hilo:
     618 + obyte |= 1
     619 + 
     620 + last = bit
     621 + if (bidx & 1):
     622 + out.append(correctbytes(obyte))
     623 + obyte = 0
     624 + 
     625 + if not (bidx & 1):
     626 + obyte << 4 # pad 0's on end
     627 + out.append(correctbytes(obyte))
     628 + return ''.join(out)
     629 + 
     630 +def manchester_encode(data, hilo=1):
     631 + '''
     632 + for the sake of testing.
     633 + assumings msb, and
     634 + '''
     635 + if hilo:
     636 + bits = (0b01, 0b10)
     637 + else:
     638 + bits = (0b10, 0b01)
     639 + 
     640 + out = []
     641 + for bidx in range(len(data)):
     642 + byte = ord(data[bidx])
     643 + obyte = 0
     644 + for bitx in range(7,-1,-1):
     645 + bit = (byte>>bitx) & 1
     646 + obyte <<= 2
     647 + obyte |= bits[bit]
     648 + 
     649 + out.append(struct.pack(">H", obyte))
     650 + return ''.join(out)
     651 + 
     652 +def findManchesterData(data, hilo=1):
     653 + poss = []
     654 + 
     655 + for x in range(8):
     656 + try:
     657 + newdata = shiftString(data, x)
     658 + thing = manchester_decode(x, newdata)
     659 + poss.append(thing)
     660 + except:
     661 + pass
     662 + 
     663 +def findManchester(data, minbytes=10):
     664 + print("DEBUG: DATA=" + repr(data))
     665 + success = []
     666 + 
     667 + last = 0
     668 + last2 = 0
     669 + lastCount = 0
     670 + minbits = minbytes * 8
     671 + 
     672 + for bidx in range(len(data)):
     673 + byt = ord(data[bidx])
     674 + for btidx in range(0, 8, 2):
     675 + # compare every other bits
     676 + bit = (byt>>(8-btidx)) & 1
     677 + 
     678 + if (bit + last + last2) in (1,2):
     679 + lastCount += 1
     680 + else:
     681 + # we're done, or not started
     682 + if lastCount >= minbits:
     683 + lenbytes = (old_div(lastCount, 8))
     684 + lenbits = lastCount % 8
     685 + startbyte = bidx - lenbytes
     686 + if lenbits > btidx:
     687 + startbyte += 1
     688 + lenbits -= 8
     689 + startbit = btidx - lenbits
     690 + 
     691 + stopbyte = startbyte + lenbytes + (0,1)[lenbits>0]
     692 + bytez = data[startbyte:stopbyte]
     693 + 
     694 + success.append((bidx, startbyte, startbit, bytez))
     695 + lastCount = 0
     696 + # cycle through
     697 + last2 = last
     698 + last = bit
     699 + return success
     700 + 
     701 + 
  • ■ ■ ■ ■ ■ ■
    rflib/cc111Xhparser.py
     1 +#!/usr/bin/env python
     2 +"""
     3 +#include<compiler.h>
     4 +/* ------------------------------------------------------------------------------------------------
     5 +* Interrupt Vectors
     6 +* ------------------------------------------------------------------------------------------------
     7 +*/
     8 +#define RFTXRX_VECTOR 0 /* RF TX done / RX ready */
     9 +#define ADC_VECTOR 1 /* ADC End of Conversion */
     10 +#define URX0_VECTOR 2 /* USART0 RX Complete */
     11 +#define URX1_VECTOR 3 /* USART1 RX Complete */
     12 +#define ENC_VECTOR 4 /* AES Encryption/Decryption Complete */
     13 +#define ST_VECTOR 5 /* Sleep Timer Compare */
     14 +#define P2INT_VECTOR 6 /* Port 2 Inputs */
     15 +#define UTX0_VECTOR 7 /* USART0 TX Complete */
     16 +#define DMA_VECTOR 8 /* DMA Transfer Complete */
     17 +#define T1_VECTOR 9 /* Timer 1 (16-bit) Capture/Compare/Overflow */
     18 +#define T2_VECTOR 10 /* Timer 2 (MAC Timer) Overflow */
     19 +#define T3_VECTOR 11 /* Timer 3 (8-bit) Capture/Compare/Overflow */
     20 +#define T4_VECTOR 12 /* Timer 4 (8-bit) Capture/Compare/Overflow */
     21 +#define P0INT_VECTOR 13 /* Port 0 Inputs */
     22 +#define UTX1_VECTOR 14 /* USART1 TX Complete */
     23 +#define P1INT_VECTOR 15 /* Port 1 Inputs */
     24 +#define RF_VECTOR 16 /* RF General Interrupts */
     25 +#define WDT_VECTOR 17 /* Watchdog Overflow in Timer Mode */
     26 + 
     27 +SFR(P0, 0x80); // Port 0
     28 + SBIT(P0_0, 0x80, 0); // Port 0 bit 0
     29 + SBIT(P0_1, 0x80, 1); // Port 0 bit 1
     30 + SBIT(P0_2, 0x80, 2); // Port 0 bit 2
     31 + SBIT(P0_3, 0x80, 3); // Port 0 bit 3
     32 + SBIT(P0_4, 0x80, 4); // Port 0 bit 4
     33 + SBIT(P0_5, 0x80, 5); // Port 0 bit 5
     34 + SBIT(P0_6, 0x80, 6); // Port 0 bit 6
     35 + SBIT(P0_7, 0x80, 7); // Port 0 bit 7
     36 + 
     37 +SFR(SP, 0x81); // Stack Pointer
     38 +SFR(DPL0, 0x82); // Data Pointer 0 Low Byte
     39 +SFR(DPH0, 0x83); // Data Pointer 0 High Byte
     40 +SFR(DPL1, 0x84); // Data Pointer 1 Low Byte
     41 +SFR(DPH1, 0x85); // Data Pointer 1 High Byte
     42 +"""
     43 + 
     44 +from __future__ import print_function
     45 + 
     46 +import sys
     47 + 
     48 + 
     49 +def parseLines(lines):
     50 + defs = {}
     51 + incomment = False
     52 + for line in lines:
     53 + # find single-line comments
     54 + slc = line.find("//")
     55 + if (slc > -1):
     56 + line = line[:slc] + "#" + line[slc+2:]
     57 + # find /* */ comments
     58 + mlcs = line.find("/*")
     59 + mlce = line.find("*/")
     60 + if (mlcs>-1):
     61 + if (mlce>-1): # both are in this line
     62 + if (mlce>mlcs): # they are "together"
     63 + if (mlce >= len(line.strip())-3):
     64 + line = line[:mlcs] + '#' + line[mlcs+2:mlce]
     65 + else:
     66 + line = line[:mlcs] + '"""' + line[mlcs+2:mlce] + '"""' + line[mlce+2:]
     67 + else: # they are *not* together
     68 + line = line[mlce+2:mlcs]
     69 + else: # only the beginning is in this line, treat like a single-line comment for now
     70 + line = line[:mlcs]
     71 + incomment = True
     72 + elif incomment: # no mlc-starter found... are we incomment? then ignore until the end of comment
     73 + if (mlce>-1):
     74 + line = line[mlce+2:]
     75 + incomment = False
     76 + else:
     77 + line = ''
     78 + if incomment: # if we're still incomment, this whole line is comment
     79 + continue
     80 + 
     81 + # chop initial and trailing whitespace
     82 + line = line.strip()
     83 + 
     84 + # now we can actually parse the line
     85 + if (line.startswith("#define ")):
     86 + line = line[8:].strip() # peel off any additional spaces after the #define
     87 + pieces = line.split(" ", 1)
     88 + if len(pieces)<2:
     89 + continue
     90 + name, value = pieces
     91 + if "(" in name:
     92 + print(("SKIPPING: %s"%(line)), file=sys.stderr)
     93 + continue # skip adding "function" defines
     94 + defs[name.strip()] = value.strip()
     95 +
     96 + elif (line.startswith("SFR(")):
     97 + endparen = line.find(")")
     98 + if (endparen == -1):
     99 + print(("ERROR: SFR without end parens: '%s'"%(line)), file=sys.stderr)
     100 + continue
     101 + line = line[4:endparen].strip()
     102 + name, value = line.split(",", 1)
     103 + defs[name.strip()] = value.strip()
     104 + elif (line.startswith("SFRX(")):
     105 + endparen = line.find(")")
     106 + if (endparen == -1):
     107 + print(("ERROR: SFRX without end parens: '%s'"%(line)), file=sys.stderr)
     108 + continue
     109 + line = line[5:endparen].strip()
     110 + name, value = line.split(",", 1)
     111 + defs[name.strip()] = value.strip()
     112 + elif (line.startswith("SBIT")):
     113 + endparen = line.find(")")
     114 + if (endparen == -1):
     115 + print(("ERROR: SBIT without end parens: '%s'"%(line)), file=sys.stderr)
     116 + continue
     117 + line = line[5:endparen].strip()
     118 + name, val1, val2 = line.split(",", 2)
     119 + defs[name.strip()] = 1 << (int(val2.strip()))
     120 + 
     121 + return defs
     122 + 
     123 + 
     124 +if __name__ == '__main__':
     125 + defs = {}
     126 + defs.update(parseLines(open('../includes/cc1110-ext.h')))
     127 + defs.update(parseLines(open('../includes/cc1111.h')))
     128 + defs.update(parseLines(open('/usr/share/sdcc/include/mcs51/cc1110.h')))
     129 + 
     130 + skeys = list(defs.keys())
     131 + skeys.sort()
     132 + out = ["%-30s = %s"%(key,defs[key]) for key in skeys]
     133 + 
     134 + trueout = []
     135 + for x in out:
     136 + try:
     137 + compile(x,'stdin','exec')
     138 + trueout.append(x)
     139 + print(x)
     140 + except:
     141 + sys.excepthook(*sys.exc_info())
     142 + 
     143 + 
     144 +
     145 + 
     146 + 
     147 + 
     148 + 
     149 + 
     150 + 
     151 + 
  • ■ ■ ■ ■ ■ ■
    rflib/ccrecvdump.py
     1 +#!/usr/bin/python
     2 + 
     3 +from __future__ import print_function
     4 + 
     5 +import sys
     6 +import serial
     7 + 
     8 +port = "ACM0"
     9 +if len(sys.argv) > 1:
     10 + port = sys.argv.pop()
     11 + 
     12 +dport = "/dev/tty" + port
     13 + 
     14 +print("Opening serial port %s for listening..." % dport)
     15 +s=serial.Serial(dport, 115200)
     16 + 
     17 +counter = 0
     18 +while True:
     19 + print("%d: %s" % (counter, repr(s.read(12))))
     20 + counter += 1
     21 + #sys.stdout.write(s.read(1))
     22 + #sys.stdout.flush()
     23 + 
  • ■ ■ ■ ■ ■ ■
    rflib/ccspecan.py
     1 +#!/usr/bin/env python
     2 +#
     3 +# Copyright 2012 atlas
     4 +#
     5 +# This file was adapted from a part of Project Ubertooth written by Jared Boone
     6 +#
     7 +# This program is free software; you can redistribute it and/or modify
     8 +# it under the terms of the GNU General Public License as published by
     9 +# the Free Software Foundation; either version 2, or (at your option)
     10 +# any later version.
     11 +#
     12 +# This program is distributed in the hope that it will be useful,
     13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     15 +# GNU General Public License for more details.
     16 +#
     17 +# You should have received a copy of the GNU General Public License
     18 +# along with this program; see the file COPYING. If not, write to
     19 +# the Free Software Foundation, Inc., 51 Franklin Street,
     20 +# Boston, MA 02110-1301, USA.
     21 + 
     22 +from __future__ import print_function
     23 +from __future__ import division
     24 + 
     25 +from future import standard_library
     26 +standard_library.install_aliases()
     27 +from builtins import bytes
     28 +from builtins import range
     29 +from past.utils import old_div
     30 +import sys
     31 +import time
     32 +import numpy
     33 +import threading
     34 +import rflib
     35 +from rflib.bits import ord23
     36 +from .bits import correctbytes
     37 +# import cPickle in Python 2 instead of pickle in Python 3
     38 +if sys.version_info < (3,):
     39 + import cPickle as pickle
     40 +else:
     41 + import pickle as pickle
     42 + 
     43 +from PySide2 import QtCore, QtGui, QtWidgets
     44 +from PySide2.QtCore import Qt, QPointF, QLineF
     45 + 
     46 +def ensureQapp():
     47 + global _qt_app
     48 + if not globals().get("_qt_app"):
     49 + _qt_app = QtWidgets.QApplication([])
     50 + 
     51 + 
     52 +APP_SPECAN = 0x43
     53 +SPECAN_QUEUE = 1
     54 + 
     55 +class SpecanThread(threading.Thread):
     56 + def __init__(self, data, low_frequency, high_frequency, freq_step, delay, new_frame_callback):
     57 + threading.Thread.__init__(self)
     58 + self.daemon = True
     59 +
     60 + self._data = data
     61 + 
     62 + self._delay = delay
     63 + self._low_frequency = low_frequency
     64 + self._high_frequency = high_frequency
     65 + self._freq_step = freq_step
     66 + self._new_frame_callback = new_frame_callback
     67 + self._stop = False
     68 + self._stopped = False
     69 + 
     70 + def run(self):
     71 + # this is where we pull in the data from the device
     72 + #frame_source = self._device.specan(self._low_frequency, self._high_frequency)
     73 + 
     74 + num_chans = int(old_div((self._high_frequency - self._low_frequency), self._freq_step))
     75 +
     76 + if type(self._data) == list:
     77 + for rssi_values, timestamp in self._data:
     78 + rssi_values = [ (old_div((ord23(x)^0x80),2))-88 for x in rssi_values[4:] ]
     79 + # since we are not accessing the dongle, we need some sort of delay
     80 + time.sleep(self._delay)
     81 + frequency_axis = numpy.linspace(self._low_frequency, self._high_frequency, num=len(rssi_values), endpoint=True)
     82 + 
     83 + self._new_frame_callback(numpy.copy(frequency_axis), numpy.copy(rssi_values))
     84 + if self._stop:
     85 + break
     86 + else:
     87 + while not self._stop:
     88 + try:
     89 + rssi_values, timestamp = self._data.recv(APP_SPECAN, SPECAN_QUEUE, 10000)
     90 + rssi_values = [ (old_div((ord23(x)^0x80),2))-88 for x in rssi_values ]
     91 + frequency_axis = numpy.linspace(self._low_frequency, self._high_frequency, num=len(rssi_values), endpoint=True)
     92 + 
     93 + self._new_frame_callback(numpy.copy(frequency_axis), numpy.copy(rssi_values))
     94 + except:
     95 + sys.excepthook(*sys.exc_info())
     96 + self._data._stopSpecAn()
     97 +
     98 + def stop(self):
     99 + self._stop = True
     100 + self.join(3.0)
     101 + self._stopped = True
     102 + 
     103 +class RenderArea(QtWidgets.QWidget):
     104 + def __init__(self, data, low_freq=2.400e9, high_freq=2.483e9, freq_step=1e6, delay=0, parent=None):
     105 + QtWidgets.QWidget.__init__(self, parent)
     106 +
     107 + self._graph = None
     108 + self._reticle = None
     109 +
     110 + self._data = data
     111 + self._delay = delay
     112 + self._frame = None
     113 + self._persisted_frames = None
     114 + self._persisted_frames_depth = 350
     115 + self._path_max = None
     116 +
     117 + self._low_frequency = low_freq #2.400e9
     118 + self._high_frequency = high_freq #2.483e9
     119 + self._frequency_step = freq_step #1e6
     120 + self._high_dbm = 0.0
     121 + self._low_dbm = -100.0
     122 + 
     123 + self._hide_markers = False
     124 + self._mouse_x = None
     125 + self._mouse_y = None
     126 + self._mouse_x2 = None
     127 + self._mouse_y2 = None
     128 +
     129 + self._thread = SpecanThread(self._data,
     130 + self._low_frequency,
     131 + self._high_frequency,
     132 + self._frequency_step,
     133 + self._delay,
     134 + self._new_frame)
     135 + self._thread.start()
     136 +
     137 + def stop_thread(self):
     138 + self._thread.stop()
     139 +
     140 + def _new_graph(self):
     141 + self._graph = QtGui.QPixmap(self.width(), self.height())
     142 + self._graph.fill(Qt.black)
     143 +
     144 + def _new_reticle(self):
     145 + self._reticle = QtGui.QPixmap(self.width(), self.height())
     146 + self._reticle.fill(Qt.transparent)
     147 +
     148 + def _new_persisted_frames(self, frequency_bins):
     149 + self._persisted_frames = numpy.empty((self._persisted_frames_depth, frequency_bins))
     150 + self._persisted_frames.fill(-128 + -54)
     151 + self._persisted_frames_next_index = 0
     152 +
     153 + def minimumSizeHint(self):
     154 + x_points = round(old_div((self._high_frequency - self._low_frequency), self._frequency_step))
     155 + y_points = round(self._high_dbm - self._low_dbm)
     156 + return QtCore.QSize(x_points * 4, y_points * 1)
     157 +
     158 + def _new_frame(self, frequency_axis, rssi_values):
     159 + #print repr(frequency_axis)
     160 + #print repr(rssi_values)
     161 + self._frame = (frequency_axis, rssi_values)
     162 + if self._persisted_frames is None:
     163 + self._new_persisted_frames(len(frequency_axis))
     164 + self._persisted_frames[self._persisted_frames_next_index] = rssi_values
     165 + self._persisted_frames_next_index = (self._persisted_frames_next_index + 1) % self._persisted_frames.shape[0]
     166 + self.update()
     167 +
     168 + def _draw_graph(self):
     169 + if self._graph is None:
     170 + self._new_graph()
     171 + elif self._graph.size() != self.size():
     172 + self._new_graph()
     173 +
     174 + painter = QtGui.QPainter(self._graph)
     175 + 
     176 + try:
     177 + painter.setRenderHint(QtGui.QPainter.Antialiasing)
     178 + painter.fillRect(0, 0, self._graph.width(), self._graph.height(), QtGui.QColor(0, 0, 0, 10))
     179 +
     180 + if self._frame:
     181 + frequency_axis, rssi_values = self._frame
     182 +
     183 + path_now = QtGui.QPainterPath()
     184 + path_max = QtGui.QPainterPath()
     185 +
     186 + bins = list(range(len(frequency_axis)))
     187 + x_axis = self._hz_to_x(frequency_axis)
     188 + y_now = self._dbm_to_y(rssi_values)
     189 + y_max = self._dbm_to_y(numpy.amax(self._persisted_frames, axis=0))
     190 +
     191 + # TODO: Wrapped Numpy types with float() to support old (<1.0) PySide API in Ubuntu 10.10
     192 + path_now.moveTo(float(x_axis[0]), float(y_now[0]))
     193 + for i in bins:
     194 + path_now.lineTo(float(x_axis[i]), float(y_now[i]))
     195 +
     196 + # TODO: Wrapped Numpy types with float() to support old (<1.0) PySide API in Ubuntu 10.10
     197 + path_max.moveTo(float(x_axis[0]), float(y_max[0]))
     198 + db_tmp = self._low_dbm
     199 + max_max = None
     200 + for i in bins:
     201 + path_max.lineTo(float(x_axis[i]), float(y_max[i]))
     202 + if self._y_to_dbm(y_max[i]) > db_tmp:
     203 + db_tmp = self._y_to_dbm(y_max[i])
     204 + max_max = i
     205 +
     206 + pen = QtGui.QPen()
     207 + pen.setBrush(Qt.white)
     208 + painter.setPen(pen)
     209 + painter.drawPath(path_now)
     210 + self._path_max = path_max
     211 + if not max_max == None and not self._hide_markers:
     212 + pen.setBrush(Qt.red)
     213 + pen.setStyle(Qt.DotLine)
     214 + painter.setPen(pen)
     215 + painter.drawText(QPointF(x_axis[max_max] + 4, 30), '%.06f' % (old_div(self._x_to_hz(x_axis[max_max]), 1e6)))
     216 + painter.drawText(QPointF(30, y_max[max_max] - 4), '%d' % (self._y_to_dbm(y_max[max_max])))
     217 + painter.drawLine(QPointF(x_axis[max_max], 0), QPointF(x_axis[max_max], self.height()))
     218 + painter.drawLine(QPointF(0, y_max[max_max]), QPointF(self.width(), y_max[max_max]))
     219 + if self._mouse_x:
     220 + painter.drawText(QPointF(self._hz_to_x(self._mouse_x) + 4, 58), '(%.06f)' % ((old_div(self._x_to_hz(x_axis[max_max]), 1e6)) - (old_div(self._mouse_x, 1e6))))
     221 + pen.setBrush(Qt.yellow)
     222 + painter.setPen(pen)
     223 + painter.drawText(QPointF(self._hz_to_x(self._mouse_x) + 4, 44), '%.06f' % (old_div(self._mouse_x, 1e6)))
     224 + painter.drawText(QPointF(54, self._dbm_to_y(self._mouse_y) - 4), '%d' % (self._mouse_y))
     225 + painter.drawLine(QPointF(self._hz_to_x(self._mouse_x), 0), QPointF(self._hz_to_x(self._mouse_x), self.height()))
     226 + painter.drawLine(QPointF(0, self._dbm_to_y(self._mouse_y)), QPointF(self.width(), self._dbm_to_y(self._mouse_y)))
     227 + if self._mouse_x2:
     228 + painter.drawText(QPointF(self._hz_to_x(self._mouse_x2) + 4, 118), '(%.06f)' % ((old_div(self._mouse_x, 1e6)) - (old_div(self._mouse_x2, 1e6))))
     229 + if self._mouse_x2:
     230 + pen.setBrush(Qt.red)
     231 + painter.setPen(pen)
     232 + painter.drawText(QPointF(self._hz_to_x(self._mouse_x2) + 4, 102), '(%.06f)' % ((old_div(self._x_to_hz(x_axis[max_max]), 1e6)) - (old_div(self._mouse_x2, 1e6))))
     233 + pen.setBrush(Qt.magenta)
     234 + painter.setPen(pen)
     235 + painter.drawText(QPointF(self._hz_to_x(self._mouse_x2) + 4, 88), '%.06f' % (old_div(self._mouse_x2, 1e6)))
     236 + painter.drawText(QPointF(78, self._dbm_to_y(self._mouse_y2) - 4), '%d' % (self._mouse_y2))
     237 + painter.drawLine(QPointF(self._hz_to_x(self._mouse_x2), 0), QPointF(self._hz_to_x(self._mouse_x2), self.height()))
     238 + painter.drawLine(QPointF(0, self._dbm_to_y(self._mouse_y2)), QPointF(self.width(), self._dbm_to_y(self._mouse_y2)))
     239 + if self._mouse_x:
     240 + painter.drawText(QPointF(self._hz_to_x(self._mouse_x) + 4, 74), '(%.06f)' % ((old_div(self._mouse_x2, 1e6)) - (old_div(self._mouse_x, 1e6))))
     241 + finally:
     242 + painter.end()
     243 +
     244 + def _draw_reticle(self):
     245 + if self._reticle is None or (self._reticle.size() != self.size()):
     246 + self._new_reticle()
     247 +
     248 + dbm_lines = [QLineF(self._hz_to_x(self._low_frequency), self._dbm_to_y(dbm),
     249 + self._hz_to_x(self._high_frequency), self._dbm_to_y(dbm))
     250 + for dbm in numpy.arange(self._low_dbm, self._high_dbm, 20.0)]
     251 + dbm_labels = [(dbm, QPointF(self._hz_to_x(self._low_frequency) + 2, self._dbm_to_y(dbm) - 2))
     252 + for dbm in numpy.arange(self._low_dbm, self._high_dbm, 20.0)]
     253 +
     254 + frequency_lines = [QLineF(self._hz_to_x(frequency), self._dbm_to_y(self._high_dbm),
     255 + self._hz_to_x(frequency), self._dbm_to_y(self._low_dbm))
     256 + for frequency in numpy.arange(self._low_frequency, self._high_frequency, self._frequency_step * 20.0)]
     257 + frequency_labels = [(frequency, QPointF(self._hz_to_x(frequency) + 2, self._dbm_to_y(self._high_dbm) + 10))
     258 + for frequency in numpy.arange(self._low_frequency, self._high_frequency, self._frequency_step * 10.0)]
     259 +
     260 + painter = QtGui.QPainter(self._reticle)
     261 + try:
     262 + painter.setRenderHint(QtGui.QPainter.Antialiasing)
     263 +
     264 + painter.setPen(Qt.blue)
     265 +
     266 + # TODO: Removed to support old (<1.0) PySide API in Ubuntu 10.10
     267 + #painter.drawLines(dbm_lines)
     268 + for dbm_line in dbm_lines: painter.drawLine(dbm_line)
     269 + # TODO: Removed to support old (<1.0) PySide API in Ubuntu 10.10
     270 + #painter.drawLines(frequency_lines)
     271 + for frequency_line in frequency_lines: painter.drawLine(frequency_line)
     272 +
     273 + painter.setPen(Qt.white)
     274 + for dbm, point in dbm_labels:
     275 + painter.drawText(point, '%+.0f' % dbm)
     276 + for frequency, point in frequency_labels:
     277 + painter.drawText(point, '%.02f' % (old_div(frequency, 1e6)))
     278 +
     279 + finally:
     280 + painter.end()
     281 +
     282 + def paintEvent(self, event):
     283 + self._draw_graph()
     284 + self._draw_reticle()
     285 +
     286 + painter = QtGui.QPainter(self)
     287 + try:
     288 + painter.setRenderHint(QtGui.QPainter.Antialiasing)
     289 + painter.setPen(QtGui.QPen())
     290 + painter.setBrush(QtGui.QBrush())
     291 + 
     292 + if self._graph:
     293 + painter.drawPixmap(0, 0, self._graph)
     294 +
     295 + if self._path_max:
     296 + painter.setPen(Qt.green)
     297 + painter.drawPath(self._path_max)
     298 + 
     299 + painter.setOpacity(0.5)
     300 + if self._reticle:
     301 + painter.drawPixmap(0, 0, self._reticle)
     302 + finally:
     303 + painter.end()
     304 + 
     305 + def _hz_to_x(self, frequency_hz):
     306 + delta = frequency_hz - self._low_frequency
     307 + range = self._high_frequency - self._low_frequency
     308 + normalized = old_div(delta, range)
     309 + #print "freq: %s \nlow: %s \nhigh: %s \ndelta: %s \nrange: %s \nnormalized: %s" % (frequency_hz, self._low_frequency, self._high_frequency, delta, range, normalized)
     310 + return normalized * self.width()
     311 + 
     312 + def _x_to_hz(self, x):
     313 + range = self._high_frequency - self._low_frequency
     314 + tmp = old_div(x, self.width())
     315 + delta = tmp * range
     316 + return delta + self._low_frequency
     317 +
     318 + def _dbm_to_y(self, dbm):
     319 + delta = self._high_dbm - dbm
     320 + range = self._high_dbm - self._low_dbm
     321 + normalized = old_div(delta, range)
     322 + return normalized * self.height()
     323 + 
     324 + def _y_to_dbm(self, y):
     325 + range = self._high_dbm - self._low_dbm
     326 + tmp = old_div(y, self.height())
     327 + delta = tmp * range
     328 + return self._high_dbm - delta
     329 + 
     330 +class Window(QtWidgets.QWidget):
     331 + def __init__(self, data, low_freq, high_freq, spacing, delay=.01, parent=None):
     332 + QtWidgets.QWidget.__init__(self, parent)
     333 + 
     334 + self._low_freq = low_freq
     335 + self._high_freq = high_freq
     336 + self._spacing = spacing
     337 + self._delay= delay
     338 + 
     339 + self._data = self._open_data(data)
     340 +
     341 + self.render_area = RenderArea(self._data, low_freq, high_freq, spacing, delay)
     342 + 
     343 + main_layout = QtWidgets.QGridLayout()
     344 + main_layout.setContentsMargins(0, 0, 0, 0)
     345 + main_layout.addWidget(self.render_area, 0, 0)
     346 + self.setLayout(main_layout)
     347 +
     348 + self.setWindowTitle("RfCat Spectrum Analyzer (thanks Ubertooth!)")
     349 + 
     350 + def sizeHint(self):
     351 + return QtCore.QSize(480, 160)
     352 +
     353 + def _open_data(self, data):
     354 + if type(data) == str:
     355 + if data == '-':
     356 + data = rflib.RfCat()
     357 + data._debug = 1
     358 + freq = int(self._low_freq)
     359 + spc = int(self._spacing)
     360 + numChans = int(old_div((self._high_freq-self._low_freq), self._spacing))
     361 + data._doSpecAn(freq, spc, numChans)
     362 + else:
     363 + data = pickle.load(open(data,'rb'))
     364 + if data is None:
     365 + raise Exception('Data not found')
     366 + return data
     367 +
     368 + def closeEvent(self, event):
     369 + self.render_area.stop_thread()
     370 + event.accept()
     371 + 
     372 + # handle mouse button clicks
     373 + def mousePressEvent(self, event):
     374 + if event.button() == Qt.LeftButton:
     375 + self.render_area._mouse_x = self.render_area._x_to_hz(float(event.x()))
     376 + self.render_area._mouse_y = self.render_area._y_to_dbm(float(event.y()))
     377 + self.render_area._hide_markers = False
     378 + if event.button() == Qt.RightButton:
     379 + self.render_area._mouse_x2 = self.render_area._x_to_hz(float(event.x()))
     380 + self.render_area._mouse_y2 = self.render_area._y_to_dbm(float(event.y()))
     381 + self.render_area._hide_markers = False
     382 + if event.button() == Qt.MidButton:
     383 + self.render_area._mouse_x = None
     384 + self.render_area._mouse_y = None
     385 + self.render_area._mouse_x2 = None
     386 + self.render_area._mouse_y2 = None
     387 + self.render_area._hide_markers = not self.render_area._hide_markers
     388 + event.accept()
     389 + return
     390 + 
     391 + # handle key presses
     392 + def keyPressEvent(self, event):
     393 + # test for non-alphanumeric keys first
     394 + # arrow key
     395 + if event.key() >= Qt.Key_Left and event.key() <= Qt.Key_Down:
     396 + # left
     397 + if event.key() == Qt.Key_Left:
     398 + self._low_freq -= self._spacing
     399 + self._high_freq -= self._spacing
     400 + # up
     401 + if event.key() == Qt.Key_Up:
     402 + self._spacing = int(self._spacing * 1.1)
     403 + # right
     404 + if event.key() == Qt.Key_Right:
     405 + self._low_freq += self._spacing
     406 + self._high_freq += self._spacing
     407 + # down
     408 + if event.key() == Qt.Key_Down:
     409 + self._spacing = int(self._spacing / 1.1)
     410 + # this will redraw window with the correct labels etc., but we also need to re-start
     411 + # specan on the dongle, and I'm not sure how best to do that!
     412 + self.layout().removeWidget(self.render_area)
     413 + self.render_area = RenderArea(self._data, self._low_freq, self._high_freq, self._spacing, self._delay)
     414 + self.layout().addWidget(self.render_area, 0, 0)
     415 + event.accept()
     416 + return
     417 + 
     418 + # anything else is alphanumeric
     419 + try:
     420 + key= correctbytes(event.key()).upper()
     421 + event.accept()
     422 + except:
     423 + print('Unknown key pressed: 0x%x' % event.key())
     424 + event.ignore()
     425 + return
     426 + if key == 'H':
     427 + print('Key Action')
     428 + print()
     429 + print(' <LEFT ARROW> Reduce base frequency by one step')
     430 + print(' <RIGHT ARROW> Increase base frequency by one step')
     431 + print(' <DOWN ARROW> Reduce frequency step 10%')
     432 + print(' <UP ARROW> Increase frequency step 10%')
     433 + print(' <LEFT MOUSE> Mark LEFT frequency / signal strength at pointer')
     434 + print(' <RIGHT MOUSE> Mark RIGHT frequency / signal strength at pointer')
     435 + print(' <MIDDLE MOUSE> Toggle visibility of frequency / signal strength markers')
     436 + print(' H Print this HELP text')
     437 + print(' M Simulate MIDDLE MOUSE click (for those with trackpads)')
     438 + print(' Q Quit')
     439 + return
     440 + if key == 'M':
     441 + self.render_area._mouse_x = None
     442 + self.render_area._mouse_y = None
     443 + self.render_area._mouse_x2 = None
     444 + self.render_area._mouse_y2 = None
     445 + self.render_area._hide_markers = not self.render_area._hide_markers
     446 + return
     447 + if key == 'Q':
     448 + print('Quit!')
     449 + self.close()
     450 + return
     451 + print('Unsupported key pressed:', key)
     452 + 
     453 +if __name__ == '__main__':
     454 + app = QtWidgets.QApplication(sys.argv)
     455 + f = sys.argv[1]
     456 + fbase = eval(sys.argv[2])
     457 + fhigh = eval(sys.argv[3])
     458 + fdelta = eval(sys.argv[4])
     459 + if len(sys.argv) > 5:
     460 + delay = eval(sys.argv[5])
     461 + else:
     462 + delay = .01
     463 + 
     464 + window = Window(f, fbase, fhigh, fdelta, delay)
     465 + #window = Window('../data.again', 902.0, 928.0, 3e-1)
     466 + window.show()
     467 + sys.exit(app.exec_())
     468 + 
  • rflib/chipcon_nic.py
    Diff is too large to be displayed.
  • ■ ■ ■ ■ ■ ■
    rflib/chipcon_usb.py
     1 +#!/usr/bin/env ipython3
     2 + 
     3 +from __future__ import print_function
     4 +from __future__ import absolute_import
     5 +from __future__ import division
     6 + 
     7 +from builtins import bytes
     8 +from builtins import str
     9 +from builtins import hex
     10 +from builtins import range
     11 +from builtins import object
     12 +from past.utils import old_div
     13 +import os
     14 +import sys
     15 +import usb
     16 +import time
     17 +import struct
     18 +import select
     19 +import threading
     20 +from binascii import hexlify
     21 + 
     22 +from . import bits
     23 +from .bits import correctbytes, ord23
     24 +from .const import *
     25 + 
     26 +if os.name == 'nt':
     27 + import msvcrt
     28 + 
     29 +def keystop(delay=0):
     30 + if os.name == 'posix':
     31 + return len(select.select([sys.stdin],[],[],delay)[0])
     32 + else:
     33 + return msvcrt.kbhit()
     34 + 
     35 +def getRfCatDevices():
     36 + '''
     37 + returns a list of USB device objects for any rfcats that are plugged in
     38 + NOTE: if any rfcats are in bootloader mode, this will cause python to Exit
     39 + '''
     40 + rfcats = []
     41 + for bus in usb.busses():
     42 + for dev in bus.devices:
     43 + # OpenMoko assigned or Legacy TI
     44 + if (dev.idVendor == 0x0451 and dev.idProduct == 0x4715) or (dev.idVendor == 0x1d50 and (dev.idProduct == 0x6047 or dev.idProduct == 0x6048 or dev.idProduct == 0x605b or dev.idProduct == 0xecc1)):
     45 + rfcats.append(dev)
     46 + 
     47 + elif (dev.idVendor == 0x1d50 and (dev.idProduct == 0x6049 or dev.idProduct == 0x604a or dev.idProduct == 0xecc0)):
     48 + print("Already in Bootloader Mode... exiting")
     49 + exit(0)
     50 + 
     51 + return rfcats
     52 + 
     53 +class ChipconUsbTimeoutException(Exception):
     54 + def __str__(self):
     55 + return "Timeout waiting for USB response."
     56 + 
     57 +direct=False
     58 + 
     59 +class USBDongle(object):
     60 + ######## INITIALIZATION ########
     61 + def __init__(self, idx=0, debug=False, copyDongle=None, RfMode=RFST_SRX):
     62 + self.chipnum = None
     63 + self.chipstr = "uninitialized"
     64 + self.rsema = None
     65 + self.xsema = None
     66 + self._bootloader = False
     67 + self._init_on_reconnect = True
     68 + self._do = None
     69 + self.idx = idx
     70 + self.cleanup()
     71 + self._debug = debug
     72 + self._quiet = False
     73 + self._threadGo = threading.Event()
     74 + self._recv_time = 0
     75 + self.radiocfg = RadioConfig()
     76 + self._rfmode = RfMode
     77 + self._radio_configured = False
     78 + 
     79 + self.ctrl_thread = threading.Thread(target=self.run_ctrl)
     80 + self.ctrl_thread.setDaemon(True)
     81 + self.ctrl_thread.start()
     82 + 
     83 + self.recv_thread = threading.Thread(target=self.runEP5_recv)
     84 + self.recv_thread.setDaemon(True)
     85 + self.recv_thread.start()
     86 + 
     87 + self.send_thread = threading.Thread(target=self.runEP5_send)
     88 + self.send_thread.setDaemon(True)
     89 + self.send_thread.start()
     90 + 
     91 + self.resetup(copyDongle=copyDongle)
     92 + self.max_packet_size = USB_MAX_BLOCK_SIZE
     93 + 
     94 + def cleanup(self):
     95 + self._usberrorcnt = 0;
     96 + self.recv_queue = b''
     97 + self.recv_mbox = {}
     98 + self.recv_event = threading.Event()
     99 + self.xmit_event = threading.Event()
     100 + self.reset_event = threading.Event()
     101 + self.xmit_queue = []
     102 + self.xmit_event.clear()
     103 + self.reset_event.clear()
     104 + self.trash = []
     105 +
     106 + def setRFparameters(self):
     107 + pass
     108 + 
     109 + def run_ctrl(self):
     110 + '''
     111 + we wait for reset events and run resetup
     112 + '''
     113 + while True:
     114 + self.reset_event.wait()
     115 + self.resetup(False)
     116 + self.reset_event.clear()
     117 + time.sleep(4)
     118 + 
     119 + def setup(self, console=True, copyDongle=None):
     120 + global dongles
     121 + 
     122 + if copyDongle is not None:
     123 + self.devnum = copyDongle.devnum
     124 + self.chipnum = copyDongle.chipnum
     125 + self.chipstr = copyDongle.chipstr
     126 + self._d = copyDongle._d
     127 + self._do = copyDongle._do
     128 + self._usbmaxi = copyDongle._usbmaxi
     129 + self._usbmaxo = copyDongle._usbmaxo
     130 + self._usbcfg = copyDongle._usbcfg
     131 + self._usbintf = copyDongle._usbintf
     132 + self._usbeps = copyDongle._usbeps
     133 + self._threadGo.set()
     134 + self.ep5timeout = EP_TIMEOUT_ACTIVE
     135 + copyDongle._threadGo.clear() # we're taking over from here.
     136 + self.rsema = copyDongle.rsema
     137 + self.xsema = copyDongle.xsema
     138 + return
     139 + 
     140 + self._internal_select_dongle(console)
     141 + self.finish_setup()
     142 + 
     143 + def _internal_select_dongle(self, console=False):
     144 + '''
     145 + strap in USB interface. this has to insert a ._d and ._do widget with
     146 + the correct USB-like interface
     147 + '''
     148 + self.ep5timeout = EP_TIMEOUT_ACTIVE
     149 + 
     150 + dongles = []
     151 + for dev in getRfCatDevices():
     152 + if self._debug: print((dev), file=sys.stderr)
     153 + do = dev.open()
     154 + iSN = do.getDescriptor(1,0,50)[16]
     155 + devnum = dev.devnum
     156 + dongles.append((devnum, dev, do))
     157 + 
     158 + dongles.sort()
     159 + if len(dongles) == 0:
     160 + raise Exception("No Dongle Found. Please insert a RFCAT dongle.")
     161 + 
     162 + # claim that interface!
     163 + do = dongles[self.idx][2]
     164 +
     165 + try:
     166 + do.claimInterface(0)
     167 + except Exception as e:
     168 + if console or self._debug: print(("Error claiming usb interface:" + repr(e)), file=sys.stderr)
     169 + 
     170 + 
     171 + 
     172 + self.devnum, self._d, self._do = dongles[self.idx]
     173 + 
     174 + self._usbcfg = self._d.configurations[0]
     175 + self._usbintf = self._usbcfg.interfaces[0][0]
     176 + self._usbeps = self._usbintf.endpoints
     177 + for ep in self._usbeps:
     178 + if ep.address & 0x80:
     179 + self._usbmaxi = ep.maxPacketSize
     180 + else:
     181 + self._usbmaxo = ep.maxPacketSize
     182 + 
     183 + def finish_setup(self):
     184 + '''
     185 + we've finished selecting and strapping in the usb dongle interface... continue
     186 + '''
     187 + self.rsema = threading.Lock()
     188 + self.xsema = threading.Lock()
     189 + 
     190 + self._usbmaxi, self._usbmaxo = (EP5IN_MAX_PACKET_SIZE, EP5OUT_MAX_PACKET_SIZE)
     191 + self._threadGo.set()
     192 + 
     193 + self.getRadioConfig()
     194 + chip = self.getPartNum()
     195 + chipstr = CHIPS.get(chip)
     196 + 
     197 + self.chipnum = chip
     198 + self.chipstr = chipstr
     199 + 
     200 + if chip == None:
     201 + print("Older firmware, consider upgrading.")
     202 + else:
     203 + self.chipstr = "unrecognized dongle: %s" % chip
     204 + 
     205 + if self._init_on_reconnect:
     206 + if self._radio_configured:
     207 + self._clear_buffers()
     208 + self.setRadioConfig()
     209 + else:
     210 + self.setRFparameters()
     211 + self._radio_configured = True
     212 + 
     213 + def resetup(self, console=True, copyDongle=None):
     214 + self._do=None
     215 + if self._bootloader:
     216 + return
     217 + if self._debug: print(("waiting (resetup) %x" % self.idx), file=sys.stderr)
     218 + while (self._do==None):
     219 + try:
     220 + self.setup(console, copyDongle)
     221 + if copyDongle is None:
     222 + self._clear_buffers(False)
     223 + self.ping(3, wait=10, silent=True)
     224 + self.setRfMode(self._rfmode)
     225 + 
     226 + except Exception as e:
     227 + #if console: sys.stderr.write('.')
     228 + if not self._quiet:
     229 + print(("Error in resetup():" + repr(e)), file=sys.stderr)
     230 + #if console or self._debug: print("Error in resetup():" + repr(e), file=sys.stderr)
     231 + time.sleep(1)
     232 + 
     233 + 
     234 + ######## BASE FOUNDATIONAL "HIDDEN" CALLS ########
     235 + def _sendEP0(self, request=0, buf=None, value=0x200, index=0, timeout=DEFAULT_USB_TIMEOUT):
     236 + if buf == None:
     237 + buf = b'HELLO THERE'
     238 + return self._do.controlMsg(USB_BM_REQTYPE_TGT_EP|USB_BM_REQTYPE_TYPE_VENDOR|USB_BM_REQTYPE_DIR_OUT, request, buf, value, index, timeout), buf
     239 + 
     240 + def _recvEP0(self, request=0, length=64, value=0, index=0, timeout=100):
     241 + retary = [b"%c"%x for x in self._do.controlMsg(USB_BM_REQTYPE_TGT_EP|USB_BM_REQTYPE_TYPE_VENDOR|USB_BM_REQTYPE_DIR_IN, request, length, value, index, timeout)]
     242 + if len(retary):
     243 + return b''.join(retary)
     244 + return b""
     245 + 
     246 + def _sendEP5(self, buf=None, timeout=DEFAULT_USB_TIMEOUT):
     247 + global direct
     248 + if (buf==None):
     249 + buf = b"\xff\x82\x07\x00ABCDEFG"
     250 + if direct:
     251 + self._do.bulkWrite(5, buf, timeout)
     252 + return
     253 + 
     254 + while (len(buf)>0):
     255 + drain = buf[:self._usbmaxo]
     256 + buf = buf[self._usbmaxo:]
     257 + 
     258 + if self._debug: print("XMIT:"+repr(drain), file=sys.stderr)
     259 + try:
     260 + numwrt = self._do.bulkWrite(5, drain, timeout)
     261 + if numwrt != len(drain):
     262 + raise Exception("Didn't write all the data!? Sent: %d != Queued: %d. REqueuing!(this may be the wrong thing to do, swat me if so)" % (numwrt, len(drain)))
     263 + except Exception as e:
     264 + if self._debug: print("requeuing on error '%s' (%s)" % (repr(drain), e), file=sys.stderr)
     265 + self.xsema.acquire()
     266 + msg = self.xmit_queue.insert(0, drain)
     267 + self.xmit_event.set()
     268 + self.xsema.release()
     269 + if self._debug: print(repr(self.xmit_queue), file=sys.stderr)
     270 +
     271 + def _recvEP5(self, timeout=100):
     272 + retary = [b"%c"%x for x in self._do.bulkRead(0x85, 500, timeout)]
     273 + if self._debug: print("RECV:"+repr(retary), file=sys.stderr)
     274 + if len(retary):
     275 + return b''.join(retary)
     276 + return b''
     277 + 
     278 + def _clear_buffers(self, clear_recv_mbox=False):
     279 + threadGoSet = self._threadGo.isSet()
     280 + self._threadGo.clear()
     281 + if self._debug:
     282 + print(("_clear_buffers()"), file=sys.stderr)
     283 + if clear_recv_mbox:
     284 + for key in list(self.recv_mbox.keys()):
     285 + self.trash.extend(self.recvAll(key))
     286 + elif self.recv_mbox.get(APP_SYSTEM) != None:
     287 + self.trash.extend(self.recvAll(APP_SYSTEM))
     288 + self.trash.append((time.time(),self.recv_queue))
     289 + self.recv_queue = b''
     290 + # self.xmit_queue = [] # do we want to keep this?
     291 + if threadGoSet: self._threadGo.set()
     292 + 
     293 + 
     294 + ######## TRANSMIT/RECEIVE THREADING ########
     295 + def runEP5_send(self):
     296 + msg = b''
     297 + self.send_threadcounter = 0
     298 + 
     299 + while True:
     300 + self._threadGo.wait()
     301 + self.send_threadcounter = (self.send_threadcounter + 1) & 0xffffffff
     302 + 
     303 + #### transmit stuff. if any exists in the xmit_queue
     304 + self.xmit_event.wait() # event driven xmit
     305 + msgsent = False
     306 + 
     307 + try:
     308 + if len(self.xmit_queue):
     309 + self.xsema.acquire()
     310 + 
     311 + msg = self.xmit_queue.pop(0)
     312 + if not len(self.xmit_queue): # if there was only one message
     313 + self.xmit_event.clear() # clear the queue, within the lock
     314 +
     315 + self.xsema.release()
     316 + 
     317 + self._sendEP5(msg)
     318 + msgsent = True
     319 + 
     320 + else:
     321 + if self._debug>3: sys.stderr.write("NoMsgToSend ")
     322 + except:
     323 + sys.excepthook(*sys.exc_info())
     324 + 
     325 + def runEP5_recv(self):
     326 + msg = b''
     327 + self.recv_threadcounter = 0
     328 + 
     329 + while True:
     330 + self._threadGo.wait()
     331 + if self._debug>3: sys.stderr.write(".")
     332 + 
     333 + self.recv_threadcounter = (self.recv_threadcounter + 1) & 0xffffffff
     334 + msgrecv = False
     335 + 
     336 + #### handle debug application
     337 + try:
     338 + q = None
     339 + b = self.recv_mbox.get(APP_DEBUG, None)
     340 + if (b != None):
     341 + for cmd in list(b.keys()):
     342 + q = b[cmd]
     343 + if len(q):
     344 + buf,timestamp = q.pop(0)
     345 + if self._debug > 1: print(("recvthread: buf length: %x\t\t cmd: %x\t\t(%s)"%(len(buf), cmd, repr(buf))), file=sys.stderr)
     346 + 
     347 + if (cmd == DEBUG_CMD_STRING):
     348 + if (len(buf) < 4):
     349 + if (len(q)):
     350 + buf2 = q.pop(0)
     351 + buf += buf2
     352 + q.insert(0,buf)
     353 + if self._debug: sys.stderr.write('*')
     354 + else:
     355 + length, = struct.unpack("<H", buf[2:4])
     356 + if self._debug >1: print(("len=%d"%length), file=sys.stderr)
     357 + if (len(buf) < 4+length):
     358 + if (len(q)):
     359 + buf2 = q.pop(0)
     360 + buf += buf2
     361 + q.insert(0,buf)
     362 + if self._debug: sys.stderr.write('&')
     363 + else:
     364 + printbuf = buf[4:4+length]
     365 + requeuebuf = buf[4+length:]
     366 + if len(requeuebuf):
     367 + if self._debug>1: print((" - DEBUG..requeuing %s"%repr(requeuebuf)), file=sys.stderr)
     368 + q.insert(0,requeuebuf)
     369 + print(("DEBUG: (%.3f) %s" % (timestamp, repr(printbuf))), file=sys.stderr)
     370 + elif (cmd == DEBUG_CMD_HEX):
     371 + #print(repr(buf), file=sys.stderr)
     372 + print("DEBUG: (%.3f) 0x%x %d"%(timestamp, struct.unpack("B", buf[4:5])[0], struct.unpack("B", buf[4:5])[0]), file=sys.stderr)
     373 + elif (cmd == DEBUG_CMD_HEX16):
     374 + #print(repr(buf), file=sys.stderr)
     375 + print("DEBUG: (%.3f) 0x%x %d"%(timestamp, struct.unpack("<H", buf[4:6])[0], struct.unpack("<H", buf[4:6])[0]), file=sys.stderr)
     376 + elif (cmd == DEBUG_CMD_HEX32):
     377 + #print(repr(buf), file=sys.stderr)
     378 + print("DEBUG: (%.3f) 0x%x %d"%(timestamp, struct.unpack("<L", buf[4:8])[0], struct.unpack("<L", buf[4:8])[0]), file=sys.stderr)
     379 + elif (cmd == DEBUG_CMD_INT):
     380 + print("DEBUG: (%.3f) %d"%(timestamp, struct.unpack("<L", buf[4:8])[0]), file=sys.stderr)
     381 + else:
     382 + print(('DEBUG COMMAND UNKNOWN: %x (buf=%s)'%(cmd,repr(buf))), file=sys.stderr)
     383 + 
     384 + except:
     385 + sys.excepthook(*sys.exc_info())
     386 + 
     387 + #### receive stuff.
     388 + if self._debug>2: print("recvthread: Doing receiving...",self.ep5timeout, file=sys.stderr)
     389 + try:
     390 + #### first we populate the queue
     391 + msg = self._recvEP5(timeout=self.ep5timeout)
     392 + if len(msg) > 0:
     393 + self.recv_queue += msg
     394 + msgrecv = True
     395 + except usb.USBError as e:
     396 + #sys.stderr.write(repr(self.recv_queue))
     397 + #sys.stderr.write(repr(e))
     398 + errstr = repr(e)
     399 + if self._debug>4: print(repr(sys.exc_info()), file=sys.stderr)
     400 + if ('No error' in errstr):
     401 + pass
     402 + elif ('Connection timed out' in errstr):
     403 + pass
     404 + elif ('Operation timed out' in errstr):
     405 + pass
     406 + else:
     407 + if ('could not release intf' in errstr):
     408 + if self._debug: print("skipping")
     409 + pass
     410 + elif ('No such device' in errstr):
     411 + self._threadGo.clear()
     412 + #self.resetup(False) ## THIS IS A PROBLEM.
     413 + self.reset_event.set()
     414 + print("===== RESETUP set from recv thread")
     415 + elif ('Input/output error' in errstr): # USBerror 5
     416 + self._threadGo.clear()
     417 + #self.resetup(False) ## THIS IS A PROBLEM.
     418 + self.reset_event.set()
     419 + print("===== RESETUP set from recv thread")
     420 + 
     421 + else:
     422 + if self._debug: print("Error in runEP5() (receiving): %s" % errstr)
     423 + if self._debug>2: sys.excepthook(*sys.exc_info())
     424 + self._usberrorcnt += 1
     425 + pass
     426 + except AttributeError as e:
     427 + if "'NoneType' object has no attribute 'bInterfaceNumber'" in str(e):
     428 + print("Error: dongle went away. USB bus problems?")
     429 + self._threadGo.clear()
     430 + #self.resetup(False)
     431 + self.reset_event.set()
     432 + 
     433 + except:
     434 + sys.excepthook(*sys.exc_info())
     435 + 
     436 + if self._debug>2: print("recvthread: Sorting mail...", file=sys.stderr)
     437 + #### parse, sort, and deliver the mail.
     438 + try:
     439 + # FIXME: is this robust? or just overcomplex?
     440 + if len(self.recv_queue):
     441 + idx = self.recv_queue.find(b'@')
     442 + if (idx==-1):
     443 + if self._debug > 3:
     444 + sys.stderr.write('@')
     445 + else:
     446 + if (idx>0):
     447 + if self._debug: print(("runEP5(): idx>0?"), file=sys.stderr)
     448 + self.trash.append(self.recv_queue[:idx])
     449 + self.recv_queue = self.recv_queue[idx:]
     450 +
     451 + # recv_queue is vulnerable here, but it's ok because we only modify it earlier in this same thread
     452 + # DON'T CHANGE recv_queue from other threads!
     453 + msg = self.recv_queue
     454 + msglen = len(msg)
     455 + #if self._debug > 2: print( "Sorting msg", len(msg), hexlify(msg)
     456 + while (msglen>=5): # if not enough to parse length... we'll wait.
     457 + if not self._recv_time: # should be 0 to start and when done with a packet
     458 + self._recv_time = time.time()
     459 + app = ord23(msg[1])
     460 + cmd = ord23(msg[2])
     461 + length, = struct.unpack("<H", msg[3:5])
     462 + 
     463 + if self._debug>1: print(("recvthread: app=%x cmd=%x len=%x"%(app,cmd,length)), file=sys.stderr)
     464 + 
     465 + if (msglen >= length+5):
     466 + #### if the queue has enough characters to handle the next message... chop it and put it in the appropriate recv_mbox
     467 + msg = self.recv_queue[1:length+5] # drop the initial '@' and chop out the right number of chars
     468 + self.recv_queue = self.recv_queue[length+5:] # chop it out of the queue
     469 + 
     470 + b = self.recv_mbox.get(app,None)
     471 + 
     472 + if self.rsema.acquire(): # THREAD SAFETY DANCE
     473 + try:
     474 + if (b == None):
     475 + b = {}
     476 + self.recv_mbox[app] = b
     477 + except:
     478 + sys.excepthook(*sys.exc_info())
     479 + finally:
     480 + self.rsema.release() # THREAD SAFETY DANCE COMPLETE
     481 +
     482 + q = b.get(cmd)
     483 + 
     484 + if self.rsema.acquire(): # THREAD SAFETY DANCE
     485 + try:
     486 + if (q is None):
     487 + q = []
     488 + b[cmd] = q
     489 + 
     490 + q.append((msg, self._recv_time))
     491 + 
     492 + # notify receivers that a new msg is available
     493 + self.recv_event.set()
     494 + self._recv_time = 0 # we've delivered the current message
     495 + 
     496 + except:
     497 + sys.excepthook(*sys.exc_info())
     498 + finally:
     499 + self.rsema.release() # THREAD SAFETY DANCE COMPLETE
     500 +
     501 + else:
     502 + if self._debug>1: sys.stderr.write('=')
     503 + 
     504 + msg = self.recv_queue
     505 + msglen = len(msg)
     506 + # end of while loop
     507 + 
     508 + except:
     509 + sys.excepthook(*sys.exc_info())
     510 + 
     511 + if self._debug>2: print("readthread: Loop finished", file=sys.stderr)
     512 + if not (msgrecv or len(msg)) :
     513 + #time.sleep(.1)
     514 + self.ep5timeout = EP_TIMEOUT_IDLE
     515 + else:
     516 + self.ep5timeout = EP_TIMEOUT_ACTIVE
     517 + if self._debug > 5: sys.stderr.write(" %s:%d .-P."%(msgrecv,len(msg)))
     518 + 
     519 + 
     520 + 
     521 + ######## APPLICATION API ########
     522 + def recv(self, app, cmd=None, wait=USB_RX_WAIT):
     523 + '''
     524 + high-level USB EP5 receive.
     525 + checks the mbox for app "app" and command "cmd" and returns the next one in the queue
     526 + if any of this does not exist yet, wait for a RECV event until "wait" times out.
     527 + RECV events are generated by the low-level recv thread "runEP5_recv()"
     528 + '''
     529 + startTime = time.time()
     530 + self.recv_event.clear() # an event is only interesting if we've already failed to find our message
     531 + 
     532 + while (time.time() - startTime)*1000 < wait:
     533 + try:
     534 + b = self.recv_mbox.get(app)
     535 + if b:
     536 + if self._debug: print("Recv msg",app,b,cmd, file=sys.stderr)
     537 + if cmd is None:
     538 + keys = list(b.keys())
     539 + if len(keys):
     540 + cmd = list(b.keys())[-1] # just grab one. no guarantees on the order
     541 + 
     542 + if b is not None and cmd is not None:
     543 + q = b.get(cmd)
     544 + if self._debug: print("debug(recv) q='%s'"%repr(q), file=sys.stderr)
     545 + 
     546 + if q is not None and self.rsema.acquire(False):
     547 + if self._debug>3: print(("rsema.UNlocked", "rsema.locked")[self.rsema.locked()],2)
     548 + try:
     549 + resp, rt = q.pop(0)
     550 + 
     551 + self.rsema.release()
     552 + if self._debug>3: print(("rsema.UNlocked", "rsema.locked")[self.rsema.locked()],2)
     553 + 
     554 + # bring it on home... this is the way out.
     555 + return resp[4:], rt
     556 + 
     557 + except IndexError:
     558 + pass
     559 + 
     560 + except AttributeError:
     561 + sys.excepthook(*sys.exc_info())
     562 + pass
     563 + 
     564 + self.rsema.release()
     565 + 
     566 + self.recv_event.wait(old_div((wait - (time.time() - startTime)*1000),1000)) # wait on recv event, with timeout of remaining time
     567 + self.recv_event.clear() # clear event, if it's set
     568 + 
     569 + except KeyboardInterrupt:
     570 + sys.excepthook(*sys.exc_info())
     571 + break
     572 + except:
     573 + sys.excepthook(*sys.exc_info())
     574 + 
     575 + raise ChipconUsbTimeoutException
     576 + 
     577 + def recvAll(self, app, cmd=None):
     578 + retval = self.recv_mbox.get(app,None)
     579 + if retval is not None:
     580 + if cmd is not None:
     581 + b = retval
     582 + if self.rsema.acquire():
     583 + #if self._debug: print ("rsema.UNlocked", "rsema.locked")[self.rsema.locked()],3
     584 + try:
     585 + retval = b.get(cmd)
     586 + b[cmd]=[]
     587 + if len(retval):
     588 + retval = [ (d[4:],t) for d,t in retval ]
     589 + except:
     590 + sys.excepthook(*sys.exc_info())
     591 + finally:
     592 + self.rsema.release()
     593 + #if self._debug: print ("rsema.UNlocked", "rsema.locked")[self.rsema.locked()],3
     594 + else:
     595 + if self.rsema.acquire():
     596 + #if self._debug: print ("rsema.UNlocked", "rsema.locked")[self.rsema.locked()],4
     597 + try:
     598 + self.recv_mbox[app]={}
     599 + finally:
     600 + self.rsema.release()
     601 + #if self._debug: print ("rsema.UNlocked", "rsema.locked")[self.rsema.locked()],4
     602 + return retval
     603 + 
     604 + def send(self, app, cmd, buf, wait=USB_TX_WAIT):
     605 + msg = b"%c%c%s%s" % (app, cmd, struct.pack("<H",len(buf)), buf)
     606 + self.xsema.acquire()
     607 + self.xmit_queue.append(msg)
     608 + self.xmit_event.set()
     609 + self.xsema.release()
     610 + if self._debug: print("Sent Msg %s" %\
     611 + hexlify(msg))
     612 + return self.recv(app, cmd, wait)
     613 + 
     614 + def reprDebugCodes(self, timeout=100):
     615 + codes = self.getDebugCodes(timeout)
     616 + if (codes != None and len(codes) == 2):
     617 + rc1 = LCS.get(codes[0])
     618 + rc2 = LCES.get(codes[0])
     619 + return 'last position: %s\nlast error: %s' % (rc1, rc2)
     620 + return codes
     621 + 
     622 + def getDebugCodes(self, timeout=100):
     623 + '''
     624 + this function uses EP0 (not the normal USB EP5) to check the last state of the dongle.
     625 + this only works if the dongle isn't in a hard-loop or some other corrupted state
     626 + that neglects usbprocessing.
     627 + 
     628 + two values are returned.
     629 + the first value is lastCode[0] and represents standard tracking messages (we were <here>)
     630 + the second value is lastCode[1] and represents exception information (writing OUT while buffer in use!)
     631 + 
     632 + messages LC_* and LCE_* (respectively) are defined in both global.h and rflib.chipcon_usb
     633 + '''
     634 + x = self._recvEP0(request=EP0_CMD_GET_DEBUG_CODES, timeout=timeout)
     635 + if (x != None and len(x)==2):
     636 + return struct.unpack("BB", x)
     637 + else:
     638 + return x
     639 + 
     640 + def clearDebugCodes(self):
     641 + retval = self.send(APP_SYSTEM, SYS_CMD_CLEAR_CODES, b" ", 1000)
     642 + return LCES.get(retval)
     643 + 
     644 + def ep0GetAddr(self):
     645 + addr = self._recvEP0(request=EP0_CMD_GET_ADDRESS)
     646 + return addr
     647 + def ep0Reset(self):
     648 + x = self._recvEP0(request=0xfe, value=0x5352, index=0x4e54)
     649 + return x
     650 + 
     651 + def ep0Peek(self, addr, length, timeout=100):
     652 + x = self._recvEP0(request=EP0_CMD_PEEKX, value=addr, length=length, timeout=timeout)
     653 + return x#x[3:]
     654 + 
     655 + def ep0Poke(self, addr, buf=b'\x00', timeout=100):
     656 + x = self._sendEP0(request=EP0_CMD_POKEX, buf=buf, value=addr, timeout=timeout)
     657 + return x
     658 + 
     659 + def ep0Ping(self, count=10):
     660 + good=0
     661 + bad=0
     662 + for x in range(count):
     663 + #r = self._recvEP0(3, 10)
     664 + try:
     665 + r = self._recvEP0(request=2, value=count, length=count, timeout=DEFAULT_USB_TIMEOUT)
     666 + print("PING: %d bytes received: %s"%(len(r), repr(r)))
     667 + except ChipconUsbTimeoutException as e:
     668 + r = None
     669 + print("Ping Failed.",e)
     670 + if r==None:
     671 + bad+=1
     672 + else:
     673 + good+=1
     674 + return (good,bad)
     675 + 
     676 + def debug(self, delay=1):
     677 + while True:
     678 + """
     679 + try:
     680 + print(("DONGLE RESPONDING: mode :%x, last error# %d"%(self.getDebugCodes()), file=sys.stderr)
     681 + except:
     682 + pass
     683 + print('recv_queue:\t\t (%d bytes) "%s"'%(len(self.recv_queue),repr(self.recv_queue)[:len(self.recv_queue)%39+20]), file=sys.stderr)
     684 + print('trash: \t\t (%d bytes) "%s"'%(len(self.trash),repr(self.trash)[:len(self.trash)%39+20]), file=sys.stderr)
     685 + print('recv_mbox \t\t (%d keys) "%s"'%(len(self.recv_mbox),repr(self.recv_mbox)[:len(repr(self.recv_mbox))%79]), file=sys.stderr)
     686 + for x in self.recv_mbox.keys():
     687 + print(' recv_mbox %d\t (%d records) "%s"'%(x,len(self.recv_mbox[x]),repr(self.recv_mbox[x])[:len(repr(self.recv_mbox[x]))%79]), file=sys.stderr)
     688 + """
     689 + print(self.reprRadioState())
     690 + print(self.reprClientState())
     691 + 
     692 + x,y,z = select.select([sys.stdin],[],[], delay)
     693 + if sys.stdin in x:
     694 + sys.stdin.read(1)
     695 + break
     696 + 
     697 + def getPartNum(self):
     698 + try:
     699 + r = self.send(APP_SYSTEM, SYS_CMD_PARTNUM, b"", 10000)
     700 + r, rt = r
     701 + return ord(r)
     702 + 
     703 + except ChipconUsbTimeoutException as e:
     704 + print("SETUP Failed.",e)
     705 + return -1
     706 + 
     707 + 
     708 + 
     709 + def ping(self, count=10, buf=b"ABCDEFGHIJKLMNOPQRSTUVWXYZ", wait=DEFAULT_USB_TIMEOUT, silent=False):
     710 + good=0
     711 + bad=0
     712 + start = time.time()
     713 + for x in range(count):
     714 + istart = time.time()
     715 +
     716 + try:
     717 + r = self.send(APP_SYSTEM, SYS_CMD_PING, buf, wait)
     718 + r,rt = r
     719 + istop = time.time()
     720 + if not silent:
     721 + print("PING: %d bytes transmitted, received: %s (%f seconds)"%(len(buf), repr(r), istop-istart))
     722 + except ChipconUsbTimeoutException as e:
     723 + r = None
     724 + if not silent:
     725 + print("Ping Failed.",e)
     726 + if r==None:
     727 + bad+=1
     728 + else:
     729 + good+=1
     730 + stop = time.time()
     731 + return (good,bad,stop-start)
     732 + 
     733 + def bootloader(self):
     734 + '''
     735 + switch to bootloader mode. based on Fergus Noble's CC-Bootloader (https://github.com/fnoble/CC-Bootloader)
     736 + this allows the firmware to be updated via USB instead of goodfet/ccdebugger
     737 + '''
     738 + try:
     739 + self._bootloader = True
     740 + r = self.send(APP_SYSTEM, SYS_CMD_BOOTLOADER, b"", wait=1)
     741 + except ChipconUsbTimeoutException:
     742 + pass
     743 +
     744 + def RESET(self):
     745 + try:
     746 + r = self.send(APP_SYSTEM, SYS_CMD_RESET, b"RESET_NOW\x00")
     747 + except ChipconUsbTimeoutException:
     748 + pass
     749 +
     750 + def peek(self, addr, bytecount=1):
     751 + r, t = self.send(APP_SYSTEM, SYS_CMD_PEEK, struct.pack("<HH", bytecount, addr))
     752 + return r
     753 + 
     754 + def poke(self, addr, data):
     755 + r, t = self.send(APP_SYSTEM, SYS_CMD_POKE, struct.pack("<H", addr) + data)
     756 + return r
     757 +
     758 + def pokeReg(self, addr, data):
     759 + r, t = self.send(APP_SYSTEM, SYS_CMD_POKE_REG, struct.pack("<H", addr) + data)
     760 + return r
     761 + 
     762 + def getBuildInfo(self):
     763 + r, t = self.send(APP_SYSTEM, SYS_CMD_BUILDTYPE, b'')
     764 + return r
     765 +
     766 + def getCompilerInfo(self):
     767 + r, t = self.send(APP_SYSTEM, SYS_CMD_COMPILER, b'')
     768 + return r
     769 + 
     770 + def getDeviceSerialNumber(self):
     771 + r, t = self.send(APP_SYSTEM, SYS_CMD_DEVICE_SERIAL_NUMBER, b'')
     772 + return r
     773 +
     774 + def getInterruptRegisters(self):
     775 + regs = {}
     776 + # IEN0,1,2
     777 + regs['IEN0'] = self.peek(IEN0,1)
     778 + regs['IEN1'] = self.peek(IEN1,1)
     779 + regs['IEN2'] = self.peek(IEN2,1)
     780 + # TCON
     781 + regs['TCON'] = self.peek(TCON,1)
     782 + # S0CON
     783 + regs['S0CON'] = self.peek(S0CON,1)
     784 + # IRCON
     785 + regs['IRCON'] = self.peek(IRCON,1)
     786 + # IRCON2
     787 + regs['IRCON2'] = self.peek(IRCON2,1)
     788 + # S1CON
     789 + regs['S1CON'] = self.peek(S1CON,1)
     790 + # RFIF
     791 + regs['RFIF'] = self.peek(RFIF,1)
     792 + # DMAIE
     793 + regs['DMAIE'] = self.peek(DMAIE,1)
     794 + # DMAIF
     795 + regs['DMAIF'] = self.peek(DMAIF,1)
     796 + # DMAIRQ
     797 + regs['DMAIRQ'] = self.peek(DMAIRQ,1)
     798 + return regs
     799 + 
     800 + def reprHardwareConfig(self):
     801 + output= []
     802 + 
     803 + hardware = self.getBuildInfo()
     804 + output.append("Dongle: %s" % hardware.split(b' ')[0])
     805 + try:
     806 + output.append("Firmware rev: %s" % hardware.split(b'r')[1])
     807 + except:
     808 + output.append("Firmware rev: Not found! Update needed!")
     809 + try:
     810 + compiler = self.getCompilerInfo()
     811 + output.append("Compiler: %s" % compiler)
     812 + except:
     813 + output.append("Compiler: Not found! Update needed!")
     814 + # see if we have a bootloader by loooking for it's recognition semaphores
     815 + # in SFR I2SCLKF0 & I2SCLKF1
     816 + if(self.peek(0xDF46,1) == b'\xF0' and self.peek(0xDF47,1) == b'\x0D'):
     817 + output.append("Bootloader: CC-Bootloader")
     818 + else:
     819 + output.append("Bootloader: Not installed")
     820 + return "\n".join(output)
     821 + 
     822 + def reprSoftwareConfig(self):
     823 + output= []
     824 + 
     825 + output.append("rflib rev: %s" % RFLIB_VERSION)
     826 + return "\n".join(output)
     827 + 
     828 + def printClientState(self, width=120):
     829 + print(self.reprClientState(width))
     830 + 
     831 + def reprClientState(self, width=120):
     832 + output = ["="*width]
     833 + output.append(' client thread cycles: %d/%d' % (self.recv_threadcounter,self.send_threadcounter))
     834 + output.append(' client errored cycles: %d' % self._usberrorcnt)
     835 + output.append(' recv_queue: (%d bytes) %s'%(len(self.recv_queue),repr(self.recv_queue)[:width-42]))
     836 + output.append(' trash: (%d blobs) "%s"'%(len(self.trash),repr(self.trash)[:width-44]))
     837 + output.append(' recv_mbox (%d keys) "%s"'%(len(self.recv_mbox),repr([hex(x) for x in list(self.recv_mbox.keys())])[:width-44]))
     838 + for app in list(self.recv_mbox.keys()):
     839 + appbox = self.recv_mbox[app]
     840 + output.append(' app 0x%x (%d records)'%(app,len(appbox)))
     841 + for cmd in list(appbox.keys()):
     842 + output.append(' [0x%x] (%d frames) "%s"'%(cmd, len(appbox[cmd]), repr(appbox[cmd])[:width-36]))
     843 + output.append('')
     844 + return "\n".join(output)
     845 + 
     846 + 
     847 + 
     848 +def unittest(self, mhz=24):
     849 + print("\nTesting USB ping()")
     850 + self.ping(3)
     851 +
     852 + print("\nTesting USB ep0Ping()")
     853 + self.ep0Ping()
     854 +
     855 + print("\nTesting USB enumeration")
     856 + print("getString(1,100): %s" % repr(self._do.getString(1,100)))
     857 + print("getString(2,100): %s" % repr(self._do.getString(2,100)))
     858 + print("getString(3,100): %s" % repr(self._do.getString(3,100)))
     859 +
     860 + print("\nTesting USB EP MAX_PACKET_SIZE handling (ep0Peek(0xf000, 100))")
     861 + print(repr(self.ep0Peek(0xf000, 100)))
     862 + 
     863 + print("\nTesting USB EP MAX_PACKET_SIZE handling (peek(0xf000, 300))")
     864 + print(repr(self.peek(0xf000, 400)))
     865 + 
     866 + print("\nTesting USB poke/peek")
     867 + data = b"".join([correctbytes(c) for c in range(120)])
     868 + where = 0xf300
     869 + self.poke(where, data)
     870 + ndata = self.peek(where, len(data))
     871 + if ndata != data:
     872 + print(" *FAILED*\n '%s'\n '%s'" % (hexlify(data), hexlify(ndata)))
     873 + raise Exception(" *FAILED*\n '%s'\n '%s'" % (hexlify(data), hexlify(ndata)))
     874 + else:
     875 + print(" passed '%s'" % (hexlify(ndata)))
     876 + 
     877 + 
     878 +if __name__ == "__main__":
     879 + idx = 0
     880 + if len(sys.argv) > 1:
     881 + idx = int(sys.argv.pop())
     882 + d = USBDongle(idx=idx, debug=False)
     883 + 
     884 + 
     885 + 
  • ■ ■ ■ ■ ■ ■
    rflib/chipcondefs.py
     1 +from rflib import vstruct
     2 +from .vstruct.primitives import *
     3 + 
     4 +class RadioConfig(vstruct.VStruct):
     5 + def __init__(self):
     6 + vstruct.VStruct.__init__(self)
     7 + self.sync1 = v_uint8() #df00
     8 + self.sync0 = v_uint8() #df01
     9 + self.pktlen = v_uint8() #df02
     10 + self.pktctrl1 = v_uint8() #df03
     11 + self.pktctrl0 = v_uint8() #df04
     12 + self.addr = v_uint8() #df05
     13 + self.channr = v_uint8() #df06
     14 + self.fsctrl1 = v_uint8() #df07
     15 + self.fsctrl0 = v_uint8() #df08
     16 + self.freq2 = v_uint8() #df09
     17 + self.freq1 = v_uint8() #df0a
     18 + self.freq0 = v_uint8() #df0b
     19 + self.mdmcfg4 = v_uint8() #df0c
     20 + self.mdmcfg3 = v_uint8() #df0d
     21 + self.mdmcfg2 = v_uint8() #df0e
     22 + self.mdmcfg1 = v_uint8() #df0f
     23 + self.mdmcfg0 = v_uint8() #df10
     24 + self.deviatn = v_uint8() #df11
     25 + self.mcsm2 = v_uint8() #df12
     26 + self.mcsm1 = v_uint8() #df13
     27 + self.mcsm0 = v_uint8() #df14
     28 + self.foccfg = v_uint8() #df15
     29 + self.bscfg = v_uint8() #df16
     30 + self.agcctrl2 = v_uint8() #df17
     31 + self.agcctrl1 = v_uint8() #df18
     32 + self.agcctrl0 = v_uint8() #df19
     33 + self.frend1 = v_uint8() #df1a
     34 + self.frend0 = v_uint8() #df1b
     35 + self.fscal3 = v_uint8() #df1c
     36 + self.fscal2 = v_uint8() #df1d
     37 + self.fscal1 = v_uint8() #df1e
     38 + self.fscal0 = v_uint8() #df1f
     39 + self.z0 = v_uint8() #df20,21,22
     40 + self.z1 = v_uint8() #df20,21,22
     41 + self.z2 = v_uint8() #df20,21,22
     42 + self.test2 = v_uint8() #df23
     43 + self.test1 = v_uint8() #df24
     44 + self.test0 = v_uint8() #df25
     45 + self.z3 = v_uint8() #df26
     46 + self.pa_table7 = v_uint8() #df27
     47 + self.pa_table6 = v_uint8() #df28
     48 + self.pa_table5 = v_uint8() #df29
     49 + self.pa_table4 = v_uint8() #df2a
     50 + self.pa_table3 = v_uint8() #df2b
     51 + self.pa_table2 = v_uint8() #df2c
     52 + self.pa_table1 = v_uint8() #df2d
     53 + self.pa_table0 = v_uint8() #df2e
     54 + self.iocfg2 = v_uint8() #df2f
     55 + self.iocfg1 = v_uint8() #df30
     56 + self.iocfg0 = v_uint8() #df31
     57 + self.z4 = v_uint8() #df32,33,34,35
     58 + self.z5 = v_uint8() #df32,33,34,35
     59 + self.z6 = v_uint8() #df32,33,34,35
     60 + self.z7 = v_uint8() #df32,33,34,35
     61 + self.partnum = v_uint8() #df36
     62 + self.chipid = v_uint8() #df37
     63 + self.freqest = v_uint8() #df38
     64 + self.lqi = v_uint8() #df39
     65 + self.rssi = v_uint8() #df3a
     66 + self.marcstate = v_uint8() #df3b
     67 + self.pkstatus = v_uint8() #df3c
     68 + self.vco_vc_dac = v_uint8() #df3d
     69 +
     70 + 
     71 + 
     72 +AC = 64
     73 +ACC = 0xE0
     74 +ACC_0 = 1
     75 +ACC_1 = 2
     76 +ACC_2 = 4
     77 +ACC_3 = 8
     78 +ACC_4 = 16
     79 +ACC_5 = 32
     80 +ACC_6 = 64
     81 +ACC_7 = 128
     82 +ACTIVE = 1
     83 +ADCCFG = 0xF2
     84 +ADCCFG_0 = 0x01
     85 +ADCCFG_1 = 0x02
     86 +ADCCFG_2 = 0x04
     87 +ADCCFG_3 = 0x08
     88 +ADCCFG_4 = 0x10
     89 +ADCCFG_5 = 0x20
     90 +ADCCFG_6 = 0x40
     91 +ADCCFG_7 = 0x80
     92 +ADCCON1 = 0xB4
     93 +ADCCON1_EOC = 0x80
     94 +ADCCON1_RCTRL = 0x0C
     95 +ADCCON1_RCTRL0 = 0x04
     96 +ADCCON1_RCTRL1 = 0x08
     97 +ADCCON1_RCTRL_COMPL = (0x00 << 2)
     98 +ADCCON1_RCTRL_LFSR13 = (0x01 << 2)
     99 +ADCCON1_ST = 0x40
     100 +ADCCON1_STSEL = 0x30
     101 +ADCCON1_STSEL0 = 0x10
     102 +ADCCON1_STSEL1 = 0x20
     103 +ADCCON2 = 0xB5
     104 +ADCCON2_ECH = 0x0F
     105 +ADCCON2_ECH0 = 0x01
     106 +ADCCON2_ECH1 = 0x02
     107 +ADCCON2_ECH2 = 0x04
     108 +ADCCON2_ECH3 = 0x08
     109 +ADCCON2_SCH = 0x0F
     110 +ADCCON2_SCH0 = 0x01
     111 +ADCCON2_SCH1 = 0x02
     112 +ADCCON2_SCH2 = 0x04
     113 +ADCCON2_SCH3 = 0x08
     114 +ADCCON2_SCH_AIN0 = (0x00)
     115 +ADCCON2_SCH_AIN0_1 = (0x08)
     116 +ADCCON2_SCH_AIN1 = (0x01)
     117 +ADCCON2_SCH_AIN2 = (0x02)
     118 +ADCCON2_SCH_AIN2_3 = (0x09)
     119 +ADCCON2_SCH_AIN3 = (0x03)
     120 +ADCCON2_SCH_AIN4 = (0x04)
     121 +ADCCON2_SCH_AIN4_5 = (0x0A)
     122 +ADCCON2_SCH_AIN5 = (0x05)
     123 +ADCCON2_SCH_AIN6 = (0x06)
     124 +ADCCON2_SCH_AIN6_7 = (0x0B)
     125 +ADCCON2_SCH_AIN7 = (0x07)
     126 +ADCCON2_SCH_GND = (0x0C)
     127 +ADCCON2_SCH_POSVOL = (0x0D)
     128 +ADCCON2_SCH_TEMPR = (0x0E)
     129 +ADCCON2_SCH_VDD_3 = (0x0F)
     130 +ADCCON2_SDIV = 0x30
     131 +ADCCON2_SDIV0 = 0x10
     132 +ADCCON2_SDIV1 = 0x20
     133 +ADCCON2_SDIV_128 = (0x01 << 4)
     134 +ADCCON2_SDIV_256 = (0x02 << 4)
     135 +ADCCON2_SDIV_512 = (0x03 << 4)
     136 +ADCCON2_SDIV_64 = (0x00 << 4)
     137 +ADCCON2_SREF = 0xC0
     138 +ADCCON2_SREF0 = 0x40
     139 +ADCCON2_SREF1 = 0x80
     140 +ADCCON2_SREF_1_25V = (0x00 << 6)
     141 +ADCCON2_SREF_AVDD = (0x02 << 6)
     142 +ADCCON2_SREF_P0_6_P0_7 = (0x03 << 6)
     143 +ADCCON2_SREF_P0_7 = (0x01 << 6)
     144 +ADCCON3 = 0xB6
     145 +ADCCON3_ECH_AIN0 = (0x00)
     146 +ADCCON3_ECH_AIN0_1 = (0x08)
     147 +ADCCON3_ECH_AIN1 = (0x01)
     148 +ADCCON3_ECH_AIN2 = (0x02)
     149 +ADCCON3_ECH_AIN2_3 = (0x09)
     150 +ADCCON3_ECH_AIN3 = (0x03)
     151 +ADCCON3_ECH_AIN4 = (0x04)
     152 +ADCCON3_ECH_AIN4_5 = (0x0A)
     153 +ADCCON3_ECH_AIN5 = (0x05)
     154 +ADCCON3_ECH_AIN6 = (0x06)
     155 +ADCCON3_ECH_AIN6_7 = (0x0B)
     156 +ADCCON3_ECH_AIN7 = (0x07)
     157 +ADCCON3_ECH_GND = (0x0C)
     158 +ADCCON3_ECH_POSVOL = (0x0D)
     159 +ADCCON3_ECH_TEMPR = (0x0E)
     160 +ADCCON3_ECH_VDD_3 = (0x0F)
     161 +ADCCON3_EDIV = 0x30
     162 +ADCCON3_EDIV0 = 0x10
     163 +ADCCON3_EDIV1 = 0x20
     164 +ADCCON3_EDIV_128 = (0x01 << 4)
     165 +ADCCON3_EDIV_256 = (0x02 << 4)
     166 +ADCCON3_EDIV_512 = (0x03 << 4)
     167 +ADCCON3_EDIV_64 = (0x00 << 4)
     168 +ADCCON3_EREF = 0xC0
     169 +ADCCON3_EREF0 = 0x40
     170 +ADCCON3_EREF1 = 0x80
     171 +ADCCON3_EREF_1_25V = (0x00 << 6)
     172 +ADCCON3_EREF_AVDD = (0x02 << 6)
     173 +ADCCON3_EREF_P0_6_P0_7 = (0x03 << 6)
     174 +ADCCON3_EREF_P0_7 = (0x01 << 6)
     175 +ADCH = 0xBB
     176 +ADCIE = 2
     177 +ADCIF = 32
     178 +ADCL = 0xBA
     179 +ADC_VECTOR = 1 # ADC End of Conversion
     180 +ADDR = 0xDF05
     181 +ADR_CHK_0_255_BRDCST = (0x03)
     182 +ADR_CHK_0_BRDCST = (0x02)
     183 +ADR_CHK_NONE = (0x00)
     184 +ADR_CHK_NO_BRDCST = (0x01)
     185 +AGCCTRL0 = 0xDF19
     186 +AGCCTRL0_AGC_FREEZE = 0x0C
     187 +AGCCTRL0_FILTER_LENGTH = 0x03
     188 +AGCCTRL0_HYST_LEVEL = 0xC0
     189 +AGCCTRL0_WAIT_TIME = 0x30
     190 +AGCCTRL1 = 0xDF18
     191 +AGCCTRL1_AGC_LNA_PRIORITY = 0x40
     192 +AGCCTRL1_CARRIER_SENSE_ABS_THR = 0x0F
     193 +AGCCTRL1_CARRIER_SENSE_REL_THR = 0x30
     194 +AGCCTRL2 = 0xDF17
     195 +AGCCTRL2_MAGN_TARGET = 0x07
     196 +AGCCTRL2_MAX_DVGA_GAIN = 0xC0
     197 +AGCCTRL2_MAX_LNA_GAIN = 0x38
     198 +B = 0xF0
     199 +BSCFG = 0xDF16
     200 +BSCFG_BS_LIMIT = 0x03
     201 +BSCFG_BS_LIMIT0 = 0x01
     202 +BSCFG_BS_LIMIT1 = 0x02
     203 +BSCFG_BS_LIMIT_0 = (0x00)
     204 +BSCFG_BS_LIMIT_12 = (0x03)
     205 +BSCFG_BS_LIMIT_3 = (0x01)
     206 +BSCFG_BS_LIMIT_6 = (0x02)
     207 +BSCFG_BS_POST_KI = 0x08
     208 +BSCFG_BS_POST_KP = 0x04
     209 +BSCFG_BS_PRE_KI = 0xC0
     210 +BSCFG_BS_PRE_KI0 = 0x40
     211 +BSCFG_BS_PRE_KI1 = 0x80
     212 +BSCFG_BS_PRE_KI_1K = (0x00 << 6)
     213 +BSCFG_BS_PRE_KI_2K = (0x01 << 6)
     214 +BSCFG_BS_PRE_KI_3K = (0x02 << 6)
     215 +BSCFG_BS_PRE_KI_4K = (0x03 << 6)
     216 +BSCFG_BS_PRE_KP = 0x30
     217 +BSCFG_BS_PRE_KP0 = 0x10
     218 +BSCFG_BS_PRE_KP1 = 0x20
     219 +BSCFG_BS_PRE_KP_1K = (0x00 << 4)
     220 +BSCFG_BS_PRE_KP_2K = (0x01 << 4)
     221 +BSCFG_BS_PRE_KP_3K = (0x02 << 4)
     222 +BSCFG_BS_PRE_KP_4K = (0x03 << 4)
     223 +B_0 = 1
     224 +B_1 = 2
     225 +B_2 = 4
     226 +B_3 = 8
     227 +B_4 = 16
     228 +B_5 = 32
     229 +B_6 = 64
     230 +B_7 = 128
     231 +CHANNR = 0xDF06
     232 +CLKCON = 0xC6
     233 +CLKCON_CLKSPD = 0x07 # bit mask, for the clock speed
     234 +CLKCON_CLKSPD0 = 0x01 # bit mask, for the clock speed
     235 +CLKCON_CLKSPD1 = 0x02 # bit mask, for the clock speed
     236 +CLKCON_CLKSPD2 = 0x04 # bit mask, for the clock speed
     237 +CLKCON_OSC = 0x40 # bit mask, for the system clock oscillator
     238 +CLKCON_OSC32 = 0x80 # bit mask, for the slow 32k clock oscillator
     239 +CLKCON_TICKSPD = 0x38 # bit mask, for timer ticks output setting
     240 +CLKCON_TICKSPD0 = 0x08 # bit mask, for timer ticks output setting
     241 +CLKCON_TICKSPD1 = 0x10 # bit mask, for timer ticks output setting
     242 +CLKCON_TICKSPD2 = 0x20 # bit mask, for timer ticks output setting
     243 +CLKSPD_DIV_1 = (0x00)
     244 +CLKSPD_DIV_128 = (0x07)
     245 +CLKSPD_DIV_16 = (0x04)
     246 +CLKSPD_DIV_2 = (0x01)
     247 +CLKSPD_DIV_32 = (0x05)
     248 +CLKSPD_DIV_4 = (0x02)
     249 +CLKSPD_DIV_64 = (0x06)
     250 +CLKSPD_DIV_8 = (0x03)
     251 +CY = 128
     252 +DEVIATN = 0xDF11
     253 +DEVIATN_DEVIATION_E = 0x70
     254 +DEVIATN_DEVIATION_E0 = 0x10
     255 +DEVIATN_DEVIATION_E1 = 0x20
     256 +DEVIATN_DEVIATION_E2 = 0x40
     257 +DEVIATN_DEVIATION_M = 0x07
     258 +DEVIATN_DEVIATION_M0 = 0x01
     259 +DEVIATN_DEVIATION_M1 = 0x02
     260 +DEVIATN_DEVIATION_M2 = 0x04
     261 +DMA0CFGH = 0xD5
     262 +DMA0CFGL = 0xD4
     263 +DMA1CFGH = 0xD3
     264 +DMA1CFGL = 0xD2
     265 +DMAARM = 0xD6
     266 +DMAARM0 = 0x01
     267 +DMAARM1 = 0x02
     268 +DMAARM2 = 0x04
     269 +DMAARM3 = 0x08
     270 +DMAARM4 = 0x10
     271 +DMAARM_ABORT = 0x80
     272 +DMAIE = 1
     273 +DMAIF = 1
     274 +DMAIRQ = 0xD1
     275 +DMAIRQ_DMAIF0 = 0x01
     276 +DMAIRQ_DMAIF1 = 0x02
     277 +DMAIRQ_DMAIF2 = 0x04
     278 +DMAIRQ_DMAIF3 = 0x08
     279 +DMAIRQ_DMAIF4 = 0x10
     280 +DMAREQ = 0xD7
     281 +DMAREQ0 = 0x01
     282 +DMAREQ1 = 0x02
     283 +DMAREQ2 = 0x04
     284 +DMAREQ3 = 0x08
     285 +DMAREQ4 = 0x10
     286 +DMA_VECTOR = 8 # DMA Transfer Complete
     287 +DPH0 = 0x83
     288 +DPH1 = 0x85
     289 +DPL0 = 0x82
     290 +DPL1 = 0x84
     291 +DPS = 0x92
     292 +DPS_VDPS = 0x01
     293 +DSM_IP_OFF_OS_OFF = (0x03) # Interpolator & output shaping disabled
     294 +DSM_IP_OFF_OS_ON = (0x02) # Interpolator disabled & output shaping enabled
     295 +DSM_IP_ON_OS_OFF = (0x01) # Interpolator enabled & output shaping disabled
     296 +DSM_IP_ON_OS_ON = (0x00) # Interpolator & output shaping enabled
     297 +EA = 128
     298 +ENCCS = 0xB3
     299 +ENCCS_CMD = 0x06
     300 +ENCCS_CMD0 = 0x02
     301 +ENCCS_CMD1 = 0x04
     302 +ENCCS_CMD_DEC = (0x01 << 1)
     303 +ENCCS_CMD_ENC = (0x00 << 1)
     304 +ENCCS_CMD_LDIV = (0x03 << 1)
     305 +ENCCS_CMD_LDKEY = (0x02 << 1)
     306 +ENCCS_MODE = 0x70
     307 +ENCCS_MODE0 = 0x10
     308 +ENCCS_MODE1 = 0x20
     309 +ENCCS_MODE2 = 0x40
     310 +ENCCS_MODE_CBC = (0x00 << 4)
     311 +ENCCS_MODE_CBCMAC = (0x05 << 4)
     312 +ENCCS_MODE_CFB = (0x01 << 4)
     313 +ENCCS_MODE_CTR = (0x03 << 4)
     314 +ENCCS_MODE_ECB = (0x04 << 4)
     315 +ENCCS_MODE_OFB = (0x02 << 4)
     316 +ENCCS_RDY = 0x08
     317 +ENCCS_ST = 0x01
     318 +ENCDI = 0xB1
     319 +ENCDO = 0xB2
     320 +ENCIE = 16
     321 +ENCIF_0 = 1
     322 +ENCIF_1 = 2
     323 +ENC_VECTOR = 4 # AES Encryption/Decryption Complete
     324 +EP_STATE_IDLE = 0
     325 +EP_STATE_RX = 2
     326 +EP_STATE_STALL = 3
     327 +EP_STATE_TX = 1
     328 +ERR = 8
     329 +F0 = 32
     330 +F1 = 2
     331 +FADDRH = 0xAD
     332 +FADDRL = 0xAC
     333 +FCTL = 0xAE
     334 +FCTL_BUSY = 0x80
     335 +FCTL_CONTRD = 0x10
     336 +FCTL_ERASE = 0x01
     337 +FCTL_SWBSY = 0x40
     338 +FCTL_WRITE = 0x02
     339 +FE = 16
     340 +FOCCFG = 0xDF15
     341 +FOCCFG_FOC_BS_CS_GATE = 0x20
     342 +FOCCFG_FOC_LIMIT = 0x03
     343 +FOCCFG_FOC_LIMIT0 = 0x01
     344 +FOCCFG_FOC_LIMIT1 = 0x02
     345 +FOCCFG_FOC_POST_K = 0x04
     346 +FOCCFG_FOC_PRE_K = 0x18
     347 +FOCCFG_FOC_PRE_K0 = 0x08
     348 +FOCCFG_FOC_PRE_K1 = 0x10
     349 +FOC_LIMIT_0 = (0x00)
     350 +FOC_LIMIT_DIV2 = (0x03)
     351 +FOC_LIMIT_DIV4 = (0x02)
     352 +FOC_LIMIT_DIV8 = (0x01)
     353 +FOC_PRE_K_1K = (0x00 << 3)
     354 +FOC_PRE_K_2K = (0x02 << 3)
     355 +FOC_PRE_K_3K = (0x03 << 3)
     356 +FOC_PRE_K_4K = (0x04 << 3)
     357 +FREND0 = 0xDF1B
     358 +FREND0_LODIV_BUF_CURRENT_TX = 0x30
     359 +FREND0_PA_POWER = 0x07
     360 +FREND1 = 0xDF1A
     361 +FREND1_LNA2MIX_CURRENT = 0x30
     362 +FREND1_LNA_CURRENT = 0xC0
     363 +FREND1_LODIV_BUF_CURRENT_RX = 0x0C
     364 +FREND1_MIX_CURRENT = 0x03
     365 +FREQ0 = 0xDF0B
     366 +FREQ1 = 0xDF0A
     367 +FREQ2 = 0xDF09
     368 +FREQEST = 0xDF38
     369 +FSCAL0 = 0xDF1F
     370 +FSCAL1 = 0xDF1E
     371 +FSCAL2 = 0xDF1D
     372 +FSCAL2_FSCAL2 = 0x1F
     373 +FSCAL2_VCO_CORE_H_EN = 0x20
     374 +FSCAL3 = 0xDF1C
     375 +FSCAL3_CHP_CURR_CAL_EN = 0x30
     376 +FSCAL3_FSCAL3 = 0xC0
     377 +FSCTRL0 = 0xDF08
     378 +FSCTRL1 = 0xDF07
     379 +FS_AUTOCAL_4TH_TO_IDLE = (0x03 << 4)
     380 +FS_AUTOCAL_FROM_IDLE = (0x01 << 4)
     381 +FS_AUTOCAL_NEVER = (0x00 << 4)
     382 +FS_AUTOCAL_TO_IDLE = (0x02 << 4)
     383 +FWDATA = 0xAF
     384 +FWT = 0xAB
     385 +I2SCFG0 = 0xDF40
     386 +I2SCFG0_ENAB = 0x01
     387 +I2SCFG0_MASTER = 0x02
     388 +I2SCFG0_RXIEN = 0x40
     389 +I2SCFG0_RXMONO = 0x04
     390 +I2SCFG0_TXIEN = 0x80
     391 +I2SCFG0_TXMONO = 0x08
     392 +I2SCFG0_ULAWC = 0x10
     393 +I2SCFG0_ULAWE = 0x20
     394 +I2SCFG1 = 0xDF41
     395 +I2SCFG1_IOLOC = 0x01
     396 +I2SCFG1_TRIGNUM = 0x06
     397 +I2SCFG1_TRIGNUM0 = 0x02
     398 +I2SCFG1_TRIGNUM1 = 0x04
     399 +I2SCFG1_TRIGNUM_IOC_1 = (0x02 << 1)
     400 +I2SCFG1_TRIGNUM_NO_TRIG = (0x00 << 1)
     401 +I2SCFG1_TRIGNUM_T1_CH0 = (0x03 << 1)
     402 +I2SCFG1_TRIGNUM_USB_SOF = (0x01 << 1)
     403 +I2SCFG1_WORDS = 0xF8
     404 +I2SCFG1_WORDS0 = 0x08
     405 +I2SCFG1_WORDS1 = 0x10
     406 +I2SCFG1_WORDS2 = 0x20
     407 +I2SCFG1_WORDS3 = 0x40
     408 +I2SCFG1_WORDS4 = 0x80
     409 +I2SCLKF0 = 0xDF46
     410 +I2SCLKF1 = 0xDF47
     411 +I2SCLKF2 = 0xDF48
     412 +I2SDATH = 0xDF43
     413 +I2SDATL = 0xDF42
     414 +I2SSTAT = 0xDF45
     415 +I2SSTAT_RXIRQ = 0x04
     416 +I2SSTAT_RXLR = 0x10
     417 +I2SSTAT_RXOVF = 0x40
     418 +I2SSTAT_TXIRQ = 0x08
     419 +I2SSTAT_TXLR = 0x20
     420 +I2SSTAT_TXUNF = 0x80
     421 +I2SSTAT_WCNT = 0x03
     422 +I2SSTAT_WCNT0 = 0x01
     423 +I2SSTAT_WCNT1 = 0x02
     424 +I2SSTAT_WCNT_10BIT = (0x02)
     425 +I2SSTAT_WCNT_9BIT = (0x01)
     426 +I2SSTAT_WCNT_9_10BIT = (0x02)
     427 +I2SWCNT = 0xDF44
     428 +IEN0 = 0xA8
     429 +IEN1 = 0xB8
     430 +IEN2 = 0x9A
     431 +IEN2_I2STXIE = 0x08
     432 +IEN2_P1IE = 0x10
     433 +IEN2_P2IE = 0x02
     434 +IEN2_RFIE = 0x01
     435 +IEN2_USBIE = 0x02
     436 +IEN2_UTX0IE = 0x04
     437 +IEN2_UTX1IE = 0x08
     438 +IEN2_WDTIE = 0x20
     439 +IOCFG0 = 0xDF31
     440 +IOCFG0_GDO0_CFG = 0x3F
     441 +IOCFG0_GDO0_INV = 0x40
     442 +IOCFG1 = 0xDF30
     443 +IOCFG1_GDO1_CFG = 0x3F
     444 +IOCFG1_GDO1_INV = 0x40
     445 +IOCFG1_GDO_DS = 0x80
     446 +IOCFG2 = 0xDF2F
     447 +IOCFG2_GDO2_CFG = 0x3F
     448 +IOCFG2_GDO2_INV = 0x40
     449 +IP0 = 0xA9
     450 +IP0_IPG0 = 0x01
     451 +IP0_IPG1 = 0x02
     452 +IP0_IPG2 = 0x04
     453 +IP0_IPG3 = 0x08
     454 +IP0_IPG4 = 0x10
     455 +IP0_IPG5 = 0x20
     456 +IP1 = 0xB9
     457 +IP1_IPG0 = 0x01
     458 +IP1_IPG1 = 0x02
     459 +IP1_IPG2 = 0x04
     460 +IP1_IPG3 = 0x08
     461 +IP1_IPG4 = 0x10
     462 +IP1_IPG5 = 0x20
     463 +IRCON = 0xC0
     464 +IRCON2 = 0xE8
     465 +IT0 = 1
     466 +IT1 = 4
     467 +LED_MODE_OFF = 0x00
     468 +LED_MODE_ON = 0x01
     469 +LQI = 0xDF39
     470 +MARCSTATE = 0xDF3B
     471 +MARCSTATE_MARC_STATE = 0x1F
     472 +MARC_STATE_BWBOOST = 0x09
     473 +MARC_STATE_ENDCAL = 0x0C
     474 +MARC_STATE_FSTXON = 0x12
     475 +MARC_STATE_FS_LOCK = 0x0A
     476 +MARC_STATE_IDLE = 0x01
     477 +MARC_STATE_IFADCON = 0x0B
     478 +MARC_STATE_MANCAL = 0x05
     479 +MARC_STATE_REGON = 0x07
     480 +MARC_STATE_REGON_MC = 0x04
     481 +MARC_STATE_RX = 0x0D
     482 +MARC_STATE_RXTX_SWITCH = 0x15
     483 +MARC_STATE_RX_END = 0x0E
     484 +MARC_STATE_RX_OVERFLOW = 0x11
     485 +MARC_STATE_RX_RST = 0x0F
     486 +MARC_STATE_SLEEP = 0x00
     487 +MARC_STATE_STARTCAL = 0x08
     488 +MARC_STATE_TX = 0x13
     489 +MARC_STATE_TXRX_SWITCH = 0x10
     490 +MARC_STATE_TX_END = 0x14
     491 +MARC_STATE_TX_UNDERFLOW = 0x16
     492 +MARC_STATE_VCOON = 0x06
     493 +MARC_STATE_VCOON_MC = 0x03
     494 +MCSM0 = 0xDF14
     495 +MCSM0_FS_AUTOCAL = 0x30
     496 +MCSM1 = 0xDF13
     497 +MCSM1_CCA_MODE = 0x30
     498 +MCSM1_CCA_MODE0 = 0x10
     499 +MCSM1_CCA_MODE1 = 0x20
     500 +MCSM1_CCA_MODE_ALWAYS = (0x00 << 4)
     501 +MCSM1_CCA_MODE_PACKET = (0x02 << 4)
     502 +MCSM1_CCA_MODE_RSSI0 = (0x01 << 4)
     503 +MCSM1_CCA_MODE_RSSI1 = (0x03 << 4)
     504 +MCSM1_RXOFF_MODE = 0x0C
     505 +MCSM1_RXOFF_MODE0 = 0x04
     506 +MCSM1_RXOFF_MODE1 = 0x08
     507 +MCSM1_RXOFF_MODE_FSTXON = (0x01 << 2)
     508 +MCSM1_RXOFF_MODE_IDLE = (0x00 << 2)
     509 +MCSM1_RXOFF_MODE_RX = (0x03 << 2)
     510 +MCSM1_RXOFF_MODE_TX = (0x02 << 2)
     511 +MCSM1_TXOFF_MODE = 0x03
     512 +MCSM1_TXOFF_MODE0 = 0x01
     513 +MCSM1_TXOFF_MODE1 = 0x02
     514 +MCSM1_TXOFF_MODE_FSTXON = (0x01 << 0)
     515 +MCSM1_TXOFF_MODE_IDLE = (0x00 << 0)
     516 +MCSM1_TXOFF_MODE_RX = (0x03 << 0)
     517 +MCSM1_TXOFF_MODE_TX = (0x02 << 0)
     518 +MCSM2 = 0xDF12
     519 +MCSM2_RX_TIME = 0x07
     520 +MCSM2_RX_TIME_QUAL = 0x08
     521 +MCSM2_RX_TIME_RSSI = 0x10
     522 +MDMCFG0 = 0xDF10
     523 +MDMCFG1 = 0xDF0F
     524 +MDMCFG1_CHANSPC_E = 0x03
     525 +MDMCFG2 = 0xDF0E
     526 +MDMCFG2_DEM_DCFILT_OFF = 0x80
     527 +MDMCFG2_MANCHESTER_EN = 0x08
     528 +MDMCFG2_MOD_FORMAT = 0x70
     529 +MDMCFG2_MOD_FORMAT0 = 0x10
     530 +MDMCFG2_MOD_FORMAT1 = 0x20
     531 +MDMCFG2_MOD_FORMAT2 = 0x40
     532 +MDMCFG2_SYNC_MODE = 0x07
     533 +MDMCFG2_SYNC_MODE0 = 0x01
     534 +MDMCFG2_SYNC_MODE1 = 0x02
     535 +MDMCFG2_SYNC_MODE2 = 0x04
     536 +MDMCFG3 = 0xDF0D
     537 +MDMCFG4 = 0xDF0C
     538 +MDMCFG4_CHANBW_E = 0xC0
     539 +MDMCFG4_CHANBW_M = 0x30
     540 +MDMCFG4_DRATE_E = 0x0F
     541 +MFMCFG1_CHANSPC_E = 0x03
     542 +MFMCFG1_CHANSPC_E0 = 0x01
     543 +MFMCFG1_CHANSPC_E1 = 0x02
     544 +MFMCFG1_FEC_EN = 0x80
     545 +MFMCFG1_NUM_PREAMBLE = 0x70
     546 +MFMCFG1_NUM_PREAMBLE0 = 0x10
     547 +MFMCFG1_NUM_PREAMBLE1 = 0x20
     548 +MFMCFG1_NUM_PREAMBLE2 = 0x40
     549 +MFMCFG1_NUM_PREAMBLE_12 = (0x05 << 4)
     550 +MFMCFG1_NUM_PREAMBLE_16 = (0x06 << 4)
     551 +MFMCFG1_NUM_PREAMBLE_2 = (0x00 << 4)
     552 +MFMCFG1_NUM_PREAMBLE_24 = (0x07 << 4)
     553 +MFMCFG1_NUM_PREAMBLE_3 = (0x01 << 4)
     554 +MFMCFG1_NUM_PREAMBLE_4 = (0x02 << 4)
     555 +MFMCFG1_NUM_PREAMBLE_6 = (0x03 << 4)
     556 +MFMCFG1_NUM_PREAMBLE_8 = (0x04 << 4)
     557 +MDMCTRL0H = 0xDF02
     558 +MEMCTR = 0xC7
     559 +MEMCTR_CACHD = 0x02
     560 +MEMCTR_PREFD = 0x01
     561 +MODE = 128
     562 +MOD_FORMAT_2_FSK = (0x00 << 4)
     563 +MOD_FORMAT_GFSK = (0x01 << 4)
     564 +MOD_FORMAT_MSK = (0x07 << 4)
     565 +MPAGE = 0x93
     566 +OV = 4
     567 +OVFIM = 64
     568 +P = 1
     569 +P0 = 0x80
     570 +P0DIR = 0xFD
     571 +P0IE = 32
     572 +P0IF = 32
     573 +P0IFG = 0x89
     574 +P0IFG_USB_RESUME = 0x80 #rw0
     575 +P0INP = 0x8F
     576 +P0INT_VECTOR = 13 # Port 0 Inputs
     577 +P0SEL = 0xF3
     578 +P0_0 = 1
     579 +P0_1 = 2
     580 +P0_2 = 4
     581 +P0_3 = 8
     582 +P0_4 = 16
     583 +P0_5 = 32
     584 +P0_6 = 64
     585 +P0_7 = 128
     586 +P1 = 0x90
     587 +P1DIR = 0xFE
     588 +P1IEN = 0x8D
     589 +P1IF = 8
     590 +P1IFG = 0x8A
     591 +P1INP = 0xF6
     592 +P1INT_VECTOR = 15 # Port 1 Inputs
     593 +P1SEL = 0xF4
     594 +P1_0 = 1
     595 +P1_1 = 2
     596 +P1_2 = 4
     597 +P1_3 = 8
     598 +P1_4 = 16
     599 +P1_5 = 32
     600 +P1_6 = 64
     601 +P1_7 = 128
     602 +P2 = 0xA0
     603 +P2DIR = 0xFF
     604 +P2DIR_0PRIP0 = 0x40
     605 +P2DIR_1PRIP0 = 0x80
     606 +P2DIR_DIRP2 = 0x1F
     607 +P2DIR_DIRP2_0 = (0x01)
     608 +P2DIR_DIRP2_1 = (0x02)
     609 +P2DIR_DIRP2_2 = (0x04)
     610 +P2DIR_DIRP2_3 = (0x08)
     611 +P2DIR_DIRP2_4 = (0x10)
     612 +P2DIR_PRIP0 = 0xC0
     613 +P2DIR_PRIP0_0 = (0x00 << 6)
     614 +P2DIR_PRIP0_1 = (0x01 << 6)
     615 +P2DIR_PRIP0_2 = (0x02 << 6)
     616 +P2DIR_PRIP0_3 = (0x03 << 6)
     617 +P2IF = 1
     618 +P2IFG = 0x8B
     619 +P2INP = 0xF7
     620 +P2INP_MDP2 = 0x1F
     621 +P2INP_MDP2_0 = (0x01)
     622 +P2INP_MDP2_1 = (0x02)
     623 +P2INP_MDP2_2 = (0x04)
     624 +P2INP_MDP2_3 = (0x08)
     625 +P2INP_MDP2_4 = (0x10)
     626 +P2INP_PDUP0 = 0x20
     627 +P2INP_PDUP1 = 0x40
     628 +P2INP_PDUP2 = 0x80
     629 +P2INT_VECTOR = 6 # Port 2 Inputs
     630 +P2SEL = 0xF5
     631 +P2SEL_PRI0P1 = 0x08
     632 +P2SEL_PRI1P1 = 0x10
     633 +P2SEL_PRI2P1 = 0x20
     634 +P2SEL_PRI3P1 = 0x40
     635 +P2SEL_SELP2_0 = 0x01
     636 +P2SEL_SELP2_3 = 0x02
     637 +P2SEL_SELP2_4 = 0x04
     638 +P2_0 = 1
     639 +P2_1 = 2
     640 +P2_2 = 4
     641 +P2_3 = 8
     642 +P2_4 = 16
     643 +P2_5 = 32
     644 +P2_6 = 64
     645 +P2_7 = 128
     646 +PARTNUM = 0xDF36
     647 +PA_TABLE0 = 0xDF2E
     648 +PA_TABLE1 = 0xDF2D
     649 +PA_TABLE2 = 0xDF2C
     650 +PA_TABLE3 = 0xDF2B
     651 +PA_TABLE4 = 0xDF2A
     652 +PA_TABLE5 = 0xDF29
     653 +PA_TABLE6 = 0xDF28
     654 +PA_TABLE7 = 0xDF27
     655 +PCON = 0x87
     656 +PCON_IDLE = 0x01
     657 +PERCFG = 0xF1
     658 +PERCFG_T1CFG = 0x40
     659 +PERCFG_T3CFG = 0x20
     660 +PERCFG_T4CFG = 0x10
     661 +PERCFG_U0CFG = 0x01
     662 +PERCFG_U1CFG = 0x02
     663 +PICTL = 0x8C
     664 +PICTL_P0ICON = 0x01
     665 +PICTL_P0IENH = 0x10
     666 +PICTL_P0IENL = 0x08
     667 +PICTL_P1ICON = 0x02
     668 +PICTL_P2ICON = 0x04
     669 +PICTL_P2IEN = 0x20
     670 +PICTL_PADSC = 0x40
     671 +PKTCTRL0 = 0xDF04
     672 +PKTCTRL0_CC2400_EN = 0x08
     673 +PKTCTRL0_CRC_EN = 0x04
     674 +PKTCTRL0_LENGTH_CONFIG = 0x03
     675 +PKTCTRL0_LENGTH_CONFIG0 = 0x01
     676 +PKTCTRL0_LENGTH_CONFIG_FIX = (0x00)
     677 +PKTCTRL0_LENGTH_CONFIG_VAR = (0x01)
     678 +PKTCTRL0_PKT_FORMAT = 0x30
     679 +PKTCTRL0_PKT_FORMAT0 = 0x10
     680 +PKTCTRL0_PKT_FORMAT1 = 0x20
     681 +PKTCTRL0_WHITE_DATA = 0x40
     682 +PKTCTRL1 = 0xDF03
     683 +PKTCTRL1_ADR_CHK = 0x03
     684 +PKTCTRL1_ADR_CHK0 = 0x01
     685 +PKTCTRL1_ADR_CHK1 = 0x02
     686 +PKTCTRL1_APPEND_STATUS = 0x04
     687 +PKTCTRL1_PQT = 0xE0
     688 +PKTCTRL1_PQT0 = 0x20
     689 +PKTCTRL1_PQT1 = 0x40
     690 +PKTCTRL1_PQT2 = 0x80
     691 +PKTLEN = 0xDF02
     692 +PKTSTATUS = 0xDF3C
     693 +PKT_FORMAT_NORM = (0x00)
     694 +PKT_FORMAT_RAND = (0x02)
     695 +PSW = 0xD0
     696 +RE = 64
     697 +RFD = 0xD9
     698 +RFIF = 0xE9
     699 +RFIF_IRQ_CCA = 0x02
     700 +RFIF_IRQ_CS = 0x08
     701 +RFIF_IRQ_DONE = 0x10
     702 +RFIF_IRQ_PQT = 0x04
     703 +RFIF_IRQ_RXOVF = 0x40
     704 +RFIF_IRQ_SFD = 0x01
     705 +RFIF_IRQ_TIMEOUT = 0x20
     706 +RFIF_IRQ_TXUNF = 0x80
     707 +RFIM = 0x91
     708 +RFIM_IM_CCA = 0x02
     709 +RFIM_IM_CS = 0x08
     710 +RFIM_IM_DONE = 0x10
     711 +RFIM_IM_PQT = 0x04
     712 +RFIM_IM_RXOVF = 0x40
     713 +RFIM_IM_SFD = 0x01
     714 +RFIM_IM_TIMEOUT = 0x20
     715 +RFIM_IM_TXUNF = 0x80
     716 +RFST = 0xE1
     717 +RFST_SCAL = 0x01
     718 +RFST_SFSTXON = 0x00
     719 +RFST_SIDLE = 0x04
     720 +RFST_SNOP = 0x05
     721 +RFST_SRX = 0x02
     722 +RFST_STX = 0x03
     723 +RFTXRXIE = 1
     724 +RFTXRXIF = 2
     725 +RFTXRX_VECTOR = 0 # RF TX done / RX ready
     726 +RF_VECTOR = 16 # RF General Interrupts
     727 +RNDH = 0xBD
     728 +RNDL = 0xBC
     729 +RS0 = 8
     730 +RS1 = 16
     731 +RSSI = 0xDF3A
     732 +RX_BYTE = 4
     733 +S0CON = 0x98
     734 +S1CON = 0x9B
     735 +S1CON_RFIF_0 = 0x01
     736 +S1CON_RFIF_1 = 0x02
     737 +SLAVE = 32
     738 +SLEEP = 0xBE
     739 +SLEEP_HFRC_S = 0x20
     740 +SLEEP_MODE = 0x03
     741 +SLEEP_MODE0 = 0x01
     742 +SLEEP_MODE1 = 0x02
     743 +SLEEP_MODE_PM0 = (0x00)
     744 +SLEEP_MODE_PM1 = (0x01)
     745 +SLEEP_MODE_PM2 = (0x02)
     746 +SLEEP_MODE_PM3 = (0x03)
     747 +SLEEP_OSC_PD = 0x04
     748 +SLEEP_RST = 0x18
     749 +SLEEP_RST0 = 0x08
     750 +SLEEP_RST1 = 0x10
     751 +SLEEP_RST_EXT = (0x01 << 3)
     752 +SLEEP_RST_POR_BOD = (0x00 << 3)
     753 +SLEEP_RST_WDT = (0x02 << 3)
     754 +SLEEP_USB_EN = 0x80
     755 +SLEEP_XOSC_S = 0x40
     756 +SP = 0x81
     757 +STIE = 32
     758 +STIF = 128
     759 +STSEL_FULL_SPEED = (0x01 << 4)
     760 +STSEL_P2_0 = (0x00 << 4)
     761 +STSEL_ST = (0x03 << 4)
     762 +STSEL_T1C0_CMP_EVT = (0x02 << 4)
     763 +ST_VECTOR = 5 # Sleep Timer Compare
     764 +SYNC0 = 0xDF01
     765 +SYNC1 = 0xDF00
     766 +SYNC_MODE_15_16 = (0x01)
     767 +SYNC_MODE_15_16_CS = (0x05)
     768 +SYNC_MODE_16_16 = (0x02)
     769 +SYNC_MODE_16_16_CS = (0x06)
     770 +SYNC_MODE_30_32 = (0x03)
     771 +SYNC_MODE_30_32_CS = (0x07)
     772 +SYNC_MODE_NO_PRE = (0x00)
     773 +SYNC_MODE_NO_PRE_CS = (0x04) # CS = carrier-sense above threshold
     774 +T1C0_BOTH_EDGE = (0x03) # Capture on both edges
     775 +T1C0_CLR_CMP_UP_SET_0 = (0x04 << 3) # Set output on compare
     776 +T1C0_CLR_ON_CMP = (0x01 << 3) # Set output on compare-up clear on 0
     777 +T1C0_FALL_EDGE = (0x02) # Capture on falling edge
     778 +T1C0_NO_CAP = (0x00) # No capture
     779 +T1C0_RISE_EDGE = (0x01) # Capture on rising edge
     780 +T1C0_SET_CMP_UP_CLR_0 = (0x03 << 3) # Clear output on compare
     781 +T1C0_SET_ON_CMP = (0x00 << 3) # Clear output on compare-up set on 0
     782 +T1C0_TOG_ON_CMP = (0x02 << 3) # Toggle output on compare
     783 +T1C1_BOTH_EDGE = (0x03) # Capture on both edges
     784 +T1C1_CLR_C1_SET_C0 = (0x06 << 3) # Clear when equal to T1CC1, set when equal to T1CC0
     785 +T1C1_CLR_CMP_UP_SET_0 = (0x04 << 3) # Clear output on compare-up set on 0
     786 +T1C1_CLR_ON_CMP = (0x01 << 3) # Clear output on compare
     787 +T1C1_DSM_MODE = (0x07 << 3) # DSM mode
     788 +T1C1_FALL_EDGE = (0x02) # Capture on falling edge
     789 +T1C1_NO_CAP = (0x00) # No capture
     790 +T1C1_RISE_EDGE = (0x01) # Capture on rising edge
     791 +T1C1_SET_C1_CLR_C0 = (0x05 << 3) # Set when equal to T1CC1, clear when equal to T1CC0
     792 +T1C1_SET_CMP_UP_CLR_0 = (0x03 << 3) # Set output on compare-up clear on 0
     793 +T1C1_SET_ON_CMP = (0x00 << 3) # Set output on compare
     794 +T1C1_TOG_ON_CMP = (0x02 << 3) # Toggle output on compare
     795 +T1C2_BOTH_EDGE = (0x03) # Capture on both edges
     796 +T1C2_CLR_C2_SET_C0 = (0x06 << 3) # Clear when equal to T1CC2, set when equal to T1CC0
     797 +T1C2_CLR_CMP_UP_SET_0 = (0x04 << 3) # Clear output on compare-up set on 0
     798 +T1C2_CLR_ON_CMP = (0x01 << 3) # Clear output on compare
     799 +T1C2_FALL_EDGE = (0x02) # Capture on falling edge
     800 +T1C2_NO_CAP = (0x00) # No capture
     801 +T1C2_RISE_EDGE = (0x01) # Capture on rising edge
     802 +T1C2_SET_C2_CLR_C0 = (0x05 << 3) # Set when equal to T1CC2, clear when equal to T1CC0
     803 +T1C2_SET_CMP_UP_CLR_0 = (0x03 << 3) # Set output on compare-up clear on 0
     804 +T1C2_SET_ON_CMP = (0x00 << 3) # Set output on compare
     805 +T1C2_TOG_ON_CMP = (0x02 << 3) # Toggle output on compare
     806 +T1CC0H = 0xDB
     807 +T1CC0L = 0xDA
     808 +T1CC1H = 0xDD
     809 +T1CC1L = 0xDC
     810 +T1CC2H = 0xDF
     811 +T1CC2L = 0xDE
     812 +T1CCTL0 = 0xE5
     813 +T1CCTL0_CAP = 0x03
     814 +T1CCTL0_CAP0 = 0x01
     815 +T1CCTL0_CAP1 = 0x02
     816 +T1CCTL0_CMP = 0x38
     817 +T1CCTL0_CMP0 = 0x08
     818 +T1CCTL0_CMP1 = 0x10
     819 +T1CCTL0_CMP2 = 0x20
     820 +T1CCTL0_CPSEL = 0x80 # Timer 1 channel 0 capture select
     821 +T1CCTL0_IM = 0x40 # Channel 0 Interrupt mask
     822 +T1CCTL0_MODE = 0x04 # Capture or compare mode
     823 +T1CCTL1 = 0xE6
     824 +T1CCTL1_CAP = 0x03
     825 +T1CCTL1_CAP0 = 0x01
     826 +T1CCTL1_CAP1 = 0x02
     827 +T1CCTL1_CMP = 0x38
     828 +T1CCTL1_CMP0 = 0x08
     829 +T1CCTL1_CMP1 = 0x10
     830 +T1CCTL1_CMP2 = 0x20
     831 +T1CCTL1_CPSEL = 0x80 # Timer 1 channel 1 capture select
     832 +T1CCTL1_DSM_SPD = 0x04
     833 +T1CCTL1_IM = 0x40 # Channel 1 Interrupt mask
     834 +T1CCTL1_MODE = 0x04 # Capture or compare mode
     835 +T1CCTL2 = 0xE7
     836 +T1CCTL2_CAP = 0x03
     837 +T1CCTL2_CAP0 = 0x01
     838 +T1CCTL2_CAP1 = 0x02
     839 +T1CCTL2_CMP = 0x38
     840 +T1CCTL2_CMP0 = 0x08
     841 +T1CCTL2_CMP1 = 0x10
     842 +T1CCTL2_CMP2 = 0x20
     843 +T1CCTL2_CPSEL = 0x80 # Timer 1 channel 2 capture select
     844 +T1CCTL2_IM = 0x40 # Channel 2 Interrupt mask
     845 +T1CCTL2_MODE = 0x04 # Capture or compare mode
     846 +T1CNTH = 0xE3
     847 +T1CNTL = 0xE2
     848 +T1CTL = 0xE4
     849 +T1CTL_CH0IF = 0x20 # Timer 1 channel 0 interrupt flag
     850 +T1CTL_CH1IF = 0x40 # Timer 1 channel 1 interrupt flag
     851 +T1CTL_CH2IF = 0x80 # Timer 1 channel 2 interrupt flag
     852 +T1CTL_DIV = 0x0C
     853 +T1CTL_DIV0 = 0x04
     854 +T1CTL_DIV1 = 0x08
     855 +T1CTL_DIV_1 = (0x00 << 2) # Divide tick frequency by 1
     856 +T1CTL_DIV_128 = (0x03 << 2) # Divide tick frequency by 128
     857 +T1CTL_DIV_32 = (0x02 << 2) # Divide tick frequency by 32
     858 +T1CTL_DIV_8 = (0x01 << 2) # Divide tick frequency by 8
     859 +T1CTL_MODE = 0x03
     860 +T1CTL_MODE0 = 0x01
     861 +T1CTL_MODE1 = 0x02
     862 +T1CTL_MODE_FREERUN = (0x01) # Free Running mode
     863 +T1CTL_MODE_MODULO = (0x02) # Modulo
     864 +T1CTL_MODE_SUSPEND = (0x00) # Operation is suspended (halt)
     865 +T1CTL_MODE_UPDOWN = (0x03) # Up/down
     866 +T1CTL_OVFIF = 0x10 # Timer 1 counter overflow interrupt flag
     867 +T1IE = 2
     868 +T1IF = 2
     869 +T1_VECTOR = 9 # Timer 1 (16-bit) Capture/Compare/Overflow
     870 +T2CT = 0x9C
     871 +T2CTL = 0x9E
     872 +T2CTL_INT = 0x10 # Enable Timer 2 interrupt
     873 +T2CTL_TEX = 0x40
     874 +T2CTL_TIG = 0x04 # Tick generator mode
     875 +T2CTL_TIP = 0x03
     876 +T2CTL_TIP0 = 0x01
     877 +T2CTL_TIP1 = 0x02
     878 +T2CTL_TIP_1024 = (0x03)
     879 +T2CTL_TIP_128 = (0x01)
     880 +T2CTL_TIP_256 = (0x02)
     881 +T2CTL_TIP_64 = (0x00)
     882 +T2IE = 4
     883 +T2IF = 4
     884 +T2PR = 0x9D
     885 +T2_VECTOR = 10 # Timer 2 (MAC Timer) Overflow
     886 +T3C0_CLR_CMP_SET_0 = (0x06 << 3) # Clear when equal to T3CC0, set on 0
     887 +T3C0_CLR_CMP_UP_SET_0 = (0x04 << 3) # Clear output on compare-up set on 0
     888 +T3C0_CLR_ON_CMP = (0x01 << 3) # Clear output on compare
     889 +T3C0_SET_CMP_CLR_255 = (0x05 << 3) # Set when equal to T3CC0, clear on 255
     890 +T3C0_SET_CMP_UP_CLR_0 = (0x03 << 3) # Set output on compare-up clear on 0
     891 +T3C0_SET_ON_CMP = (0x00 << 3) # Set output on compare
     892 +T3C0_TOG_ON_CMP = (0x02 << 3) # Toggle output on compare
     893 +T3C1_CLR_CMP_SET_C0 = (0x06 << 3) # Clear when equal to T3CC1, set when equal to T3CC0
     894 +T3C1_CLR_CMP_UP_SET_0 = (0x04 << 3) # Clear output on compare-up set on 0
     895 +T3C1_CLR_ON_CMP = (0x01 << 3) # Clear output on compare
     896 +T3C1_SET_CMP_CLR_C0 = (0x05 << 3) # Set when equal to T3CC1, clear when equal to T3CC0
     897 +T3C1_SET_CMP_UP_CLR_0 = (0x03 << 3) # Set output on compare-up clear on 0
     898 +T3C1_SET_ON_CMP = (0x00 << 3) # Set output on compare
     899 +T3C1_TOG_ON_CMP = (0x02 << 3) # Toggle output on compare
     900 +T3CC0 = 0xCD
     901 +T3CC1 = 0xCF
     902 +T3CCTL0 = 0xCC
     903 +T3CCTL0_CMP = 0x38
     904 +T3CCTL0_CMP0 = 0x08
     905 +T3CCTL0_CMP1 = 0x10
     906 +T3CCTL0_CMP2 = 0x20
     907 +T3CCTL0_IM = 0x40
     908 +T3CCTL0_MODE = 0x04
     909 +T3CCTL1 = 0xCE
     910 +T3CCTL1_CMP = 0x38
     911 +T3CCTL1_CMP0 = 0x08
     912 +T3CCTL1_CMP1 = 0x10
     913 +T3CCTL1_CMP2 = 0x20
     914 +T3CCTL1_IM = 0x40
     915 +T3CCTL1_MODE = 0x04
     916 +T3CH0IF = 2
     917 +T3CH1IF = 4
     918 +T3CNT = 0xCA
     919 +T3CTL = 0xCB
     920 +T3CTL_CLR = 0x04
     921 +T3CTL_DIV = 0xE0
     922 +T3CTL_DIV0 = 0x20
     923 +T3CTL_DIV1 = 0x40
     924 +T3CTL_DIV2 = 0x80
     925 +T3CTL_DIV_1 = (0x00 << 5)
     926 +T3CTL_DIV_128 = (0x07 << 5)
     927 +T3CTL_DIV_16 = (0x04 << 5)
     928 +T3CTL_DIV_2 = (0x01 << 5)
     929 +T3CTL_DIV_32 = (0x05 << 5)
     930 +T3CTL_DIV_4 = (0x02 << 5)
     931 +T3CTL_DIV_64 = (0x06 << 5)
     932 +T3CTL_DIV_8 = (0x03 << 5)
     933 +T3CTL_MODE = 0x03
     934 +T3CTL_MODE0 = 0x01
     935 +T3CTL_MODE1 = 0x02
     936 +T3CTL_MODE_DOWN = (0x01)
     937 +T3CTL_MODE_FREERUN = (0x00)
     938 +T3CTL_MODE_MODULO = (0x02)
     939 +T3CTL_MODE_UPDOWN = (0x03)
     940 +T3CTL_OVFIM = 0x08
     941 +T3CTL_START = 0x10
     942 +T3IE = 8
     943 +T3IF = 8
     944 +T3OVFIF = 1
     945 +T3_VECTOR = 11 # Timer 3 (8-bit) Capture/Compare/Overflow
     946 +T4CC0 = 0xED
     947 +T4CC1 = 0xEF
     948 +T4CCTL0 = 0xEC
     949 +T4CCTL0_CLR_CMP_SET_0 = (0x06 << 3)
     950 +T4CCTL0_CLR_CMP_UP_SET_0 = (0x04 << 3)
     951 +T4CCTL0_CLR_ON_CMP = (0x01 << 3)
     952 +T4CCTL0_CMP = 0x38
     953 +T4CCTL0_CMP0 = 0x08
     954 +T4CCTL0_CMP1 = 0x10
     955 +T4CCTL0_CMP2 = 0x20
     956 +T4CCTL0_IM = 0x40
     957 +T4CCTL0_MODE = 0x04
     958 +T4CCTL0_SET_CMP_CLR_255 = (0x05 << 3)
     959 +T4CCTL0_SET_CMP_UP_CLR_0 = (0x03 << 3)
     960 +T4CCTL0_SET_ON_CMP = (0x00 << 3)
     961 +T4CCTL0_TOG_ON_CMP = (0x02 << 3)
     962 +T4CCTL1 = 0xEE
     963 +T4CCTL1_CLR_CMP_SET_C0 = (0x06 << 3)
     964 +T4CCTL1_CLR_CMP_UP_SET_0 = (0x04 << 3)
     965 +T4CCTL1_CLR_ON_CMP = (0x01 << 3)
     966 +T4CCTL1_CMP = 0x38
     967 +T4CCTL1_CMP0 = 0x08
     968 +T4CCTL1_CMP1 = 0x10
     969 +T4CCTL1_CMP2 = 0x20
     970 +T4CCTL1_IM = 0x40
     971 +T4CCTL1_MODE = 0x04
     972 +T4CCTL1_SET_CMP_CLR_C0 = (0x05 << 3)
     973 +T4CCTL1_SET_CMP_UP_CLR_0 = (0x03 << 3)
     974 +T4CCTL1_SET_ON_CMP = (0x00 << 3)
     975 +T4CCTL1_TOG_ON_CMP = (0x02 << 3)
     976 +T4CH0IF = 16
     977 +T4CH1IF = 32
     978 +T4CNT = 0xEA
     979 +T4CTL = 0xEB
     980 +T4CTL_CLR = 0x04
     981 +T4CTL_DIV = 0xE0
     982 +T4CTL_DIV0 = 0x20
     983 +T4CTL_DIV1 = 0x40
     984 +T4CTL_DIV2 = 0x80
     985 +T4CTL_DIV_1 = (0x00 << 5)
     986 +T4CTL_DIV_128 = (0x07 << 5)
     987 +T4CTL_DIV_16 = (0x04 << 5)
     988 +T4CTL_DIV_2 = (0x01 << 5)
     989 +T4CTL_DIV_32 = (0x05 << 5)
     990 +T4CTL_DIV_4 = (0x02 << 5)
     991 +T4CTL_DIV_64 = (0x06 << 5)
     992 +T4CTL_DIV_8 = (0x03 << 5)
     993 +T4CTL_MODE = 0x03
     994 +T4CTL_MODE0 = 0x01
     995 +T4CTL_MODE1 = 0x02
     996 +T4CTL_MODE_DOWN = (0x01)
     997 +T4CTL_MODE_FREERUN = (0x00)
     998 +T4CTL_MODE_MODULO = (0x02)
     999 +T4CTL_MODE_UPDOWN = (0x03)
     1000 +T4CTL_OVFIM = 0x08
     1001 +T4CTL_START = 0x10
     1002 +T4IE = 16
     1003 +T4IF = 16
     1004 +T4OVFIF = 8
     1005 +T4_VECTOR = 12 # Timer 4 (8-bit) Capture/Compare/Overflow
     1006 +TCON = 0x88
     1007 +TEST0 = 0xDF25
     1008 +TEST1 = 0xDF24
     1009 +TEST2 = 0xDF23
     1010 +TICKSPD_DIV_1 = (0x00 << 3)
     1011 +TICKSPD_DIV_128 = (0x07 << 3)
     1012 +TICKSPD_DIV_16 = (0x04 << 3)
     1013 +TICKSPD_DIV_2 = (0x01 << 3)
     1014 +TICKSPD_DIV_32 = (0x05 << 3)
     1015 +TICKSPD_DIV_4 = (0x02 << 3)
     1016 +TICKSPD_DIV_64 = (0x06 << 3)
     1017 +TICKSPD_DIV_8 = (0x03 << 3)
     1018 +TIMIF = 0xD8
     1019 +TX_BYTE = 2
     1020 +U0BAUD = 0xC2
     1021 +U0CSR = 0x86
     1022 +U0CSR_ACTIVE = 0x01
     1023 +U0CSR_ERR = 0x08
     1024 +U0CSR_FE = 0x10
     1025 +U0CSR_MODE = 0x80
     1026 +U0CSR_RE = 0x40
     1027 +U0CSR_RX_BYTE = 0x04
     1028 +U0CSR_SLAVE = 0x20
     1029 +U0CSR_TX_BYTE = 0x02
     1030 +U0DBUF = 0xC1
     1031 +U0GCR = 0xC5
     1032 +U0GCR_BAUD_E = 0x1F
     1033 +U0GCR_BAUD_E0 = 0x01
     1034 +U0GCR_BAUD_E1 = 0x02
     1035 +U0GCR_BAUD_E2 = 0x04
     1036 +U0GCR_BAUD_E3 = 0x08
     1037 +U0GCR_BAUD_E4 = 0x10
     1038 +U0GCR_CPHA = 0x40
     1039 +U0GCR_CPOL = 0x80
     1040 +U0GCR_ORDER = 0x20
     1041 +U0UCR = 0xC4
     1042 +U0UCR_BIT9 = 0x10
     1043 +U0UCR_D9 = 0x20
     1044 +U0UCR_FLOW = 0x40
     1045 +U0UCR_FLUSH = 0x80
     1046 +U0UCR_PARITY = 0x08
     1047 +U0UCR_SPB = 0x04
     1048 +U0UCR_START = 0x01
     1049 +U0UCR_STOP = 0x02
     1050 +U1BAUD = 0xFA
     1051 +U1CSR = 0xF8
     1052 +U1CSR_ACTIVE = 0x01
     1053 +U1CSR_ERR = 0x08
     1054 +U1CSR_FE = 0x10
     1055 +U1CSR_MODE = 0x80
     1056 +U1CSR_RE = 0x40
     1057 +U1CSR_RX_BYTE = 0x04
     1058 +U1CSR_SLAVE = 0x20
     1059 +U1CSR_TX_BYTE = 0x02
     1060 +U1DBUF = 0xF9
     1061 +U1GCR = 0xFC
     1062 +U1GCR_BAUD_E = 0x1F
     1063 +U1GCR_BAUD_E0 = 0x01
     1064 +U1GCR_BAUD_E1 = 0x02
     1065 +U1GCR_BAUD_E2 = 0x04
     1066 +U1GCR_BAUD_E3 = 0x08
     1067 +U1GCR_BAUD_E4 = 0x10
     1068 +U1GCR_CPHA = 0x40
     1069 +U1GCR_CPOL = 0x80
     1070 +U1GCR_ORDER = 0x20
     1071 +U1UCR = 0xFB
     1072 +U1UCR_BIT9 = 0x10
     1073 +U1UCR_D9 = 0x20
     1074 +U1UCR_FLOW = 0x40
     1075 +U1UCR_FLUSH = 0x80
     1076 +U1UCR_PARITY = 0x08
     1077 +U1UCR_SPB = 0x04
     1078 +U1UCR_START = 0x01
     1079 +U1UCR_STOP = 0x02
     1080 +URX0IE = 4
     1081 +URX0IF = 8
     1082 +URX0_VECTOR = 2 # USART0 RX Complete
     1083 +URX1IE = 8
     1084 +URX1IF = 128
     1085 +URX1_VECTOR = 3 # USART1 RX Complete
     1086 +USBADDR = 0xDE00
     1087 +USBADDR_UPDATE = 0x80 #r
     1088 +USBCIE = 0xDE0B
     1089 +USBCIE_RESUMEIE = 0x02 #rw
     1090 +USBCIE_RSTIE = 0x04 #rw
     1091 +USBCIE_SOFIE = 0x08 #rw
     1092 +USBCIE_SUSPENDIE = 0x01 #rw
     1093 +USBCIF = 0xDE06
     1094 +USBCIF_RESUMEIF = 0x02 #r h0
     1095 +USBCIF_RSTIF = 0x04 #r h0
     1096 +USBCIF_SOFIF = 0x08 #r h0
     1097 +USBCIF_SUSPENDIF = 0x01 #r h0
     1098 +USBCNT0 = 0xDE16
     1099 +USBCNTH = 0xDE17
     1100 +USBCNTL = 0xDE16
     1101 +USBCS0 = 0xDE11
     1102 +USBCS0_CLR_OUTPKT_RDY = 0x40 #rw h0
     1103 +USBCS0_CLR_SETUP_END = 0x80 #rw h0
     1104 +USBCS0_DATA_END = 0x08 #rw h0
     1105 +USBCS0_INPKT_RDY = 0x02 #rw h0
     1106 +USBCS0_OUTPKT_RDY = 0x01 #r
     1107 +USBCS0_SEND_STALL = 0x20 #rw h0
     1108 +USBCS0_SENT_STALL = 0x04 #rw h1
     1109 +USBCS0_SETUP_END = 0x10 #r
     1110 +USBCSIH = 0xDE12
     1111 +USBCSIH_AUTOSET = 0x80 #rw
     1112 +USBCSIH_FORCE_DATA_TOG = 0x08 #rw
     1113 +USBCSIH_IN_DBL_BUF = 0x01 #rw
     1114 +USBCSIH_ISO = 0x40 #rw
     1115 +USBCSIL = 0xDE11
     1116 +USBCSIL_CLR_DATA_TOG = 0x40 #rw h0
     1117 +USBCSIL_FLUSH_PACKET = 0x08 #rw h0
     1118 +USBCSIL_INPKT_RDY = 0x01 #rw h0
     1119 +USBCSIL_PKT_PRESENT = 0x02 #r
     1120 +USBCSIL_SEND_STALL = 0x10 #rw
     1121 +USBCSIL_SENT_STALL = 0x20 #rw
     1122 +USBCSIL_UNDERRUN = 0x04 #rw
     1123 +USBCSOH = 0xDE15
     1124 +USBCSOH_AUTOCLEAR = 0x80 #rw
     1125 +USBCSOH_ISO = 0x40 #rw
     1126 +USBCSOH_OUT_DBL_BUF = 0x01 #rw
     1127 +USBCSOL = 0xDE14
     1128 +USBCSOL_CLR_DATA_TOG = 0x80 #rw h0
     1129 +USBCSOL_DATA_ERROR = 0x08 #r
     1130 +USBCSOL_FIFO_FULL = 0x02 #r
     1131 +USBCSOL_FLUSH_PACKET = 0x10 #rw
     1132 +USBCSOL_OUTPKT_RDY = 0x01 #rw
     1133 +USBCSOL_OVERRUN = 0x04 #rw
     1134 +USBCSOL_SEND_STALL = 0x20 #rw
     1135 +USBCSOL_SENT_STALL = 0x40 #rw
     1136 +USBF0 = 0xDE20
     1137 +USBF1 = 0xDE22
     1138 +USBF2 = 0xDE24
     1139 +USBF3 = 0xDE26
     1140 +USBF4 = 0xDE28
     1141 +USBF5 = 0xDE2A
     1142 +USBFRMH = 0xDE0D
     1143 +USBFRML = 0xDE0C
     1144 +USBIF = 1
     1145 +USBIIE = 0xDE07
     1146 +USBIIE_EP0IE = 0x01 #rw
     1147 +USBIIE_INEP1IE = 0x02 #rw
     1148 +USBIIE_INEP2IE = 0x04 #rw
     1149 +USBIIE_INEP3IE = 0x08 #rw
     1150 +USBIIE_INEP4IE = 0x10 #rw
     1151 +USBIIE_INEP5IE = 0x20 #rw
     1152 +USBIIF = 0xDE02
     1153 +USBIIF_EP0IF = 0x01 #r h0
     1154 +USBIIF_INEP1IF = 0x02 #r h0
     1155 +USBIIF_INEP2IF = 0x04 #r h0
     1156 +USBIIF_INEP3IF = 0x08 #r h0
     1157 +USBIIF_INEP4IF = 0x10 #r h0
     1158 +USBIIF_INEP5IF = 0x20 #r h0
     1159 +USBINDEX = 0xDE0E
     1160 +USBMAXI = 0xDE10
     1161 +USBMAXO = 0xDE13
     1162 +USBOIE = 0xDE09
     1163 +USBOIE_EP1IE = 0x02 #rw
     1164 +USBOIE_EP2IE = 0x04 #rw
     1165 +USBOIE_EP3IE = 0x08 #rw
     1166 +USBOIE_EP4IE = 0x10 #rw
     1167 +USBOIE_EP5IE = 0x20 #rw
     1168 +USBOIF = 0xDE04
     1169 +USBOIF_OUTEP1IF = 0x02 #r h0
     1170 +USBOIF_OUTEP2IF = 0x04 #r h0
     1171 +USBOIF_OUTEP3IF = 0x08 #r h0
     1172 +USBOIF_OUTEP4IF = 0x10 #r h0
     1173 +USBOIF_OUTEP5IF = 0x20 #r h0
     1174 +USBPOW = 0xDE01
     1175 +USBPOW_ISO_WAIT_SOF = 0x80 #rw
     1176 +USBPOW_RESUME = 0x04 #rw
     1177 +USBPOW_RST = 0x08 #r
     1178 +USBPOW_SUSPEND = 0x02 #r
     1179 +USBPOW_SUSPEND_EN = 0x01 #rw
     1180 +USB_BM_REQTYPE_DIRMASK = 0x80
     1181 +USB_BM_REQTYPE_DIR_IN = 0x80
     1182 +USB_BM_REQTYPE_DIR_OUT = 0x00
     1183 +USB_BM_REQTYPE_TGTMASK = 0x1f
     1184 +USB_BM_REQTYPE_TGT_DEV = 0x00
     1185 +USB_BM_REQTYPE_TGT_EP = 0x02
     1186 +USB_BM_REQTYPE_TGT_INTF = 0x01
     1187 +USB_BM_REQTYPE_TYPEMASK = 0x60
     1188 +USB_BM_REQTYPE_TYPE_CLASS = 0x20
     1189 +USB_BM_REQTYPE_TYPE_RESERVED = 0x60
     1190 +USB_BM_REQTYPE_TYPE_STD = 0x00
     1191 +USB_BM_REQTYPE_TYPE_VENDOR = 0x40
     1192 +USB_CLEAR_FEATURE = 0x01
     1193 +USB_DESC_CONFIG = 0x02
     1194 +USB_DESC_DEVICE = 0x01
     1195 +USB_DESC_ENDPOINT = 0x05
     1196 +USB_DESC_INTERFACE = 0x04
     1197 +USB_DESC_STRING = 0x03
     1198 +USB_ENABLE_PIN = P1_0
     1199 +USB_GET_CONFIGURATION = 0x08
     1200 +USB_GET_DESCRIPTOR = 0x06
     1201 +USB_GET_INTERFACE = 0x0a
     1202 +USB_GET_STATUS = 0x00
     1203 +USB_SET_ADDRESS = 0x05
     1204 +USB_SET_CONFIGURATION = 0x09
     1205 +USB_SET_DESCRIPTOR = 0x07
     1206 +USB_SET_FEATURE = 0x03
     1207 +USB_SET_INTERFACE = 0x11
     1208 +USB_STATE_BLINK = 0xff
     1209 +USB_STATE_IDLE = 0
     1210 +USB_STATE_RESET = 3
     1211 +USB_STATE_RESUME = 2
     1212 +USB_STATE_SUSPEND = 1
     1213 +USB_STATE_WAIT_ADDR = 4
     1214 +USB_SYNCH_FRAME = 0x12
     1215 +UTX0IF = 2
     1216 +UTX0_VECTOR = 7 # USART0 TX Complete
     1217 +UTX1IF = 4
     1218 +UTX1_VECTOR = 14 # USART1 TX Complete
     1219 +VCO_VC_DAC = 0xDF3D
     1220 +VERSION = 0xDF37
     1221 +WDCTL = 0xC9
     1222 +WDCTL_CLR = 0xF0
     1223 +WDCTL_CLR0 = 0x10
     1224 +WDCTL_CLR1 = 0x20
     1225 +WDCTL_CLR2 = 0x40
     1226 +WDCTL_CLR3 = 0x80
     1227 +WDCTL_EN = 0x08
     1228 +WDCTL_INT = 0x03
     1229 +WDCTL_INT0 = 0x01
     1230 +WDCTL_INT1 = 0x02
     1231 +WDCTL_INT1_MSEC_250 = (0x01)
     1232 +WDCTL_INT2_MSEC_15 = (0x02)
     1233 +WDCTL_INT3_MSEC_2 = (0x03)
     1234 +WDCTL_INT_SEC_1 = (0x00)
     1235 +WDCTL_MODE = 0x04
     1236 +WDTIF = 16
     1237 +WDT_VECTOR = 17 # Watchdog Overflow in Timer Mode
     1238 +WORCTL_WOR_RES = 0x03
     1239 +WORCTL_WOR_RES0 = 0x01
     1240 +WORCTL_WOR_RES1 = 0x02
     1241 +WORCTL_WOR_RESET = 0x04
     1242 +WORCTL_WOR_RES_1 = (0x00)
     1243 +WORCTL_WOR_RES_1024 = (0x02)
     1244 +WORCTL_WOR_RES_32 = (0x01)
     1245 +WORCTL_WOR_RES_32768 = (0x03)
     1246 +WORCTRL = 0xA2
     1247 +WOREVT0 = 0xA3
     1248 +WOREVT1 = 0xA4
     1249 +WORIRQ = 0xA1
     1250 +WORIRQ_EVENT0_FLAG = 0x01
     1251 +WORIRQ_EVENT0_MASK = 0x10
     1252 +WORTIME0 = 0xA5
     1253 +WORTIME1 = 0xA6
     1254 +X_ADCCFG = 0xDFF2
     1255 +X_ADCCON1 = 0xDFB4
     1256 +X_ADCCON2 = 0xDFB5
     1257 +X_ADCCON3 = 0xDFB6
     1258 +X_ADCH = 0xDFBB
     1259 +X_ADCL = 0xDFBA
     1260 +X_CLKCON = 0xDFC6
     1261 +X_DMA0CFGH = 0xDFD5
     1262 +X_DMA0CFGL = 0xDFD4
     1263 +X_DMA1CFGH = 0xDFD3
     1264 +X_DMA1CFGL = 0xDFD2
     1265 +X_DMAARM = 0xDFD6
     1266 +X_DMAIRQ = 0xDFD1
     1267 +X_DMAREQ = 0xDFD7
     1268 +X_ENCCS = 0xDFB3
     1269 +X_ENCDI = 0xDFB1
     1270 +X_ENCDO = 0xDFB2
     1271 +X_FADDRH = 0xDFAD
     1272 +X_FADDRL = 0xDFAC
     1273 +X_FCTL = 0xDFAE
     1274 +X_FWDATA = 0xDFAF
     1275 +X_FWT = 0xDFAB
     1276 +X_MEMCTR = 0xDFC7
     1277 +X_MPAGE = 0xDF93
     1278 +X_P0DIR = 0xDFFD
     1279 +X_P0IFG = 0xDF89
     1280 +X_P0INP = 0xDF8F
     1281 +X_P0SEL = 0xDFF3
     1282 +X_P1DIR = 0xDFFE
     1283 +X_P1IEN = 0xDF8D
     1284 +X_P1IFG = 0xDF8A
     1285 +X_P1INP = 0xDFF6
     1286 +X_P1SEL = 0xDFF4
     1287 +X_P2DIR = 0xDFFF
     1288 +X_P2IFG = 0xDF8B
     1289 +X_P2INP = 0xDFF7
     1290 +X_P2SEL = 0xDFF5
     1291 +X_PERCFG = 0xDFF1
     1292 +X_PICTL = 0xDF8C
     1293 +X_RFD = 0xDFD9
     1294 +X_RFIF = 0xDFE9
     1295 +X_RFIM = 0xDF91
     1296 +X_RFST = 0xDFE1
     1297 +X_RNDH = 0xDFBD
     1298 +X_RNDL = 0xDFBC
     1299 +X_SLEEP = 0xDFBE
     1300 +X_T1CC0H = 0xDFDB
     1301 +X_T1CC0L = 0xDFDA
     1302 +X_T1CC1H = 0xDFDD
     1303 +X_T1CC1L = 0xDFDC
     1304 +X_T1CC2H = 0xDFDF
     1305 +X_T1CC2L = 0xDFDE
     1306 +X_T1CCTL0 = 0xDFE5
     1307 +X_T1CCTL1 = 0xDFE6
     1308 +X_T1CCTL2 = 0xDFE7
     1309 +X_T1CNTH = 0xDFE3
     1310 +X_T1CNTL = 0xDFE2
     1311 +X_T1CTL = 0xDFE4
     1312 +X_T2CT = 0xDF9C
     1313 +X_T2CTL = 0xDF9E
     1314 +X_T2PR = 0xDF9D
     1315 +X_T3CC0 = 0xDFCD
     1316 +X_T3CC1 = 0xDFCF
     1317 +X_T3CCTL0 = 0xDFCC
     1318 +X_T3CCTL1 = 0xDFCE
     1319 +X_T3CNT = 0xDFCA
     1320 +X_T3CTL = 0xDFCB
     1321 +X_T4CC0 = 0xDFED
     1322 +X_T4CC1 = 0xDFEF
     1323 +X_T4CCTL0 = 0xDFEC
     1324 +X_T4CCTL1 = 0xDFEE
     1325 +X_T4CNT = 0xDFEA
     1326 +X_T4CTL = 0xDFEB
     1327 +X_TIMIF = 0xDFD8
     1328 +X_U0BAUD = 0xDFC2
     1329 +X_U0CSR = 0xDF86
     1330 +X_U0DBUF = 0xDFC1
     1331 +X_U0GCR = 0xDFC5
     1332 +X_U0UCR = 0xDFC4
     1333 +X_U1BAUD = 0xDFFA
     1334 +X_U1CSR = 0xDFF8
     1335 +X_U1DBUF = 0xDFF9
     1336 +X_U1GCR = 0xDFFC
     1337 +X_U1UCR = 0xDFFB
     1338 +X_WDCTL = 0xDFC9
     1339 +X_WORCTRL = 0xDFA2
     1340 +X_WOREVT0 = 0xDFA3
     1341 +X_WOREVT1 = 0xDFA4
     1342 +X_WORIRQ = 0xDFA1
     1343 +X_WORTIME0 = 0xDFA5
     1344 +X_WORTIME1 = 0xDFA6
     1345 +_NA_ACC = 0xDFE0
     1346 +_NA_B = 0xDFF0
     1347 +_NA_DPH0 = 0xDF83
     1348 +_NA_DPH1 = 0xDF85
     1349 +_NA_DPL0 = 0xDF82
     1350 +_NA_DPL1 = 0xDF84
     1351 +_NA_DPS = 0xDF92
     1352 +_NA_IEN0 = 0xDFA8
     1353 +_NA_IEN1 = 0xDFB8
     1354 +_NA_IEN2 = 0xDF9A
     1355 +_NA_IP0 = 0xDFA9
     1356 +_NA_IP1 = 0xDFB9
     1357 +_NA_IRCON = 0xDFC0
     1358 +_NA_IRCON2 = 0xDFE8
     1359 +_NA_P0 = 0xDF80
     1360 +_NA_P1 = 0xDF90
     1361 +_NA_P2 = 0xDFA0
     1362 +_NA_PCON = 0xDF87
     1363 +_NA_PSW = 0xDFD0
     1364 +_NA_S0CON = 0xDF98
     1365 +_NA_S1CON = 0xDF9B
     1366 +_NA_SP = 0xDF81
     1367 +_NA_TCON = 0xDF88
     1368 +_SFR8E = 0x8E
     1369 +_SFR94 = 0x94
     1370 +_SFR95 = 0x95
     1371 +_SFR96 = 0x96
     1372 +_SFR97 = 0x97
     1373 +_SFR99 = 0x99
     1374 +_SFR9F = 0x9F
     1375 +_SFRA7 = 0xA7
     1376 +_SFRAA = 0xAA
     1377 +_SFRB0 = 0xB0
     1378 +_SFRB7 = 0xB7
     1379 +_SFRBF = 0xBF
     1380 +_SFRC3 = 0xC3
     1381 +_SFRC8 = 0xC8
     1382 +_XPAGE = 0x93
     1383 +_XREGDF20 = 0xDF20
     1384 +_XREGDF21 = 0xDF21
     1385 +_XREGDF22 = 0xDF22
     1386 +_XREGDF26 = 0xDF26
     1387 +_XREGDF32 = 0xDF32
     1388 +_XREGDF33 = 0xDF33
     1389 +_XREGDF34 = 0xDF34
     1390 +_XREGDF35 = 0xDF35
     1391 +_X_SFR8E = 0xDF8E
     1392 +_X_SFR94 = 0xDF94
     1393 +_X_SFR95 = 0xDF95
     1394 +_X_SFR96 = 0xDF96
     1395 +_X_SFR97 = 0xDF97
     1396 +_X_SFR99 = 0xDF99
     1397 +_X_SFR9F = 0xDF9F
     1398 +_X_SFRA7 = 0xDFA7
     1399 +_X_SFRAA = 0xDFAA
     1400 +_X_SFRB0 = 0xDFB0
     1401 +_X_SFRB7 = 0xDFB7
     1402 +_X_SFRBF = 0xDFBF
     1403 +_X_SFRC3 = 0xDFC3
     1404 +_X_SFRC8 = 0xDFC8
     1405 + 
     1406 +# AES co-processor
     1407 +# defines for specifying desired crypto operations.
     1408 +# AES_CRYPTO is in two halves:
     1409 +# upper 4 bits mirror CC1111 mode (ENCCS_MODE_CBC etc.)
     1410 +# lower 4 bits are switches
     1411 +# AES_CRYPTO[7:4] ENCCS_MODE...
     1412 +# AES_CRYPTO[3] OUTBOUND 0 == OFF, 1 == ON
     1413 +# AES_CRYPTO[2] OUTBOUND 0 == Decrypt, 1 == Encrypt
     1414 +# AES_CRYPTO[1] INBOUND 0 == OFF, 1 == ON
     1415 +# AES_CRYPTO[0] INBOUND 0 == Decrypt, 1 == Encrypt
     1416 +# bitfields
     1417 +AES_CRYPTO_MODE = 0xF0
     1418 +AES_CRYPTO_OUT = 0x0C
     1419 +AES_CRYPTO_OUT_ENABLE = 0x08
     1420 +AES_CRYPTO_OUT_ON = (0x01 << 3)
     1421 +AES_CRYPTO_OUT_OFF = (0x00 << 3)
     1422 +AES_CRYPTO_OUT_TYPE = 0x04
     1423 +AES_CRYPTO_OUT_DECRYPT = (0x00 << 2)
     1424 +AES_CRYPTO_OUT_ENCRYPT = (0x01 << 2)
     1425 +AES_CRYPTO_IN = 0x03
     1426 +AES_CRYPTO_IN_ENABLE = 0x02
     1427 +AES_CRYPTO_IN_ON = (0x01 << 1)
     1428 +AES_CRYPTO_IN_OFF = (0x00 << 1)
     1429 +AES_CRYPTO_IN_TYPE = 0x01
     1430 +AES_CRYPTO_IN_DECRYPT = (0x00 << 0)
     1431 +AES_CRYPTO_IN_ENCRYPT = (0x01 << 0)
     1432 +AES_CRYPTO_NONE = 0x00
     1433 +AES_CRYPTO_DEFAULT = (ENCCS_MODE_CBC | AES_CRYPTO_OUT_ON | AES_CRYPTO_OUT_ENCRYPT | AES_CRYPTO_IN_ON | AES_CRYPTO_IN_DECRYPT)
     1434 +# flags
     1435 +AES_DISABLE = 0x00
     1436 +AES_ENABLE = 0x01
     1437 +AES_DECRYPT = 0x00
     1438 +AES_ENCRYPT = 0x01
     1439 + 
     1440 + 
     1441 + 
     1442 +ADCCON1S = {}
     1443 +ADCCON2S = {}
     1444 +ADCCON3S = {}
     1445 +AGCCTRL0S = {}
     1446 +AGCCTRL1S = {}
     1447 +BSCFGS = {}
     1448 +CLKCONS = {}
     1449 +CLKSPDS = {}
     1450 +DEVIATNS = {}
     1451 +IEN0S = {}
     1452 +IEN1S = {}
     1453 +IEN2S = {}
     1454 +IOCFG0S = {}
     1455 +IOCFG1S = {}
     1456 +IOCFG2S = {}
     1457 +MARC_STATES = {}
     1458 +MCSM0S = {}
     1459 +MCSM1S = {}
     1460 +MCSM2S = {}
     1461 +MDMCFG2S = {}
     1462 +PKTCTRL0S = {}
     1463 +PKTCTRL1S = {}
     1464 +RFIFS = {}
     1465 +RFIMS = {}
     1466 + 
     1467 +for key,val in list(globals().items()):
     1468 + if key.startswith("RFIF_"):
     1469 + RFIFS[val] = key
     1470 + elif key.startswith("RFIM_"):
     1471 + RFIMS[val] = key
     1472 + elif key.startswith("ADCCON1_"):
     1473 + ADCCON1S[val] = key
     1474 + elif key.startswith("ADCCON2_"):
     1475 + ADCCON2S[val] = key
     1476 + elif key.startswith("ADCCON3_"):
     1477 + ADCCON3S[val] = key
     1478 + elif key.startswith("AGCCTRL0_"):
     1479 + AGCCTRL0S[val] = key
     1480 + elif key.startswith("AGCCTRL1_"):
     1481 + AGCCTRL1S[val] = key
     1482 + elif key.startswith("BSCFG_"):
     1483 + BSCFGS[val] = key
     1484 + elif key.startswith("CLKCON_"):
     1485 + CLKCONS[val] = key
     1486 + elif key.startswith("CLKSPD_"):
     1487 + CLKSPDS[val] = key
     1488 + elif key.startswith("DEVIATN_"):
     1489 + DEVIATNS[val] = key
     1490 + elif key.startswith("IEN0_"):
     1491 + IEN0S[val] = key
     1492 + elif key.startswith("IEN1_"):
     1493 + IEN1S[val] = key
     1494 + elif key.startswith("IEN2_"):
     1495 + IEN2S[val] = key
     1496 + elif key.startswith("IOCFG0_"):
     1497 + IOCFG0S[val] = key
     1498 + elif key.startswith("IOCFG1_"):
     1499 + IOCFG1S[val] = key
     1500 + elif key.startswith("IOCFG2_"):
     1501 + IOCFG2S[val] = key
     1502 + elif key.startswith("MARC_STATE_"):
     1503 + MARC_STATES[val] = key
     1504 + elif key.startswith("MCSM0_"):
     1505 + MCSM0S[val] = key
     1506 + elif key.startswith("MCSM1_"):
     1507 + MCSM1S[val] = key
     1508 + elif key.startswith("MCSM2_"):
     1509 + MCSM2S[val] = key
     1510 + elif key.startswith("MDMCFG2_"):
     1511 + MDMCFG2S[val] = key
     1512 + elif key.startswith("PKTCTRL0_"):
     1513 + PKTCTRL0S[val] = key
     1514 + elif key.startswith("PKTCTRL1_"):
     1515 + PKTCTRL1S[val] = key
     1516 + 
     1517 + 
     1518 + 
     1519 + 
  • ■ ■ ■ ■ ■ ■
    rflib/const.py
     1 +from .rflib_defs import *
     2 +from .chipcondefs import *
     3 +from .rflib_version import *
     4 + 
     5 +#### supporting chipcon_usb.py
     6 +DEFAULT_USB_TIMEOUT = 1000
     7 + 
     8 +EP_TIMEOUT_IDLE = 400
     9 +EP_TIMEOUT_ACTIVE = 10
     10 + 
     11 +USB_MAX_BLOCK_SIZE = 512
     12 +USB_RX_WAIT = 1000
     13 +USB_TX_WAIT = 10000
     14 + 
     15 +USB_BM_REQTYPE_TGTMASK =0x1f
     16 +USB_BM_REQTYPE_TGT_DEV =0x00
     17 +USB_BM_REQTYPE_TGT_INTF =0x01
     18 +USB_BM_REQTYPE_TGT_EP =0x02
     19 + 
     20 +USB_BM_REQTYPE_TYPEMASK =0x60
     21 +USB_BM_REQTYPE_TYPE_STD =0x00
     22 +USB_BM_REQTYPE_TYPE_CLASS =0x20
     23 +USB_BM_REQTYPE_TYPE_VENDOR =0x40
     24 +USB_BM_REQTYPE_TYPE_RESERVED =0x60
     25 + 
     26 +USB_BM_REQTYPE_DIRMASK =0x80
     27 +USB_BM_REQTYPE_DIR_OUT =0x00
     28 +USB_BM_REQTYPE_DIR_IN =0x80
     29 + 
     30 +USB_GET_STATUS =0x00
     31 +USB_CLEAR_FEATURE =0x01
     32 +USB_SET_FEATURE =0x03
     33 +USB_SET_ADDRESS =0x05
     34 +USB_GET_DESCRIPTOR =0x06
     35 +USB_SET_DESCRIPTOR =0x07
     36 +USB_GET_CONFIGURATION =0x08
     37 +USB_SET_CONFIGURATION =0x09
     38 +USB_GET_INTERFACE =0x0a
     39 +USB_SET_INTERFACE =0x11
     40 +USB_SYNCH_FRAME =0x12
     41 + 
     42 +APP_GENERIC = 0x01
     43 +APP_DEBUG = 0xfe
     44 +APP_SYSTEM = 0xff
     45 + 
     46 + 
     47 +SYS_CMD_PEEK = 0x80
     48 +SYS_CMD_POKE = 0x81
     49 +SYS_CMD_PING = 0x82
     50 +SYS_CMD_STATUS = 0x83
     51 +SYS_CMD_POKE_REG = 0x84
     52 +SYS_CMD_GET_CLOCK = 0x85
     53 +SYS_CMD_BUILDTYPE = 0x86
     54 +SYS_CMD_BOOTLOADER = 0x87
     55 +SYS_CMD_RFMODE = 0x88
     56 +SYS_CMD_COMPILER = 0x89
     57 +SYS_CMD_PARTNUM = 0x8e
     58 +SYS_CMD_RESET = 0x8f
     59 +SYS_CMD_CLEAR_CODES = 0x90
     60 +SYS_CMD_DEVICE_SERIAL_NUMBER = 0x91
     61 +SYS_CMD_LED_MODE = 0x93
     62 + 
     63 +EP0_CMD_GET_DEBUG_CODES = 0x00
     64 +EP0_CMD_GET_ADDRESS = 0x01
     65 +EP0_CMD_POKEX = 0x01
     66 +EP0_CMD_PEEKX = 0x02
     67 +EP0_CMD_PING0 = 0x03
     68 +EP0_CMD_PING1 = 0x04
     69 +EP0_CMD_RESET = 0xfe
     70 + 
     71 + 
     72 +DEBUG_CMD_STRING = 0xf0
     73 +DEBUG_CMD_HEX = 0xf1
     74 +DEBUG_CMD_HEX16 = 0xf2
     75 +DEBUG_CMD_HEX32 = 0xf3
     76 +DEBUG_CMD_INT = 0xf4
     77 + 
     78 +EP5OUT_MAX_PACKET_SIZE = 64
     79 +EP5IN_MAX_PACKET_SIZE = 64
     80 +# EP5OUT_BUFFER_SIZE must match firmware/include/chipcon_usb.h definition
     81 +EP5OUT_BUFFER_SIZE = 516
     82 + 
     83 +LC_USB_INITUSB = 0x2
     84 +LC_MAIN_RFIF = 0xd
     85 +LC_USB_DATA_RESET_RESUME = 0xa
     86 +LC_USB_RESET = 0xb
     87 +LC_USB_EP5OUT = 0xc
     88 +LC_RF_VECTOR = 0x10
     89 +LC_RFTXRX_VECTOR = 0x11
     90 + 
     91 +LCE_USB_EP5_TX_WHILE_INBUF_WRITTEN = 0x1
     92 +LCE_USB_EP0_SENT_STALL = 0x4
     93 +LCE_USB_EP5_OUT_WHILE_OUTBUF_WRITTEN = 0x5
     94 +LCE_USB_EP5_LEN_TOO_BIG = 0x6
     95 +LCE_USB_EP5_GOT_CRAP = 0x7
     96 +LCE_USB_EP5_STALL = 0x8
     97 +LCE_USB_DATA_LEFTOVER_FLAGS = 0x9
     98 +LCE_RF_RXOVF = 0x10
     99 +LCE_RF_TXUNF = 0x11
     100 + 
     101 +RCS = {}
     102 +LCS = {}
     103 +LCES = {}
     104 +lcls = locals()
     105 +for lcl in list(lcls.keys()):
     106 + if lcl.startswith("LCE_"):
     107 + LCES[lcl] = lcls[lcl]
     108 + LCES[lcls[lcl]] = lcl
     109 + if lcl.startswith("LC_"):
     110 + LCS[lcl] = lcls[lcl]
     111 + LCS[lcls[lcl]] = lcl
     112 + if lcl.startswith("RC_"):
     113 + RCS[lcl] = lcls[lcl]
     114 + RCS[lcls[lcl]] = lcl
     115 + 
     116 +CHIPS = {
     117 + 0x91: "CC2511",
     118 + 0x81: "CC2510",
     119 + 0x11: "CC1111",
     120 + 0x01: "CC1110",
     121 + 0x40: "FakeDongle",
     122 + }
     123 + 
     124 + 
     125 +#### supporting chipcon_nic.py
     126 +# band limits in Hz
     127 +FREQ_MIN_300 = 281000000
     128 +FREQ_MAX_300 = 361000000
     129 +FREQ_MIN_400 = 378000000
     130 +FREQ_MAX_400 = 481000000
     131 +FREQ_MIN_900 = 749000000
     132 +FREQ_MAX_900 = 962000000
     133 + 
     134 +# band transition points in Hz
     135 +FREQ_EDGE_400 = 369000000
     136 +FREQ_EDGE_900 = 615000000
     137 + 
     138 +# VCO transition points in Hz
     139 +FREQ_MID_300 = 318000000
     140 +FREQ_MID_400 = 424000000
     141 +FREQ_MID_900 = 848000000
     142 + 
     143 +SYNCM_NONE = 0
     144 +SYNCM_15_of_16 = 1
     145 +SYNCM_16_of_16 = 2
     146 +SYNCM_30_of_32 = 3
     147 +SYNCM_CARRIER = 4
     148 +SYNCM_CARRIER_15_of_16 = 5
     149 +SYNCM_CARRIER_16_of_16 = 6
     150 +SYNCM_CARRIER_30_of_32 = 7
     151 + 
     152 +RF_SUCCESS = 0
     153 + 
     154 +RF_MAX_TX_BLOCK = 255
     155 +RF_MAX_TX_CHUNK = 240 # must match MAX_TX_MSGLEN in firmware/include/FHSS.h
     156 + # and be divisible by 16 for crypto operations
     157 +RF_MAX_TX_LONG = 65535
     158 +RF_MAX_RX_BLOCK = 512 # must match BUFFER_SIZE definition in firmware/include/cc1111rf.h
     159 + 
     160 +APP_NIC = 0x42
     161 +APP_SPECAN = 0x43
     162 + 
     163 +NIC_RECV = 0x1
     164 +NIC_XMIT = 0x2
     165 +NIC_SET_ID = 0x3
     166 +NIC_SET_RECV_LARGE = 0x5
     167 +NIC_SET_AES_MODE = 0x6
     168 +NIC_GET_AES_MODE = 0x7
     169 +NIC_SET_AES_IV = 0x8
     170 +NIC_SET_AES_KEY = 0x9
     171 +NIC_SET_AMP_MODE = 0xa
     172 +NIC_GET_AMP_MODE = 0xb
     173 +NIC_LONG_XMIT = 0xc
     174 +NIC_LONG_XMIT_MORE = 0xd
     175 + 
     176 +FHSS_SET_CHANNELS = 0x10
     177 +FHSS_NEXT_CHANNEL = 0x11
     178 +FHSS_CHANGE_CHANNEL = 0x12
     179 +FHSS_SET_MAC_THRESHOLD = 0x13
     180 +FHSS_GET_MAC_THRESHOLD = 0x14
     181 +FHSS_SET_MAC_DATA = 0x15
     182 +FHSS_GET_MAC_DATA = 0x16
     183 +FHSS_XMIT = 0x17
     184 +FHSS_GET_CHANNELS = 0x18
     185 + 
     186 +FHSS_SET_STATE = 0x20
     187 +FHSS_GET_STATE = 0x21
     188 +FHSS_START_SYNC = 0x22
     189 +FHSS_START_HOPPING = 0x23
     190 +FHSS_STOP_HOPPING = 0x24
     191 + 
     192 +FHSS_STATE_NONHOPPING = 0
     193 +FHSS_STATE_DISCOVERY = 1
     194 +FHSS_STATE_SYNCHING = 2
     195 +FHSS_LAST_NONHOPPING_STATE = FHSS_STATE_SYNCHING
     196 + 
     197 +FHSS_STATE_SYNCHED = 3
     198 +FHSS_STATE_SYNC_MASTER = 4
     199 +FHSS_STATE_SYNCINGMASTER = 5
     200 +FHSS_LAST_STATE = 5 # used for testing
     201 + 
     202 + 
     203 +FHSS_STATES = {}
     204 +for key,val in list(globals().items()):
     205 + if key.startswith("FHSS_STATE_"):
     206 + FHSS_STATES[key] = val
     207 + FHSS_STATES[val] = key
     208 +
     209 +""" MODULATIONS
     210 +Note that MSK is only supported for data rates above 26 kBaud and GFSK,
     211 +ASK , and OOK is only supported for data rate up until 250 kBaud. MSK
     212 +cannot be used if Manchester encoding/decoding is enabled.
     213 +"""
     214 +MOD_2FSK = 0x00
     215 +MOD_GFSK = 0x10
     216 +MOD_ASK_OOK = 0x30
     217 +MOD_4FSK = 0x40
     218 +MOD_MSK = 0x70
     219 +MANCHESTER = 0x08
     220 + 
     221 +MODULATIONS = {
     222 + MOD_2FSK : "2FSK",
     223 + MOD_GFSK : "GFSK",
     224 + MOD_4FSK : "4FSK", # note: radio doesn't support Manchester encoding in 4FSK
     225 + MOD_ASK_OOK : "ASK/OOK",
     226 + MOD_MSK : "MSK",
     227 + MOD_2FSK | MANCHESTER : "2FSK/Manchester encoding",
     228 + MOD_GFSK | MANCHESTER : "GFSK/Manchester encoding",
     229 + MOD_ASK_OOK | MANCHESTER : "ASK/OOK/Manchester encoding",
     230 + MOD_MSK | MANCHESTER : "MSK/Manchester encoding",
     231 + }
     232 + 
     233 +SYNCMODES = {
     234 + SYNCM_NONE: "None",
     235 + SYNCM_15_of_16: "15 of 16 bits must match",
     236 + SYNCM_16_of_16: "16 of 16 bits must match",
     237 + SYNCM_30_of_32: "30 of 32 sync bits must match",
     238 + SYNCM_CARRIER: "Carrier Detect",
     239 + SYNCM_CARRIER_15_of_16: "Carrier Detect and 15 of 16 sync bits must match",
     240 + SYNCM_CARRIER_16_of_16: "Carrier Detect and 16 of 16 sync bits must match",
     241 + SYNCM_CARRIER_30_of_32: "Carrier Detect and 30 of 32 sync bits must match",
     242 + }
     243 + 
     244 +BSLIMITS = {
     245 + BSCFG_BS_LIMIT_0: "No data rate offset compensation performed",
     246 + BSCFG_BS_LIMIT_3: "+/- 3.125% data rate offset",
     247 + BSCFG_BS_LIMIT_6: "+/- 6.25% data rate offset",
     248 + BSCFG_BS_LIMIT_12: "+/- 12.5% data rate offset",
     249 + }
     250 + 
     251 +AESMODES = {
     252 + ENCCS_MODE_CBC: "CBC - Cipher Block Chaining",
     253 + ENCCS_MODE_CBCMAC: "CBC-MAC - Cipher Block Chaining Message Authentication Code",
     254 + ENCCS_MODE_CFB: "CFB - Cipher Feedback",
     255 + ENCCS_MODE_CTR: "CTR - Counter",
     256 + ENCCS_MODE_ECB: "ECB - Electronic Codebook",
     257 + ENCCS_MODE_OFB: "OFB - Output Feedback",
     258 + }
     259 + 
     260 +NUM_PREAMBLE = [2, 3, 4, 6, 8, 12, 16, 24 ]
     261 + 
     262 +ADR_CHK_TYPES = [
     263 + "No address check",
     264 + "Address Check, No Broadcast",
     265 + "Address Check, 0x00 is broadcast",
     266 + "Address Check, 0x00 and 0xff are broadcast",
     267 + ]
     268 + 
     269 + 
     270 + 
     271 +PKT_FORMATS = [
     272 + "Normal mode",
     273 + "reserved...",
     274 + "Random TX mode",
     275 + "reserved",
     276 + ]
     277 + 
     278 +LENGTH_CONFIGS = [
     279 + "Fixed Packet Mode",
     280 + "Variable Packet Mode (len=first byte after sync word)",
     281 + "reserved",
     282 + "reserved",
     283 + ]
     284 + 
     285 + 
     286 +# RFST (0xE1) - RF Strobe Commands
     287 +RFST_SFSTXON = 0x00
     288 +RFST_SCAL = 0x01
     289 +RFST_SRX = 0x02
     290 +RFST_STX = 0x03
     291 +RFST_SIDLE = 0x04
     292 +RFST_SNOP = 0x05
     293 + 
     294 +# 0xDF3B: MARCSTATE - Main Radio Control State Machine State
     295 +MARCSTATE_MARC_STATE = 0x1F
     296 + 
     297 +MARC_STATE_SLEEP = 0x00
     298 +MARC_STATE_IDLE = 0x01
     299 +MARC_STATE_VCOON_MC = 0x03
     300 +MARC_STATE_REGON_MC = 0x04
     301 +MARC_STATE_MANCAL = 0x05
     302 +MARC_STATE_VCOON = 0x06
     303 +MARC_STATE_REGON = 0x07
     304 +MARC_STATE_STARTCAL = 0x08
     305 +MARC_STATE_BWBOOST = 0x09
     306 +MARC_STATE_FS_LOCK = 0x0A
     307 +MARC_STATE_IFADCON = 0x0B
     308 +MARC_STATE_ENDCAL = 0x0C
     309 +MARC_STATE_RX = 0x0D
     310 +MARC_STATE_RX_END = 0x0E
     311 +MARC_STATE_RX_RST = 0x0F
     312 +MARC_STATE_TXRX_SWITCH = 0x10
     313 +MARC_STATE_RX_OVERFLOW = 0x11
     314 +MARC_STATE_FSTXON = 0x12
     315 +MARC_STATE_TX = 0x13
     316 +MARC_STATE_TX_END = 0x14
     317 +MARC_STATE_RXTX_SWITCH = 0x15
     318 +MARC_STATE_TX_UNDERFLOW = 0x16
     319 + 
     320 + 
     321 +MARC_STATE_MAPPINGS = [
     322 + (0, 'MARC_STATE_SLEEP', RFST_SIDLE),
     323 + (1, 'MARC_STATE_IDLE', RFST_SIDLE),
     324 + (3, 'MARC_STATE_VCOON_MC', RFST_SIDLE),
     325 + (4, 'MARC_STATE_REGON_MC', RFST_SIDLE),
     326 + (5, 'MARC_STATE_MANCAL', RFST_SCAL),
     327 + (6, 'MARC_STATE_VCOON', RFST_SIDLE),
     328 + (7, 'MARC_STATE_REGON', RFST_SIDLE),
     329 + (8, 'MARC_STATE_STARTCAL', RFST_SCAL),
     330 + (9, 'MARC_STATE_BWBOOST', RFST_SIDLE),
     331 + (10, 'MARC_STATE_FS_LOCK', RFST_SIDLE),
     332 + (11, 'MARC_STATE_IFADCON', RFST_SIDLE),
     333 + (12, 'MARC_STATE_ENDCAL', RFST_SCAL),
     334 + (13, 'MARC_STATE_RX', RFST_SRX),
     335 + (14, 'MARC_STATE_RX_END', RFST_SRX ), # FIXME: this should actually be the config setting in register
     336 + (15, 'MARC_STATE_RX_RST', RFST_SRX),
     337 + (16, 'MARC_STATE_TXRX_SWITCH', RFST_SIDLE),
     338 + (17, 'MARC_STATE_RX_OVERFLOW', RFST_SIDLE),
     339 + (18, 'MARC_STATE_FSTXON', RFST_SFSTXON),
     340 + (19, 'MARC_STATE_TX', RFST_STX),
     341 + (20, 'MARC_STATE_TX_END', RFST_STX), # FIXME: this should actually be the config setting in register
     342 + (21, 'MARC_STATE_RXTX_SWITCH', RFST_SIDLE),
     343 + (22, 'MARC_STATE_TX_UNDERFLOW', RFST_SIDLE) # FIXME: this should actually be the config setting in register
     344 +]
     345 + 
     346 +MODES = {}
     347 +for num,name,rfst in MARC_STATE_MAPPINGS:
     348 + MODES[num] = name
     349 + MODES[name] = num
     350 + 
     351 + 
     352 +T2SETTINGS = {}
     353 +T2SETTINGS_24MHz = {
     354 + 100: (4, 147, 3),
     355 + 150: (5, 110, 3),
     356 + 200: (5, 146, 3),
     357 + 250: (5, 183, 3),
     358 + }
     359 +T2SETTINGS_26MHz = {
     360 + 100: (4, 158, 3),
     361 + 150: (5, 119, 3),
     362 + 200: (5, 158, 3),
     363 + 250: (5, 198, 3),
     364 + }
     365 +
     366 +TIP = (64,128,256,1024)
     367 + 
     368 +CHIPmhz = {
     369 + 0x91: 24,
     370 + 0x81: 26,
     371 + 0x11: 24,
     372 + 0x01: 26,
     373 +}
     374 + 
     375 +# FAKE DONGLE settings. mostly used for unittests.
     376 +FAKE_PARTNUM = 0x40
     377 +FAKE_DEBUG_CODES = (0x41, 0x42)
     378 +FAKE_DONGLE_BUILDDATA = b'DONS BROKEN FAKE DONGLE r0001\0'
     379 +FAKE_DONGLE_COMPILER = b'ATLASv100'
     380 +FAKE_DONGLE_SERIALNUM = b'0x47145'
     381 +FAKE_INTERRUPT_REGISTERS = {
     382 + 'IEN0': b'\xff',
     383 + 'IEN1': b'\x01',
     384 + 'IEN2': b'\xe0',
     385 + 'TCON': b'\xff',
     386 + 'S0CON': b'\x05',
     387 + 'IRCON': b'\x02',
     388 + 'IRCON2': b'\t',
     389 + 'S1CON': b'\x02',
     390 + 'RFIF': b'\x04',
     391 + 'DMAIE': b'\x01',
     392 + 'DMAIF': b'\x01',
     393 + 'DMAIRQ': b'\x10'}
     394 +# initial radio config
     395 +FAKE_MEM_DF00 = b'\x0cN\xff@\x00\x00\x00\x0c\x00%\x95U\xca\xa3\x01#\x116\x07\x0f\x18\x17l\x03@\x91\xb6\x10\xef*+\x1fY??\x881\t\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x11\x03\x12\x80\xaa\r\x90\xfd'
     396 + 
  • ■ ■ ■ ■ ■ ■
    rflib/fakedongle_nic.py
     1 +import rflib
     2 + 
     3 +import usb
     4 +import time
     5 +import queue
     6 +import logging
     7 +import unittest
     8 +import threading
     9 +import traceback
     10 + 
     11 +from rflib.const import *
     12 +from rflib.bits import ord23
     13 + 
     14 +logging.basicConfig(level=logging.INFO, format='%(asctime)s:%(levelname)s:%(name)s: %(message)s')
     15 +logger = logging.getLogger(__name__)
     16 + 
     17 +EP0BUFSIZE = 512
     18 + 
     19 + 
     20 +class fakeMemory:
     21 + def __init__(self, size=64*1024):
     22 + self.memory = [0 for x in range(size)]
     23 + self.mmio = {}
     24 + #self.mmio[X_RFST] = self.mmio_RFST
     25 + #self.mmio[X_RFST] = self.mmio_MARCSTATE
     26 + 
     27 + def readMemory(self, addr, size):
     28 + logger.debug("fm.readMemory(0x%x, 0x%x)", addr, size)
     29 + chunk = b''.join([b'%c' % x for x in self.memory[addr:addr+size]])
     30 + if len(chunk) < size:
     31 + chunk += b"@" * (size-len(chunk))
     32 + return chunk
     33 + 
     34 + def writeMemory(self, addr, data):
     35 + logger.debug("fm.writeMemory(0x%x, %r)", addr, data)
     36 + #if type(data) == str:
     37 + # raise(Exception("Cannot write 'str' to fakeMemory! Must use 'bytes'"))
     38 + 
     39 + for x in range(len(data)):
     40 + tgt = addr+x
     41 + val = data[x]
     42 + 
     43 + handler = self.mmio.get(tgt)
     44 + if handler is not None:
     45 + val = handler(tgt, data[x])
     46 + 
     47 + # if we didn't return None from the handler, write it anyway
     48 + if val is not None:
     49 + self.memory[tgt] = val
     50 + 
     51 + def mmio_RFST(self, tgt, dbyte):
     52 + logger.info('mmio_RFST(0x%x, %r)', tgt, dbyte)
     53 + print("RFST==%x (%x)" % (self.readMemory(X_RFST, 1), ord(dbyte)))
     54 + 
     55 + 
     56 + # configure MARCSTATE
     57 + val = ord(dbyte)
     58 + if val in (2, 3):
     59 + val = dbyte+10
     60 + 
     61 + else:
     62 + val = MARC_STATE_RX
     63 + 
     64 + self.writeMemory(MARCSTATE, b'%c'%(val))
     65 + 
     66 + # still set RFST
     67 + return dbyte
     68 + 
     69 + def mmio_MARCSTATE(self, tgt, dbyte):
     70 + rfst = self.readMemory(X_RFST, 1)
     71 + logger.info('mmio_MARCSTATE(0x%x, %r) rfst=%r', tgt, dbyte, rfst)
     72 + return MARC_STATE_RX
     73 + 
     74 +class fakeDon:
     75 + pass
     76 + 
     77 + 
     78 + 
     79 +MAX_CHANNELS = 880
     80 +MAX_TX_MSGS = 2
     81 +MAX_TX_MSGLEN = 240 # must match RF_MAX_TX_CHUNK in rflib/chipcon_nic.py
     82 + # and be divisible by 16 for crypto operations
     83 +DEFAULT_NUM_CHANS = 83
     84 +DEFAULT_NUM_CHANHOPS = 83
     85 + 
     86 +class MAC_Data:
     87 + def __init__(self):
     88 + self.mac_state = FHSS_STATE_NONHOPPING
     89 + self.MAC_threshold = 6 # when the T2 clock as overflowed this many times, change channel
     90 + self.MAC_timer = 0 # this tracks how many times it's overflowed (really? 32-bits for these two?!?)
     91 + self.NumChannels = DEFAULT_NUM_CHANS # in case of multiple paths through the available channels
     92 + self.NumChannelHops = DEFAULT_NUM_CHANHOPS # total number of channels in pattern (>= g_MaxChannels)
     93 + self.curChanIdx = 0 # indicates current channel index of the hopping pattern
     94 + self.tLastStateChange = 0
     95 + self.tLastHop = 0
     96 + self.desperatelySeeking = 0 # this should be unnecessary, and should instead use mac_state?
     97 + self.txMsgIdx = 0
     98 + self.txMsgIdxDone = 0
     99 + self.synched_chans = 0
     100 + 
     101 + def serialize(self):
     102 + return struct.pack("<B8H2BH",
     103 + self.mac_state,
     104 + self.MAC_threshold,
     105 + self.MAC_timer,
     106 + self.NumChannels,
     107 + self.NumChannelHops,
     108 + self.curChanIdx,
     109 + self.tLastStateChange,
     110 + self.tLastHop,
     111 + self.desperatelySeeking,
     112 + self.txMsgIdx,
     113 + self.txMsgIdxDone,
     114 + self.synched_chans)
     115 + 
     116 + def deserialize(self, data):
     117 + (self.mac_state,
     118 + self.MAC_threshold,
     119 + self.MAC_timer,
     120 + self.NumChannels,
     121 + self.NumChannelHops,
     122 + self.curChanIdx,
     123 + self.tLastStateChange,
     124 + self.tLastHop,
     125 + self.desperatelySeeking,
     126 + self.txMsgIdx,
     127 + self.txMsgIdxDone,
     128 + self.synched_chans) = struct.unpack("<B8H2BH", data)
     129 + 
     130 + 
     131 +class fakeDongle:
     132 + '''
     133 + This class emulates a real RfCat dongle (the physical device), as well as LibUSB.
     134 + '''
     135 + def __init__(self):
     136 + self._recvbuf = b''
     137 + self.bulk5 = queue.Queue()
     138 + self.bulk0 = [0 for x in range(EP0BUFSIZE)]
     139 + self.memory = fakeMemory()
     140 + 
     141 + self.start_ts = time.time()
     142 + self.aesMode = 0
     143 + self.ampMode = 0
     144 + self.macdata = MAC_Data()
     145 + self.NIC_ID = 0
     146 + self.g_txMsgQueue = ['\0'*(MAX_TX_MSGLEN+1) for x in range(MAX_TX_MSGS)]
     147 + self.g_Channels = b''
     148 + 
     149 + self.memory.writeMemory(0xdf00, FAKE_MEM_DF00)
     150 + self.memory.writeMemory(0xdf46, b'\xf0\x0d')
     151 + for intreg, intval in list(FAKE_INTERRUPT_REGISTERS.items()):
     152 + logger.info('setting interrupt register: %r = %r', intreg, intval)
     153 + self.memory.writeMemory(eval(intreg), intval)
     154 + 
     155 + def clock(self):
     156 + return time.time() - self.start_ts
     157 + 
     158 + def controlMsg(self, flags, request, buf, value, index, timeout):
     159 + logger.info("controlMsg: 0x%x %r %r 0x%x %r %r", flags, request, buf, value, index, timeout)
     160 + try:
     161 + # split by direction (IN/OUT)
     162 + if flags & USB_BM_REQTYPE_DIR_IN:
     163 + logger.info("<= fakeDoer.controlMsg(flags=0x%x, request=%r, buf=%r, value=%r, index=%x, timeout=%r)", flags, request, buf, value, index, timeout)
     164 + if request == EP0_CMD_GET_DEBUG_CODES:
     165 + return b'AB'
     166 + if request == EP0_CMD_PEEKX:
     167 + return self.memory.readMemory(value, buf)
     168 + 
     169 + else: # flags & USB_BM_REQTYPE_DIR_OUT fails since USB_BM_REQTYPE_DIR_OUT == 0!
     170 + logger.info("=> fakeDoer.controlMsg(flags=0x%x, request=%r, buf=%r, value=%r, index=%x, timeout=%r)", flags, request, buf, value, index, timeout)
     171 + if request == EP0_CMD_POKEX:
     172 + self.memory.writeMemory(value, buf)
     173 + 
     174 + except:
     175 + logger.error(traceback.format_exc())
     176 + 
     177 + def txdata(self, app, cmd, data):
     178 + if type(data) == int and data < 0x100:
     179 + data = b'%c' % data
     180 + self.bulk5.put(struct.pack('<BBH', app, cmd, len(data)) + data)
     181 + 
     182 + def bulkWrite(self, chan, buf, timeout=1):
     183 + try:
     184 + # handle write "parts"
     185 + buflen = len(buf) # need to return this, because that's what the libusb interface does.
     186 + self._recvbuf += buf
     187 + logger.debug("=> fakeDoer.bulkWrite(5, %r)", buf)
     188 + 
     189 + curbuflen = len(self._recvbuf)
     190 + if curbuflen < 4:
     191 + return buflen
     192 + 
     193 + app, cmd, mlen = struct.unpack("<BBH", self._recvbuf[:4])
     194 + 
     195 + if curbuflen < mlen+2:
     196 + logger.info("bulkWrite: returning because buffer isn't big enough: len: %x need: %x", curbuflen, mlen+2)
     197 + return buflen
     198 + 
     199 + # now handle a packet
     200 + pkt = self._recvbuf[:mlen+4]
     201 + 
     202 + data = pkt[4:]
     203 + #print("_recvbuf:%r\t\tpkt:%r\t\tapp:%x\tcmd:%x\tdata:%r\t\tmlen:%r\t" % (self._recvbuf, pkt, app, cmd, data, hex(mlen)))
     204 + self._recvbuf = self._recvbuf[mlen+4:]
     205 + 
     206 + # handle commands for the SYSTEM app
     207 + if app == APP_SYSTEM:
     208 + if cmd == SYS_CMD_PEEK:
     209 + size, addr = struct.unpack("<HH", data[:4])
     210 + retmsg = self.memory.readMemory(addr, size)
     211 + self.txdata(app, cmd, retmsg)
     212 + 
     213 + elif cmd == SYS_CMD_POKE:
     214 + addr, = struct.unpack("<H", data[:2])
     215 + size = mlen - 2
     216 + chunk = data[2:2+size]
     217 + logger.info("=>> POKE: pkt:%r\t\tdata:%r\t\tsize:%r\t\taddr:%r\t\t%r", repr(pkt), repr(data), hex(size), hex(addr), chunk)
     218 + self.memory.writeMemory(addr, chunk)
     219 + 
     220 + self.bulk5.put(pkt)
     221 + 
     222 + elif cmd == SYS_CMD_PING:
     223 + self.bulk5.put(pkt)
     224 + 
     225 + elif cmd == SYS_CMD_BUILDTYPE:
     226 + self.txdata(app, cmd, FAKE_DONGLE_BUILDDATA)
     227 + 
     228 + elif cmd == SYS_CMD_COMPILER:
     229 + self.txdata(app, cmd, FAKE_DONGLE_COMPILER)
     230 + 
     231 + elif cmd == SYS_CMD_DEVICE_SERIAL_NUMBER:
     232 + self.txdata(app, cmd, FAKE_DONGLE_SERIALNUM)
     233 + 
     234 + elif cmd == SYS_CMD_RFMODE:
     235 + if len(data) > 1:
     236 + logger.warning("ummm. what's this extra data in your SYS_CMD_RFMODE command?")
     237 + if len(data) == 0:
     238 + logger.warning("SYS_CMD_RFMODE: need a byte to put in X_RFST!")
     239 + else:
     240 + self.memory.writeMemory(X_RFST, data[0:1])
     241 + self.txdata(app, cmd, data)
     242 + 
     243 + else:
     244 + self.log(b'WTFO! no APP_SYSTEM::0x%x', cmd)
     245 + self.bulk5.put(pkt)
     246 + 
     247 + # handle commands for the NIC app
     248 + elif app == APP_NIC:
     249 + if cmd == NIC_GET_AES_MODE:
     250 + self.txdata(app, cmd, b'%c' % self.aesMode)
     251 + 
     252 + elif cmd == NIC_SET_AES_MODE:
     253 + self.aesMode = ord23(data[0])
     254 + self.txdata(app, cmd, b'%c' % self.aesMode)
     255 + 
     256 + elif cmd == NIC_SET_AMP_MODE:
     257 + self.ampMode = ord23(data[0])
     258 + self.txdata(app, cmd, b'%c' % self.ampMode)
     259 + 
     260 + elif cmd == NIC_GET_AMP_MODE:
     261 + self.txdata(app, cmd, b'%c' % self.ampMode)
     262 + 
     263 + elif cmd == NIC_SET_AES_IV:
     264 + self.setAES(data, ENCCS_CMD_LDIV, (self.aesMode & AES_CRYPTO_MODE))
     265 + self.txdata(app, cmd, data[:16])
     266 + 
     267 + elif cmd == NIC_SET_AES_KEY:
     268 + self.setAES(data, ENCCS_CMD_LDKEY, (self.aesMode & AES_CRYPTO_MODE))
     269 + self.txdata(app, cmd, data[:16])
     270 + 
     271 + elif cmd == NIC_SET_ID:
     272 + # fixme: sending 8 bit to 16 bit function???
     273 + self.NIC_ID = ord23(data[0])
     274 + self.txdata(app, cmd, data[0])
     275 + 
     276 + elif cmd == NIC_LONG_XMIT:
     277 + # load up macdata queues, follow-on with
     278 + #
     279 + #
     280 + # this is duplicating our work in transmit_long(). pick one.
     281 + if (macdata.mac_state != FHSS_STATE_NONHOPPING):
     282 + data[0] = RC_RF_MODE_INCOMPAT
     283 + self.txdata(app, cmd, data[0])
     284 +
     285 + else:
     286 + length, blocks = struct.unpack("<HB", data[:2])
     287 + txTotal= 0
     288 + data[0] = transmit_long(data[3:], length, blocks)
     289 + self.txdata(app, cmd, data[0])
     290 + 
     291 + elif cmd == NIC_LONG_XMIT_MORE:
     292 + length = ord23(data[0])
     293 + if (length == 0):
     294 + if(rfTxTotalTXLen):
     295 + self.debug("dropout final wait!")
     296 + #debughex16(rfTxTotalTXLen)
     297 + #debughex(g_txMsgQueue[0][0])
     298 + #debughex(g_txMsgQueue[1][0])
     299 + self.lastCode[1] = LCE_DROPPED_PACKET
     300 + data[0] = RC_TX_DROPPED_PACKET
     301 + #LED = 0
     302 + #resetRFSTATE()
     303 + self.macdata.mac_state = FHSS_STATE_NONHOPPING
     304 + self.txdata(app, cmd, b'%c' % RC_TX_DROPPED_PACKET)
     305 + return
     306 +
     307 + #LED = 0
     308 + self.macdata.mac_state = FHSS_STATE_NONHOPPING
     309 + self.debug("total bytes tx:")
     310 + #debughex16(txTotal)
     311 + self.txdata(app, cmd, b'%c' % LCE_NO_ERROR)
     312 + return
     313 +
     314 + # catch if we've been called out of sequence, or we've had an underrun
     315 + if (self.macdata.mac_state != FHSS_STATE_LONG_XMIT):
     316 + self.debug("underrun")
     317 + # TX underrun
     318 + if(self.lastCode[1] == LCE_DROPPED_PACKET):
     319 + self.txdata(app, cmd, b'%c' % RC_TX_DROPPED_PACKET)
     320 +
     321 + else:
     322 + self.lastCode[1] = LCE_RF_MULTI_BUFFER_NOT_INIT
     323 + self.txdata(app, cmd, b'%c' % RC_RF_MODE_INCOMPAT)
     324 +
     325 + #LED = 0
     326 + #resetRFSTATE()
     327 + self.macdata.mac_state = FHSS_STATE_NONHOPPING
     328 + else:
     329 + # add data to rolling datafer
     330 + #data[0] = MAC_tx(&data[1], (__xdata u8) len)
     331 + # check for any other error return
     332 + #if(data[0] && data[0] != RC_ERR_BUFFER_NOT_AVAILABLE)
     333 + #{
     334 + # debug("datafer error");
     335 + # debughex(data[0]);
     336 + # LED = 0;
     337 + # resetRFSTATE();
     338 + # self.macdata.mac_state = FHSS_STATE_NONHOPPING;
     339 + #}
     340 + self.txdata(app, cmd, data[0]);
     341 + 
     342 + elif cmd == FHSS_XMIT:
     343 + length = ord23(data[0])
     344 + #len += (*data++) << 8;
     345 + #repeat = *data++;
     346 + #repeat += (*data++) << 8;
     347 + #offset = *data++;
     348 + #offset += (*data++) << 8;
     349 + #transmit(data, len, repeat, offset);
     350 + #MAC_tx(data, len);
     351 + ##/// for some strange reason, if we call this in MAC_tx it dies, but not from here. ugh.
     352 + if (length > MAX_TX_MSGLEN):
     353 + self.debug("FHSSxmit message too long");
     354 + self.txdata(app, cmd, b'%c' % length);
     355 + return buflen
     356 + 
     357 + elif (self.g_txMsgQueue[self.macdata.txMsgIdx][0] != 0):
     358 + self.debug("still waiting on the last packet");
     359 + self.txdata(app, cmd, b'%c' % length);
     360 + return buflen
     361 + 
     362 + g_txMsgQueue[self.macdata.txMsgIdx][0] = length
     363 + g_txMsgQueue[self.macdata.txMsgIdx][1] = data[1:]
     364 + 
     365 + self.macdata.txMsgIdx += 1
     366 + if (self.macdata.txMsgIdx >= MAX_TX_MSGS):
     367 + self.macdata.txMsgIdx = 0;
     368 + 
     369 + self.txdata(app, cmd, b'%c' % length)
     370 +
     371 + elif cmd == FHSS_SET_CHANNELS:
     372 + self.macdata.NumChannels = ord23(data[0])
     373 + if (self.macdata.NumChannels <= MAX_CHANNELS):
     374 + self.g_Channels = data[2:self.macdata.NumChannels]
     375 + self.txdata(app, cmd, struct.pack("<H", self.macdata.NumChannels))
     376 + 
     377 + else:
     378 + self.txdata(app, cmd, b"NO DEAL")
     379 + 
     380 + elif cmd == FHSS_GET_CHANNELS:
     381 + self.txdata(app, cmd, self.g_Channels)
     382 + 
     383 + elif cmd == FHSS_NEXT_CHANNEL:
     384 + #MAC_set_chanidx(MAC_getNextChannel());
     385 + self.macdata.curChanIdx += 1
     386 + 
     387 + chan = self.setFHSSchanByIdx(self.macdata.curChanIdx)
     388 + self.txdata(app, cmd, b'%c' % chan)
     389 + 
     390 + elif cmd == FHSS_CHANGE_CHANNEL:
     391 + #PHY_set_channel(data[0]);
     392 + self.memory.writeMemory(CHANNR, data[0])
     393 + self.txdata(app, cmd, data[0]);
     394 + 
     395 + elif cmd == FHSS_START_HOPPING:
     396 + self.begin_hopping(0);
     397 + self.txdata(app, cmd, data[0]);
     398 + 
     399 + elif cmd == FHSS_STOP_HOPPING:
     400 + self.stop_hopping();
     401 + self.txdata(app, cmd, data[0]);
     402 + 
     403 + elif cmd == FHSS_SET_MAC_THRESHOLD:
     404 + self.macdata.MAC_threshold = ord23(data[0])
     405 + self.txdata(app, cmd, data[0]);
     406 + 
     407 + elif cmd == FHSS_GET_MAC_THRESHOLD:
     408 + self.txdata(app, cmd, struct.pack("<I", self.macdata.MAC_threshold))
     409 + 
     410 + elif cmd == FHSS_SET_MAC_DATA:
     411 + self.debugx(data);
     412 + #debughex(data[0]);
     413 + self.macdata.deserialize(data)
     414 + self.txdata(app, cmd, data);
     415 + 
     416 + elif cmd == FHSS_GET_MAC_DATA:
     417 + self.macdata.MAC_timer = self.get_rf_MAC_timer()
     418 + self.txdata(app, cmd, self.macdata.serialize());
     419 + 
     420 + elif cmd == FHSS_START_SYNC:
     421 + #MAC_sync(data[0])
     422 + self.txdata(app, cmd, data[0]);
     423 +
     424 + elif cmd == FHSS_SET_STATE:
     425 + # store the main timer value for beginning of this phase.
     426 + self.macdata.tLastStateChange = self.clock()
     427 + self.macdata.mac_state = ord23(data[0])
     428 +
     429 + # if macdata.mac_state is > 2, make sure the T2 interrupt is set
     430 + # if macdata.mac_state <= 2, make sure T2 interrupt is ignored
     431 + if self.macdata.mac_state in (FHSS_STATE_NONHOPPING, FHSS_STATE_DISCOVERY, FHSS_STATE_SYNCHING):
     432 + self.stop_hopping();
     433 + 
     434 + elif self.macdata.mac_state == FHSS_STATE_SYNCINGMASTER:
     435 + self.MAC_do_Master_scanny_thingy();
     436 + 
     437 + elif self.macdata.mac_state in (FHSS_STATE_SYNCHED, FHSS_STATE_SYNC_MASTER):
     438 + self.begin_hopping(0);
     439 +
     440 + self.txdata(app, cmd, data[0]);
     441 +
     442 + elif cmd == FHSS_GET_STATE:
     443 + self.txdata(app, cmd, self.macdata.mac_state)
     444 +
     445 + else:
     446 + self.log(b'WTFO! no APP_NIC::0x%x', cmd)
     447 + self.bulk5.put(pkt)
     448 + else:
     449 + # everything else... just echo
     450 + self.bulk5.put(pkt)
     451 + 
     452 + return buflen
     453 + 
     454 + except:
     455 + logger.error(traceback.format_exc())
     456 + 
     457 + def bulkRead(self, chan, length, timeout=1):
     458 + '''
     459 + In standard USB fashion, bulkRead() handles the "IN" communication, whereby the "host"
     460 + pulls information back from the "device". ie. our responses to commands.
     461 + 
     462 + RfCat polls this function repeatedly, to provide the illusion of bi-directional
     463 + communication, when in fact USB (pre-v3) is completely host-driven. If a USB device
     464 + gets to talk, it's because the host asked for information.
     465 + 
     466 + For our purposes, bulkRead() simply pops data out of the EP5 Bulk "queue" and returns.
     467 + 
     468 + This has *nothing* to do with "reading" from the memory. bulkRead() gives the dongle
     469 + the "talking stick"
     470 + '''
     471 + starttime = time.time()
     472 + 
     473 + while time.time() - starttime < timeout:
     474 + try:
     475 + out = self.bulk5.get_nowait()
     476 + logger.debug('<= fakeDoer.bulkRead(5, %r) == %r', length, out)
     477 + return b"@" + out
     478 + except queue.Empty:
     479 + time.sleep(.05)
     480 + 
     481 + logger.debug('<= fakeDoer.bulkRead(5, %r) == <EmptyQueue>', length)
     482 + raise usb.USBError('Operation timed out (FakeDongle)')
     483 + 
     484 + def log(self, msg, *args):
     485 + if len(args):
     486 + msg = msg % args
     487 + self.txdata(APP_DEBUG, DEBUG_CMD_STRING, msg)
     488 + 
     489 + # no need to reinvent the wheel, this is a difference in CC1111 memories, not functionality
     490 + debug = log
     491 + debugx = log
     492 + 
     493 + def setAES(self, data, cmd, flags):
     494 + '''
     495 + For now, we do nothing.
     496 + '''
     497 + return
     498 + 
     499 + def setFHSSchanByIdx(self, chanidx):
     500 + chan = self.g_Channels[chanidx]
     501 + self.memory.writeMemory(CHANNR, chan)
     502 + return chan
     503 + 
     504 + def begin_hopping(self, startchan):
     505 + self.memory.writeMemory(CHANNR, b'%c' % startchan)
     506 + return
     507 + def stop_hopping(self):
     508 + return
     509 + 
     510 + def get_rf_MAC_timer(self):
     511 + return int((self.clock() * 20) % self.macdata.MAC_threshold)
     512 + 
     513 +class FakeRfCat(rflib.RfCat):
     514 + def __init__(self, idx=0, debug=False, copyDongle=None, RfMode=RFST_SRX):
     515 + # instantiate ourself as an official RfCat dongle
     516 + rflib.RfCat.__init__(self, idx, debug, copyDongle, RfMode)
     517 + 
     518 + def _internal_select_dongle(self, console=False):
     519 + self._d = fakeDon()
     520 + self._do = fakeDongle()
     521 + self.console = console
     522 + 
     523 + def getPartNum(self):
     524 + return FAKE_PARTNUM
     525 + 
     526 + 
Please wait...
Page is in error, reload to recover