Ejemplo n.º 1
0
    def __init__(self,
                 LED_STATE=default_LED_STATE,
                 Fxosc=default_Fxosc,
                 Fstep=default_Fstep,
                 callsign=None,
                 node_id=default_node_id,
                 network_id=default_network_id,
                 carrier_freq=default_carrier_freq,
                 carrier_dev=default_carrier_dev,
                 carrier_bitrate=default_bitrate):
        self._mode = OPMODE_SLEEP
        self.LED_STATE = LED_STATE
        self.Fxosc = Fxosc
        self.Fstep = Fstep
        self.callsign = callsign
        self.RFM_SPI = SPI(0, 0)
        self.RFM_SPI.msh = 5000000
        self.carrier_freq = carrier_freq
        self.carrier_dev = carrier_dev
        self.bitrate = carrier_bitrate
        self.node_id = node_id
        self.network_id = network_id

        if self.callsign is None:
            raise NoCallSign("FCC Callsign not defined")
        self.ord_callsign = map(ord, list(self.callsign))
        self._io_setup()
        GPIO.output(BLUE_LEDPIN, GPIO.LOW)
        self.reset_radio()
        return
Ejemplo n.º 2
0
class DAC():
    """ This class uses an actual DAC """

    def __init__(self, channel):
        """ Channel is the pwm output is on (0..15) """
        self.channel = channel
        self.offset = 0.0
        if 'SPI' in globals():
            # init the SPI for the DAC
            try:
                self.spi2_0 = SPI(0, 0)
            except IOError:
                self.spi2_0 = SPI(1, 0)
            self.spi2_0.bpw = 8
            self.spi2_0.mode = 1
        else:
            logging.warning("Unable to set up SPI")
            self.spi2_0 = None

    def set_voltage(self, voltage):
        logging.debug("Setting voltage to "+str(voltage))         
        if self.spi2_0 is None:
            logging.debug("SPI2_0 missing")
            return

        v_ref = 3.3                    # Voltage reference on the DAC
        dacval = int((voltage * 256.0) / v_ref)
        byte1 = ((dacval & 0xF0) >> 4) | (self.channel << 4)
        byte2 = (dacval & 0x0F) << 4
        self.spi2_0.writebytes([byte1, byte2])       # Update all channels
        self.spi2_0.writebytes([0xA0, 0xFF])
Ejemplo n.º 3
0
class DAC():
  """ This class uses an actual DAC """

  def __init__(self, channel):
    """ Channel is the pwm output is on (0..15) """
    self.channel = channel
    self.offset = 0.0
    if 'SPI' in globals():
      # init the SPI for the DAC
      self.spi2_0 = SPI(2, 0)
      self.spi2_0.bpw = 8
      self.spi2_0.mode = 1
    else:
      logging.warning("Unable to set up SPI")
      self.spi2_0 = None

  def set_voltage(self, voltage):
    logging.debug("Setting voltage to " + str(voltage))
    if self.spi2_0 is None:
      logging.debug("SPI2_0 missing")
      return

    v_ref = 3.3    # Voltage reference on the DAC
    dacval = int((voltage * 256.0) / v_ref)
    byte1 = ((dacval & 0xF0) >> 4) | (self.channel << 4)
    byte2 = (dacval & 0x0F) << 4
    self.spi2_0.writebytes([byte1, byte2])    # Update all channels
    self.spi2_0.writebytes([0xA0, 0xFF])
Ejemplo n.º 4
0
 def __init__(self, length, missing):
     # the important piece of this for reuse is setting up the interface
     # the rest sets up the strip of leds for what we intend to do with them
     self.interface = SPI(0, 1)
     self.full_length = length
     self.missing_leds = missing
     self.outbuff = [[128, 128, 128]] * length
     self.reset_buffer([128, 128, 128])
Ejemplo n.º 5
0
 def __init__(self):
     self.val = None
     self.tempList = []
     self.spi = SPI(0, 0)
     self.spi.msh = 1000000
     GPIO.setup(CS_PIN, GPIO.OUT)
     GPIO.output(CS_PIN, GPIO.HIGH)
     self.inter = Interpolate(x, y)
Ejemplo n.º 6
0
 def __init__(self, channel):
   """ Channel is the pwm output is on (0..15) """
   self.channel = channel
   self.offset = 0.0
   if 'SPI' in globals():
     # init the SPI for the DAC
     self.spi2_0 = SPI(2, 0)
     self.spi2_0.bpw = 8
     self.spi2_0.mode = 1
   else:
     logging.warning("Unable to set up SPI")
     self.spi2_0 = None
Ejemplo n.º 7
0
	def __init__(self, bus):
		# Use Adafruit_BBIO.SPI to initialize the cap
		# and the spi bus configuration
		s = SPI(bus, self.__DEVICE)
		s.msh = self.__SPEED
		s.mode = self.__MODE
		s.close()

		# Use normal file for writing bytes
		dev = '/dev/spidev%s.%s' % (bus + 1, self.__DEVICE)
		self.spi = open(dev, 'wb')
		print 'Opened %s, Freq: %sHz' % (dev, self.__SPEED)
Ejemplo n.º 8
0
 def __init__(self):
     self.spi = SPI(
         0, 0
     )  #/dev/spidev1.0  (be sure to run Python with su if 'no permission'
     self.spi.msh = 1000000  #SPI clock set to 1MHz (slowed from 10MHz for better stability across setups)
     self.spi.bpw = 8  # bits per word
     self.spi.threewire = False  # not half-duplex
     self.spi.lsbfirst = False  # we want MSB first
     self.spi.mode = 0  # options are modes 0 through 3
     self.spi.cshigh = False  # we want chip select to be active low
     self.spi.open(0, 0)  # make it so
     time.sleep(0.05)
Ejemplo n.º 9
0
def factory(bus=0, device=0, dev="rpi"):
    if dev == "rpi":
        import spidev
        s = spidev.SpiDev()
        s.open(0, 0)
        return s
    elif dev == "bbb":
        from Adafruit_BBIO.SPI import SPI
        bus = 1
        s = SPI(bus, device)
        s.mode = 0
        return s
Ejemplo n.º 10
0
    def init_spi(self):
        logging.debug("Initializing spi...")
        self.spi = SPI(0, 0)  #/dev/spidev1.0

        #   SPI Mode 	Clock Polarity (CPOL/CKP) 	Clock Phase (CPHA) 	Clock Edge (CKE/NCPHA)
        #   0 	        0 	                        0 	                1
        #   1 	        0 	                        1 	                0
        #   2 	        1 	                        0 	                1
        #   3 	        1 	                        1 	                0
        self.spi.mode = 0
        self.spi.msh = SPI_CLOCK_RATE  #this is clock speed setting
        self.spi.open(0, 0)
Ejemplo n.º 11
0
    def __init__(self, unix_socket_path, *args, **kwargs):
        self.unix_socket_path = unix_socket_path
        self.connection = None
        self.welcome_socket = None

        spi = SPI(0, 0)
        spi.msh = 2000000
        spi.mode = 1
        self.chs = [0, 1, 2, 3]
        self.ADC0 = ADC("P9_24", spi)
        self.ADC1 = ADC("P9_26", spi)
        self.ADC2 = ADC("P9_28", spi)
        self.ADC3 = ADC("P9_30", spi)
Ejemplo n.º 12
0
    def begin(self, major, minor, ce_pin, irq_pin):
        # Initialize SPI bus
        self.spidev = SPI(major, minor)
        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        GPIO.setup(self.ce_pin, GPIO.OUT)
        GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        self.write_register(NRF24.SETUP_RETR, (int('0100', 2) << NRF24.ARD) |
                            (int('1111', 2) << NRF24.ARC))

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(
            NRF24.STATUS,
            _BV(NRF24.RX_DR) | _BV(NRF24.TX_DS) | _BV(NRF24.MAX_RT))

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.setChannel(self.channel)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()
Ejemplo n.º 13
0
 def __init__(self, channel):
     """ Channel is the pwm output is on (0..15) """
     self.channel = channel
     self.offset = 0.0
     if 'SPI' in globals():
         # init the SPI for the DAC
         try:
             self.spi2_0 = SPI(0, 0)
         except IOError:
             self.spi2_0 = SPI(1, 0)
         self.spi2_0.bpw = 8
         self.spi2_0.mode = 1
     else:
         logging.warning("Unable to set up SPI")
         self.spi2_0 = None
Ejemplo n.º 14
0
 def __init__(self, bus, device, cePin, csnPin, irqPin):
     self.__bus = bus
     self.__device = device
     self.cePin = cePin
     self.csnPin = csnPin
     self.irqPin = irqPin
     self.spi = SPI(self.__bus, self.__device)
     self.spi.msh = 10000
     self.spi.bpw = 8  # bits/word
     self.spi.threewire = False
     self.spi.lsbfirst = False
     self.spi.mode = 0
     self.spi.cshigh = False
     self.spi.open(0, 0)
     self.last_payload = ""
Ejemplo n.º 15
0
    def __init__(self, coarsePin="P9_15", finePin="P9_16", readPin="P9_14", clockRate=100000):
        self.CS_FB_COARSE_PIN = coarsePin
        self.CS_FB_FINE_PIN = finePin
        self.CS_ADC_PIN = readPin
        self.FB_CLK_RATE = clockRate
        
        GPIO.setup(self.CS_FB_COARSE_PIN, GPIO.OUT)
        GPIO.setup(self.CS_FB_FINE_PIN, GPIO.OUT)
        GPIO.setup(self.CS_ADC_PIN, GPIO.OUT)
        self.spi00 = SPI(0,0)
        self.spi00.msh = self.FB_CLK_RATE
        
        self.fname = "dacValues.pyon"

        self.maxDACvalue = (1<<16)-1
        
        # Ca43
        self.kHz_per_mG = -2.45
        # measured
        self.mG_per_mA = 146 / 56.64
        # (sensor+DiffAmp) equivalent : 6.06ohm
        # Verr: voltage of error signal
        self.mA_per_mVerr = 1 / 6.06

        self.mG_per_mVerr = self.mG_per_mA * self.mA_per_mVerr
        self.kHz_per_mVerr = self.kHz_per_mG * self.mG_per_mVerr

        # maximum DAC output: 2.048V
        self.mVDAC_per_DACvalue = 2.048e3 / self.maxDACvalue

        # estimates for the slope qubit_freq'(DACvalue)
        # fine DAC gain 1
        # coarse DAC gain 200
        self.kHz_per_fDACvalue_est = self.kHz_per_mG * self.mG_per_mVerr * self.mVDAC_per_DACvalue
        self.kHz_per_cDACvalue_est = self.kHz_per_mG * self.mG_per_mVerr * 200 * self.mVDAC_per_DACvalue
Ejemplo n.º 16
0
 def setup_spi(self):
     #This is for BB Black
     self.spi = SPI(self.spi_bus, self.spi_client)
     self.spi.msh = self.spi_freq
     self.spi.mode = self.spi_mode
     self.bpw = self.spi_bits_per_word
     self.spi.cshigh = self.spi_cshigh
Ejemplo n.º 17
0
	def __init__(self, spi = SPI(0,0), gpio_nrst = 'P9_23', gpio_dc = 'P9_24', gpio_nled = 'P9_25'):
		self.gpio_nrst = gpio_nrst
		self.gpio_dc = gpio_dc
		self.gpio_nled = gpio_nled

		self.spi = spi
		self.spi.msh = 4000000
		self.spi.mode = 0b00
		self.spi.bpw = 8
		self.spi.lsbfirst = False
		self.spi.threewire = False
		self.spi.cshigh = False

		GPIO.setup(self.gpio_nrst, GPIO.OUT, initial = GPIO.LOW)
		sleep(0.1) # workaround until library waits for permissions
		GPIO.setup(self.gpio_nrst, GPIO.OUT, initial = GPIO.LOW)
		GPIO.output(self.gpio_nrst, GPIO.LOW) # Reset.

		GPIO.setup(self.gpio_dc, GPIO.OUT, initial = GPIO.LOW)
		sleep(0.1)
		GPIO.setup(self.gpio_dc, GPIO.OUT, initial = GPIO.LOW)
		GPIO.output(self.gpio_dc, GPIO.LOW) # Command.

		if self.gpio_nled:
			GPIO.setup(self.gpio_nled, GPIO.OUT, initial = GPIO.HIGH)
			sleep(0.1)
			GPIO.setup(self.gpio_nled, GPIO.OUT, initial = GPIO.HIGH)
			GPIO.output(self.gpio_nled, GPIO.HIGH) # Off.

		self.reset()
Ejemplo n.º 18
0
	def __init__(self, isRFM69HW=True, interruptPin=DIO0_PIN, csPin=NSS_PIN):
		self._isRFM69HW = isRFM69HW
		self._interruptPin = interruptPin
		self._csPin = csPin

		self.SPI = SPI(SPI_BUS, SPI_CS)
		self.SPI.bpw = 8
		self.SPI.mode = 0
		self.SPI.msh = SPI_CLK_SPEED
		self.SPI.lsbfirst = False

		GPIO.setup(self._interruptPin, GPIO.IN)
		self.lastIrqLevel = GPIO.input(self._interruptPin)
		GPIO.setup(self._csPin, GPIO.OUT)
		GPIO.output(self._csPin, GPIO.HIGH)

		self.start_time = datetime.datetime.now()
Ejemplo n.º 19
0
 def __init__(self, length, missing):
     # the important piece of this for reuse is setting up the interface
     # the rest sets up the strip of leds for what we intend to do with them
     self.interface = SPI(0,1)
     self.full_length = length
     self.missing_leds = missing
     self.outbuff = [[128, 128, 128]] * length
     self.reset_buffer([128, 128, 128])
Ejemplo n.º 20
0
def getLight():
    #print("Reading Light Data")

    spi = SPI(1, 0)
    spi.msh = 100000
    spi.bpw = 8

    spi.writebytes([0x35])
    sleep(0.01)
    lightVals = spi.readbytes(3)
    light = str(lightVals[0]) + str(lightVals[1]) + str(lightVals[2])

    spi.close()
    return light
Ejemplo n.º 21
0
def getMoist_ch1():
    #print("Reading Moisture CH 1")

    spi = SPI(1, 0)
    spi.msh = 100000
    spi.bpw = 8

    spi.writebytes([0x31])
    sleep(0.01)
    moistureVals = spi.readbytes(3)
    moisture = str(moistureVals[0]) + str(moistureVals[1]) + str(moistureVals[2])

    spi.close()
    return moisture
Ejemplo n.º 22
0
    def __init__(self, partial_refresh_limit=32, fast_refresh=True):
        """ Initialize the EPD class.
        `partial_refresh_limit` - number of partial refreshes before a full refrersh is forced
        `fast_frefresh` - enable or disable the fast refresh mode,
                          see smart_update() method documentation for details"""
        self.width = EPD_WIDTH
        """ Display width, in pixels """
        self.height = EPD_HEIGHT
        """ Display height, in pixels """
        self.fast_refresh = fast_refresh
        """ enable or disable the fast refresh mode """
        self.partial_refresh_limit = partial_refresh_limit
        """ number of partial refreshes before a full refrersh is forced """

        self._last_frame = None
        self._partial_refresh_count = 0
        self._init_performed = False
        self.spi = SPI(1, 0)
Ejemplo n.º 23
0
class PT100(Sensor):
    def __init__(self):
        self.val = None
        self.tempList = []
        self.spi = SPI(0, 0)
        self.spi.msh = 1000000
        GPIO.setup(CS_PIN, GPIO.OUT)
        GPIO.output(CS_PIN, GPIO.HIGH)
        self.inter = Interpolate(x, y)

    def spi_read(self):
        GPIO.output(CS_PIN, GPIO.LOW)
        self.spi.xfer([REG_CONF, CNF_ONESHOT])
        GPIO.output(CS_PIN, GPIO.HIGH)
        time.sleep(0.1)

        GPIO.output(CS_PIN, GPIO.LOW)
        self.spi.xfer([REG_LSB])
        lsb = self.spi.readbytes(1)
        GPIO.output(CS_PIN, GPIO.HIGH)

        GPIO.output(CS_PIN, GPIO.LOW)
        self.spi.xfer([REG_MSB])
        msb = self.spi.readbytes(1)
        GPIO.output(CS_PIN, GPIO.HIGH)

        err = (False, True)[lsb[0] & 1]

        adc = (msb[0] << 8 | lsb[0]) >> 1
        return (err, adc)

    def update(self):
        value = 0
        err = False
        for i in range(10):
            err, adc = self.spi_read()
            if err:
                break
            value = value + adc
        if err:
            #self.val=None
            return
        value = value / 10.

        res = (value / 2**15 * 400)

        self.tempList.append(self.inter(res))
        if len(self.tempList) > 5:
            del self.tempList[0]
        tSum = 0
        for t in self.tempList:
            tSum = tSum + t
        self.val = tSum / len(self.tempList)
Ejemplo n.º 24
0
  def __init__(self):
	self.spi = SPI(0,0) #/dev/spidev1.0  (be sure to run Python with su if 'no permission'
	self.spi.msh=1000000 #SPI clock set to 1MHz (slowed from 10MHz for better stability across setups)
	self.spi.bpw = 8 # bits per word
	self.spi.threewire = False # not half-duplex
	self.spi.lsbfirst = False # we want MSB first
	self.spi.mode = 0 # options are modes 0 through 3
	self.spi.cshigh = False # we want chip select to be active low
	self.spi.open(0,0) # make it so
	time.sleep(0.05)
Ejemplo n.º 25
0
    def __init__(self):
        # create outer classes with ability to change inner parameters

        # using two's complement
        # CONSTS
        self.DAC_SEND = "0001"  # value to be sending information to dac
        self.MAX_NEG = -pow(2, 19)  # max neg value that can be achieved
        self.MAX_POS = int(
            0b01111111111111111111)  # max pos value that can be achieved
        self.MAX_CLOCK = 340000  # maximal clock value we can get in Hz
        self.MIN_CLOCK = 50000  # minimal clock value we can get in Hz
        self.IP = '192.168.0.20'
        self.PORT = 5555

        self.act_val = 0  # actual value
        self.clock = self.MIN_CLOCK  # begin with min value

        self.spi = SPI(1, 0)  # spi for our communication
        self.spi.mode = 0b00
        self.spi.msh = self.clock

        # Triggers for the DAC
        self.reset = False
        self.ldac = False
        GPIO.setup("P8_17", GPIO.OUT)  # LDAC
        GPIO.setup("P8_18", GPIO.OUT)  # RESET
        GPIO.output("P8_18", self.reset)
        GPIO.output("P8_17", self.ldac)

        # Address for which DAC
        self.dac_address = list()
        self.dac_address = [0, 0, 0, 0, 0]  # default
        GPIO.setup("P9_15", GPIO.OUT)  # P0
        GPIO.setup("P9_11", GPIO.OUT)  # P1
        GPIO.setup("P9_12", GPIO.OUT)  # P2
        GPIO.setup("P9_13", GPIO.OUT)  # P3
        GPIO.setup("P9_14", GPIO.OUT)  # P4
        GPIO.output("P9_15", GPIO.LOW)  # P0
        GPIO.output("P9_11", GPIO.LOW)  # P1
        GPIO.output("P9_12", GPIO.LOW)  # P2
        GPIO.output("P9_13", GPIO.LOW)  # P3
        GPIO.output("P9_14", GPIO.LOW)  # P4
        self.initializeDAC()
Ejemplo n.º 26
0
def Watering():
    print("watering")

    spi = SPI(1, 0)
    spi.msh = 100000
    spi.bpw = 8

    list = []
    i=0
    while i<50:
        spi.writebytes([0x31])
        sleep(0.1)
        list.append(spi.readbytes(3))
        print(list.pop())
        ++i
        sleep(0.5)
    spi.close()
Ejemplo n.º 27
0
def startWatering():
    print("Started watering...")

    session['watering_command_status'] = "ON"

    # send the signal to arduino to start watering
    spi = SPI(1, 0)
    spi.msh = 100000
    spi.bpw = 8

    # send the appropriate signal
    spi.writebytes([0x36])  # '6'

    print(spi.readbytes(1))

    spi.close()

    return flask.redirect("/")
Ejemplo n.º 28
0
def stopWatering():
    print("Stopping watering")

    session['watering_command_status'] = "OFF"

    # send the signal to arduino to stop watering
    spi = SPI(1, 0)
    spi.msh = 100000
    spi.bpw = 8

    # send the appropriate signal
    spi.writebytes([0x37])  # '7'

    print(spi.readbytes(1))

    spi.close()

    return flask.redirect("/")
Ejemplo n.º 29
0
    def __init__(self, bus, device):
        super(MAX7221, self).__init__(8, 8)
        SPI(bus, device).mode = 0
        self.spi_bus = SPI(bus, device)
        self.buf = [0, 0, 0, 0, 0, 0, 0, 0]

        self.OP_NOP = 0x0
        self.OP_DIG0 = 0x1
        self.OP_DIG1 = 0x2
        self.OP_DIG2 = 0x3
        self.OP_DIG3 = 0x4
        self.OP_DIG4 = 0x5
        self.OP_DIG5 = 0x6
        self.OP_DIG6 = 0x7
        self.OP_DIG7 = 0x8
        self.OP_DECODEMODE = 0x9
        self.OP_INTENSITY = 0xA
        self.OP_SCANLIMIT = 0xB
        self.OP_SHUTDOWN = 0xC
        self.OP_DISPLAYTEST = 0xF

        self.init()
Ejemplo n.º 30
0
def ini_levels():

    check_ok = 0
    update_data = 0x39

    # spi.set_clock_hz(1000000)
    # spi.set_mode(0)
    # spi.set_bit_order(SPI.MSBFIRST)
    SPI_PORT = 0
    SPI_DEVICE = 0
    # SPI setup

    spi = SPI(0, 0)  #/dev/spidev1.0
    spi.msh = 100000  # SPI clock set to 100 kHz
    spi.bpw = 8  # bits/word
    spi.threewire = False
    spi.lsbfirst = False
    spi.mode = 0
    spi.cshigh = False  # ADS1248 chip select (active low)
    # spi.open(0,0)
    spi.open(SPI_PORT, SPI_DEVICE)

    print "SPI port ", SPI_PORT, "  ", SPI_DEVICE, " open"
Ejemplo n.º 31
0
    def __init__(self, maxClock=3300000):
        # using two's complement
        self.dacSend = "0001"
        self.max_raw_minus = -pow(2, 19)  # maximal value that can be achieved
        self.max_raw_plus = int(0b01111111111111111111)
        self.actVal = 0  # actual value
        # SPI
        self.spi = SPI(1, 0)  # choose SPI device
        self.spi.mode = 0b00
        if maxClock > 1000:
            self.spi.msh = maxClock
        else:
            self.spi.msh = 3300000
            print("Minumum clock speed is 10000, setting default 33Mhz")
        # Start values
        self.reset = 0
        self.ldac = 0  # in the beggining the device is not ready(remember they are inverted)

        # P8
        GPIO.setup("P8_17", GPIO.OUT)  # LDAC
        GPIO.output("P8_17", self.ldac)
        GPIO.setup("P8_18", GPIO.OUT)  # RESET
        GPIO.output("P8_18", self.reset)

        # GPIO.setup("P8_15", GPIO.OUT) #ext rsten
        # GPIO.setup("P8_14", GPIO.OUT) # PLL LOCK
        # GPIO.setup("P8_16", GPIO.OUT) # ext Ioupden
        # NOT USED

        # P9 (addresses)
        self.dacAddress = [0, 0, 0, 0, 0]  # default
        GPIO.setup("P9_11", GPIO.OUT)  # P1
        GPIO.setup("P9_12", GPIO.OUT)  # P2
        GPIO.setup("P9_13", GPIO.OUT)  # P3
        GPIO.setup("P9_14", GPIO.OUT)  # P4
        GPIO.setup("P9_15", GPIO.OUT)  # P0
Ejemplo n.º 32
0
    def begin(self, major, minor, ce_pin, irq_pin):
        # Initialize SPI bus
        self.spidev = SPI(major, minor) 
        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        GPIO.setup(self.ce_pin, GPIO.OUT)
        GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        self.write_register(NRF24.SETUP_RETR, (int('0100', 2) << NRF24.ARD) | (int('1111', 2) << NRF24.ARC))

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(NRF24.STATUS, _BV(NRF24.RX_DR) | _BV(NRF24.TX_DS) | _BV(NRF24.MAX_RT))

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.setChannel(self.channel)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()
Ejemplo n.º 33
0
	def __init__(self, isRFM69HW=True, interruptPin=DIO0_PIN, csPin=NSS_PIN):
		self._isRFM69HW = isRFM69HW
		self._interruptPin = interruptPin
		self._csPin = csPin

		self.SPI = SPI(SPI_BUS, SPI_CS)
		self.SPI.bpw = 8
		self.SPI.mode = 0
		self.SPI.msh = SPI_CLK_SPEED
		self.SPI.lsbfirst = False

		GPIO.setup(self._interruptPin, GPIO.IN)
		self.lastIrqLevel = GPIO.input(self._interruptPin)
		GPIO.setup(self._csPin, GPIO.OUT)
		GPIO.output(self._csPin, GPIO.HIGH)

		self.start_time = datetime.datetime.now()
Ejemplo n.º 34
0
    def __init__(self, bus):
        # Use Adafruit_BBIO.SPI to initialize the cap
        # and the spi bus configuration
        s = SPI(bus, self.__DEVICE)
        s.msh = self.__SPEED
        s.mode = self.__MODE
        s.close()

        # Use normal file for writing bytes
        dev = '/dev/spidev%s.%s' % (bus + 1, self.__DEVICE)
        self.spi = open(dev, 'wb')
        print 'Opened %s, Freq: %sHz' % (dev, self.__SPEED)
Ejemplo n.º 35
0
    def __init__(self, bus, device):
    	super(MAX7221, self).__init__(8, 8)
        SPI(bus, device).mode = 0
        self.spi_bus = SPI(bus, device)
        self.buf = [0, 0, 0, 0, 0, 0, 0, 0]

        self.OP_NOP = 0x0
        self.OP_DIG0 = 0x1
        self.OP_DIG1 = 0x2
        self.OP_DIG2 = 0x3
        self.OP_DIG3 = 0x4
        self.OP_DIG4 = 0x5
        self.OP_DIG5 = 0x6
        self.OP_DIG6 = 0x7
        self.OP_DIG7 = 0x8
        self.OP_DECODEMODE = 0x9
        self.OP_INTENSITY = 0xA
        self.OP_SCANLIMIT = 0xB
        self.OP_SHUTDOWN = 0xC
        self.OP_DISPLAYTEST = 0xF

        self.init()
Ejemplo n.º 36
0
class LED_LPD8806(object):
  # Constructor
  def __init__(self):
	self.spi = SPI(0,0) #/dev/spidev1.0  (be sure to run Python with su if 'no permission'
	self.spi.msh=1000000 #SPI clock set to 1MHz (slowed from 10MHz for better stability across setups)
	self.spi.bpw = 8 # bits per word
	self.spi.threewire = False # not half-duplex
	self.spi.lsbfirst = False # we want MSB first
	self.spi.mode = 0 # options are modes 0 through 3
	self.spi.cshigh = False # we want chip select to be active low
	self.spi.open(0,0) # make it so
	time.sleep(0.05)

  def setup(self, led_pixels, debug=False):
	if (debug):
		print "Initializing LED strip"
	global pixels
	pixels = [[0x80 for x in range(3)] for y in range(led_pixels)]
	for i in range(led_pixels):
	        pixels[i]=[0x00, 0x00, 0x00]

  # Define LED functions:
  # --------------------

  # Update pixel display with a given delay time between pixel updates:
  def writestrip(self, delay):
	if (delay < 0):
		delay = 0
	for i in range(len(pixels)):
		self.spi.writebytes([0x00, 0x00, 0x00]) #prepare write
	for i in range(len(pixels)):
		self.spi.writebytes(pixels[i]) #write colors to pixels
		time.sleep(delay)

  # Turn off all LEDs:
  def clearstrip(self):
	global pixels
	for i in range(len(pixels)):
		self.spi.writebytes([0x00, 0x00, 0x00]) #prepare write
	for i in range(len(pixels)):
		pixels[i] = [0x80, 0x80, 0x80]
	self.writestrip(0)


  # Set an individual pixel to a specific color (to display later):
  def setpixelcolor(self, n, g, r, b):
	global pixels
	if (n >= len(pixels)):
		return
	if (n < 0):
		return
	if (g > 0xFF):
		g = 0xFF
	if (g < 0x80):
		g = 0x80
	if (r > 0xFF):
		r = 0xFF
	if (r < 0x80):
		r = 0x80
	if (b > 0xFF):
		b = 0xFF
	if (b < 0x80):
		b = 0x80
	pixels[n] = [g, r, b]

  # Update display with warmer colors (more red light) by a specified amount with a delay between pixels
  def warmstrip(self, warmth, delay):
	global pixels
	if (delay < 0):
		delay = 0
	for n in range(len(pixels)):
                if((pixels[n][1] + warmth) < 0x80):
                        pixels[n][1] = 0x80
                elif((pixels[n][2] + warmth) > 0xFF):
                        pixels[n][1] = 0xFF
                else:
			pixels[n][1] = pixels[n][1]+warmth
	self.writestrip(delay)

  # Update display with cooler colors (more blue) by a specified amount with a delay between each pixel
  def coolstrip(self, coolfactor, delay):
	global pixels
	if (delay < 0):
		delay = 0
	for n in range(len(pixels)):
                if((pixels[n][2] + coolfactor) < 0x80):
                        pixels[n][2] = 0x80
                elif((pixels[n][2] + coolfactor) > 0xFF):
                        pixels[n][2] = 0xFF
                else:
                        pixels[n][2] = pixels[n][2]+coolfactor

	self.writestrip(delay)

  # Update display with greener colors by a specified amount with a set delay between each pixel
  def greenstrip(self, lushness, delay):
	global pixels
	if (delay < 0):
		delay = 0
	for n in range(len(pixels)):
                if((pixels[n][0] + lushness) < 0x80):
                        pixels[n][0] = 0x80
                else:
                        pixels[n][0] = pixels[n][0]+lushness
	self.writestrip(delay)

  # Update display with brighter (whiter) light by specified amount with a set delay between pixel updates
  def brightenstrip(self, brightness, delay):
	global pixels
	if (delay < 0):
		delay = 0
        for n in range(len(pixels)):
                if((pixels[n][0] + brightness) < 0x80):
                        pixels[n][0] = 0x80
		elif((pixels[n][0] + brightness) > 0xFF):
			pixels[n][0] = 0xFF
                else:
                        pixels[n][0] = pixels[n][0]+brightness
                if((pixels[n][1] + brightness) < 0x80):
                        pixels[n][1] = 0x80
                elif((pixels[n][1] + brightness) > 0xFF):
                        pixels[n][1] = 0xFF
                else:
                        pixels[n][1] = pixels[n][1]+brightness
                if((pixels[n][2] + brightness) < 0x80):
                        pixels[n][2] = 0x80
                elif((pixels[n][2] + brightness) > 0xFF):
                        pixels[n][2] = 0xFF
                else:
                        pixels[n][2] = pixels[n][2]+brightness
	self.writestrip(delay)

  # Darken display (less light) by specified amount with a set delay between pixel updates
  def dimstrip(self, dimness, delay):
	global pixels
	if (delay < 0):
		delay = 0
	for n in range(len(pixels)):
		if((pixels[n][0] - dimness) < 0x80):
			pixels[n][0] = 0x80
                elif((pixels[n][0] - dimness) > 0xFF):
                        pixels[n][0] = 0xFF
		else:
			pixels[n][0] = pixels[n][0]-dimness
		if((pixels[n][1] - dimness) < 0x80):
			pixels[n][1] = 0x80
		elif((pixels[n][1] - dimness) > 0xFF):
			pixels[n][1] = 0xFF
		else:
			pixels[n][1] = pixels[n][1]-dimness
		if((pixels[n][2] - dimness) < 0x80):
			pixels[n][2] = 0x80
		elif((pixels[n][2] - dimness) > 0xFF):
			pixels[n][2] = 0xFF
		else:
			pixels[n][2] = pixels[n][2]-dimness
	self.writestrip(delay)
Ejemplo n.º 37
0
def ADCinit():	
	RegWrite(ADS1248.MUX0, 0b00000001);	# MUX0:  Pos. input: AIN0, Neg. input: AIN1 (Burnout current source off) 
	RegWrite(ADS1248.MUX1, 0b00100000);	# MUX1:  REF0, normal operation
	RegWrite(ADS1248.SYS0, 0b00000000);	# SYS0:  PGA Gain = 1, 5 SPS
	RegWrite(ADS1248.IDAC0,0b00000000);	# IDAC0: off
	RegWrite(ADS1248.IDAC1,0b11001100);	# IDAC1: n.c.
	RegWrite(ADS1248.VBIAS,0b00000000);	# VBIAS: BIAS voltage disabled
 	RegWrite(ADS1248.OFC0, 0b00000000);	# OFC0:  0 => reset offset calibration
	RegWrite(ADS1248.OFC1, 0b00000000);	# OFC1:  0 => reset offset calibration
	RegWrite(ADS1248.OFC2, 0b00000000);	# OFC2:  0 => reset offset calibration
	RegWrite(ADS1248.GPIOCFG, 0b00000000);	# GPIOCFG: all used as analog inputs
	RegWrite(ADS1248.GPIODIR, 0b00000000);	# GPIODIR: -
	RegWrite(ADS1248.GPIODAT, 0b00000000);	# GPIODAT: -
	
spi = SPI(0,0)	#/dev/spidev1.0
spi.msh=10000 # SPI clock set to 100 kHz
spi.bpw = 8  # bits/word
spi.threewire = False
spi.lsbfirst = False
spi.mode = 1 
spi.cshigh = False  # ADS1248 chip select (active low)
spi.open(0,0)

GPIO.setup("P9_14", GPIO.OUT)


# drive START high to start conversion

GPIO.setup(ADS1248.STARTPIN, GPIO.OUT)
GPIO.output(ADS1248.STARTPIN,GPIO.HIGH)
Ejemplo n.º 38
0
"""

import logging

spi = None

# Load SPI module
try:
    from Adafruit_BBIO.SPI import SPI
except ImportError:
    pass

if 'SPI' in globals():
    # Init the SPI for the serial to parallel
    try:
        spi = SPI(1, 1)
    except:
        pass
    spi.bpw = 8
    spi.mode = 0
else:
    logging.warning("Unable to set up SPI")
    spi = None

class ShiftRegister(object):

    registers = list()
    
    @staticmethod
    def commit():
        """ Send the values to the serial to parallel chips """
Ejemplo n.º 39
0
from Adafruit_BBIO.SPI import SPI 

spi = SPI(1,0) 
spi.mode=2 

spi.msh=200000 
spi.open(1,0) 

print spi.readbytes(4)
#print spi.xfer2([32, 11, 110, 22, 220]) 
spi.close() 
Ejemplo n.º 40
0
from Adafruit_BBIO.SPI import SPI 

spi = SPI(1,0) 
spi.mode=2 

spi.msh=2000000 
spi.open(1,0) 

print spi.xfer2([32, 11, 110, 22, 220]) 
spi.close() 
import Adafruit_BBIO.GPIO as GPIO
from Adafruit_BBIO.SPI import SPI
# from ADS126x_constants import *

spi = SPI(0, 0)

# class ADS126x():

START_PIN = "P9_23"
RSTN_PIN = "P9_24"
DRDY_PIN = "P9_26"

GPIO.setup(RSTN_PIN, GPIO.OUT, pull_up_down=GPIO.PUD_UP)
GPIO.output(RSTN_PIN, GPIO.HIGH)

GPIO.setup(START_PIN, GPIO.OUT, pull_up_down=GPIO.PUD_DOWN)
GPIO.output(START_PIN, GPIO.LOW)

GPIO.setup(DRDY_PIN, GPIO.IN)

R0 = 100.0
A = 3.9083e-3
B = -5.775e-7
C = -4.183e-12


def R2C(R):
    if R >= 100.0:
        return (-R0*A
                +(R0**2 * A**2
                  - 4 * R0 * B * (R0 - R))**0.5)\
Ejemplo n.º 42
0
from Adafruit_BBIO.SPI import SPI

spi = SPI(0,0)
spi.open(0,0)
#spi.msh = 100000
spi.bpw = 8
#spi.mode = b00
try:
#while True:
        # set CS bit high, choose first channel to read from

        #channel = 0;
        #adc = spi.xfer([1,8,0])
        #data = ((adc[1]&3) << 8) + adc[2]

        channelSelect = 0xC0
        channelSelect |= 0x18
        channelSelect <<= 3
        fsr = spi.xfer2([channelSelect, 0x00, 0x00])
        #result = spi.readbytes(2)
        #result2 = spi.readbytes(1)

        resultFinal = 0x0000
        resultFinal = 0x0300 & (resultFinal | (fsr[1] << 8 ))
        resultFinal |= ( ( 0x00FF  & fsr[2]) )
        #print (8 + channel ) << 4
        #print resultFinal

	###################################
	####################################
	resultFinal = 1 #temp
Ejemplo n.º 43
0
class NRF24:
    # Some limits
    MAX_CHANNEL = 127
    MAX_PAYLOAD_SIZE = 32

    # PA Levels
    PA_MIN = 0x00
    PA_LOW = 0x01
    PA_HIGH = 0x02
    PA_MAX = 0x03
    PA_ERROR = 0x04

    # Bit rates
    BR_1MBPS = 0
    BR_2MBPS = 1
    BR_250KBPS = 2

    # CRC
    CRC_DISABLED = 0
    CRC_8 = 1
    CRC_16 = 2

    # Registers
    CONFIG = 0x00
    EN_AA = 0x01
    EN_RXADDR = 0x02
    SETUP_AW = 0x03
    SETUP_RETR = 0x04
    RF_CH = 0x05
    RF_SETUP = 0x06
    STATUS = 0x07
    OBSERVE_TX = 0x08
    RPD = 0x09  # CD on Non-P version
    RX_ADDR_P0 = 0x0A
    RX_ADDR_P1 = 0x0B
    RX_ADDR_P2 = 0x0C
    RX_ADDR_P3 = 0x0D
    RX_ADDR_P4 = 0x0E
    RX_ADDR_P5 = 0x0F
    TX_ADDR = 0x10
    RX_PW_P0 = 0x11
    RX_PW_P1 = 0x12
    RX_PW_P2 = 0x13
    RX_PW_P3 = 0x14
    RX_PW_P4 = 0x15
    RX_PW_P5 = 0x16
    FIFO_STATUS = 0x17
    DYNPD = 0x1C
    FEATURE = 0x1D

    # Bit Mask Mnemonics - CONFIG register
    MASK_RX_DR = 0x40
    MASK_TX_DS = 0x20
    MASK_MAX_RT = 0x10
    EN_CRC = 0x08
    CRCO = 0x04
    PWR_UP = 0x02
    PRIM_RX = 0x01
    
    # Bit Mask Mnemonics - STATUS register
    RX_DR = 0x40
    TX_DS = 0x20
    MAX_RT = 0x10
    TX_FULL = 0x01
    RX_P_NO_MASK = 0x0E # isolate pipe number

    # Bit Mask Mnemonics - FIFO_STATUS register
    TX_REUSE = 0x40
    TXFIFO_FULL = 0x20
    TXFIFO_EMPTY = 0x10
    RXFIFO_FULL = 0x02
    RXFIFO_EMPTY = 0x01

    # Bit Mask Mnemonics - DYNPD register
    DPL_P5 = 0x20
    DPL_P4 = 0x10
    DPL_P3 = 0x08
    DPL_P2 = 0x04
    DPL_P1 = 0x02
    DPL_P0 = 0x01
    
    # Bit Mask Mnemonics - FEATURE register
    EN_DPL = 0x04
    EN_ACK_PAY = 0x02
    EN_DYN_ACK = 0x01

    # Shift counts
    ARD = 4
    ARC = 0
    PLOS_CNT = 4
    ARC_CNT = 0
    RX_P_NO = 1

    # Instruction Mnemonics
    R_REGISTER = 0x00
    W_REGISTER = 0x20
    REGISTER_MASK = 0x1F
    ACTIVATE = 0x50
    R_RX_PL_WID = 0x60
    R_RX_PAYLOAD = 0x61
    W_TX_PAYLOAD = 0xA0
    W_ACK_PAYLOAD = 0xA8
    FLUSH_TX = 0xE1
    FLUSH_RX = 0xE2
    REUSE_TX_PL = 0xE3
    NOP = 0xFF

    # Non-P omissions
    LNA_HCURR = 0x01
    LNA_ON = 1
    LNA_OFF = 0

    # P model Mask Mnemonics
    RF_DR_LOW = 0x20
    RF_DR_HIGH = 0x08
    RF_PWR_LOW = 0x02
    RF_PWR_HIGH = 0x04

    datarate_e_str_P = ["1MBPS", "2MBPS", "250KBPS"]
    model_e_str_P = ["nRF24L01", "nRF24l01+"]
    crclength_e_str_P = ["Disabled", "8 bits", "16 bits"]
    pa_dbm_e_str_P = ["PA_MIN", "PA_LOW", "PA_HIGH", "PA_MAX"]

    @staticmethod
    def print_single_status_line(name, value):
        """Prints name = value"""
        print("{0:<16}= {1}".format(name, value))

    @staticmethod
    def _to_8b_list(data):
        """Convert an arbitray iteratable or single int to a list of ints
            where each int is smaller than 256."""
        if isinstance(data, str):
            data = [ord(x) & 0xFF for x in data]
        elif isinstance(data, (int, long)):
            data = [data & 0xFF]
        else:
            data = [int(x) & 0xFF for x in data]
        return data

    def __init__(self, major=None, minor=None, ce_pin=None, irq_pin=None):
        """Construtor.
        
            major and minor selects SPI port,
            ce_pin is optional GPIO pin number for CE signal
            irq_pin is optional GPIO pin number for IRQ signal"""
        # defaults and miscelaneous initialization
        self.payload_size = 32  # *< Fixed size of payloads
        self.ack_payload_available = False  # *< Whether there is an ack payload waiting
        self.dynamic_payloads_enabled = False  # *< Whether dynamic payloads are enabled.
        self.ack_payload_length = 5  # *< Dynamic size of pending ack payload.
        self.pipe0_reading_address = None  # *< Last address set on pipe 0 for reading.
        self.spidev = None
        self.last_error = 0
        self.auto_ack = 0
        self.address_length = 5

        # If all parameters are available, lets start the radio!
        if major is not None and minor is not None and irq_pin is not None:
            self.begin(major, minor, ce_pin, irq_pin)

    def begin(self, major, minor, ce_pin, irq_pin):
        """Radio initialization, must be called before anything else.
        
            major and minor selects SPI port,
            ce_pin is GPIO pin number for CE signal
            irq_pin is optional GPIO pin number for IRQ signal"""
        # Initialize SPI bus
        if ADAFRUID_BBIO_SPI:
            self.spidev = SPI(major, minor)
            self.spidev.bpw = 8
            try:
                self.spidev.msh = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed
        else:
            self.spidev = spidev.SpiDev()
            self.spidev.open(major, minor)
            self.spidev.bits_per_word = 8
            try:
                self.spidev.max_speed_hz = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed

        self.spidev.cshigh = False
        self.spidev.mode = 0
        self.spidev.loop = False
        self.spidev.lsbfirst = False
        self.spidev.threewire = False

        # Save pin numbers
        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        # If CE pin is not used, CE signal must be always high
        if self.ce_pin is not None:
            GPIO.setup(self.ce_pin, GPIO.OUT)
        
        # IRQ pin is optional
        if self.irq_pin is not None:
            GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Reset radio registers
        self.reset()

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        self.p_variant = False  # False for RF24L01 and true for RF24L01P
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        # This must be done after setDataRate()
        self.setRetries(int('0101', 2), 15)
        # Line bellow will set maximum (4ms) delay
        #self.setRetries(15, 15)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.channel = 76
        self.setChannel(self.channel)

        # Powers up the radio, this can take up to 4.5ms
        # when CE is low radio will be in standby and will initiate
        # reception or transmission very shortly after CE is raised
        # If CE pin is not used, will Power up only on startListening and stopListening
        if self.ce_pin is not None:
            self.powerUp()

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()
        self.clear_irq_flags()

    def end(self):
        """ End use of the radio """
        self.ce(0)
        if self.spidev:
            self.powerDown()
            self.spidev.close()
            self.spidev = None

    def startListening(self):
        """ Set radio for reception
        
            Use openReadingPipe to set up reception pipes before listening """
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) | NRF24.PWR_UP | NRF24.PRIM_RX)
        self.flush_tx()
        self.flush_rx()
        self.clear_irq_flags()

        # Restore the pipe0 address, if exists
        if self.pipe0_reading_address:
            self.write_register(self.RX_ADDR_P0, self.pipe0_reading_address)

        # Go!
        self.ce(1)

        # wait for the radio to come up
        if self.ce_pin is None:
            time.sleep(45 / 10000.0) # 4.5 ms
        else:
            time.sleep(130 / 1000000.0) # 130us

    def ce(self, level, pulse=0):
        """ Controls CE pin """
        # CE Pin is optional (but highly recommended)
        if self.ce_pin is not None:
            GPIO.output(self.ce_pin, level)
            if pulse > 0:
                time.sleep(pulse)
                GPIO.output(self.ce_pin, 1 - level)

    def irqWait(self, timeout=30000):
        """ Wait for IRQ pin LOW, timeout in miliseconds """
        if self.irq_pin is None:
            return True
        # TODO: A race condition may occur here. => wait for level?
        if GPIO.input(self.irq_pin) == 0:  # Pin is already down. Packet is waiting?
            return True

        try:
            return GPIO.wait_for_edge(self.irq_pin, GPIO.FALLING, timeout) == 1
        except TypeError:  # Timeout parameter not supported
            return GPIO.wait_for_edge(self.irq_pin, GPIO.FALLING) == 1
        except AttributeError:
            raise RuntimeError("GPIO lib does not support wait_for_edge()")

    def read_register(self, reg, length=1):
        """ Read one or more registers """
        buf = [NRF24.R_REGISTER | (NRF24.REGISTER_MASK & reg)]
        buf += [NRF24.NOP] * max(1, length)

        resp = self.spidev.xfer2(buf)
        if length == 1:
            return resp[1]

        return resp[1:]

    def write_register(self, reg, value):
        """ Write register value """
        buf = [NRF24.W_REGISTER | (NRF24.REGISTER_MASK & reg)]
        buf += self._to_8b_list(value)
        self.spidev.xfer2(buf)

    def write_payload(self, buf):
        """ Writes data to the payload register, automatically padding it
            to match the required length. Returns the number of bytes
            actually written. """
        buf = self._to_8b_list(buf)
        if self.dynamic_payloads_enabled:
            if len(buf) > self.MAX_PAYLOAD_SIZE:
                raise RuntimeError("Dynamic payload is larger than the " +
                                   "maximum size.")
            blank_len = 0
        else:
            if len(buf) > self.payload_size:
                raise RuntimeError("Payload is larger than the fixed payload" +
                                   "size (%d vs. %d bytes)" % (len(buf), self.payload_size))
            blank_len = self.payload_size - len(buf)

        txbuffer = [NRF24.W_TX_PAYLOAD] + buf + ([0x00] * blank_len)
        self.spidev.xfer2(txbuffer)
        return len(txbuffer) - 1

    def read_payload(self, buf, buf_len=-1):
        """ Reads data from the payload register and clears the
            DR bit of the STATUS register. """
        if buf_len < 0:
            buf_len = self.payload_size

        if not self.dynamic_payloads_enabled:
            data_len = min(self.payload_size, buf_len)
            blank_len = self.payload_size - data_len
        else:
            data_len = self.getDynamicPayloadSize()
            blank_len = 0

        txbuffer = [NRF24.R_RX_PAYLOAD] + [NRF24.NOP] * (blank_len + data_len)

        payload = self.spidev.xfer2(txbuffer)
        del buf[:]
        buf += payload[1:data_len + 1]

        self.write_register(NRF24.STATUS, NRF24.RX_DR)

        return data_len

    def flush_rx(self):
        """ Flush RX buffer, return status """
        return self.spidev.xfer2([NRF24.FLUSH_RX])[0]

    def flush_tx(self):
        """ Flush TX buffer, return status """
        return self.spidev.xfer2([NRF24.FLUSH_TX])[0]

    def get_status(self):
        """ Read status register """
        return self.spidev.xfer2([NRF24.NOP])[0]

    def print_status(self, status):
        """ Print decoded status """
        status_str = "0x{0:02x} RX_DR={1:x} TX_DS={2:x} MAX_RT={3:x} RX_P_NO={4:x} TX_FULL={5:x}".format(
            status,
            1 if status & NRF24.RX_DR else 0,
            1 if status & NRF24.TX_DS else 0,
            1 if status & NRF24.MAX_RT else 0,
            ((status >> NRF24.RX_P_NO) & int("111", 2)),
            1 if status & NRF24.TX_FULL else 0)

        self.print_single_status_line("STATUS", status_str)

    def print_observe_tx(self, value):
        """ Print decoded observe_tx register:
        
            lost packets (accumulated) and retransmited packets (last tx) """
        tx_str = "OBSERVE_TX=0x{0:02x}: POLS_CNT={2:x} ARC_CNT={2:x}\r\n".format(
            value,
            (value >> NRF24.PLOS_CNT) & int("1111", 2),
            (value >> NRF24.ARC_CNT) & int("1111", 2))
        self.print_single_status_line("OBSERVE_TX", tx_str)

    def print_byte_register(self, name, reg, qty=1):
        """ Print byte registers """
        registers = ["0x{:0>2x}".format(self.read_register(reg+r)) for r in range(0, qty)]
        self.print_single_status_line(name, " ".join(registers))

    def print_address_register(self, name, reg, qty=1):
        """ Print address register (LSB to MSB) """
        address_registers = ["0x{0:>02x}{1:>02x}{2:>02x}{3:>02x}{4:>02x}".format(
            *self.read_register(reg+r, 5))
            for r in range(qty)]

        self.print_single_status_line(name, " ".join(address_registers))

    def setChannel(self, channel):
        """ Set radio channel (0 to MAX_CHANNEL) """
        if channel < 0 or channel > self.MAX_CHANNEL:
            raise RuntimeError("Channel number out of range")
        self.channel = channel
        self.write_register(NRF24.RF_CH, channel)

    def getChannel(self):
        """ Read channel register """
        return self.read_register(NRF24.RF_CH)

    def setPayloadSize(self, size):
        """ Set payload size """
        self.payload_size = min(max(size, 1), NRF24.MAX_PAYLOAD_SIZE)

    def getPayloadSize(self):
        """ Get payload size """
        return self.payload_size

    def printDetails(self):
        """ Prints register values and other information """
        self.print_status(self.get_status())
        self.print_address_register("RX_ADDR_P0-1", NRF24.RX_ADDR_P0, 2)
        self.print_byte_register("RX_ADDR_P2-5", NRF24.RX_ADDR_P2, 4)
        self.print_address_register("TX_ADDR", NRF24.TX_ADDR)

        self.print_byte_register("RX_PW_P0-6", NRF24.RX_PW_P0, 6)
        self.print_byte_register("EN_AA", NRF24.EN_AA)
        self.print_byte_register("EN_RXADDR", NRF24.EN_RXADDR)
        self.print_byte_register("RF_CH", NRF24.RF_CH)
        self.print_byte_register("RF_SETUP", NRF24.RF_SETUP)
        self.print_byte_register("SETUP_AW", NRF24.SETUP_AW)
        self.print_byte_register("OBSERVE_TX", NRF24.OBSERVE_TX)
        self.print_byte_register("CONFIG", NRF24.CONFIG)
        self.print_byte_register("FIFO_STATUS", NRF24.FIFO_STATUS)
        self.print_byte_register("DYNPD", NRF24.DYNPD)
        self.print_byte_register("FEATURE", NRF24.FEATURE)

        self.print_single_status_line("Data Rate", NRF24.datarate_e_str_P[self.getDataRate()])
        self.print_single_status_line("Model", NRF24.model_e_str_P[self.isPVariant()])
        self.print_single_status_line("CRC Length", NRF24.crclength_e_str_P[self.getCRCLength()])
        self.print_single_status_line("PA Power", NRF24.pa_dbm_e_str_P[self.getPALevel()])

    def stopListening(self):
        """ Stop listenning and set up transmission """
        self.ce(0)
        self.flush_tx()
        self.flush_rx()
        self.clear_irq_flags()

        # Enable TX
        self.write_register(NRF24.CONFIG,
                            (self.read_register(NRF24.CONFIG) | NRF24.PWR_UP) & ~NRF24.PRIM_RX)

        # Enable pipe 0 for auto-ack
        self.write_register(NRF24.EN_RXADDR, self.read_register(NRF24.EN_RXADDR) | 1)

        # wait for the radio to come up
        if self.ce_pin is None:
            time.sleep(45 / 10000.0) # 4.5 ms
        else:
            time.sleep(130 / 1000000.0) # 130us

    def powerDown(self):
        """ Power down radio """
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) & ~ NRF24.PWR_UP)

    def powerUp(self):
        """ Power up radio """
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) | NRF24.PWR_UP)
        time.sleep(4.5e-3)

    def write(self, buf):
        """ Sends buf and wait for end of transmission and acknowledgement
        
            call stopListenning and openWritingPipe before sending
            buf can be a single int or a container of char or int """
        self.last_error = None
        length = self.write_payload(buf)
        self.ce(1)

        sent_at = monotonic()
        packet_time = ((1 + length + self.crc_length + self.address_length) * 8 + 9)/(self.data_rate_bits * 1000.)

        if self.auto_ack != 0:
            packet_time *= 2

        if self.retries != 0 and self.auto_ack != 0:
            timeout = sent_at + (packet_time + self.delay)*self.retries
        else:
            timeout = sent_at + packet_time * 2  # 2 is empiric

        while monotonic() < timeout:
            time.sleep(packet_time)
            status = self.get_status()
            if status & NRF24.TX_DS:
                self.ce(0)
                return True

            if status & NRF24.MAX_RT:
                self.last_error = 'MAX_RT'
                self.ce(0)
                break

        self.ce(0)
        if self.last_error is None:
            self.last_error = 'TIMEOUT'

        self.flush_tx()  # Avoid leaving the payload in tx fifo
        return False

    def startFastWrite(self, buf):
        """ Starts sending of buf but do not wait for end of transmission. CE is left high."""
        self.write_payload(buf)
        self.ce(1)

    def startWrite(self, buf):
        """ Starts sending of buf but do not wait for end of transmission. CE is pulsed."""
        self.write_payload(buf)
        self.ce(1, 10e-6) # Pulse CE to start tranmission

    def getDynamicPayloadSize(self):
        """ Reads the size of received payload when using dynamic payloads """
        return self.spidev.xfer2([NRF24.R_RX_PL_WID, NRF24.NOP])[1]

    def available(self, pipe_num=None, irq_wait=False, irq_timeout=30000):
        """ Tests if there is a reception available
            
            pipe_num should be None or a list. If not None, it will receive information 
            on pipes with available data.
            
            if irq_wait is True, will wait for IRQ line to change from HIGH to LOW
            irq_timeout is the timeout for this wait, in miliseconds """
        status = self.get_status()
        result = False

        # Sometimes the radio specifies that there is data in one pipe but
        # doesn't set the RX flag...
        if status & NRF24.RX_DR or (status & NRF24.RX_P_NO_MASK != NRF24.RX_P_NO_MASK):
            result = True
        else:
            if irq_wait:  # Will use IRQ wait
                if self.irqWait(irq_timeout):  # Do we have a packet?
                    status = self.get_status()  # Seems like we do!
                    if status & NRF24.RX_DR or (status & NRF24.RX_P_NO_MASK != NRF24.RX_P_NO_MASK):
                        result = True

        if pipe_num is not None:
            del pipe_num[:]
            if result:
                pipe_num.append((status & NRF24.RX_P_NO_MASK) >> NRF24.RX_P_NO)

        # Handle ack payload receipt
        if status & NRF24.TX_DS:
            self.write_register(NRF24.STATUS, NRF24.TX_DS)

        return result

    def read(self, buf, buf_len=-1):
        """ Read payload from received packet. Returns != 0 if there are more packets in the FIFO. """
        # Fetch the payload
        self.read_payload(buf, buf_len)

        # was this the last of the data available?
        return self.read_register(NRF24.FIFO_STATUS) & NRF24.RXFIFO_EMPTY

    def clear_irq_flags(self):
        """ Clear flags in status register. """
        self.write_register(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

    def whatHappened(self):
        """ Read the status & reset the status in one easy call
        
            Returns a dictionary informing tx_ok, tx_fail and rx_ready
            """
        status = self.spidev.xfer2(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)[0]

        # Report to the user what happened
        tx_ok = status & NRF24.TX_DS
        tx_fail = status & NRF24.MAX_RT
        rx_ready = status & NRF24.RX_DR
        return {'tx_ok': tx_ok, "tx_fail": tx_fail, "rx_ready": rx_ready}

    def openWritingPipe(self, address):
        """ Sets tx address 
            
            address is the address in transmited packet (2 to 5 bytes), LSB to MSB
            """
        self.write_register(NRF24.RX_ADDR_P0, address)
        self.write_register(NRF24.TX_ADDR, address)
        if not self.dynamic_payloads_enabled:
            self.write_register(NRF24.RX_PW_P0, self.payload_size)

    def openReadingPipe(self, pipe, address):
        """ Sets rx address for a pipe and enables it for recieving
            
            pipe should be 0 to 5
            address is the address
                for pipe 0 or 1, 2 to 5 bytes LSB to MSB
                for pipes 2 to 5, 1 byte (LSB, MSB cames from pipe 1)
            """
        if pipe >= 6:
            raise RuntimeError("Invalid pipe number")
        if (pipe >= 2 and len(address) > 1) or len(address) > 5:
            raise RuntimeError("Invalid adress length")

        # If this is pipe 0, cache the address.  This is needed because
        # openWritingPipe() will overwrite the pipe 0 address, so
        # startListening() will have to restore it.
        if pipe == 0:
            self.pipe0_reading_address = address

        self.write_register(NRF24.RX_ADDR_P0 + pipe, address)
        if not self.dynamic_payloads_enabled:
            self.write_register(NRF24.RX_PW_P0 + pipe, self.payload_size)

        # Note it would be more efficient to set all of the bits for all open
        # pipes at once.  However, I thought it would make the calling code
        # more simple to do it this way.
        self.write_register(NRF24.EN_RXADDR,
                            self.read_register(NRF24.EN_RXADDR) | (1 << pipe))

    def closeReadingPipe(self, pipe):
        """ Disabe a receiving pipe """
        self.write_register(NRF24.EN_RXADDR,
                            self.read_register(NRF24.EN_RXADDR) & ~(1 << pipe))

    def toggle_features(self):
        """ Enable DUNPD and FEATURE registers on non P variant """
        buf = [NRF24.ACTIVATE, 0x73]
        self.spidev.xfer2(buf)

    def enableDynamicPayloads(self):
        """ Enables dynamic size payloads """
        # First try writing to the features
        self.write_register(NRF24.FEATURE, self.read_register(NRF24.FEATURE) | NRF24.EN_DPL)

        # If it didn't work, the features are not enabled
        if not self.read_register(NRF24.FEATURE):
            # So enable them and try again
            self.toggle_features()
            self.write_register(NRF24.FEATURE, self.read_register(NRF24.FEATURE) | NRF24.EN_DPL)

        # Enable dynamic payload on all pipes
        # Not sure the use case of only having dynamic payload on certain
        # pipes, so the library does not support it.
        self.write_register(NRF24.DYNPD, self.read_register(NRF24.DYNPD) | 0b00111111)

        self.dynamic_payloads_enabled = True

    def enableAckPayload(self):
        """ Enable ack payload and dynamic payload features """
        # First try writing to the features
        self.write_register(NRF24.FEATURE,
                            self.read_register(NRF24.FEATURE) | NRF24.EN_ACK_PAY | NRF24.EN_DPL)

        # If it didn't work, the features are not enabled
        if not self.read_register(NRF24.FEATURE):
            # So enable them and try again
            self.toggle_features()
            self.write_register(NRF24.FEATURE,
                                self.read_register(NRF24.FEATURE) | NRF24.EN_ACK_PAY | NRF24.EN_DPL)

        # Enable dynamic payload on pipes 0 & 1
        self.write_register(NRF24.DYNPD, self.read_register(NRF24.DYNPD) | NRF24.DPL_P1 | NRF24.DPL_P0)

    def writeAckPayload(self, pipe, buf, buf_len):
        """ Write payload for acknowledgement """
        txbuffer = [NRF24.W_ACK_PAYLOAD | (pipe & 0x7)]

        max_payload_size = 32
        data_len = min(buf_len, max_payload_size)
        txbuffer.extend(buf[0:data_len])

        self.spidev.xfer2(txbuffer)

    def isAckPayloadAvailable(self):
        """ Check if there is a payload in a acknowledgement.

            Note: this will clear the ack payload flag. """
        result = self.ack_payload_available
        self.ack_payload_available = False
        return result

    def isPVariant(self):
        """ Returns true if nRF24L01+, False if nRF24L01 """
        return self.p_variant

    def setAutoAck(self, enable):
        """ Enable or disable auto acknoledge for all pipes """
        if enable:
            self.write_register(NRF24.EN_AA, 0x3F)
            self.auto_ack = 0x3f
            if self.self.getCRCLength() == NFR24.CRC_DISABLED:
                self.setCRCLength(NRF24.CRC_8)  # Enhanced Shockburst requires at least 1 byte CRC
        else:
            self.auto_ack = 0
            self.write_register(NRF24.EN_AA, 0)

    def setAutoAckPipe(self, pipe, enable):
        """ Enable or disable auto acknoledge for an specific pipe """
        if pipe <= 6:
            en_aa = self.read_register(NRF24.EN_AA)
            if enable:
                if self.self.getCRCLength() == NFR24.CRC_DISABLED:
                    self.setCRCLength(NRF24.CRC_8)  # Enhanced Shockburst requires at least 1 byte CRC
                en_aa |= 1 << pipe
                self.auto_ack |= 1 << pipe
            else:
                en_aa &= ~1 << pipe
                self.auto_ack &= ~1 << pipe

            self.write_register(NRF24.EN_AA, en_aa)

    def setAddressWidth(self, width):
        """ Set address width (2 to 5 bytes) """
        if width >= 2 and width <= 5:
            self.write_register(NRF24.SETUP_AW, width - 2)
            self.address_width = width

    def testCarrier(self):
        """ Tests if there is a radio signal at current channel. """
        return self.read_register(NRF24.RPD) & 1

    def setPALevel(self, level):
        """ Set transmission level """
        setup = self.read_register(NRF24.RF_SETUP)
        setup &= ~(NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH)

        if level == NRF24.PA_MAX:
            setup |= NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH
        elif level == NRF24.PA_HIGH:
            setup |= NRF24.RF_PWR_HIGH
        elif level == NRF24.PA_LOW:
            setup |= NRF24.RF_PWR_LOW
        elif level == NRF24.PA_MIN:
            pass
        elif level == NRF24.PA_ERROR:
            # On error, go to maximum PA
            setup |= NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH

        self.write_register(NRF24.RF_SETUP, setup)

    def getPALevel(self):
        """ Inform current transmission level """
        power = self.read_register(NRF24.RF_SETUP) & (NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH)
        if power == (NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH):
            return NRF24.PA_MAX
        elif power == NRF24.RF_PWR_HIGH:
            return NRF24.PA_HIGH
        elif power == NRF24.RF_PWR_LOW:
            return NRF24.PA_LOW
        else:
            return NRF24.PA_MIN

    def setDataRate(self, speed):
        """ Set data rate. returns True if success. """
        setup = self.read_register(NRF24.RF_SETUP)
        setup &= ~(NRF24.RF_DR_LOW | NRF24.RF_DR_HIGH)

        if speed == NRF24.BR_250KBPS:
            # Must set the RF_DR_LOW to 1 RF_DR_HIGH (used to be RF_DR) is already 0
            # Making it '10'.
            self.data_rate_bits = 250
            self.data_rate = NRF24.BR_250KBPS
            setup |= NRF24.RF_DR_LOW
        elif speed == NRF24.BR_2MBPS:
            # Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
            # Making it '01'
            self.data_rate_bits = 2000
            self.data_rate = NRF24.BR_2MBPS
            setup |= NRF24.RF_DR_HIGH
        else:
            # 1Mbs
            self.data_rate_bits = 1000
            self.data_rate = NRF24.BR_1MBPS

        self.write_register(NRF24.RF_SETUP, setup)

        # Verify our result
        return self.read_register(NRF24.RF_SETUP) == setup

    def getDataRate(self):
        """ Inform current data rate """
        dr = self.read_register(NRF24.RF_SETUP) & (NRF24.RF_DR_LOW | NRF24.RF_DR_HIGH)
        # Order matters in our case below
        if dr == NRF24.RF_DR_LOW:
            # '10' = 250KBPS
            return NRF24.BR_250KBPS
        elif dr == NRF24.RF_DR_HIGH:
            # '01' = 2MBPS
            return NRF24.BR_2MBPS
        else:
            # '00' = 1MBPS
            return NRF24.BR_1MBPS

    def setCRCLength(self, length):
        """ Set CRC length 
        
            length = CRC_DISABLED, CRC_8 or CRC_16 """
        config = self.read_register(NRF24.CONFIG) & ~(NRF24.EN_CRC | NRF24.CRCO)

        if length == NRF24.CRC_DISABLED:
            self.crc_length = 0
        elif length == NRF24.CRC_8:
            config |= NRF24.EN_CRC
            self.crc_length = 1
        else:
            config |= NRF24.EN_CRC
            config |= NRF24.CRCO
            self.crc_length = 2

        self.write_register(NRF24.CONFIG, config)

    def getCRCLength(self):
        """ Get CRC length 
        
            returns CRC_DISABLED, CRC_8 or CRC_16 """
        result = NRF24.CRC_DISABLED
        config = self.read_register(NRF24.CONFIG) & (NRF24.CRCO | NRF24.EN_CRC)

        if config & NRF24.EN_CRC:
            if config & NRF24.CRCO:
                result = NRF24.CRC_16
            else:
                result = NRF24.CRC_8

        return result

    def disableCRC(self):
        """ Disable CRC """
        disable = self.read_register(NRF24.CONFIG) & ~NRF24.EN_CRC
        self.write_register(NRF24.CONFIG, disable)

    def setRetries(self, delay, count):
        """ Set timeout and number of retries
        
            delay (timeout) 0-15 as per datasheet
            count 0-15 max number of retries (0=disable retries)"""
        self.write_register(NRF24.SETUP_RETR, (delay & 0xf) << NRF24.ARD | (count & 0xf) << NRF24.ARC)
        self.delay = delay * 0.000250
        self.retries = count
        self.max_timeout = (self.payload_size / float(self.data_rate_bits) + self.delay) * self.retries
        self.timeout = (self.payload_size / float(self.data_rate_bits) + self.delay)

    def getRetries(self):
        """ Return current retry configuration. """
        return self.read_register(NRF24.SETUP_RETR)

    def getMaxTimeout(self):
        """ Return current maximum timeout (no ack after all retries). """
        return self.max_timeout

    def getTimeout(self):
        """ Return current timeout for one transmission. """
        return self.timeout

    def reset(self):
        """ Make sure the NRF is in the same state as after power up
            to avoid problems resulting from left over configuration
            from other programs."""
        self.ce(0)
        reset_values = {0: 0x08, 1: 0x3F, 2: 0x03, 3: 0x03, 4: 0x03, 5: 0x02, 6: 0x0e,
                        0x0a: [0xe7, 0xe7, 0xe7, 0xe7, 0xe7],
                        0x0b: [0xc2, 0xc2, 0xc2, 0xc2, 0xc2],
                        0x0c: 0xc3, 0x0d: 0xc4, 0x0e: 0xc5, 0x0f: 0xc6,
                        0x10: [0xe7, 0xe7, 0xe7, 0xe7, 0xe7],
                        0x11: 0, 0x12: 0, 0x13: 0, 0x14: 0, 0x15: 0, 0x16: 0,
                        0x1c: 0, 0x1d: 0}
        for reg, value in reset_values.items():
            self.write_register(reg, value)

        self.flush_rx()
        self.flush_tx()
Ejemplo n.º 44
0
class ltc1858:
    def __init__(self,
                 spi_bus = 0,
                 spi_client = 0,
                 spi_freq = 1000000,
                 spi_mode = 0b00,
                 RD = "P9_12"):
        #define pins
        self.logger = logging.getLogger('LTC1858')
        self.logger.setLevel(logging.WARNING)

        self.spi_bus = spi_bus
        self.spi_client = spi_client
        self.spi_freq = spi_freq #1Mhz is plenty
        self.spi_mode = spi_mode
        
        """We actually send 16 bits but the SPI protocol is a bit screwy
        It's just easier currently to send two 8 bit words as protocol
        is broken"""
        self.spi_bits_per_word = 8
        self.spi_cshigh = False
        
        #Need the RD set to low to get data - Could do something    
        #more fancy with this later

        self.RD = RD

        self.data_in = BitArray(14)
        self.vrange = {"+-5V" : 0b00,
                     "+5V" : 0b10,
                     "+-10V" : 0b01,
                     "+10V" : 0b11}

        #Create a chan dict as not standard binary
        self.chans = {0 : 0b000,
                      1 : 0b100,
                      2 : 0b001,
                      3 : 0b101,
                      4 : 0b010,
                      5 : 0b110,
                      6 : 0b011,
                      7 : 0b111}


        self.adc_reg = {"Monitor" : False,
                        "Range" : "+5V",
                        "V" : 0,
                        "Command" : 0}

        #Bitstring is terribly slow so for a register
        #read we use a preconstructed bitstring rather
        #Than create every time
        
        self.chip_reg = []
        for i in xrange(8):
            self.chip_reg.append(self.adc_reg.copy())

        self.single_ended = 0b1

        self.setup_chip()
        self.setup_spi()

    def setup_spi(self):
        #This is for BB Black
        self.spi = SPI(self.spi_bus, self.spi_client)
        self.spi.msh = self.spi_freq
        self.spi.mode = self.spi_mode
        self.bpw = self.spi_bits_per_word
        self.spi.cshigh = self.spi_cshigh
        
    def setup_chip(self):
        #Just need to setup RD and make sure it is low
        GPIO.setup(self.RD, GPIO.OUT)
        GPIO.output(self.RD, False)
     

    def set_reg(self,adc,monitor,adc_range):
        self.chip_reg[adc]["Monitor"] = monitor
        self.chip_reg[adc]["Range"] = adc_range
        self.chip_reg[adc]["Command"] = self.construct_word(adc,adc_range)

    def construct_word(self, chan_no, vrange):
        t_word = BitArray(8)
        t_word[0] = self.single_ended
        t_word[1:4] = self.chans[chan_no]
        t_word[4:6] = self.vrange[vrange]
        
        #Ignore nap and sleep
        return t_word

    def single_read(self, chan_no, v_range):
        #Need to set command and then read back so 
        #two words - Just send the same word twice
        #self.send_data(self.construct_word(chan_no, v_range))
        data_out = self.send_data(self.construct_word(chan_no, v_range))
        data_conv  = self.convert_to_v(data_out, v_range)
        return data_conv

    def register_read(self):
        #This does one pass at reading all dac inputs
        for i in xrange(8):
            if self.chip_reg[i]["Monitor"] is True:
                data_out = self.send_data(self.chip_reg[i]["Command"])
                vv = self.convert_to_v(data_out, self.chip_reg[i]["Range"])
                self.chip_reg[i]["V"] = vv
                                      
    def send_data(self,data):
        self.spi.writebytes([data.uint,0x00]) #Send data then zeros as per DS
        #at 1MHz we don't care if it's duplex read
        a,b = self.spi.readbytes(2)
        self.data_in[0:8] = a 
        self.data_in[8:] = (b >> 2)
        return self.data_in

    def convert_to_v(self,num, v_range):  
        if v_range == "+5V":
            return 5.0*num.uint/2**14
        elif v_range == "+10V":
            return 10.0*num.uint/2**14
        elif v_range == "+-5V":
                return num.int*5.0/2**13
        elif v_range == "+-10V":
            return num.int*10.0/2**13
        else:
            return -69
Ejemplo n.º 45
0
class NRF24:
    MAX_CHANNEL = 127
    MAX_PAYLOAD_SIZE = 32

    # PA Levels
    PA_MIN = 0x00
    PA_LOW = 0x01
    PA_HIGH = 0x02
    PA_MAX = 0x03
    PA_ERROR = 0x04

    # Bit rates
    BR_1MBPS = 0
    BR_2MBPS = 1
    BR_250KBPS = 2

    # CRC
    CRC_DISABLED = 0x0
    CRC_8 = 0x02
    CRC_16 = 0x04
    CRC_ENABLED = 0x08

    EN_CRC = 0x08
    CRCO = 0x04

    # Registers
    CONFIG = 0x00
    EN_AA = 0x01
    EN_RXADDR = 0x02
    SETUP_AW = 0x03
    SETUP_RETR = 0x04
    RF_CH = 0x05
    RF_SETUP = 0x06
    STATUS = 0x07
    OBSERVE_TX = 0x08
    RPD = 0x09
    RX_ADDR_P0 = 0x0A
    RX_ADDR_P1 = 0x0B
    RX_ADDR_P2 = 0x0C
    RX_ADDR_P3 = 0x0D
    RX_ADDR_P4 = 0x0E
    RX_ADDR_P5 = 0x0F
    TX_ADDR = 0x10
    RX_PW_P0 = 0x11
    RX_PW_P1 = 0x12
    RX_PW_P2 = 0x13
    RX_PW_P3 = 0x14
    RX_PW_P4 = 0x15
    RX_PW_P5 = 0x16
    FIFO_STATUS = 0x17
    DYNPD = 0x1C
    FEATURE = 0x1D

    # Bit Mnemonics */
    MASK_RX_DR = 0x40
    MASK_TX_DS = 0x20
    MASK_MAX_RT = 0x10

    PWR_UP = 0x02
    PRIM_RX = 0x01
    PLL_LOCK = 0x10
    RX_DR = 0x40
    TX_DS = 0x20
    MAX_RT = 0x10
    TX_FULL = 0x01

    EN_DPL = 0x04
    EN_ACK_PAY = 0x02
    EN_DYN_ACK = 0x01

    # Shift counts
    ARD = 4
    ARC = 0
    PLOS_CNT = 4
    ARC_CNT = 0
    RX_P_NO = 1

    TX_REUSE = 6
    FIFO_FULL = 5
    TX_EMPTY = 4
    RX_FULL = 1
    RX_EMPTY = 0

    DPL_P5 = 5
    DPL_P4 = 4
    DPL_P3 = 3
    DPL_P2 = 2
    DPL_P1 = 1
    DPL_P0 = 0

    #Masks
    RX_P_NO_MASK = 0x0E

    # Instruction Mnemonics
    R_REGISTER = 0x00
    W_REGISTER = 0x20
    REGISTER_MASK = 0x1F
    ACTIVATE = 0x50
    R_RX_PL_WID = 0x60
    R_RX_PAYLOAD = 0x61
    W_TX_PAYLOAD = 0xA0
    W_ACK_PAYLOAD = 0xA8
    FLUSH_TX = 0xE1
    FLUSH_RX = 0xE2
    REUSE_TX_PL = 0xE3
    NOP = 0xFF

    # Non-P omissions
    LNA_HCURR = 0x01
    LNA_ON = 1
    LNA_OFF = 0

    # P model bit Mnemonics
    RF_DR_LOW = 0x20
    RF_DR_HIGH = 0x08
    RF_PWR_LOW = 0x02
    RF_PWR_HIGH = 0x04

    datarate_e_str_P = ["1MBPS", "2MBPS", "250KBPS"]
    model_e_str_P = ["nRF24L01", "nRF24l01+"]
    crclength_e_str_P = ["Disabled", "", "8 bits", "", "16 bits"]
    pa_dbm_e_str_P = ["PA_MIN", "PA_LOW", "PA_HIGH", "PA_MAX"]

    @staticmethod
    def print_single_status_line(name, value):
        print("{0:<16}= {1}".format(name, value))

    @staticmethod
    def _to_8b_list(data):
        """Convert an arbitray iteratable or single int to a list of ints
            where each int is smaller than 256."""
        if isinstance(data, str):
            data = [ord(x) for x in data]
        elif isinstance(data, (int, long)):
            data = [data]
        else:
            data = [int(x) for x in data]

        #for byte in data:
        #    if byte < 0 or byte > 255:
        #        raise RuntimeError("Value %d is larger than 8 bits" % byte)
        return data

    def __init__(self, major=None, minor=None, ce_pin=None, irq_pin=None):
        self.ce_pin = "P9_15"
        self.irq_pin = "P9_16"
        self.channel = 76
        self.data_rate = NRF24.BR_1MBPS
        self.data_rate_bits = 1000
        self.p_variant = False  # False for RF24L01 and true for RF24L01P
        self.payload_size = 5  # *< Fixed size of payloads
        self.ack_payload_available = False  # *< Whether there is an ack payload waiting
        self.dynamic_payloads_enabled = False  # *< Whether dynamic payloads are enabled.
        self.ack_payload_length = 5  # *< Dynamic size of pending ack payload.
        self.pipe0_reading_address = None  # *< Last address set on pipe 0 for reading.
        self.spidev = None
        self.last_error = 0
        self.crc_length = 0
        self.auto_ack = 0x3F
        self.address_length = 5

        # If all parameters are available, lets start the radio!
        if major is not None and minor is not None and irq_pin is not None:
            self.begin(major, minor, ce_pin, irq_pin)

    def begin(self, major, minor, ce_pin, irq_pin):
        # Initialize SPI bus

        if ADAFRUID_BBIO_SPI:
            self.spidev = SPI(major, minor)
            self.spidev.bpw = 8
            try:
                self.spidev.msh = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed
        else:
            self.spidev = spidev.SpiDev()
            self.spidev.open(major, minor)

            self.spidev.bits_per_word = 8

            try:
                self.spidev.max_speed_hz = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed

        self.spidev.cshigh = False
        self.spidev.mode = 0
        self.spidev.loop = False
        self.spidev.lsbfirst = False
        self.spidev.threewire = False

        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        if self.ce_pin is not None:
            GPIO.setup(self.ce_pin, GPIO.OUT)

        GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Reset radio configuration
        self.reset()

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        self.setRetries(int('0101', 2), 15)

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.setChannel(self.channel)

        self.setRetries(15, 15)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()
        self.clear_irq_flags()

    def end(self):
        if self.spidev:
            self.spidev.close()
            self.spidev = None

    def startListening(self):
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) | NRF24.PWR_UP | NRF24.PRIM_RX)
        self.write_register(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        self.flush_tx()
        self.flush_rx()
        self.clear_irq_flags()

        # Restore the pipe0 address, if exists
        if self.pipe0_reading_address:
            self.write_register(self.RX_ADDR_P0, self.pipe0_reading_address)

        # Go!
        self.ce(1)

    def ce(self, level, pulse=0):
        # CE Pin is optional
        if self.ce_pin is not None:
            GPIO.output(self.ce_pin, level)
            if pulse > 0:
                time.sleep(pulse)
                GPIO.output(self.ce_pin, 1 - level)

    def irqWait(self, timeout=30000):
        # TODO: A race condition may occur here. => wait for level?
        if GPIO.input(self.irq_pin) == 0:  # Pin is already down. Packet is waiting?
            return True

        try:
            return GPIO.wait_for_edge(self.irq_pin, GPIO.FALLING, timeout) == 1
        except TypeError:  # Timeout parameter not supported
            return GPIO.wait_for_edge(self.irq_pin, GPIO.FALLING) == 1
        except AttributeError:
            raise RuntimeError("GPIO lib does not support wait_for_edge()")

    def read_register(self, reg, length=1):
        buf = [NRF24.R_REGISTER | (NRF24.REGISTER_MASK & reg)]
        buf += [NRF24.NOP] * max(1, length)

        resp = self.spidev.xfer2(buf)
        if length == 1:
            return resp[1]

        return resp[1:]

    def write_register(self, reg, value):
        """ Write register value """
        buf = [NRF24.W_REGISTER | (NRF24.REGISTER_MASK & reg)]
        buf += self._to_8b_list(value)
        self.spidev.xfer2(buf)

    def write_payload(self, buf):
        """ Writes data to the payload register, automatically padding it
            to match the required length. Returns the number of bytes
            actually written. """

        buf = self._to_8b_list(buf)
        if self.dynamic_payloads_enabled:
            if len(buf) > self.MAX_PAYLOAD_SIZE:
                raise RuntimeError("Dynamic payload is larger than the " +
                                   "maximum size.")
            blank_len = 0
        else:
            if len(buf) > self.payload_size:
                raise RuntimeError("Payload is larger than the fixed payload" +
                                   "size (%d vs. %d bytes)" % (len(buf), self.payload_size))
            blank_len = self.payload_size - len(buf)

        txbuffer = [NRF24.W_TX_PAYLOAD] + buf + ([0x00] * blank_len)
        self.spidev.xfer2(txbuffer)
        return len(txbuffer) - 1

    def read_payload(self, buf, buf_len=-1):
        """ Reads data from the payload register and sets the
            DR bit of the STATUS register. """

        if buf_len < 0:
            buf_len = self.payload_size

        if not self.dynamic_payloads_enabled:
            data_len = min(self.payload_size, buf_len)
            blank_len = self.payload_size - data_len
        else:
            data_len = self.getDynamicPayloadSize()
            blank_len = 0

        txbuffer = [NRF24.R_RX_PAYLOAD] + [NRF24.NOP] * (blank_len + data_len + 1)

        payload = self.spidev.xfer2(txbuffer)
        del buf[:]
        buf += payload[1:data_len + 1]

        self.write_register(NRF24.STATUS, NRF24.RX_DR)

        return data_len

    def flush_rx(self):
        return self.spidev.xfer2([NRF24.FLUSH_RX])[0]

    def flush_tx(self):
        return self.spidev.xfer2([NRF24.FLUSH_TX])[0]

    def get_status(self):
        return self.spidev.xfer2([NRF24.NOP])[0]

    def get_status_str(self, status):
        status_str = "STATUS\t = 0x{0:02x} RX_DR={1:x} TX_DS={2:x} MAX_RT={3:x} RX_P_NO={4:x} TX_FULL={5:x}".format(
            status,
            1 if status & NRF24.RX_DR else 0,
            1 if status & NRF24.TX_DS else 0,
            1 if status & NRF24.MAX_RT else 0,
            ((status >> NRF24.RX_P_NO) & int("111", 2)),
            1 if status & NRF24.TX_FULL else 0)
        return status_str

        
    def print_status(self, status):
        print self.get_status_str(status)
        
    def get_observe_tx_str(self, value):
        tx_str = "OBSERVE_TX=0x{0:02x}: POLS_CNT={2:x} ARC_CNT={2:x}\r\n".format(
            value,
            (value >> NRF24.PLOS_CNT) & int("1111",2),
            (value >> NRF24.ARC_CNT)  & int("1111",2)
            )
        return tx_str

    def print_observe_tx(self, value):
        print self.get_observe_tx_str(value)

    def get_byte_register_str(self, name, reg, qty=1):
        extra_tab = '\t' if len(name) < 8 else 0
        byte_str= "%s\t%c =" % (name, extra_tab)
        while qty > 0:
            byte_str+= " 0x%02x" % (self.read_register(reg))
            qty -= 1
            reg += 1
        return byte_str
        

    def print_byte_register(self, name, reg, qty=1):
        print self.get_address_register_str(name, reg, qty)

    def get_address_register_str(self, name, reg, qty=1):
        extra_tab = '\t' if len(name) < 8 else 0
        addr_str = "%s\t%c =" % (name, extra_tab)

        while qty > 0:
            qty -= 1
            buf = reversed(self.read_register(reg, 5))
            reg += 1
            addr_str+=" 0x"
            for i in buf:
                addr_str+="%02x" % i
        return addr_str
    
    def print_address_register(self, name, reg, qty=1):
        print self.get_address_register_str(name, reg, qty)

        self.print_single_status_line(name, " ".join(address_registers))

    def setChannel(self, channel):
        if channel < 0 or channel > self.MAX_CHANNEL:
            raise RuntimeError("Channel number out of range")
        self.channel = channel
        self.write_register(NRF24.RF_CH, channel)

    def getChannel(self):
        return self.read_register(NRF24.RF_CH)

    def setPayloadSize(self, size):
        self.payload_size = min(max(size, 1), NRF24.MAX_PAYLOAD_SIZE)

    def getPayloadSize(self):
        return self.payload_size

    def getDetails(self):
        return  "\n".join([self.get_status_str(self.get_status()),
            self.get_address_register_str("RX_ADDR_P0-1", NRF24.RX_ADDR_P0, 2),
            self.get_byte_register_str("RX_ADDR_P2-5", NRF24.RX_ADDR_P2, 4),
            self.get_address_register_str("TX_ADDR", NRF24.TX_ADDR),
            self.get_byte_register_str("RX_PW_P0-6", NRF24.RX_PW_P0, 6),
            self.get_byte_register_str("EN_AA", NRF24.EN_AA),
            self.get_byte_register_str("EN_RXADDR", NRF24.EN_RXADDR),
            self.get_byte_register_str("RF_CH", NRF24.RF_CH),
            self.get_byte_register_str("RF_SETUP", NRF24.RF_SETUP),
            self.get_byte_register_str("CONFIG", NRF24.CONFIG),
            self.get_byte_register_str("DYNPD/FEATURE", NRF24.DYNPD, 2),
            "Data Rate\t = %s" % NRF24.datarate_e_str_P[self.getDataRate()],
            "Model\t\t = %s" % NRF24.model_e_str_P[self.isPVariant()],
            "CRC Length\t = %s" % NRF24.crclength_e_str_P[self.getCRCLength()],
            "PA Power\t = %s" % NRF24.pa_dbm_e_str_P[self.getPALevel()]])


    def printDetails(self):
        print self.getDetails()

    def stopListening(self):
        self.ce(0)
        self.flush_tx()
        self.flush_rx()
        self.clear_irq_flags()

        # Enable TX
        self.write_register(NRF24.CONFIG,
                            (self.read_register(NRF24.CONFIG) | NRF24.PWR_UP) & ~NRF24.PRIM_RX)

        # Enable pipe 0 for auto-ack
        self.write_register(NRF24.EN_RXADDR, self.read_register(NRF24.EN_RXADDR) | 1)

    def powerDown(self):
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) & ~ NRF24.PWR_UP)

    def powerUp(self):
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) | NRF24.PWR_UP)
        time.sleep(150e-6)

    def write(self, buf):
        self.last_error = None
        length = self.write_payload(buf)
        self.ce(1)

        sent_at = monotonic()
        packet_time = ((1 + length + self.crc_length + self.address_length) * 8 + 9)/(self.data_rate_bits * 1000.)

        if self.auto_ack != 0:
            packet_time *= 2

        if self.retries != 0 and self.auto_ack != 0:
            timeout = sent_at + (packet_time + self.delay)*self.retries
        else:
            timeout = sent_at + packet_time * 2  # 2 is empiric

        #while NRF24.TX_DS &  self.get_status() == 0:
        #    pass

        #print monotonic() - sent_at
        #print packet_time

        while monotonic() < timeout:
            time.sleep(packet_time)
            status = self.get_status()
            if status & NRF24.TX_DS:
                self.ce(0)
                return True

            if status & NRF24.MAX_RT:
                self.last_error = 'MAX_RT'
                self.ce(0)
                break

        self.ce(0)
        if self.last_error is None:
            self.last_error = 'TIMEOUT'

        self.flush_tx()  # Avoid leaving the payload in tx fifo
        return False

    def startFastWrite(self, buf):
        """
            Do not wait for CE HIGH->LOW
        """
        # Send the payload
        self.write_payload(buf)

        self.ce(1)

    def startWrite(self, buf):
        # Send the payload
        self.write_payload(buf)

        # Allons!
        self.ce(1, 10e-6)

    def getDynamicPayloadSize(self):
        return self.spidev.xfer2([NRF24.R_RX_PL_WID, NRF24.NOP])[1]

    def available(self, pipe_num=None, irq_wait=False, irq_timeout=30000):
        status = self.get_status()
        result = False

        # Sometimes the radio specifies that there is data in one pipe but
        # doesn't set the RX flag...
        if status & NRF24.RX_DR or (status & NRF24.RX_P_NO_MASK != NRF24.RX_P_NO_MASK):
            result = True
        else:
            if irq_wait:  # Will use IRQ wait
                if self.irqWait(irq_timeout):  # Do we have a packet?
                    status = self.get_status()  # Seems like we do!
                    if status & NRF24.RX_DR or (status & NRF24.RX_P_NO_MASK != NRF24.RX_P_NO_MASK):
                        result = True
        # read status once again see Note on page 52 or 56 in product specification 1.0
        # Note: The 3 bit pipe information in the STATUS register is updated during the IRQ pin high to low
        #transition. The pipe information is unreliable if the STATUS register is read during an IRQ pin
        #high to low transition.
        status = self.get_status()
        del pipe_num[:]
        if result and pipe_num is not None:
            pipe_num.append((status & NRF24.RX_P_NO_MASK) >> NRF24.RX_P_NO)

        # Handle ack payload receipt
        if status & NRF24.TX_DS:
            self.write_register(NRF24.STATUS, NRF24.TX_DS)

        return result

    def read(self, buf, buf_len=-1):
        # Fetch the payload
        self.read_payload(buf, buf_len)

        # was this the last of the data available?
        return self.read_register(NRF24.FIFO_STATUS & NRF24.RX_EMPTY)

    def clear_irq_flags(self):
        self.write_register(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

    def whatHappened(self):
        # Read the status & reset the status in one easy call
        # Or is that such a good idea?
        self.write_register(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        status = self.get_status()
        self.clear_irq_flags()

        # Report to the user what happened
        tx_ok = status & NRF24.TX_DS
        tx_fail = status & NRF24.MAX_RT
        rx_ready = status & NRF24.RX_DR
        return {'tx_ok': tx_ok, "tx_fail": tx_fail, "rx_ready": rx_ready}

    def openWritingPipe(self, value):
        # Note that the NRF24L01(+)
        # expects it LSB first.

        self.write_register(NRF24.RX_ADDR_P0, value)
        self.write_register(NRF24.TX_ADDR, value)
        if not self.dynamic_payloads_enabled:
            self.write_register(NRF24.RX_PW_P0, self.payload_size)

    def openReadingPipe(self, pipe, address):
        # If this is pipe 0, cache the address.  This is needed because
        # openWritingPipe() will overwrite the pipe 0 address, so
        # startListening() will have to restore it.
        if pipe >= 6:
            raise RuntimeError("Invalid pipe number")
        if (pipe >= 2 and len(address) > 1) or len(address) > 5:
            raise RuntimeError("Invalid adress length")

        if pipe == 0:
            self.pipe0_reading_address = address

        self.write_register(NRF24.RX_ADDR_P0 + pipe, address)
        if not self.dynamic_payloads_enabled:
            self.write_register(NRF24.RX_PW_P0 + pipe, self.payload_size)

        # Note it would be more efficient to set all of the bits for all open
        # pipes at once.  However, I thought it would make the calling code
        # more simple to do it this way.
        self.write_register(NRF24.EN_RXADDR,
                            self.read_register(NRF24.EN_RXADDR) | (1 << pipe))

    def closeReadingPipe(self, pipe):
        self.write_register(NRF24.EN_RXADDR,
                            self.read_register(NRF24.EN_RXADDR) & ~(1 << pipe))

    def toggle_features(self):
        buf = [NRF24.ACTIVATE, 0x73]
        self.spidev.xfer2(buf)

    def enableDynamicPayloads(self):
        # Enable dynamic payload throughout the system
        self.write_register(NRF24.FEATURE, self.read_register(NRF24.FEATURE) | NRF24.EN_DPL)

        # If it didn't work, the features are not enabled
        if not self.read_register(NRF24.FEATURE):
            # So enable them and try again
            self.toggle_features()
            self.write_register(NRF24.FEATURE, self.read_register(NRF24.FEATURE) | NRF24.EN_DPL)

        # Enable dynamic payload on all pipes

        # Not sure the use case of only having dynamic payload on certain
        # pipes, so the library does not support it.
        self.write_register(NRF24.DYNPD, self.read_register(NRF24.DYNPD) | 0b00111111)

        self.dynamic_payloads_enabled = True

    def enableAckPayload(self):
        # enable ack payload and dynamic payload features
        self.write_register(NRF24.FEATURE,
                            self.read_register(NRF24.FEATURE) | NRF24.EN_ACK_PAY | NRF24.EN_DPL)

        # If it didn't work, the features are not enabled
        if not self.read_register(NRF24.FEATURE):
            # So enable them and try again
            self.toggle_features()
            self.write_register(NRF24.FEATURE,
                                self.read_register(NRF24.FEATURE) | NRF24.EN_ACK_PAY | NRF24.EN_DPL)

        # Enable dynamic payload on pipes 0 & 1
        self.write_register(NRF24.DYNPD, self.read_register(NRF24.DYNPD) | NRF24.DPL_P1 | NRF24.DPL_P0)

    def writeAckPayload(self, pipe, buf, buf_len):
        txbuffer = [NRF24.W_ACK_PAYLOAD | (pipe & 0x7)]

        max_payload_size = 32
        data_len = min(buf_len, max_payload_size)
        txbuffer.extend(buf[0:data_len])

        self.spidev.xfer2(txbuffer)

    def isAckPayloadAvailable(self):
        result = self.ack_payload_available
        self.ack_payload_available = False
        return result

    def isPVariant(self):
        return self.p_variant

    def setAutoAck(self, enable):
        if enable:
            self.write_register(NRF24.EN_AA, 0x3F)
            self.auto_ack = 0x3f
            if self.crc_length == 0:
                self.setCRCLength(NRF24.CRC_8)  # Enhanced Shockburst requires at least 1 byte CRC
        else:
            self.auto_ack = 0
            self.write_register(NRF24.EN_AA, 0)

    def setAutoAckPipe(self, pipe, enable):
        if pipe <= 6:
            en_aa = self.read_register(NRF24.EN_AA)
            if enable:
                self.setCRCLength(NRF24.CRC_8)  # Enhanced Shockburst requires at least 1 byte CRC
                en_aa |= 1 << pipe
                self.auto_ack |= 1 << pipe
            else:
                en_aa &= ~1 << pipe
                self.auto_ack &= ~1 << pipe

            self.write_register(NRF24.EN_AA, en_aa)

    def setAddressWidth(self, width):
        if width >= 2 and width <= 5:
            self.write_register(NRF24.SETUP_AW, width - 2)
            self.address_width = width

    def testCarrier(self):
        return self.read_register(NRF24.RPD) & 1

    def setPALevel(self, level):
        setup = self.read_register(NRF24.RF_SETUP)
        setup &= ~(NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH)

        if level == NRF24.PA_MAX:
            setup |= NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH
        elif level == NRF24.PA_HIGH:
            setup |= NRF24.RF_PWR_HIGH
        elif level == NRF24.PA_LOW:
            setup |= NRF24.RF_PWR_LOW
        elif level == NRF24.PA_MIN:
            pass
        elif level == NRF24.PA_ERROR:
            # On error, go to maximum PA
            setup |= NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH

        self.write_register(NRF24.RF_SETUP, setup)

    def getPALevel(self):
        power = self.read_register(NRF24.RF_SETUP) & (NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH)
        if power == (NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH):
            return NRF24.PA_MAX
        elif power == NRF24.RF_PWR_HIGH:
            return NRF24.PA_HIGH
        elif power == NRF24.RF_PWR_LOW:
            return NRF24.PA_LOW
        else:
            return NRF24.PA_MIN

    def setDataRate(self, speed):
        setup = self.read_register(NRF24.RF_SETUP)
        setup &= ~(NRF24.RF_DR_LOW | NRF24.RF_DR_HIGH)

        if speed == NRF24.BR_250KBPS:
            # Must set the RF_DR_LOW to 1 RF_DR_HIGH (used to be RF_DR) is already 0
            # Making it '10'.
            self.data_rate_bits = 250
            self.data_rate = NRF24.BR_250KBPS
            setup |= NRF24.RF_DR_LOW
        elif speed == NRF24.BR_2MBPS:
            # Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
            # Making it '01'
            self.data_rate_bits = 2000
            self.data_rate = NRF24.BR_2MBPS
            setup |= NRF24.RF_DR_HIGH
        else:
            # 1Mbs
            self.data_rate_bits = 1000
            self.data_rate = NRF24.BR_1MBPS

        self.write_register(NRF24.RF_SETUP, setup)

        # Verify our result
        return self.read_register(NRF24.RF_SETUP) == setup

    def getDataRate(self):
        dr = self.read_register(NRF24.RF_SETUP) & (NRF24.RF_DR_LOW | NRF24.RF_DR_HIGH)
        # Order matters in our case below
        if dr == NRF24.RF_DR_LOW:
            # '10' = 250KBPS
            return NRF24.BR_250KBPS
        elif dr == NRF24.RF_DR_HIGH:
            # '01' = 2MBPS
            return NRF24.BR_2MBPS
        else:
            # '00' = 1MBPS
            return NRF24.BR_1MBPS

    def setCRCLength(self, length):
        config = self.read_register(NRF24.CONFIG) & ~(NRF24.EN_CRC | NRF24.CRCO)

        if length == NRF24.CRC_DISABLED:
            self.crc_length = 0
        elif length == NRF24.CRC_8:
            config |= NRF24.EN_CRC
            config &= ~NRF24.CRCO
            self.crc_length = 1
        else:
            config |= NRF24.EN_CRC
            config |= NRF24.CRCO
            self.crc_length = 2

        self.write_register(NRF24.CONFIG, config)

    def getCRCLength(self):
        result = NRF24.CRC_DISABLED
        config = self.read_register(NRF24.CONFIG) & (NRF24.CRCO | NRF24.EN_CRC)

        if config & NRF24.EN_CRC:
            if config & NRF24.CRCO:
                result = NRF24.CRC_16
            else:
                result = NRF24.CRC_8

        return result

    def disableCRC(self):
        disable = self.read_register(NRF24.CONFIG) & ~NRF24.EN_CRC
        self.write_register(NRF24.CONFIG, disable)

    def setRetries(self, delay, count):
        self.write_register(NRF24.SETUP_RETR, (delay & 0xf) << NRF24.ARD | (count & 0xf) << NRF24.ARC)
        self.delay = delay * 0.000250
        self.retries = count
        self.max_timeout = (self.payload_size / float(self.data_rate_bits) + self.delay) * self.retries
        self.timeout = (self.payload_size / float(self.data_rate_bits) + self.delay)

    def getRetries(self):
        return self.read_register(NRF24.SETUP_RETR)

    def getMaxTimeout(self):
        return self.max_timeout

    def getTimeout(self):
        return self.timeout

    def reset(self):
        """ Make sure the NRF is in the same state as after power up
            to avoid problems resulting from left over configuration
            from other programs."""
        self.ce(0)
        reset_values = {0: 0x08, 1: 0x3F, 2: 0x02, 3: 0x03, 4: 0x03, 5: 0x02, 6: 0x06,
                        0x0a: [0xe7, 0xe7, 0xe7, 0xe7, 0xe7],
                        0x0b: [0xc2, 0xc2, 0xc2, 0xc2, 0xc2],
                        0x0c: 0xc3, 0x0d: 0xc4, 0x0e: 0xc5, 0x0f: 0xc6,
                        0x10: [0xe7, 0xe7, 0xe7, 0xe7, 0xe7],
                        0x11: 0, 0x12: 0, 0x13: 0, 0x14: 0, 0x15: 0, 0x16: 0,
                        0x1c: 0, 0x1d: 0}
        for reg, value in reset_values.items():
            self.write_register(reg, value)

        self.flush_rx()
        self.flush_tx()
Ejemplo n.º 46
0
class NRF24:
    MAX_CHANNEL = 127
    MAX_PAYLOAD_SIZE = 32

    # PA Levels
    PA_MIN = 0x00
    PA_LOW = 0x01
    PA_HIGH = 0x02
    PA_MAX = 0x03
    PA_ERROR = 0x04

    # Bit rates
    BR_1MBPS = 0
    BR_2MBPS = 1
    BR_250KBPS = 2

    # CRC
    CRC_DISABLED = 0x0
    CRC_8 = 0x02
    CRC_16 = 0x04
    CRC_ENABLED = 0x08

    EN_CRC = 0x08
    CRCO = 0x04

    # Registers
    CONFIG = 0x00
    EN_AA = 0x01
    EN_RXADDR = 0x02
    SETUP_AW = 0x03
    SETUP_RETR = 0x04
    RF_CH = 0x05
    RF_SETUP = 0x06
    STATUS = 0x07
    OBSERVE_TX = 0x08
    RPD = 0x09
    RX_ADDR_P0 = 0x0A
    RX_ADDR_P1 = 0x0B
    RX_ADDR_P2 = 0x0C
    RX_ADDR_P3 = 0x0D
    RX_ADDR_P4 = 0x0E
    RX_ADDR_P5 = 0x0F
    TX_ADDR = 0x10
    RX_PW_P0 = 0x11
    RX_PW_P1 = 0x12
    RX_PW_P2 = 0x13
    RX_PW_P3 = 0x14
    RX_PW_P4 = 0x15
    RX_PW_P5 = 0x16
    FIFO_STATUS = 0x17
    DYNPD = 0x1C
    FEATURE = 0x1D

    # Bit Mnemonics */
    MASK_RX_DR = 0x40
    MASK_TX_DS = 0x20
    MASK_MAX_RT = 0x10

    PWR_UP = 0x02
    PRIM_RX = 0x01
    PLL_LOCK = 0x10
    RX_DR = 0x40
    TX_DS = 0x20
    MAX_RT = 0x10
    TX_FULL = 0x01

    EN_DPL = 0x04
    EN_ACK_PAY = 0x02
    EN_DYN_ACK = 0x01

    # Shift counts
    ARD = 4
    ARC = 0
    PLOS_CNT = 4
    ARC_CNT = 0
    RX_P_NO = 1

    TX_REUSE = 6
    FIFO_FULL = 5
    TX_EMPTY = 4
    RX_FULL = 1
    RX_EMPTY = 0

    DPL_P5 = 5
    DPL_P4 = 4
    DPL_P3 = 3
    DPL_P2 = 2
    DPL_P1 = 1
    DPL_P0 = 0

    #Masks
    RX_P_NO_MASK = 0x0E

    # Instruction Mnemonics
    R_REGISTER = 0x00
    W_REGISTER = 0x20
    REGISTER_MASK = 0x1F
    ACTIVATE = 0x50
    R_RX_PL_WID = 0x60
    R_RX_PAYLOAD = 0x61
    W_TX_PAYLOAD = 0xA0
    W_ACK_PAYLOAD = 0xA8
    FLUSH_TX = 0xE1
    FLUSH_RX = 0xE2
    REUSE_TX_PL = 0xE3
    NOP = 0xFF

    # Non-P omissions
    LNA_HCURR = 0x01
    LNA_ON = 1
    LNA_OFF = 0

    # P model bit Mnemonics
    RF_DR_LOW = 0x20
    RF_DR_HIGH = 0x08
    RF_PWR_LOW = 0x02
    RF_PWR_HIGH = 0x04

    datarate_e_str_P = ["1MBPS", "2MBPS", "250KBPS"]
    model_e_str_P = ["nRF24L01", "nRF24l01+"]
    crclength_e_str_P = ["Disabled", "", "8 bits", "", "16 bits"]
    pa_dbm_e_str_P = ["PA_MIN", "PA_LOW", "PA_HIGH", "PA_MAX"]

    @staticmethod
    def print_single_status_line(name, value):
        print("{0:<16}= {1}".format(name, value))

    @staticmethod
    def _to_8b_list(data):
        """Convert an arbitray iteratable or single int to a list of ints
            where each int is smaller than 256."""
        if isinstance(data, str):
            data = [ord(x) for x in data]
        elif isinstance(data, (int, long)):
            data = [data]
        else:
            data = [int(x) for x in data]

        #for byte in data:
        #    if byte < 0 or byte > 255:
        #        raise RuntimeError("Value %d is larger than 8 bits" % byte)
        return data

    def __init__(self, major=None, minor=None, ce_pin=None, irq_pin=None):
        self.ce_pin = "P9_15"
        self.irq_pin = "P9_16"
        self.channel = 76
        self.data_rate = NRF24.BR_1MBPS
        self.data_rate_bits = 1000
        self.p_variant = False  # False for RF24L01 and true for RF24L01P
        self.payload_size = 5  # *< Fixed size of payloads
        self.ack_payload_available = False  # *< Whether there is an ack payload waiting
        self.dynamic_payloads_enabled = False  # *< Whether dynamic payloads are enabled.
        self.ack_payload_length = 5  # *< Dynamic size of pending ack payload.
        self.pipe0_reading_address = None  # *< Last address set on pipe 0 for reading.
        self.spidev = None
        self.last_error = 0
        self.crc_length = 0
        self.auto_ack = 0x3F
        self.address_length = 5

        # If all parameters are available, lets start the radio!
        if major is not None and minor is not None and irq_pin is not None:
            self.begin(major, minor, ce_pin, irq_pin)

    def begin(self, major, minor, ce_pin, irq_pin):
        # Initialize SPI bus

        if ADAFRUID_BBIO_SPI:
            self.spidev = SPI(major, minor)
            self.spidev.bpw = 8
            try:
                self.spidev.msh = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed
        else:
            self.spidev = spidev.SpiDev()
            self.spidev.open(major, minor)

            self.spidev.bits_per_word = 8

            try:
                self.spidev.max_speed_hz = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed

        self.spidev.cshigh = False
        self.spidev.mode = 0
        self.spidev.loop = False
        self.spidev.lsbfirst = False
        self.spidev.threewire = False

        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        if self.ce_pin is not None:
            GPIO.setup(self.ce_pin, GPIO.OUT)

        GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Reset radio configuration
        self.reset()

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        self.setRetries(int('0101', 2), 15)

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(NRF24.STATUS,
                            NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.setChannel(self.channel)

        self.setRetries(15, 15)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()
        self.clear_irq_flags()

    def end(self):
        if self.spidev:
            self.spidev.close()
            self.spidev = None

    def startListening(self):
        self.write_register(
            NRF24.CONFIG,
            self.read_register(NRF24.CONFIG) | NRF24.PWR_UP | NRF24.PRIM_RX)
        self.write_register(NRF24.STATUS,
                            NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        self.flush_tx()
        self.flush_rx()
        self.clear_irq_flags()

        # Restore the pipe0 address, if exists
        if self.pipe0_reading_address:
            self.write_register(self.RX_ADDR_P0, self.pipe0_reading_address)

        # Go!
        self.ce(1)

    def ce(self, level, pulse=0):
        # CE Pin is optional
        if self.ce_pin is not None:
            GPIO.output(self.ce_pin, level)
            if pulse > 0:
                time.sleep(pulse)
                GPIO.output(self.ce_pin, 1 - level)

    def irqWait(self, timeout=30000):
        # TODO: A race condition may occur here. => wait for level?
        if GPIO.input(
                self.irq_pin) == 0:  # Pin is already down. Packet is waiting?
            return True

        try:
            return GPIO.wait_for_edge(self.irq_pin, GPIO.FALLING, timeout) == 1
        except TypeError:  # Timeout parameter not supported
            return GPIO.wait_for_edge(self.irq_pin, GPIO.FALLING) == 1
        except AttributeError:
            raise RuntimeError("GPIO lib does not support wait_for_edge()")

    def read_register(self, reg, length=1):
        buf = [NRF24.R_REGISTER | (NRF24.REGISTER_MASK & reg)]
        buf += [NRF24.NOP] * max(1, length)

        resp = self.spidev.xfer2(buf)
        if length == 1:
            return resp[1]

        return resp[1:]

    def write_register(self, reg, value):
        """ Write register value """
        buf = [NRF24.W_REGISTER | (NRF24.REGISTER_MASK & reg)]
        buf += self._to_8b_list(value)
        self.spidev.xfer2(buf)

    def write_payload(self, buf):
        """ Writes data to the payload register, automatically padding it
            to match the required length. Returns the number of bytes
            actually written. """

        buf = self._to_8b_list(buf)
        if self.dynamic_payloads_enabled:
            if len(buf) > self.MAX_PAYLOAD_SIZE:
                raise RuntimeError("Dynamic payload is larger than the " +
                                   "maximum size.")
            blank_len = 0
        else:
            if len(buf) > self.payload_size:
                raise RuntimeError("Payload is larger than the fixed payload" +
                                   "size (%d vs. %d bytes)" %
                                   (len(buf), self.payload_size))
            blank_len = self.payload_size - len(buf)

        txbuffer = [NRF24.W_TX_PAYLOAD] + buf + ([0x00] * blank_len)
        self.spidev.xfer2(txbuffer)
        return len(txbuffer) - 1

    def read_payload(self, buf, buf_len=-1):
        """ Reads data from the payload register and sets the
            DR bit of the STATUS register. """

        if buf_len < 0:
            buf_len = self.payload_size

        if not self.dynamic_payloads_enabled:
            data_len = min(self.payload_size, buf_len)
            blank_len = self.payload_size - data_len
        else:
            data_len = self.getDynamicPayloadSize()
            blank_len = 0

        txbuffer = [NRF24.R_RX_PAYLOAD
                    ] + [NRF24.NOP] * (blank_len + data_len + 1)

        payload = self.spidev.xfer2(txbuffer)
        del buf[:]
        buf += payload[1:data_len + 1]

        self.write_register(NRF24.STATUS, NRF24.RX_DR)

        return data_len

    def flush_rx(self):
        return self.spidev.xfer2([NRF24.FLUSH_RX])[0]

    def flush_tx(self):
        return self.spidev.xfer2([NRF24.FLUSH_TX])[0]

    def get_status(self):
        return self.spidev.xfer2([NRF24.NOP])[0]

    def print_status(self, status):
        status_str = "0x{0:02x} RX_DR={1:x} TX_DS={2:x} MAX_RT={3:x} RX_P_NO={4:x} TX_FULL={5:x}".format(
            status, 1 if status & NRF24.RX_DR else 0,
            1 if status & NRF24.TX_DS else 0,
            1 if status & NRF24.MAX_RT else 0,
            ((status >> NRF24.RX_P_NO) & int("111", 2)),
            1 if status & NRF24.TX_FULL else 0)

        self.print_single_status_line("STATUS", status_str)

    def print_observe_tx(self, value):
        tx_str = "OBSERVE_TX=0x{0:02x}: POLS_CNT={2:x} ARC_CNT={2:x}\r\n".format(
            value, (value >> NRF24.PLOS_CNT) & int("1111", 2),
            (value >> NRF24.ARC_CNT) & int("1111", 2))
        self.print_single_status_line("OBSERVE_TX", tx_str)

    def print_byte_register(self, name, reg, qty=1):
        registers = [
            "0x{:0>2x}".format(self.read_register(reg + r))
            for r in range(0, qty)
        ]
        self.print_single_status_line(name, " ".join(registers))

    def print_address_register(self, name, reg, qty=1):
        address_registers = [
            "0x{0:>02x}{1:>02x}{2:>02x}{3:>02x}{4:>02x}".format(
                *self.read_register(reg + r, 5)) for r in range(qty)
        ]

        self.print_single_status_line(name, " ".join(address_registers))

    def setChannel(self, channel):
        if channel < 0 or channel > self.MAX_CHANNEL:
            raise RuntimeError("Channel number out of range")
        self.channel = channel
        self.write_register(NRF24.RF_CH, channel)

    def getChannel(self):
        return self.read_register(NRF24.RF_CH)

    def setPayloadSize(self, size):
        self.payload_size = min(max(size, 1), NRF24.MAX_PAYLOAD_SIZE)

    def getPayloadSize(self):
        return self.payload_size

    def printDetails(self):
        self.print_status(self.get_status())
        self.print_address_register("RX_ADDR_P0-1", NRF24.RX_ADDR_P0, 2)
        self.print_byte_register("RX_ADDR_P2-5", NRF24.RX_ADDR_P2, 4)
        self.print_address_register("TX_ADDR", NRF24.TX_ADDR)

        self.print_byte_register("RX_PW_P0-6", NRF24.RX_PW_P0, 6)
        self.print_byte_register("EN_AA", NRF24.EN_AA)
        self.print_byte_register("EN_RXADDR", NRF24.EN_RXADDR)
        self.print_byte_register("RF_CH", NRF24.RF_CH)
        self.print_byte_register("RF_SETUP", NRF24.RF_SETUP)
        self.print_byte_register("SETUP_AW", NRF24.SETUP_AW)
        self.print_byte_register("OBSERVE_TX", NRF24.OBSERVE_TX)
        self.print_byte_register("CONFIG", NRF24.CONFIG)
        self.print_byte_register("FIFO_STATUS", NRF24.FIFO_STATUS)
        self.print_byte_register("DYNPD", NRF24.DYNPD)
        self.print_byte_register("FEATURE", NRF24.FEATURE)

        self.print_single_status_line(
            "Data Rate", NRF24.datarate_e_str_P[self.getDataRate()])
        self.print_single_status_line("Model",
                                      NRF24.model_e_str_P[self.isPVariant()])
        self.print_single_status_line(
            "CRC Length", NRF24.crclength_e_str_P[self.getCRCLength()])
        self.print_single_status_line("PA Power",
                                      NRF24.pa_dbm_e_str_P[self.getPALevel()])

    def stopListening(self):
        self.ce(0)
        self.flush_tx()
        self.flush_rx()
        self.clear_irq_flags()

        # Enable TX
        self.write_register(NRF24.CONFIG,
                            (self.read_register(NRF24.CONFIG) | NRF24.PWR_UP)
                            & ~NRF24.PRIM_RX)

        # Enable pipe 0 for auto-ack
        self.write_register(NRF24.EN_RXADDR,
                            self.read_register(NRF24.EN_RXADDR) | 1)

    def powerDown(self):
        self.write_register(NRF24.CONFIG,
                            self.read_register(NRF24.CONFIG) & ~NRF24.PWR_UP)

    def powerUp(self):
        self.write_register(NRF24.CONFIG,
                            self.read_register(NRF24.CONFIG) | NRF24.PWR_UP)
        time.sleep(150e-6)

    def write(self, buf):
        self.last_error = None
        length = self.write_payload(buf)
        self.ce(1)

        sent_at = monotonic()
        packet_time = (
            (1 + length + self.crc_length + self.address_length) * 8 +
            9) / (self.data_rate_bits * 1000.)

        if self.auto_ack != 0:
            packet_time *= 2

        if self.retries != 0 and self.auto_ack != 0:
            timeout = sent_at + (packet_time + self.delay) * self.retries
        else:
            timeout = sent_at + packet_time * 2  # 2 is empiric

        #while NRF24.TX_DS &  self.get_status() == 0:
        #    pass

        #print monotonic() - sent_at
        #print packet_time

        while monotonic() < timeout:
            time.sleep(packet_time)
            status = self.get_status()
            if status & NRF24.TX_DS:
                self.ce(0)
                return True

            if status & NRF24.MAX_RT:
                self.last_error = 'MAX_RT'
                self.ce(0)
                break

        self.ce(0)
        if self.last_error is None:
            self.last_error = 'TIMEOUT'

        self.flush_tx()  # Avoid leaving the payload in tx fifo
        return False

    def startFastWrite(self, buf):
        """
            Do not wait for CE HIGH->LOW
        """
        # Send the payload
        self.write_payload(buf)

        self.ce(1)

    def startWrite(self, buf):
        # Send the payload
        self.write_payload(buf)

        # Allons!
        self.ce(1, 10e-6)

    def getDynamicPayloadSize(self):
        return self.spidev.xfer2([NRF24.R_RX_PL_WID, NRF24.NOP])[1]

    def available(self, pipe_num=None, irq_wait=False, irq_timeout=30000):
        status = self.get_status()
        result = False

        # Sometimes the radio specifies that there is data in one pipe but
        # doesn't set the RX flag...
        if status & NRF24.RX_DR or (status & NRF24.RX_P_NO_MASK !=
                                    NRF24.RX_P_NO_MASK):
            result = True
        else:
            if irq_wait:  # Will use IRQ wait
                if self.irqWait(irq_timeout):  # Do we have a packet?
                    status = self.get_status()  # Seems like we do!
                    if status & NRF24.RX_DR or (status & NRF24.RX_P_NO_MASK !=
                                                NRF24.RX_P_NO_MASK):
                        result = True

        if result and pipe_num is not None:
            del pipe_num[:]
            pipe_num.append((status & NRF24.RX_P_NO_MASK) >> NRF24.RX_P_NO)

        # Handle ack payload receipt
        if status & NRF24.TX_DS:
            self.write_register(NRF24.STATUS, NRF24.TX_DS)

        return result

    def read(self, buf, buf_len=-1):
        # Fetch the payload
        self.read_payload(buf, buf_len)

        # was this the last of the data available?
        return self.read_register(NRF24.FIFO_STATUS & NRF24.RX_EMPTY)

    def clear_irq_flags(self):
        self.write_register(NRF24.STATUS,
                            NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

    def whatHappened(self):
        # Read the status & reset the status in one easy call
        # Or is that such a good idea?
        self.write_register(NRF24.STATUS,
                            NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        status = self.get_status()
        self.clear_irq_flags()

        # Report to the user what happened
        tx_ok = status & NRF24.TX_DS
        tx_fail = status & NRF24.MAX_RT
        rx_ready = status & NRF24.RX_DR
        return {'tx_ok': tx_ok, "tx_fail": tx_fail, "rx_ready": rx_ready}

    def openWritingPipe(self, value):
        # Note that the NRF24L01(+)
        # expects it LSB first.

        self.write_register(NRF24.RX_ADDR_P0, value)
        self.write_register(NRF24.TX_ADDR, value)
        if not self.dynamic_payloads_enabled:
            self.write_register(NRF24.RX_PW_P0, self.payload_size)

    def openReadingPipe(self, pipe, address):
        # If this is pipe 0, cache the address.  This is needed because
        # openWritingPipe() will overwrite the pipe 0 address, so
        # startListening() will have to restore it.
        if pipe >= 6:
            raise RuntimeError("Invalid pipe number")
        if (pipe >= 2 and len(address) > 1) or len(address) > 5:
            raise RuntimeError("Invalid adress length")

        if pipe == 0:
            self.pipe0_reading_address = address

        self.write_register(NRF24.RX_ADDR_P0 + pipe, address)
        if not self.dynamic_payloads_enabled:
            self.write_register(NRF24.RX_PW_P0 + pipe, self.payload_size)

        # Note it would be more efficient to set all of the bits for all open
        # pipes at once.  However, I thought it would make the calling code
        # more simple to do it this way.
        self.write_register(NRF24.EN_RXADDR,
                            self.read_register(NRF24.EN_RXADDR) | (1 << pipe))

    def closeReadingPipe(self, pipe):
        self.write_register(NRF24.EN_RXADDR,
                            self.read_register(NRF24.EN_RXADDR) & ~(1 << pipe))

    def toggle_features(self):
        buf = [NRF24.ACTIVATE, 0x73]
        self.spidev.xfer2(buf)

    def enableDynamicPayloads(self):
        # Enable dynamic payload throughout the system
        self.write_register(NRF24.FEATURE,
                            self.read_register(NRF24.FEATURE) | NRF24.EN_DPL)

        # If it didn't work, the features are not enabled
        if not self.read_register(NRF24.FEATURE):
            # So enable them and try again
            self.toggle_features()
            self.write_register(
                NRF24.FEATURE,
                self.read_register(NRF24.FEATURE) | NRF24.EN_DPL)

        # Enable dynamic payload on all pipes

        # Not sure the use case of only having dynamic payload on certain
        # pipes, so the library does not support it.
        self.write_register(NRF24.DYNPD,
                            self.read_register(NRF24.DYNPD) | 0b00111111)

        self.dynamic_payloads_enabled = True

    def enableAckPayload(self):
        # enable ack payload and dynamic payload features
        self.write_register(
            NRF24.FEATURE,
            self.read_register(NRF24.FEATURE) | NRF24.EN_ACK_PAY
            | NRF24.EN_DPL)

        # If it didn't work, the features are not enabled
        if not self.read_register(NRF24.FEATURE):
            # So enable them and try again
            self.toggle_features()
            self.write_register(
                NRF24.FEATURE,
                self.read_register(NRF24.FEATURE) | NRF24.EN_ACK_PAY
                | NRF24.EN_DPL)

        # Enable dynamic payload on pipes 0 & 1
        self.write_register(
            NRF24.DYNPD,
            self.read_register(NRF24.DYNPD) | NRF24.DPL_P1 | NRF24.DPL_P0)

    def writeAckPayload(self, pipe, buf, buf_len):
        txbuffer = [NRF24.W_ACK_PAYLOAD | (pipe & 0x7)]

        max_payload_size = 32
        data_len = min(buf_len, max_payload_size)
        txbuffer.extend(buf[0:data_len])

        self.spidev.xfer2(txbuffer)

    def isAckPayloadAvailable(self):
        result = self.ack_payload_available
        self.ack_payload_available = False
        return result

    def isPVariant(self):
        return self.p_variant

    def setAutoAck(self, enable):
        if enable:
            self.write_register(NRF24.EN_AA, 0x3F)
            self.auto_ack = 0x3f
            if self.crc_length == 0:
                self.setCRCLength(
                    NRF24.CRC_8
                )  # Enhanced Shockburst requires at least 1 byte CRC
        else:
            self.auto_ack = 0
            self.write_register(NRF24.EN_AA, 0)

    def setAutoAckPipe(self, pipe, enable):
        if pipe <= 6:
            en_aa = self.read_register(NRF24.EN_AA)
            if enable:
                self.setCRCLength(
                    NRF24.CRC_8
                )  # Enhanced Shockburst requires at least 1 byte CRC
                en_aa |= 1 << pipe
                self.auto_ack |= 1 << pipe
            else:
                en_aa &= ~1 << pipe
                self.auto_ack &= ~1 << pipe

            self.write_register(NRF24.EN_AA, en_aa)

    def setAddressWidth(self, width):
        if width >= 2 and width <= 5:
            self.write_register(NRF24.SETUP_AW, width - 2)
            self.address_width = width

    def testCarrier(self):
        return self.read_register(NRF24.RPD) & 1

    def setPALevel(self, level):
        setup = self.read_register(NRF24.RF_SETUP)
        setup &= ~(NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH)

        if level == NRF24.PA_MAX:
            setup |= NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH
        elif level == NRF24.PA_HIGH:
            setup |= NRF24.RF_PWR_HIGH
        elif level == NRF24.PA_LOW:
            setup |= NRF24.RF_PWR_LOW
        elif level == NRF24.PA_MIN:
            pass
        elif level == NRF24.PA_ERROR:
            # On error, go to maximum PA
            setup |= NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH

        self.write_register(NRF24.RF_SETUP, setup)

    def getPALevel(self):
        power = self.read_register(
            NRF24.RF_SETUP) & (NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH)
        if power == (NRF24.RF_PWR_LOW | NRF24.RF_PWR_HIGH):
            return NRF24.PA_MAX
        elif power == NRF24.RF_PWR_HIGH:
            return NRF24.PA_HIGH
        elif power == NRF24.RF_PWR_LOW:
            return NRF24.PA_LOW
        else:
            return NRF24.PA_MIN

    def setDataRate(self, speed):
        setup = self.read_register(NRF24.RF_SETUP)
        setup &= ~(NRF24.RF_DR_LOW | NRF24.RF_DR_HIGH)

        if speed == NRF24.BR_250KBPS:
            # Must set the RF_DR_LOW to 1 RF_DR_HIGH (used to be RF_DR) is already 0
            # Making it '10'.
            self.data_rate_bits = 250
            self.data_rate = NRF24.BR_250KBPS
            setup |= NRF24.RF_DR_LOW
        elif speed == NRF24.BR_2MBPS:
            # Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
            # Making it '01'
            self.data_rate_bits = 2000
            self.data_rate = NRF24.BR_2MBPS
            setup |= NRF24.RF_DR_HIGH
        else:
            # 1Mbs
            self.data_rate_bits = 1000
            self.data_rate = NRF24.BR_1MBPS

        self.write_register(NRF24.RF_SETUP, setup)

        # Verify our result
        return self.read_register(NRF24.RF_SETUP) == setup

    def getDataRate(self):
        dr = self.read_register(
            NRF24.RF_SETUP) & (NRF24.RF_DR_LOW | NRF24.RF_DR_HIGH)
        # Order matters in our case below
        if dr == NRF24.RF_DR_LOW:
            # '10' = 250KBPS
            return NRF24.BR_250KBPS
        elif dr == NRF24.RF_DR_HIGH:
            # '01' = 2MBPS
            return NRF24.BR_2MBPS
        else:
            # '00' = 1MBPS
            return NRF24.BR_1MBPS

    def setCRCLength(self, length):
        config = self.read_register(
            NRF24.CONFIG) & ~(NRF24.EN_CRC | NRF24.CRCO)

        if length == NRF24.CRC_DISABLED:
            self.crc_length = 0
        elif length == NRF24.CRC_8:
            config |= NRF24.EN_CRC
            config &= ~NRF24.CRCO
            self.crc_length = 1
        else:
            config |= NRF24.EN_CRC
            config |= NRF24.CRCO
            self.crc_length = 2

        self.write_register(NRF24.CONFIG, config)

    def getCRCLength(self):
        result = NRF24.CRC_DISABLED
        config = self.read_register(NRF24.CONFIG) & (NRF24.CRCO | NRF24.EN_CRC)

        if config & NRF24.EN_CRC:
            if config & NRF24.CRCO:
                result = NRF24.CRC_16
            else:
                result = NRF24.CRC_8

        return result

    def disableCRC(self):
        disable = self.read_register(NRF24.CONFIG) & ~NRF24.EN_CRC
        self.write_register(NRF24.CONFIG, disable)

    def setRetries(self, delay, count):
        self.write_register(NRF24.SETUP_RETR, (delay & 0xf) << NRF24.ARD |
                            (count & 0xf) << NRF24.ARC)
        self.delay = delay * 0.000250
        self.retries = count
        self.max_timeout = (self.payload_size / float(self.data_rate_bits) +
                            self.delay) * self.retries
        self.timeout = (self.payload_size / float(self.data_rate_bits) +
                        self.delay)

    def getRetries(self):
        return self.read_register(NRF24.SETUP_RETR)

    def getMaxTimeout(self):
        return self.max_timeout

    def getTimeout(self):
        return self.timeout

    def reset(self):
        """ Make sure the NRF is in the same state as after power up
            to avoid problems resulting from left over configuration
            from other programs."""
        self.ce(0)
        reset_values = {
            0: 0x08,
            1: 0x3F,
            2: 0x02,
            3: 0x03,
            4: 0x03,
            5: 0x02,
            6: 0x06,
            0x0a: [0xe7, 0xe7, 0xe7, 0xe7, 0xe7],
            0x0b: [0xc2, 0xc2, 0xc2, 0xc2, 0xc2],
            0x0c: 0xc3,
            0x0d: 0xc4,
            0x0e: 0xc5,
            0x0f: 0xc6,
            0x10: [0xe7, 0xe7, 0xe7, 0xe7, 0xe7],
            0x11: 0,
            0x12: 0,
            0x13: 0,
            0x14: 0,
            0x15: 0,
            0x16: 0,
            0x1c: 0,
            0x1d: 0
        }
        for reg, value in reset_values.items():
            self.write_register(reg, value)

        self.flush_rx()
        self.flush_tx()
Ejemplo n.º 47
0
class MAX7221(Display.Display):

    def __init__(self, bus, device):
    	super(MAX7221, self).__init__(8, 8)
        SPI(bus, device).mode = 0
        self.spi_bus = SPI(bus, device)
        self.buf = [0, 0, 0, 0, 0, 0, 0, 0]

        self.OP_NOP = 0x0
        self.OP_DIG0 = 0x1
        self.OP_DIG1 = 0x2
        self.OP_DIG2 = 0x3
        self.OP_DIG3 = 0x4
        self.OP_DIG4 = 0x5
        self.OP_DIG5 = 0x6
        self.OP_DIG6 = 0x7
        self.OP_DIG7 = 0x8
        self.OP_DECODEMODE = 0x9
        self.OP_INTENSITY = 0xA
        self.OP_SCANLIMIT = 0xB
        self.OP_SHUTDOWN = 0xC
        self.OP_DISPLAYTEST = 0xF

        self.init()

    def rotate(self, x, n):
        return (x << n) | (x >> (8 - n))

    def init(self):
        self.write_command(self.OP_DISPLAYTEST, 0x0)
        self.write_command(self.OP_SCANLIMIT, 0x7)
        self.write_command(self.OP_DECODEMODE, 0x0)
        self.shutdown(False)
        self.update_display()

    def shutdown(self, off):
        if off:
            off = 0
        else:
            off = 1
        self.write_command(self.OP_SHUTDOWN, off)

    def write_spi(self, reg, data):
        self.spi_bus.writebytes([reg, data])

    def write_command(self, command, arg):
        self.write_spi(command, arg)

    def write_display(self, buffer):
        for col in range(0, len(buffer)):
            self.write_spi(col + 0x1, buffer[col])

    def update_display(self):
        self.write_display(self.buf)

    def draw_pixel(self, x, y, color):
        if color == 1:
            self.buf[y] = self.buf[y] | (1 << x)
        elif color == 0:
            self.buf[y] = self.buf[y] & ~(1 << x)
        self.update_display()

    def draw_fast_hline(self, x, y, w, color):
    	self.write_spi(0x1 + y, (0xFF >> (8 - w)) << x)
Ejemplo n.º 48
0
Archivo: test.py Proyecto: 5montest/spi
#!/usr/bin/env python2
# -*- coding: utf-8 -*-

### New Python Template File
### H27 Mar 16

import os, sys
import time
import Adafruit_BBIO.GPIO as GPIO
from Adafruit_BBIO.SPI import SPI

GPIO.setup("P9_12",GPIO.OUT)
GPIO.output("P9_12",GPIO.HIGH)
print("GPIO >> HIGH")

spi_in = SPI(0, 0)
spi_out = SPI(0, 1)

spi_out.msh = 500000

while True:
    
    GPIO.output("P9_12",GPIO.LOW)
    print("GPIO >> LOW")
    spi_out.writebytes([0b00001111])
    print("write >> num")
    print spi_in.readbytes(1)
    GPIO.output("P9_12",GPIO.HIGH)
    print("GPIO >> HIGH")
    time.sleep(1)
Ejemplo n.º 49
0
#!/usr/bin/python

from Adafruit_BBIO.SPI import SPI
from time import sleep
spi = SPI(0,0)
spi.bpw = 12
spi.msh = 100000
spi.lsbfirst = False
spi.mode = 0
spi.open

tlc5947_count = 2
tlc5947_channels = 24
# buffer = [0x000] * 48
buffer = [0x000] * (tlc5947_count * tlc5947_channels)

#spi.writebytes(buffer)
#print buffer


spi.writebytes(buffer)


#sleep(1)

spi.close


# CS_0  P9_17 lat
# DO    P9_21 din
# DI    P9_18 n/c
Ejemplo n.º 50
0
    def begin(self, major, minor, ce_pin, irq_pin):
        # Initialize SPI bus

        if ADAFRUID_BBIO_SPI:
            self.spidev = SPI(major, minor)
            self.spidev.bpw = 8
            try:
                self.spidev.msh = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed
        else:
            self.spidev = spidev.SpiDev()
            self.spidev.open(major, minor)

            self.spidev.bits_per_word = 8

            try:
                self.spidev.max_speed_hz = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed

        self.spidev.cshigh = False
        self.spidev.mode = 0
        self.spidev.loop = False
        self.spidev.lsbfirst = False
        self.spidev.threewire = False

        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        if self.ce_pin is not None:
            GPIO.setup(self.ce_pin, GPIO.OUT)

        GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Reset radio configuration
        self.reset()

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        self.setRetries(int('0101', 2), 15)

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.setChannel(self.channel)

        self.setRetries(15, 15)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()
        self.clear_irq_flags()
Ejemplo n.º 51
0
    def begin(self, major, minor, ce_pin, irq_pin):
        """Radio initialization, must be called before anything else.
        
            major and minor selects SPI port,
            ce_pin is GPIO pin number for CE signal
            irq_pin is optional GPIO pin number for IRQ signal"""
        # Initialize SPI bus
        if ADAFRUID_BBIO_SPI:
            self.spidev = SPI(major, minor)
            self.spidev.bpw = 8
            try:
                self.spidev.msh = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed
        else:
            self.spidev = spidev.SpiDev()
            self.spidev.open(major, minor)
            self.spidev.bits_per_word = 8
            try:
                self.spidev.max_speed_hz = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed

        self.spidev.cshigh = False
        self.spidev.mode = 0
        self.spidev.loop = False
        self.spidev.lsbfirst = False
        self.spidev.threewire = False

        # Save pin numbers
        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        # If CE pin is not used, CE signal must be always high
        if self.ce_pin is not None:
            GPIO.setup(self.ce_pin, GPIO.OUT)
        
        # IRQ pin is optional
        if self.irq_pin is not None:
            GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Reset radio registers
        self.reset()

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        self.p_variant = False  # False for RF24L01 and true for RF24L01P
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        # This must be done after setDataRate()
        self.setRetries(int('0101', 2), 15)
        # Line bellow will set maximum (4ms) delay
        #self.setRetries(15, 15)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.channel = 76
        self.setChannel(self.channel)

        # Powers up the radio, this can take up to 4.5ms
        # when CE is low radio will be in standby and will initiate
        # reception or transmission very shortly after CE is raised
        # If CE pin is not used, will Power up only on startListening and stopListening
        if self.ce_pin is not None:
            self.powerUp()

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(NRF24.STATUS, NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()
        self.clear_irq_flags()
Ejemplo n.º 52
0
#!/usr/bin/python

from Adafruit_BBIO.SPI import SPI

spi = SPI(0,0)

spi.lsbfirst=False
spi.msh=1000000

spi.cshigh=False
spi.xfer2([0x36])
spi.cshigh=True

for reg in range(0x0,0x3d+1,1):
 spi.cshigh=False
 send = [ reg+0xc0 , 0x0 ]
 recv = spi.xfer2(send)
 spi.cshigh=True
 print reg,recv

patable=9*[0]
patable[0]=0x3e+0xc0

spi.cshigh=False
dd = spi.xfer2(patable)
spi.cshigh=True
print 0x3e,dd

rxfifo=65*[0]
rxfifo[0]=0x3f+0xc0
Ejemplo n.º 53
0
                value[12]).split('x')[1] + ":" + hex(value[11]).split('x')[1]
    #print(address)
    rssi = value[17] - 256
    #print(rssi)
    if rssi > -70:
        if value[28] == 128:
            print("%s, 1, %d") % (address, rssi)
        if value[28] == 129:
            print("%s, 2, %d") % (address, rssi)
        if value[28] == 130:
            print("%s, 3, %d") % (address, rssi)
        if value[28] == 131:
            print("%s, 4, %d") % (address, rssi)


bt = SPI(0, 0)
bt.mode = 1
bt.msh = 1000000

#reset the module

GPIO.output("P9_12", GPIO.LOW)
time.sleep(0.1)
GPIO.output("P9_12", GPIO.HIGH)

# initialize bt module
k = 0
while k < 100:
    #print("Sending init message")
    bt.xfer2([
        0x00, 0xFE, 0x2A, 0x01, 0x00, 0xFE, 0x26, 0x02, 0x0A, 0x00, 0x00, 0x00,
Ejemplo n.º 54
0
#!/usr/bin/env	python
# -*-	coding: utf-8 -*-
import time
from Adafruit_BBIO.SPI import SPI

spi_in = SPI(0, 0)
spi_out = SPI(0, 1)


while True:
	try:
		print spi_in.readbytes(1)
		time.sleep(0.03)

	except KeyboardInterrupt:
		Break

Ejemplo n.º 55
0
from Adafruit_BBIO.SPI import SPI
import time
import numpy as np
import scipy as sp
import peakutils

spi = SPI(0, 0)
spi.mode = 1
spi.bpw = 8
spi.msh = 8000000


def put_in_reset():
    print "\nput in reset"
    print spi.xfer2([int("16", 16), int("2F", 16), int("01", 16)])


def read_this_fifo(this, that):
    #print "\nread this fifo"
    #print "sent: 08", this, that, " 00. Got:"
    resp = spi.xfer2(
        [int("08", 16),
         int(str(this), 16),
         int(str(that), 16),
         int("00", 16)])
    print resp
    return resp


def put_out_reset():
    print "\nput out reset"
Ejemplo n.º 56
0
class ledstrip:
    
    def __init__(self, length, missing):
        # the important piece of this for reuse is setting up the interface
        # the rest sets up the strip of leds for what we intend to do with them
        self.interface = SPI(0,1)
        self.full_length = length
        self.missing_leds = missing
        self.outbuff = [[128, 128, 128]] * length
        self.reset_buffer([128, 128, 128])
        
    def reset_buffer(self, color):
        for i in range(0, len(self.outbuff), 1):
            self.outbuff[i] = color

    def write(self):
        # this guy here, plus a small amount of init code elsewhere,
        # is all we really need to make the led strips work. The rest is just
        # for ease of use.
        self.interface.writebytes([0] * (int(self.full_length / 32) + 1) + [0])
        for i in range(0, len(self.outbuff), 1):
	    if not i in self.missing_leds:
                self.interface.writebytes(self.outbuff[i])

    def twocolorfade(self, bcolor, tcolor, length):
        outcolor = []
        totalshift = [0, 0, 0]
        for i in range(0, 3, 1):
            totalshift[i] = tcolor[i] - bcolor[i]
        for i in range(0, length, 1):
            outcolor.append([])
            for j in range(0, 3, 1):
                outcolor[i].append(bcolor[j] + (int(totalshift[j] / float(length) * i)))
        return outcolor

    def movingtwocolor(self, bcols, tcols, strip_length, gradient_width, delay):
        bfade = self.twocolorfade(bcols[0], bcols[1], gradient_width)
        for frame in bfade:
            seg1 = self.twocolorfade(frame, tcols[0], strip_length)
            seg2 = [] + seg1
            seg2.reverse()
            self.outbuff = seg1 + seg2 + seg1
            self.write()
            time.sleep(delay)
        bfade = self.twocolorfade(tcols[0], tcols[1], gradient_width)
        for frame in bfade:
            seg1 = self.twocolorfade(bcols[1], frame, strip_length)
            seg2 = [] + seg1
            seg2.reverse()
            self.outbuff = seg1 + seg2 + seg1
            self.write()
            time.sleep(delay)
        bfade = self.twocolorfade(tcols[1], tcols[0], gradient_width)
        for frame in bfade:
            seg1 = self.twocolorfade(bcols[1], frame, strip_length)
            seg2 = [] + seg1
            seg2.reverse()
            self.outbuff = seg1 + seg2 + seg1
            self.write()
            time.sleep(delay)
        bfade = self.twocolorfade(bcols[1], bcols[0], gradient_width)
        for frame in bfade:
            seg1 = self.twocolorfade(frame, tcols[0], strip_length)
            seg2 = [] + seg1
            seg2.reverse()
            self.outbuff = seg1 + seg2 + seg1
            self.write()
            time.sleep(delay)

            
    def run_sequence(self, fcol, bcol, length, delay, sequence, step, loops, timechange):
        # with run_sequence, we can do pretty much anything, 
        # provided we can set up the sequence properly
        # long list of parameters gives us what we need to make that happen
        # fcol : foreground color (the color value for the leds in sequence)
        # bcol : background color (the color value for the leds not in sequence)
        # length : number of leds still active trailing the "current" one in sequence
        # delay : time between steps in sequence
        # sequence : a list (processed in the order provided) of leds to activate
        # step : number of leds in sequence to skip per step (useful for moving a whole group at once)
        # loops : number of times to iterate through the sequence completely
        # timechange : somewhat handy but not wholly necessary per loop multiplier for delay variable
        #              can be used to increase or decrease timestep over several loops without re-running sequence
        pos = 0
        loops = loops - 1
        firstrun = True
        self.reset_buffer(bcol)
        while pos < len(sequence):
            self.reset_buffer(bcol)
            for tail in range(0, length, 1):
                if pos - tail >= 0 or not firstrun:    
                    self.outbuff[sequence[pos - tail]] = fcol
            if pos < len(sequence):
                if pos == len(sequence) - 1 and loops:
                    pos = 0
                    firstrun = False
                    loops = loops - 1
                    delay = delay * timechange
                elif pos == len(sequence) - 1 and length:
                    length = length - 1
                else:
                    pos = pos + step
            time.sleep(delay)
            self.write()
        self.reset_buffer(bcol)
        self.write()
Ejemplo n.º 57
0
    def begin(self, major, minor, ce_pin, irq_pin):
        # Initialize SPI bus

        if ADAFRUID_BBIO_SPI:
            self.spidev = SPI(major, minor)
            self.spidev.bpw = 8
            try:
                self.spidev.msh = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed
        else:
            self.spidev = spidev.SpiDev()
            self.spidev.open(major, minor)

            self.spidev.bits_per_word = 8

            try:
                self.spidev.max_speed_hz = 10000000  # Maximum supported by NRF24L01+
            except IOError:
                pass  # Hardware does not support this speed

        self.spidev.cshigh = False
        self.spidev.mode = 0
        self.spidev.loop = False
        self.spidev.lsbfirst = False
        self.spidev.threewire = False

        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        if self.ce_pin is not None:
            GPIO.setup(self.ce_pin, GPIO.OUT)

        GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Reset radio configuration
        self.reset()

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        self.setRetries(int('0101', 2), 15)

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(NRF24.STATUS,
                            NRF24.RX_DR | NRF24.TX_DS | NRF24.MAX_RT)

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.setChannel(self.channel)

        self.setRetries(15, 15)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()
        self.clear_irq_flags()
Ejemplo n.º 58
0
class RFM69(BaseRadio):
	DATA = []
	DATALEN = 0
	SENDERID = 0
	TARGETID = 0
	PAYLOADLEN = 0
	ACK_REQUESTED = False
	ACK_RECEIVED = False
	RSSI = 0
	_mode = 0
	_interruptPin = DIO0_PIN
	_csPin = NSS_PIN
	_address = 0
	_promiscuousMode = False
	_powerLevel = 31
	_isRFM69HW = True
	
	def __init__(self, isRFM69HW=True, interruptPin=DIO0_PIN, csPin=NSS_PIN):
		self._isRFM69HW = isRFM69HW
		self._interruptPin = interruptPin
		self._csPin = csPin

		self.SPI = SPI(SPI_BUS, SPI_CS)
		self.SPI.bpw = 8
		self.SPI.mode = 0
		self.SPI.msh = SPI_CLK_SPEED
		self.SPI.lsbfirst = False

		GPIO.setup(self._interruptPin, GPIO.IN)
		self.lastIrqLevel = GPIO.input(self._interruptPin)
		GPIO.setup(self._csPin, GPIO.OUT)
		GPIO.output(self._csPin, GPIO.HIGH)

		self.start_time = datetime.datetime.now()

	# Convention I want to stick to is a single underscore to indicate "private" methods.
	# I'm grouping all the private stuff up at the beginning.

	def _millis(self):
		delta = datetime.datetime.now() - self.start_time
		return delta.total_seconds() * 1000

	def _readReg(self, addr):
		self._select()
		self.SPI.writebytes([addr & 0x7F])
		result = self.SPI.readbytes(1)[0]
	#	print "readReg {} = {}". format(hex(addr), hex(result))
		self._unselect()
		return result

	def _writeReg(self, addr, value):
	#	print "writeReg, Address {}:{}". format(hex(addr), hex(value))
		self._select()
		self.SPI.writebytes([addr | 0x80, value])
		self._unselect()

	# Select the transceiver
	def _select(self):
		GPIO.output(self._csPin, GPIO.LOW)

	# Unselect the transceiver chip
	def _unselect(self): 
		GPIO.output(self._csPin, GPIO.HIGH)
	
	def _setMode(self, newMode):
		if newMode == RF69_MODE_TX:
			self._writeReg(REG_OPMODE, (self._readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER)
			if self._isRFM69HW:
				self.setHighPowerRegs(True)
		elif newMode == RF69_MODE_RX:
			self._writeReg(REG_OPMODE, (self._readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER)
			if self._isRFM69HW:
				self.setHighPowerRegs(False)
		elif newMode == RF69_MODE_SYNTH:
			self._writeReg(REG_OPMODE, (self._readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER)
		elif newMode == RF69_MODE_STANDBY:
			self._writeReg(REG_OPMODE, (self._readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY)
		elif newMode == RF69_MODE_SLEEP:
			self._writeReg(REG_OPMODE, (self._readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SLEEP)

		# we are using packet mode, so this check is not really needed
		# but waiting for mode ready is necessary when going from sleep because the FIFO may not 
		# be immediately available from previous mode
		while (self._mode == RF69_MODE_SLEEP and (self._readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00): # Wait for ModeReady
			pass
		self._mode = newMode

	def _canSend(self):
		#if signal stronger than -100dBm is detected assume channel activity
		if (self._mode == RF69_MODE_RX and self.PAYLOADLEN == 0 and self.getRSSI() < CSMA_LIMIT): 
			self._setMode(RF69_MODE_STANDBY)
			return True
		return False

	def _sendFrame(self, toAddress, buffer, bufferSize, requestACK=False, sendACK=False):
		self._setMode(RF69_MODE_STANDBY) #turn off receiver to prevent reception while filling fifo
		while ((self._readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00):
			pass # Wait for ModeReady
		self._writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00) # DIO0 is "Packet Sent"
		if bufferSize > RF69_MAX_DATA_LEN:
			bufferSize = RF69_MAX_DATA_LEN

		#write to FIFO
		self._select()
		self.SPI.writebytes([REG_FIFO | 0x80, bufferSize + 3, toAddress, self._address])

		#control byte
		if (sendACK):
			self.SPI.writebytes([0x80])
		elif (requestACK):
			self.SPI.writebytes([0x40])
		else:
			self.SPI.writebytes([0x00])
		bufferBytes = []
		for i in range(0, bufferSize):
			self.SPI.writebytes([ord(buffer[i])])
		self._unselect()

		# no need to wait for transmit mode to be ready since its handled by the radio
		self._setMode(RF69_MODE_TX)
		txStart = self._millis()
		# wait for DIO0 to turn HIGH signalling transmission finish
		while (GPIO.input(self._interruptPin) == 0 and self._millis()-txStart < RF69_TX_LIMIT_MS):
			pass
		self._setMode(RF69_MODE_STANDBY)

	def _interruptHandler(self):
		if (self._mode == RF69_MODE_RX and (self._readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)):
			self._setMode(RF69_MODE_STANDBY)
			self._select()
			self.SPI.writebytes([REG_FIFO & 0x7f])
			self.PAYLOADLEN = self.SPI.readbytes(1)[0]
			self.PAYLOADLEN = 66 if self.PAYLOADLEN > 66 else self.PAYLOADLEN
			self.TARGETID = self.SPI.readbytes(1)[0]
			# match this node's address, or broadcast address or anything in promiscuous mode
			# address situation could receive packets that are malformed and don't fit this libraries extra fields
			if(not(self._promiscuousMode or self.TARGETID==self._address or self.TARGETID==RF69_BROADCAST_ADDR) or self.PAYLOADLEN < 3):
				self.PAYLOADLEN = 0
				self._unselect()
				self._receiveBegin()
				return

			self.DATALEN = self.PAYLOADLEN - 3
			self.SENDERID = self.SPI.readbytes(1)[0]
			CTLbyte = self.SPI.readbytes(1)[0]

			self.ACK_RECEIVED = CTLbyte & 0x80 #extract ACK-requested flag
			self.ACK_REQUESTED = CTLbyte & 0x40 #extract ACK-received flag

			self.DATA = self.SPI.readbytes(self.DATALEN)
			self._unselect()
			self._setMode(RF69_MODE_RX)
		self.RSSI = self.getRSSI()

	def _noInterrupts(self):
		pass

	def _interrupts(self):
		pass

	def _receiveBegin(self):
		self.DATALEN = 0
		self.SENDERID = 0
		self.TARGETID = 0
		self.PAYLOADLEN = 0
		self.ACK_REQUESTED = 0
		self.ACK_RECEIVED = 0
		self.RSSI = 0
		if (self._readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY):
			# avoid RX deadlocks
			self._writeReg(REG_PACKETCONFIG2, (self._readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART)
		#set DIO0 to "PAYLOADREADY" in receive mode
		self._writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01) 
		self._setMode(RF69_MODE_RX)

	def initialize(self, freqBand, nodeId, networkID):
		self._address = nodeId
		config = [
			[ REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY ],
			[ REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 ], #no shaping
			[ REG_BITRATEMSB, RF_BITRATEMSB_55555], #default:4.8 KBPS
			[ REG_BITRATELSB, RF_BITRATELSB_55555],
			[ REG_FDEVMSB, RF_FDEVMSB_50000], #default:5khz, (FDEV + BitRate/2 <= 500Khz)
			[ REG_FDEVLSB, RF_FDEVLSB_50000],
			[ REG_FRFMSB, RF_FRFMSB_315 if freqBand == RF69_315MHZ else (RF_FRFMSB_433 if freqBand == RF69_433MHZ else (RF_FRFMSB_868 if freqBand == RF69_868MHZ else RF_FRFMSB_915)) ],
			[ REG_FRFMID, RF_FRFMID_315 if freqBand == RF69_315MHZ else (RF_FRFMID_433 if freqBand == RF69_433MHZ else (RF_FRFMID_868 if freqBand == RF69_868MHZ else RF_FRFMID_915)) ],
			[ REG_FRFLSB, RF_FRFLSB_315 if freqBand == RF69_315MHZ else (RF_FRFLSB_433 if freqBand == RF69_433MHZ else (RF_FRFLSB_868 if freqBand == RF69_868MHZ else RF_FRFLSB_915)) ],

			# looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm
			# +17dBm and +20dBm are possible on RFM69HW
			# +13dBm formula: Pout=-18+OutputPower (with PA0 or PA1**)
			# +17dBm formula: Pout=-14+OutputPower (with PA1 and PA2)**
			# +20dBm formula: Pout=-11+OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet)
			#[ REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111],
			#[ REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 ], #over current protection (default is 95mA)

			# RXBW defaults are [ REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5] (RxBw: 10.4khz)
			[ REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 ], #(BitRate < 2 * RxBw)
			# for BR-19200: #* 0x19 */ [ REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 ],
			[ REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 ], #DIO0 is the only IRQ we're using
			[ REG_RSSITHRESH, 220 ], #must be set to dBm = (-Sensitivity / 2) - default is 0xE4=228 so -114dBm
			#[ REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE ] # default 3 preamble bytes 0xAAAAAA
			[ REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 ],
			[ REG_SYNCVALUE1, 0x2D ],	  #attempt to make this compatible with sync1 byte of RFM12B lib
			[ REG_SYNCVALUE2, networkID ], #NETWORK ID
			[ REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF ],
			[ REG_PAYLOADLENGTH, 66 ], #in variable length mode: the max frame size, not used in TX
			#[ REG_NODEADRS, nodeID ], #turned off because we're not using address filtering
			[ REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE ], #TX on FIFO not empty
			[ REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF ], #RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
			# for BR-19200: #* 0x3d */ [ REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF ], #RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
			#[ REG_TESTDAGC, RF_DAGC_CONTINUOUS ], # run DAGC continuously in RX mode
			[ REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 ], # run DAGC continuously in RX mode, recommended default for AfcLowBetaOn=0
			[255, 0]
		]

		print "writing REG_SYNCVALUE1"
		while self._readReg(REG_SYNCVALUE1) != 0xaa:
			self._writeReg(REG_SYNCVALUE1, 0xaa)
		while self._readReg(REG_SYNCVALUE1) != 0x55:
			self._writeReg(REG_SYNCVALUE1, 0x55)
		print "done writing REG_SYNCVALUE1"

		for chunk in config:
			self._writeReg(chunk[0], chunk[1])

		self.setEncryptionKey(None)
		self.setHighPower(self._isRFM69HW)
		self._setMode(RF69_MODE_STANDBY)
		# wait for mode ready
		while (self._readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00:
			pass
		self._interrupts()

	def sleep(self):
		self._setMode(RF69_MODE_SLEEP)

	def setAddress(self, addr):
		self._address = addr
		self._writeReg(REG_NODEADRS, self._address)

	def setNetwork(self, networkID):
		self._writeReg(REG_SYNCVALUE2, networkID)
	
	# set output power: 0=min, 31=max
	# this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver
	def setPowerLevel(self, powerLevel):
		self._powerLevel = powerLevel
		self._writeReg(REG_PALEVEL, (_readReg(REG_PALEVEL) & 0xE0) | (self._powerLevel if self._powerLevel < 31 else 31))

	def send(self, toAddress, buffer, bufferSize, requestACK):
		self._writeReg(REG_PACKETCONFIG2, (self._readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART) # avoid RX deadlocks
		now = self._millis()
		while (not self._canSend() and self._millis()-now < RF69_CSMA_LIMIT_MS):
			self.receiveDone()
		self._sendFrame(toAddress, buffer, bufferSize, requestACK, False)
	
	# to increase the chance of getting a packet across, call this function instead of send
	# and it handles all the ACK requesting/retrying for you :)
	# The only twist is that you have to manually listen to ACK requests on the other side and send back the ACKs
	# The reason for the semi-automaton is that the lib is ingterrupt driven and
	# requires user action to read the received data and decide what to do with it
	# replies usually take only 5-8ms at 50kbps@915Mhz
	def sendWithRetry(self, toAddress, buffer, bufferSize, retries=2, retryWaitTime=40):
		for i in range(0, retries):
			self.send(toAddress, buffer, bufferSize, True)
		sentTime = self._millis()
		while self._millis()-sentTime<retryWaitTime:
			if self.ACKReceived(toAddress):
				return True
		return False
	
	# Should be polled immediately after sending a packet with ACK request
	def ACKReceived(self, fromNodeID):
		if self.receiveDone():
			return (self.SENDERID == fromNodeID or fromNodeID == RF69_BROADCAST_ADDR) and self.ACK_RECEIVED
		return False

	#check whether an ACK was requested in the last received packet (non-broadcasted packet)
	def ACKRequested(self):
		return self.ACK_REQUESTED and (self.TARGETID != RF69_BROADCAST_ADDR)

	# Should be called immediately after reception in case sender wants ACK
	def sendACK(self, buffer="", bufferSize=0):
		sender = self.SENDERID
		_RSSI = self.RSSI #save payload received RSSI value
		self._writeReg(REG_PACKETCONFIG2, (self._readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART) # avoid RX deadlocks
		now = self._millis()
		while (not self._canSend() and self._millis()-now < RF69_CSMA_LIMIT_MS):
			self.receiveDone()
		self._sendFrame(sender, buffer, bufferSize, False, True)
		self.RSSI = _RSSI #restore payload RSSI
	
	def receiveDone(self):
		self._noInterrupts() #re-enabled in _unselect() via _setMode() or via _receiveBegin()
		if GPIO.input(self._interruptPin):
			self._interruptHandler()
		if (self._mode == RF69_MODE_RX and self.PAYLOADLEN > 0):
			self._setMode(RF69_MODE_STANDBY) #enables interrupts
			return True
		elif (self._mode == RF69_MODE_RX):  #already in RX no payload yet
			self._interrupts() #explicitly re-enable interrupts
			return False
		self._receiveBegin()
		return False
	
	# To enable encryption: radio.encrypt("ABCDEFGHIJKLMNOP")
	# To disable encryption: radio.encrypt(null)
	# KEY HAS TO BE 16 bytes !!!
	def setEncryptionKey(self, key):
		if key is not None:
			if len(key) != 16:
				raise Exception("Key must be exactly 16 bytes!")
		self._setMode(RF69_MODE_STANDBY)
		if (key is not None):
			keyBytes = []
			self._select()
			self.SPI.writebytes([REG_AESKEY1 | 0x80])
			for i in range(0,16):
				keyBytes.append(ord(key[i]))
			self.SPI.writebytes(keyBytes)
			self._unselect()
		self._writeReg(REG_PACKETCONFIG2, (self._readReg(REG_PACKETCONFIG2) & 0xFE) | (0 if key is None else 1))

	# The following methods are not required by BaseRadio.
	# They depend too heavily on the specific radio hardware and would not get any benefit from being part of the
	# BaseRadio class.

	def getRSSI(self, forceTrigger=False):
		rssi = 0
		if (forceTrigger):
			# RSSI trigger not needed if DAGC is in continuous mode
			self._writeReg(REG_RSSICONFIG, RF_RSSI_START)
			while ((self._readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00):
				pass # Wait for RSSI_Ready
		rssi = -self._readReg(REG_RSSIVALUE)
		rssi >>= 1
		return rssi

	# ON  = disable filtering to capture all frames on network
	# OFF = enable node+broadcast filtering to capture only frames sent to this/broadcast address
	def setPromiscuous(self, onOff):
		self._promiscuousMode = onOff

	def setHighPower(self, onOff):
		self._isRFM69HW = onOff
		self._writeReg(REG_OCP, RF_OCP_OFF if self._isRFM69HW else RF_OCP_ON)
		if (self._isRFM69HW):
			# enable P1 & P2 amplifier stages
			self._writeReg(REG_PALEVEL, (self._readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON) 
		else:
			# enable P0 only
			self._writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | self.powerLevel) 

	def setHighPowerRegs(self, onOff):
		self._writeReg(REG_TESTPA1, 0x5D if onOff else 0x55)
		self._writeReg(REG_TESTPA2, 0x7C if onOff else 0x70)
	
	def readAllRegs(self):
		print "Register, Address, Value"
		print "REG_FIFO, 0x00, {}".format(hex(self._readReg(REG_FIFO)))
		print "REG_OPMODE, 0x01, {}".format(hex(self._readReg(REG_OPMODE)))
		print "REG_DATAMODUL, 0x02, {}".format(hex(self._readReg(REG_DATAMODUL)))
		print "REG_BITRATEMSB, 0x03, {}".format(hex(self._readReg(REG_BITRATEMSB)))
		print "REG_BITRATELSB, 0x04, {}".format(hex(self._readReg(REG_BITRATELSB)))
		print "REG_FDEVMSB, 0x05, {}".format(hex(self._readReg(REG_FDEVMSB)))
		print "REG_FDEVLSB, 0x06, {}".format(hex(self._readReg(REG_FDEVLSB)))
		print "REG_FRFMSB, 0x07, {}".format(hex(self._readReg(REG_FRFMSB)))
		print "REG_FRFMID, 0x08, {}".format(hex(self._readReg(REG_FRFMID)))
		print "REG_FRFLSB, 0x09, {}".format(hex(self._readReg(REG_FRFLSB)))
		print "REG_OSC1, 0x0A, {}".format(hex(self._readReg(REG_OSC1)))
		print "REG_AFCCTRL, 0x0B, {}".format(hex(self._readReg(REG_AFCCTRL)))
		print "REG_LOWBAT, 0x0C, {}".format(hex(self._readReg(REG_LOWBAT)))
		print "REG_LISTEN1, 0x0D, {}".format(hex(self._readReg(REG_LISTEN1)))
		print "REG_LISTEN2, 0x0E, {}".format(hex(self._readReg(REG_LISTEN2)))
		print "REG_LISTEN3, 0x0F, {}".format(hex(self._readReg(REG_LISTEN3)))
		print "REG_VERSION, 0x10, {}".format(hex(self._readReg(REG_VERSION)))
		print "REG_PALEVEL, 0x11, {}".format(hex(self._readReg(REG_PALEVEL)))
		print "REG_PARAMP, 0x12, {}".format(hex(self._readReg(REG_PARAMP)))
		print "REG_OCP, 0x13, {}".format(hex(self._readReg(REG_OCP)))
		print "REG_AGCREF, 0x14, {}".format(hex(self._readReg(REG_AGCREF)))
		print "REG_AGCTHRESH1, 0x15, {}".format(hex(self._readReg(REG_AGCTHRESH1)))
		print "REG_AGCTHRESH2, 0x16, {}".format(hex(self._readReg(REG_AGCTHRESH2)))
		print "REG_AGCTHRESH3, 0x17, {}".format(hex(self._readReg(REG_AGCTHRESH3)))
		print "REG_LNA, 0x18, {}".format(hex(self._readReg(REG_LNA)))
		print "REG_RXBW, 0x19, {}".format(hex(self._readReg(REG_RXBW)))
		print "REG_AFCBW, 0x1A, {}".format(hex(self._readReg(REG_AFCBW)))
		print "REG_OOKPEAK, 0x1B, {}".format(hex(self._readReg(REG_OOKPEAK)))
		print "REG_OOKAVG, 0x1C, {}".format(hex(self._readReg(REG_OOKAVG)))
		print "REG_OOKFIX, 0x1D, {}".format(hex(self._readReg(REG_OOKFIX)))
		print "REG_AFCFEI, 0x1E, {}".format(hex(self._readReg(REG_AFCFEI)))
		print "REG_AFCMSB, 0x1F, {}".format(hex(self._readReg(REG_AFCMSB)))
		print "REG_AFCLSB, 0x20, {}".format(hex(self._readReg(REG_AFCLSB)))
		print "REG_FEIMSB, 0x21, {}".format(hex(self._readReg(REG_FEIMSB)))
		print "REG_FEILSB, 0x22, {}".format(hex(self._readReg(REG_FEILSB)))
		print "REG_RSSICONFIG, 0x23, {}".format(hex(self._readReg(REG_RSSICONFIG)))
		print "REG_RSSIVALUE, 0x24, {}".format(hex(self._readReg(REG_RSSIVALUE)))
		print "REG_DIOMAPPING1, 0x25, {}".format(hex(self._readReg(REG_DIOMAPPING1)))
		print "REG_DIOMAPPING2, 0x26, {}".format(hex(self._readReg(REG_DIOMAPPING2)))
		print "REG_IRQFLAGS1, 0x27, {}".format(hex(self._readReg(REG_IRQFLAGS1)))
		print "REG_IRQFLAGS2, 0x28, {}".format(hex(self._readReg(REG_IRQFLAGS2)))
		print "REG_RSSITHRESH, 0x29, {}".format(hex(self._readReg(REG_RSSITHRESH)))
		print "REG_RXTIMEOUT1, 0x2A, {}".format(hex(self._readReg(REG_RXTIMEOUT1)))
		print "REG_RXTIMEOUT2, 0x2B, {}".format(hex(self._readReg(REG_RXTIMEOUT2)))
		print "REG_PREAMBLEMSB, 0x2C, {}".format(hex(self._readReg(REG_PREAMBLEMSB)))
		print "REG_PREAMBLELSB, 0x2D, {}".format(hex(self._readReg(REG_PREAMBLELSB)))
		print "REG_SYNCCONFIG, 0x2E, {}".format(hex(self._readReg(REG_SYNCCONFIG)))
		print "REG_SYNCVALUE1, 0x2F, {}".format(hex(self._readReg(REG_SYNCVALUE1)))
		print "REG_SYNCVALUE2, 0x30, {}".format(hex(self._readReg(REG_SYNCVALUE2)))
		print "REG_SYNCVALUE3, 0x31, {}".format(hex(self._readReg(REG_SYNCVALUE3)))
		print "REG_SYNCVALUE4, 0x32, {}".format(hex(self._readReg(REG_SYNCVALUE4)))
		print "REG_SYNCVALUE5, 0x33, {}".format(hex(self._readReg(REG_SYNCVALUE5)))
		print "REG_SYNCVALUE6, 0x34, {}".format(hex(self._readReg(REG_SYNCVALUE6)))
		print "REG_SYNCVALUE7, 0x35, {}".format(hex(self._readReg(REG_SYNCVALUE7)))
		print "REG_SYNCVALUE8, 0x36, {}".format(hex(self._readReg(REG_SYNCVALUE8)))
		print "REG_PACKETCONFIG1, 0x37, {}".format(hex(self._readReg(REG_PACKETCONFIG1)))
		print "REG_PAYLOADLENGTH, 0x38, {}".format(hex(self._readReg(REG_PAYLOADLENGTH)))
		print "REG_NODEADRS, 0x39, {}".format(hex(self._readReg(REG_NODEADRS)))
		print "REG_BROADCASTADRS, 0x3A, {}".format(hex(self._readReg(REG_BROADCASTADRS)))
		print "REG_AUTOMODES, 0x3B, {}".format(hex(self._readReg(REG_AUTOMODES)))
		print "REG_FIFOTHRESH, 0x3C, {}".format(hex(self._readReg(REG_FIFOTHRESH)))
		print "REG_PACKETCONFIG2, 0x3D, {}".format(hex(self._readReg(REG_PACKETCONFIG2)))
		print "REG_AESKEY1, 0x3E, {}".format(hex(self._readReg(REG_AESKEY1)))
		print "REG_AESKEY2, 0x3F, {}".format(hex(self._readReg(REG_AESKEY2)))
		print "REG_AESKEY3, 0x40, {}".format(hex(self._readReg(REG_AESKEY3)))
		print "REG_AESKEY4, 0x41, {}".format(hex(self._readReg(REG_AESKEY4)))
		print "REG_AESKEY5, 0x42, {}".format(hex(self._readReg(REG_AESKEY5)))
		print "REG_AESKEY6, 0x43, {}".format(hex(self._readReg(REG_AESKEY6)))
		print "REG_AESKEY7, 0x44, {}".format(hex(self._readReg(REG_AESKEY7)))
		print "REG_AESKEY8, 0x45, {}".format(hex(self._readReg(REG_AESKEY8)))
		print "REG_AESKEY9, 0x46, {}".format(hex(self._readReg(REG_AESKEY9)))
		print "REG_AESKEY10, 0x47, {}".format(hex(self._readReg(REG_AESKEY10)))
		print "REG_AESKEY11, 0x48, {}".format(hex(self._readReg(REG_AESKEY11)))
		print "REG_AESKEY12, 0x49, {}".format(hex(self._readReg(REG_AESKEY12)))
		print "REG_AESKEY13, 0x4A, {}".format(hex(self._readReg(REG_AESKEY13)))
		print "REG_AESKEY14, 0x4B, {}".format(hex(self._readReg(REG_AESKEY14)))
		print "REG_AESKEY15, 0x4C, {}".format(hex(self._readReg(REG_AESKEY15)))
		print "REG_AESKEY16, 0x4D, {}".format(hex(self._readReg(REG_AESKEY16)))
		print "REG_TEMP1, 0x4E, {}".format(hex(self._readReg(REG_TEMP1)))
		print "REG_TEMP2, 0x4F, {}".format(hex(self._readReg(REG_TEMP2)))
		if self._isRFM69HW:
			print "REG_TESTPA1, 0x5A, {}".format(hex(self._readReg(REG_TESTPA1)))
			print "REG_TESTPA2, 0x5C, {}".format(hex(self._readReg(REG_TESTPA2)))
		print "REG_TESTDAGC, 0x6F, {}".format(hex(self._readReg(REG_TESTDAGC)))

	# returns centigrade
	def readTemperature(self, calFactor):  
		self._setMode(RF69_MODE_STANDBY)
		self._writeReg(REG_TEMP1, RF_TEMP1_MEAS_START)
		while ((self._readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)):
			pass
		#'complement'corrects the slope, rising temp = rising val
		# COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction
		return ~self._readReg(REG_TEMP2) + COURSE_TEMP_COEF + calFactor 

	def rcCalibration(self):
		_writeReg(REG_OSC1, RF_OSC1_RCCAL_START)
		while ((_readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00):
			pass
Ejemplo n.º 59
0
import time
from Adafruit_BBIO.SPI import SPI

spi_in = SPI(0,0)
spi_out = SPI(0,1)

while True:
    try:
        spi_out.writebytes([0x50])
        print spi_in.readbytes(2)
        time.sleep(0.02)
    except KeyboardInterrupt:
        break

Ejemplo n.º 60
0
class NRF24:
    MAX_CHANNEL = 127
    MAX_PAYLOAD_SIZE = 32

    # PA Levels
    PA_MIN = 0
    PA_LOW = 1
    PA_HIGH = 2
    PA_MAX = 3
    PA_ERROR = 4

    # Bit rates
    BR_1MBPS = 0
    BR_2MBPS = 1
    BR_250KBPS = 2

    # CRC
    CRC_DISABLED = 0
    CRC_8 = 1
    CRC_16 = 2
    CRC_ENABLED = 3

    # Registers
    CONFIG = 0x00
    EN_AA = 0x01
    EN_RXADDR = 0x02
    SETUP_AW = 0x03
    SETUP_RETR = 0x04
    RF_CH = 0x05
    RF_SETUP = 0x06
    STATUS = 0x07
    OBSERVE_TX = 0x08
    CD = 0x09
    RX_ADDR_P0 = 0x0A
    RX_ADDR_P1 = 0x0B
    RX_ADDR_P2 = 0x0C
    RX_ADDR_P3 = 0x0D
    RX_ADDR_P4 = 0x0E
    RX_ADDR_P5 = 0x0F
    TX_ADDR = 0x10
    RX_PW_P0 = 0x11
    RX_PW_P1 = 0x12
    RX_PW_P2 = 0x13
    RX_PW_P3 = 0x14
    RX_PW_P4 = 0x15
    RX_PW_P5 = 0x16
    FIFO_STATUS = 0x17
    DYNPD = 0x1C
    FEATURE = 0x1D


    # Bit Mnemonics */
    MASK_RX_DR = 6
    MASK_TX_DS = 5
    MASK_MAX_RT = 4
    EN_CRC = 3
    CRCO = 2
    PWR_UP = 1
    PRIM_RX = 0
    ENAA_P5 = 5
    ENAA_P4 = 4
    ENAA_P3 = 3
    ENAA_P2 = 2
    ENAA_P1 = 1
    ENAA_P0 = 0
    ERX_P5 = 5
    ERX_P4 = 4
    ERX_P3 = 3
    ERX_P2 = 2
    ERX_P1 = 1
    ERX_P0 = 0
    AW = 0
    ARD = 4
    ARC = 0
    PLL_LOCK = 4
    RF_DR = 3
    RF_PWR = 6
    RX_DR = 6
    TX_DS = 5
    MAX_RT = 4
    RX_P_NO = 1
    TX_FULL = 0
    PLOS_CNT = 4
    ARC_CNT = 0
    TX_REUSE = 6
    FIFO_FULL = 5
    TX_EMPTY = 4
    RX_FULL = 1
    RX_EMPTY = 0
    DPL_P5 = 5
    DPL_P4 = 4
    DPL_P3 = 3
    DPL_P2 = 2
    DPL_P1 = 1
    DPL_P0 = 0
    EN_DPL = 2
    EN_ACK_PAY = 1
    EN_DYN_ACK = 0

    # Instruction Mnemonics
    R_REGISTER = 0x00
    W_REGISTER = 0x20
    REGISTER_MASK = 0x1F
    ACTIVATE = 0x50
    R_RX_PL_WID = 0x60
    R_RX_PAYLOAD = 0x61
    W_TX_PAYLOAD = 0xA0
    W_ACK_PAYLOAD = 0xA8
    FLUSH_TX = 0xE1
    FLUSH_RX = 0xE2
    REUSE_TX_PL = 0xE3
    NOP = 0xFF


    # Non-P omissions
    LNA_HCURR = 0x00

    # P model memory Map
    RPD = 0x09

    # P model bit Mnemonics
    RF_DR_LOW = 5
    RF_DR_HIGH = 3
    RF_PWR_LOW = 1
    RF_PWR_HIGH = 2

    # Signal Mnemonics
    LOW = 0
    HIGH = 1

    datarate_e_str_P = ["1MBPS", "2MBPS", "250KBPS"]
    model_e_str_P = ["nRF24L01", "nRF24l01+"]
    crclength_e_str_P = ["Disabled", "8 bits", "16 bits"]
    pa_dbm_e_str_P = ["PA_MIN", "PA_LOW", "PA_MED", "PA_HIGH"]
    child_pipe = [RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5]

    child_payload_size = [RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5]
    child_pipe_enable = [ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5]

    def __init__(self):
        self.ce_pin = "P9_15"
        self.irq_pin = "P9_16"
        self.channel = 76
        self.data_rate = NRF24.BR_1MBPS
        self.wide_band = False # 2Mbs data rate in use?
        self.p_variant = False # False for RF24L01 and true for RF24L01P
        self.payload_size = 5 #*< Fixed size of payloads
        self.ack_payload_available = False #*< Whether there is an ack payload waiting
        self.dynamic_payloads_enabled = False #*< Whether dynamic payloads are enabled.
        self.ack_payload_length = 5 #*< Dynamic size of pending ack payload.
        self.pipe0_reading_address = None #*< Last address set on pipe 0 for reading.
        self.spidev = None

    def ce(self, level):
        if level == NRF24.HIGH:
            GPIO.output(self.ce_pin, GPIO.HIGH)
        else:
            GPIO.output(self.ce_pin, GPIO.LOW)
        return

    def irqWait(self, timeout = 30000):
        # CHANGE: detect module name because wait_for_edge is not available in
        # other libraries
        if GPIO.__name__ != "Adafruit_BBIO.GPIO":
            return False

        # TODO: A race condition may occur here.
        if GPIO.input(self.irq_pin) == 0: # Pin is already down. Packet is waiting?
            return True

        return GPIO.wait_for_edge(self.irq_pin, GPIO.FALLING, timeout) == 1

    def read_register(self, reg, blen=1):
        buf = [NRF24.R_REGISTER | ( NRF24.REGISTER_MASK & reg )]
        for col in range(blen):
            buf.append(NRF24.NOP)

        resp = self.spidev.xfer2(buf)
        if blen == 1:
            return resp[1]

        return resp[1:blen + 1]

    def write_register(self, reg, value, length=-1):
        buf = [NRF24.W_REGISTER | ( NRF24.REGISTER_MASK & reg )]
        if isinstance(value, (int, long)):
            if length < 0:
                length = 1

            length = min(4, length)
            for i in range(length):
                buf.insert(1, int(value & 0xff))
                value >>= 8

        elif isinstance(value, list):
            if length < 0:
                length = len(value)

            for i in range(min(len(value), length)):
                buf.append(int(value[len(value) - i - 1] & 0xff))
        else:
            raise Exception("Value must be int or list")

        return self.spidev.xfer2(buf)[0]


    def write_payload(self, buf):
        data_len = min(self.payload_size, len(buf))
        blank_len = 0
        if not self.dynamic_payloads_enabled:
            blank_len = self.payload_size - data_len

        txbuffer = [NRF24.W_TX_PAYLOAD]
        for n in buf:
            t = type(n)
            if t is str:
                txbuffer.append(ord(n))
            elif t is int:
                txbuffer.append(n)
            else:
                raise Exception("Only ints and chars are supported: Found " + str(t))

        if blank_len != 0:
            blank = [0x00 for i in range(blank_len)]
            txbuffer.extend(blank)

        return self.spidev.xfer2(txbuffer)

    def read_payload(self, buf, buf_len=-1):
        if buf_len < 0:
            buf_len = self.payload_size
        data_len = min(self.payload_size, buf_len)
        blank_len = 0
        if not self.dynamic_payloads_enabled:
            blank_len = self.payload_size - data_len

        txbuffer = [NRF24.NOP for i in range(0, blank_len + data_len + 1)]
        txbuffer[0] = NRF24.R_RX_PAYLOAD

        payload = self.spidev.xfer2(txbuffer)
        del buf[:]
        buf.extend(payload[1:data_len + 1])
        return data_len

    def flush_rx(self):
        return self.spidev.xfer2([NRF24.FLUSH_RX])[0]

    def flush_tx(self):
        return self.spidev.xfer2([NRF24.FLUSH_TX])[0]

    def get_status(self):
        return self.spidev.xfer2([NRF24.NOP])[0]

    def print_status(self, status):
        status_str = "STATUS\t = 0x{0:02x} RX_DR={1:x} TX_DS={2:x} MAX_RT={3:x} RX_P_NO={4:x} TX_FULL={5:x}".format(
            status,
            1 if status & _BV(NRF24.RX_DR) else 0,
            1 if status & _BV(NRF24.TX_DS) else 0,
            1 if status & _BV(NRF24.MAX_RT) else 0,
            ((status >> NRF24.RX_P_NO) & int("111", 2)),
            1 if status & _BV(NRF24.TX_FULL) else 0)

        print status_str

    def print_observe_tx(self, value):
        tx_str = "OBSERVE_TX=0x{0:02x}: POLS_CNT={2:x} ARC_CNT={2:x}\r\n".format(
            value,
            (value >> NRF24.PLOS_CNT) & int("1111",2),
            (value >> NRF24.ARC_CNT)  & int("1111",2)
            )
        print tx_str

    def print_byte_register(self, name, reg, qty=1):
        extra_tab = '\t' if len(name) < 8 else 0
        print "%s\t%c =" % (name, extra_tab),
        while qty > 0:
            print "0x%02x" % (self.read_register(reg)),
            qty -= 1
            reg += 1

        print ""

    def print_address_register(self, name, reg, qty=1):
        extra_tab = '\t' if len(name) < 8 else 0
        print "%s\t%c =" % (name, extra_tab),

        while qty > 0:
            qty -= 1
            buf = reversed(self.read_register(reg, 5))
            reg += 1
            sys.stdout.write(" 0x"),
            for i in buf:
                sys.stdout.write("%02x" % i)

        print ""


    def setChannel(self, channel):
        self.channel = min(max(0, channel), NRF24.MAX_CHANNEL)
        self.write_register(NRF24.RF_CH, self.channel)

    def getChannel(self):
        return self.read_register(NRF24.RF_CH)

    def setPayloadSize(self, size):
        self.payload_size = min(max(size, 1), NRF24.MAX_PAYLOAD_SIZE)

    def getPayloadSize(self):
        return self.payload_size

    def printDetails(self):
        self.print_status(self.get_status())
        self.print_address_register("RX_ADDR_P0-1", NRF24.RX_ADDR_P0, 2)
        self.print_byte_register("RX_ADDR_P2-5", NRF24.RX_ADDR_P2, 4)
        self.print_address_register("TX_ADDR", NRF24.TX_ADDR)

        self.print_byte_register("RX_PW_P0-6", NRF24.RX_PW_P0, 6)
        self.print_byte_register("EN_AA", NRF24.EN_AA)
        self.print_byte_register("EN_RXADDR", NRF24.EN_RXADDR)
        self.print_byte_register("RF_CH", NRF24.RF_CH)
        self.print_byte_register("RF_SETUP", NRF24.RF_SETUP)
        self.print_byte_register("CONFIG", NRF24.CONFIG)
        self.print_byte_register("DYNPD/FEATURE", NRF24.DYNPD, 2)

        #
        print "Data Rate\t = %s" % NRF24.datarate_e_str_P[self.getDataRate()]
        print "Model\t\t = %s" % NRF24.model_e_str_P[self.isPVariant()]
        print "CRC Length\t = %s" % NRF24.crclength_e_str_P[self.getCRCLength()]
        print "PA Power\t = %s" % NRF24.pa_dbm_e_str_P[self.getPALevel()]

    def begin(self, major, minor, ce_pin, irq_pin):
        # Initialize SPI bus
        self.spidev = SPI(major, minor) 
        self.ce_pin = ce_pin
        self.irq_pin = irq_pin

        GPIO.setup(self.ce_pin, GPIO.OUT)
        GPIO.setup(self.irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        time.sleep(5 / 1000000.0)

        # Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
        # WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
        # sizes must never be used. See documentation for a more complete explanation.
        self.write_register(NRF24.SETUP_RETR, (int('0100', 2) << NRF24.ARD) | (int('1111', 2) << NRF24.ARC))

        # Restore our default PA level
        self.setPALevel(NRF24.PA_MAX)

        # Determine if this is a p or non-p RF24 module and then
        # reset our data rate back to default value. This works
        # because a non-P variant won't allow the data rate to
        # be set to 250Kbps.
        if self.setDataRate(NRF24.BR_250KBPS):
            self.p_variant = True

        # Then set the data rate to the slowest (and most reliable) speed supported by all
        # hardware.
        self.setDataRate(NRF24.BR_1MBPS)

        # Initialize CRC and request 2-byte (16bit) CRC
        self.setCRCLength(NRF24.CRC_16)

        # Disable dynamic payloads, to match dynamic_payloads_enabled setting
        self.write_register(NRF24.DYNPD, 0)

        # Reset current status
        # Notice reset and flush is the last thing we do
        self.write_register(NRF24.STATUS, _BV(NRF24.RX_DR) | _BV(NRF24.TX_DS) | _BV(NRF24.MAX_RT))

        # Set up default configuration.  Callers can always change it later.
        # This channel should be universally safe and not bleed over into adjacent
        # spectrum.
        self.setChannel(self.channel)

        # Flush buffers
        self.flush_rx()
        self.flush_tx()

    def end(self):
        if self.spidev:
            self.spidev.close()
            self.spidev = None

    def startListening(self):
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) | _BV(NRF24.PWR_UP) | _BV(NRF24.PRIM_RX))
        self.write_register(NRF24.STATUS, _BV(NRF24.RX_DR) | _BV(NRF24.TX_DS) | _BV(NRF24.MAX_RT))

        # Restore the pipe0 address, if exists
        if self.pipe0_reading_address:
            self.write_register(self.RX_ADDR_P0, self.pipe0_reading_address, 5)

        # Go!
        self.ce(NRF24.HIGH)

        # wait for the radio to come up (130us actually only needed)
        time.sleep(130 / 1000000.0)

    def stopListening(self):
        self.ce(NRF24.LOW)
        self.flush_tx()
        self.flush_rx()

    def powerDown(self):
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) & ~_BV(NRF24.PWR_UP))

    def powerUp(self):
        self.write_register(NRF24.CONFIG, self.read_register(NRF24.CONFIG) | _BV(NRF24.PWR_UP))
        time.sleep(150 / 1000000.0)

    def write(self, buf):
        # Begin the write
        self.startWrite(buf)

        timeout = self.getMaxTimeout() #s to wait for timeout
        sent_at = time.time()

        while True:
            #status = self.read_register(NRF24.OBSERVE_TX, 1)
            status = self.get_status()
            if (status & (_BV(NRF24.TX_DS) | _BV(NRF24.MAX_RT))) or (time.time() - sent_at > timeout ):
                break
            time.sleep(10 / 1000000.0)

        what = self.whatHappened()

        result = what['tx_ok']

        # Handle the ack packet
        if what['rx_ready']:
            self.ack_payload_length = self.getDynamicPayloadSize()

        return result

    def startWrite(self, buf):
        # Transmitter power-up
        self.write_register(NRF24.CONFIG, (self.read_register(NRF24.CONFIG) | _BV(NRF24.PWR_UP) ) & ~_BV(NRF24.PRIM_RX))

        # Send the payload
        self.write_payload(buf)

        # Allons!
        self.ce(NRF24.HIGH)
        time.sleep(10 / 1000000.0)
        self.ce(NRF24.LOW)

    def getDynamicPayloadSize(self):
        return self.spidev.xfer2([NRF24.R_RX_PL_WID, NRF24.NOP])[1]

    def available(self, pipe_num=None, irq_wait=False, irq_timeout=30000):
        if not pipe_num:
            pipe_num = []

        status = self.get_status()
        result = False

        # Sometimes the radio specifies that there is data in one pipe but
        # doesn't set the RX flag...
        if status & _BV(NRF24.RX_DR) or (status & 0b00001110 != 0b00001110):
            result = True
        else:
            if irq_wait: # Will use IRQ wait
                if self.irqWait(irq_timeout): # Do we have a packet?
                    status = self.get_status() # Seems like we do!
                    if status & _BV(NRF24.RX_DR) or (status & 0b00001110 != 0b00001110):
                        result = True 

        if result:
            # If the caller wants the pipe number, include that
            if len(pipe_num) >= 1:
                pipe_num[0] = ( status >> NRF24.RX_P_NO ) & 0b00000111

                # Clear the status bit

                # ??? Should this REALLY be cleared now?  Or wait until we
                # actually READ the payload?
        self.write_register(NRF24.STATUS, _BV(NRF24.RX_DR))

        # Handle ack payload receipt
        if status & _BV(NRF24.TX_DS):
            self.write_register(NRF24.STATUS, _BV(NRF24.TX_DS))

        return result

    def read(self, buf, buf_len=-1):
        # Fetch the payload
        self.read_payload(buf, buf_len)

        # was this the last of the data available?
        return self.read_register(NRF24.FIFO_STATUS) & _BV(NRF24.RX_EMPTY)

    def whatHappened(self):
        # Read the status & reset the status in one easy call
        # Or is that such a good idea?
        status = self.write_register(NRF24.STATUS, _BV(NRF24.RX_DR) | _BV(NRF24.TX_DS) | _BV(NRF24.MAX_RT))

        # Report to the user what happened
        tx_ok = status & _BV(NRF24.TX_DS)
        tx_fail = status & _BV(NRF24.MAX_RT)
        rx_ready = status & _BV(NRF24.RX_DR)
        return {'tx_ok': tx_ok, "tx_fail": tx_fail, "rx_ready": rx_ready}

    def openWritingPipe(self, value):
        # Note that the NRF24L01(+)
        # expects it LSB first.

        self.write_register(NRF24.RX_ADDR_P0, value, 5)
        self.write_register(NRF24.TX_ADDR, value, 5)

        max_payload_size = 32
        self.write_register(NRF24.RX_PW_P0, min(self.payload_size, max_payload_size))

    def openReadingPipe(self, child, address):
        # If this is pipe 0, cache the address.  This is needed because
        # openWritingPipe() will overwrite the pipe 0 address, so
        # startListening() will have to restore it.
        if child == 0:
            self.pipe0_reading_address = address

        if child <= 6:
            # For pipes 2-5, only write the LSB
            if child < 2:
                self.write_register(NRF24.child_pipe[child], address, 5)
            else:
                self.write_register(NRF24.child_pipe[child], address, 1)

            self.write_register(NRF24.child_payload_size[child], self.payload_size)

            # Note it would be more efficient to set all of the bits for all open
            # pipes at once.  However, I thought it would make the calling code
            # more simple to do it this way.
            self.write_register(NRF24.EN_RXADDR,
                                self.read_register(NRF24.EN_RXADDR) | _BV(NRF24.child_pipe_enable[child]))


    def closeReadingPipe(self, pipe):
        self.write_register(NRF24.EN_RXADDR,
            self.read_register(EN_RXADDR) & ~_BV(NRF24.child_pipe_enable[pipe]))


    def toggle_features(self):
        buf = [NRF24.ACTIVATE, 0x73]
        self.spidev.xfer2(buf)

    def enableDynamicPayloads(self):
        # Enable dynamic payload throughout the system
        self.write_register(NRF24.FEATURE, self.read_register(NRF24.FEATURE) | _BV(NRF24.EN_DPL))

        # If it didn't work, the features are not enabled
        if not self.read_register(NRF24.FEATURE):
            # So enable them and try again
            self.toggle_features()
            self.write_register(NRF24.FEATURE, self.read_register(NRF24.FEATURE) | _BV(NRF24.EN_DPL))

        # Enable dynamic payload on all pipes

        # Not sure the use case of only having dynamic payload on certain
        # pipes, so the library does not support it.
        self.write_register(NRF24.DYNPD, self.read_register(NRF24.DYNPD) | _BV(NRF24.DPL_P5) | _BV(NRF24.DPL_P4) | _BV(
            NRF24.DPL_P3) | _BV(NRF24.DPL_P2) | _BV(NRF24.DPL_P1) | _BV(NRF24.DPL_P0))

        self.dynamic_payloads_enabled = True


    def enableAckPayload(self):
        # enable ack payload and dynamic payload features
        self.write_register(NRF24.FEATURE,
                            self.read_register(NRF24.FEATURE) | _BV(NRF24.EN_ACK_PAY) | _BV(NRF24.EN_DPL))

        # If it didn't work, the features are not enabled
        if not self.read_register(NRF24.FEATURE):
            # So enable them and try again
            self.toggle_features()
            self.write_register(NRF24.FEATURE,
                                self.read_register(NRF24.FEATURE) | _BV(NRF24.EN_ACK_PAY) | _BV(NRF24.EN_DPL))

        # Enable dynamic payload on pipes 0 & 1
        self.write_register(NRF24.DYNPD, self.read_register(NRF24.DYNPD) | _BV(NRF24.DPL_P1) | _BV(NRF24.DPL_P0))

    def writeAckPayload(self, pipe, buf, buf_len):
        txbuffer = [NRF24.W_ACK_PAYLOAD | ( pipe & 0x7 )]

        max_payload_size = 32
        data_len = min(buf_len, max_payload_size)
        txbuffer.extend(buf[0:data_len])

        self.spidev.xfer2(txbuffer)

    def isAckPayloadAvailable(self):
        result = self.ack_payload_available
        self.ack_payload_available = False
        return result

    def isPVariant(self):
        return self.p_variant

    def setAutoAck(self, enable):
        if enable:
            self.write_register(NRF24.EN_AA, int('111111',2))
        else:
            self.write_register(NRF24.EN_AA, 0)

    def setAutoAckPipe(self, pipe, enable):
        if pipe <= 6:
            en_aa = self.read_register(NRF24.EN_AA)
            if enable:
                en_aa |= _BV(pipe)
            else:
                en_aa &= ~_BV(pipe)

            self.write_register(NRF24.EN_AA, en_aa)

    def testCarrier(self):
        return self.read_register(NRF24.CD) & 1

    def testRPD(self):
        return self.read_register(NRF24.RPD) & 1

    def setPALevel(self, level):
        setup = self.read_register(NRF24.RF_SETUP)
        setup &= ~( _BV(NRF24.RF_PWR_LOW) | _BV(NRF24.RF_PWR_HIGH))
        # switch uses RAM (evil!)
        if level == NRF24.PA_MAX:
            setup |= (_BV(NRF24.RF_PWR_LOW) | _BV(NRF24.RF_PWR_HIGH))
        elif level == NRF24.PA_HIGH:
            setup |= _BV(NRF24.RF_PWR_HIGH)
        elif level == NRF24.PA_LOW:
            setup |= _BV(NRF24.RF_PWR_LOW)
        elif level == NRF24.PA_MIN:
            nop = 0
        elif level == NRF24.PA_ERROR:
            # On error, go to maximum PA
            setup |= (_BV(NRF24.RF_PWR_LOW) | _BV(NRF24.RF_PWR_HIGH))

        self.write_register(NRF24.RF_SETUP, setup)


    def getPALevel(self):
        power = self.read_register(NRF24.RF_SETUP) & (_BV(NRF24.RF_PWR_LOW) | _BV(NRF24.RF_PWR_HIGH))

        if power == (_BV(NRF24.RF_PWR_LOW) | _BV(NRF24.RF_PWR_HIGH)):
            return NRF24.PA_MAX
        elif power == _BV(NRF24.RF_PWR_HIGH):
            return NRF24.PA_HIGH
        elif power == _BV(NRF24.RF_PWR_LOW):
            return NRF24.PA_LOW
        else:
            return NRF24.PA_MIN

    def setDataRate(self, speed):
        result = False
        setup = self.read_register(NRF24.RF_SETUP)

        # HIGH and LOW '00' is 1Mbs - our default
        self.wide_band = False
        setup &= ~(_BV(NRF24.RF_DR_LOW) | _BV(NRF24.RF_DR_HIGH))

        if speed == NRF24.BR_250KBPS:
            # Must set the RF_DR_LOW to 1 RF_DR_HIGH (used to be RF_DR) is already 0
            # Making it '10'.
            self.wide_band = False
            setup |= _BV(NRF24.RF_DR_LOW)
        else:
            # Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
            # Making it '01'
            if speed == NRF24.BR_2MBPS:
                self.wide_band = True
                setup |= _BV(NRF24.RF_DR_HIGH)
            else:
                # 1Mbs
                self.wide_band = False

        self.write_register(NRF24.RF_SETUP, setup)

        # Verify our result
        if self.read_register(NRF24.RF_SETUP) == setup:
            result = True
        else:
            self.wide_band = False
        return result

    def getDataRate(self):
        dr = self.read_register(NRF24.RF_SETUP) & (_BV(NRF24.RF_DR_LOW) | _BV(NRF24.RF_DR_HIGH))
        # Order matters in our case below
        if dr == _BV(NRF24.RF_DR_LOW):
            # '10' = 250KBPS
            return NRF24.BR_250KBPS
        elif dr == _BV(NRF24.RF_DR_HIGH):
            # '01' = 2MBPS
            return NRF24.BR_2MBPS
        else:
            # '00' = 1MBPS
            return NRF24.BR_1MBPS


    def setCRCLength(self, length):
        config = self.read_register(NRF24.CONFIG) & ~( _BV(NRF24.CRC_16) | _BV(NRF24.CRC_ENABLED))

        if length == NRF24.CRC_DISABLED:
            # Do nothing, we turned it off above.
            self.write_register(NRF24.CONFIG, config)
            return
        elif length == NRF24.CRC_8:
            config |= _BV(NRF24.CRC_ENABLED)
            config |= _BV(NRF24.CRC_8)
        else:
            config |= _BV(NRF24.CRC_ENABLED)
            config |= _BV(NRF24.CRC_16)

        self.write_register(NRF24.CONFIG, config)

    def getCRCLength(self):
        result = NRF24.CRC_DISABLED
        config = self.read_register(NRF24.CONFIG) & ( _BV(NRF24.CRCO) | _BV(NRF24.EN_CRC))

        if config & _BV(NRF24.EN_CRC):
            if config & _BV(NRF24.CRCO):
                result = NRF24.CRC_16
            else:
                result = NRF24.CRC_8

        return result

    def disableCRC(self):
        disable = self.read_register(NRF24.CONFIG) & ~_BV(NRF24.EN_CRC)
        self.write_register(NRF24.CONFIG, disable)

    def setRetries(self, delay, count):
        self.write_register(NRF24.SETUP_RETR, (delay & 0xf) << NRF24.ARD | (count & 0xf) << NRF24.ARC)


    def getRetries(self):
        return self.read_register(NRF24.SETUP_RETR)

    def getMaxTimeout(self):
        retries = self.getRetries()
        return ((250+(250*((retries& 0xf0)>>4 ))) * (retries & 0x0f)) / 1000000.0