Esempio n. 1
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])
Esempio 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])
Esempio n. 3
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
Esempio n. 4
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
Esempio n. 5
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()
Esempio n. 6
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("/")
Esempio n. 7
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("/")
Esempio n. 8
0
def PullData():
    print("pull data")

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

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

    spi.writebytes([0x31])
    sleep(0.1)
    moistureVals1 = spi.readbytes(3)
    moisture1 = str(moistureVals1[0]) + str(moistureVals1[1]) + str(moistureVals1[2])

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

    Data = []
    Data.append(moisture)
    Data.append(moisture1)
    Data.append(light)

    spi.close()
    return Data
Esempio n. 9
0
File: test.py Progetto: 5montest/spi
### 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)

GPIO.cleanup()


Esempio n. 10
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)
Esempio n. 11
0
class BStabBb:
  
    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
        
    def get_max_dac_value(self):
        return self.maxDACvalue
    
    def adjust_b_field(self, freq_diff, corrFactor=1):
        [cDAC, fDAC] = self.calcNewDACvaluesFromFreqDiff(freq_diff, corrFactor)
        self.setStabiliserDACs(cDAC, fDAC)
        
    def setStabiliserDACs(self, cDacValue, fDacValue, verbose=False):
        """Update feedback DAC values"""
        self.set_DAC_values(CDAC=cDacValue,FDAC=fDacValue)
        dacValues = {'cDAC':cDacValue,'fDAC':fDacValue}
        pyon.store_file(self.fname, dacValues)
        #self.set_dataset("BField_stabiliser.cDAC", float(cDacValue), persist=True, broadcast=True)
        #self.set_dataset("BField_stabiliser.fDAC", float(fDacValue), persist=True, broadcast=True)
        #if verbose:
        #    print("Update DACs {} {} --- Done.".format(int(cDacValue),int(fDacValue)))
        return dacValues

    def checkStabiliserOutput(self, volt_margin=3, verbose=False):
        """Read feedback shunt voltage via ssh connection"""
        shunt_ok = False
        shunt_voltage = self.read_voltage()

        if shunt_voltage > (10-volt_margin):
            shunt_ok_msg = "Too high!"
        elif shunt_voltage < volt_margin:
            shunt_ok_msg = "Too low!"
        else:
            shunt_ok = True
            shunt_ok_msg = "Fine."
        if verbose:
            print("Read ADC --- Shunt input voltage: {} --- {}".format(shunt_voltage, shunt_ok_msg))
        # to do: raise Error when railing
        return shunt_ok
        
    def getSlopes(self):
        """Return conversion factors [cDAC_per_mG,fDAC_per_mG] """
        """Use for scanning the magnetic field"""
        # fine DAC gain 1
        # coarse DAC gain 200
        mG_per_fDACvalue = self.mG_per_mVerr * self.mVDAC_per_DACvalue
        mG_per_cDACvalue = self.mG_per_mVerr * 200 * self.mVDAC_per_DACvalue
        return {'cDAC_per_mG': 1.0/mG_per_cDACvalue,
                'fDAC_per_mG': 1.0/mG_per_fDACvalue}
        
        
    def calcNewDACvaluesFromFreqDiff(self, freq_diff, corrFactor=1):
        """Calculate new DAC values, based on the stretch qubit frequency difference to the setpoint"""
        # least significant bits in mV output
        fDAClsb = self.mVDAC_per_DACvalue
        # VERR = 200*cDAC + fDAC - 202*DIFF_SIG
        cDAClsb = 200 * fDAClsb
        
        VERR_diff = freq_diff / self.kHz_per_mVerr / 1e3
        VERR_corr = VERR_diff * corrFactor

        if abs(VERR_corr) > 10*cDAClsb:
            change_cDAC = - int(round(VERR_corr / cDAClsb))
            change_fDAC = 0
        else:
            change_cDAC = 0
            change_fDAC = - int(round(VERR_corr / fDAClsb))
        
        try:
            oldDacValues = pyon.load_file(self.fname)
            #old_cDAC = self.get_dataset("BField_stabiliser.cDAC")
            #old_fDAC = self.get_dataset("BField_stabiliser.fDAC")
        except FileNotFoundError:
            print('Error: could not find file. Using default values')
            oldDacValues = {'cDAC':54710,'fDAC':33354}
        old_cDAC = oldDacValues['cDAC']
        old_fDAC = oldDacValues['fDAC']
        
        new_cDAC = old_cDAC + change_cDAC
        new_fDAC = old_fDAC + change_fDAC
        
        # when fDAC out of range, change coarse DAC
        if (new_fDAC > self.maxDACvalue or new_fDAC < 0):
            new_cDAC += (new_fDAC-30000)/200
            new_fDAC = 30000
        
        return [new_cDAC, new_fDAC]
  
        
    def set_DAC_values(self,CDAC=-1,FDAC=-1):
        ''' this is the external function to be called for setting the coarse and fine dac '''
        if CDAC is not -1:
            self._set_coarse_dac(CDAC)
        if FDAC is not -1:
            self._set_fine_dac(FDAC)

    def read_voltage(self,verbose=0):
        ''' this is the external function to be called for reading out the ADC voltage '''
        # for AD7477:
        # 2 bytes
        bytes = self._read_value(self.CS_ADC_PIN, 2)
        # most significant bit first
        num = bytes[0] * 256 + bytes[1]
        # 4 leading zeros, 2 trailing zeros
        num = num >> 2
        # 5V reference, 10 bits
        AV = 5.0 * num / 1024
        
        # G=0.33 for voltage divider between shunt and ADC
        # convert to feedback shunt input voltage
        FB_SHNT_IN_V = 3 * AV
        
        if verbose:
            print("byte response: %X %X"% (bytes[0], bytes[1]))
            print("num respose: %d" % (num))
            print("ADC input voltage: %.2f" % (AV))
            print("Feedback shunt input voltage: %.2f" % (FB_SHNT_IN_V))
        
        return AV
    
    def test_set_pin(self,logicHigh=1,pin="P8_14"):
        ''' this is a test function to set a pin on the beaglebone to high or low '''
        GPIO.setup(pin, GPIO.OUT)
        if logicHigh:
            GPIO.output(pin, GPIO.HIGH)
        else:
            GPIO.output(pin, GPIO.LOW)
    
    def _set_coarse_dac(self,value):
        self._set_dac_value(self.CS_FB_COARSE_PIN, value)

    def _set_fine_dac(self,value):
        self._set_dac_value(self.CS_FB_FINE_PIN, value)
    
    def _set_dac_value(self, cs_pin, value):
        GPIO.output(cs_pin, GPIO.LOW)
        
        value = self._check_dac_value(value)
        
        # check if value is in range
        MSByte = value >> 8
        LSByte = value - (MSByte << 8)
        # write
        self.spi00.writebytes([MSByte,LSByte])
        
        GPIO.output(cs_pin, GPIO.HIGH)
        
    def _check_dac_value(self,value):
        value = int(value)
        if value > 65535:
            value = 65535
        if value < 0:
            value = 0
        return value
    
    def _read_value(self,cs_pin, length):
        ''' internal read value of analogue voltage '''
        GPIO.output(cs_pin, GPIO.LOW)
        
        bytes = self.spi00.readbytes(length)
        
        GPIO.output(cs_pin, GPIO.HIGH)
        return bytes

    def ping(self):
        return True
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
Esempio n. 13
0
POWER SYSTEM:
	PWR_SYS = "P9_16"
'''
#=======================================================
#	testing SPI
#=======================================================

while (1):
    # RST = 1 --> address
    #	GPIO.output(RST, GPIO.HIGH)
    #	time.sleep(0.001)
    # RST = 0 --> slaves
    #	GPIO.output(RST, GPIO.LOW)
    #	time.sleep(0.001)

    # send data through SPI
    spi1.writebytes([0x20, 0x03, 0x12])
    spi0.writebytes([0x02, 0x30, 0x21])

#	GPIO.output(PWR_SYS, GPIO.HIGH)
#	GPIO.output(RST, GPIO.HIGH)
#	GPIO.output(CLR, GPIO.HIGH)
#	GPIO.output(LDAC, GPIO.HIGH)
#	GPIO.output(CNV, GPIO.HIGH)

#	GPIO.output(PWR_SYS, GPIO.LOW)
#	GPIO.output(RST, GPIO.LOW)
#	GPIO.output(CLR, GPIO.LOW)
#	GPIO.output(LDAC, GPIO.LOW)
#	GPIO.output(CNV, GPIO.LOW)
Esempio n. 14
0
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
# SCLK  P9_22 clk

Esempio n. 15
0
    print "Board temp = ", boardTemp

    return tempAdc


def readLevelsAvg():
    crossSumm = 0.0
    longSumm = 0.0
    levelsAvg = (0.0), (0.0)
    averageCount = 10
    for i in range(10):
        crossSumm += readCross()
        longSumm += readLong()
    levelsAvg[0] = crossSumm / averageCount
    levelsAvg[1] = longSumm / averageCount
    #levelsAvg = [crossSumm / averageCount], [longSumm / averageCount]

    return levelsAvg


while (True):

    spi.writebytes([0x39])  # Update data
    time.sleep(.5)
    # crossData = readCross()
    # longData = readLong()
    # print "Cross\t", crossData, "\t\tLong\t", longData
    levelData = readLevelsAvg()

    print "Cross\t", levelData[0], "\t\tLong\t", levelData[1]
Esempio n. 16
0
class Brightbar:

    #[brightness, blue, green, red]
    pixel_buffer = [POWER, 0, 0, 0] * LEDS_PER_PANEL * NUM_PANELS
    start_clock = None
    animation_time = 20000

    def __init__(self):
        self.init_spi()
        #animation = GifAnimation('gifs/extracted/trippy_39_30x30')
        #animation = SparkleAnimation(None, SparkleAnimation.SPEED_SLOW, [POWER,255,255,255], 1000)
        #animation = SparkleAnimation(None, 2000, [POWER,255,255,255], 1000)
        #animation = LinesAnimation(None, 3000, [POWER,255,255,255], 0)
        animation = RainAnimation(None, .1, [POWER, 0.0, 200.0, 0.0])
        self.animations = [
            SparkleAnimation(None, 2000, [POWER, 255, 255, 255], 1000),
            LinesAnimation(None, 3000, [POWER, 255, 255, 255], 0),
            RainAnimation(None, .1, [POWER, 0.0, 200.0, 0.0])
        ]
        self.render_thread = None

    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)

    def debug_frame(self, data):
        for y in range(PANEL_Y):
            line = str(y) + ": "
            for x in range(PANEL_X):
                offset = (y * PANEL_X + x) * 4
                line += "|" + str(data[offset]) + "," + str(
                    data[offset + 1]) + "," + str(
                        data[offset + 2]) + "," + str(data[offset + 3])
            print line

    #render a full frame
    def render(self):
        #logging.debug("buffer size: " + str(len(self.pixel_buffer)) + " start render: " + str(time.time()))
        start_time = time.time()
        #logging.debug(" start render: " + str(start_time))
        #make a copy of the buffer to work on in case we need to switch the order of bytes
        #data = self.pixel_buffer[:]
        offset = 0
        #the panels run in a snake S shape, so every other line needs to have bytes reversed
        if REVERSE_ALTERNATE_LINES:
            for i in range(0, PANEL_Y):
                if (i % 2) == 0:
                    continue
                offset = i * PANEL_X * 4
                line_length = PANEL_X * 4
                line = data[offset:offset + line_length]
                reversed_line = [0] * line_length
                j = line_length - 4  #start one color from the end, and go backwards through the line
                while j >= 0:
                    reversed_line[line_length - j - 4] = line[j]
                    reversed_line[line_length - j - 3] = line[j + 1]
                    reversed_line[line_length - j - 2] = line[j + 2]
                    reversed_line[line_length - j - 1] = line[j + 3]
                    j = j - 4

                data[offset:offset + PANEL_X * 4] = reversed_line

        #self.write_apa102(data)
        #logging.debug("length of buffer: " + str(len(self.pixel_buffer)))
        #logging.debug(self.pixel_buffer)
        self.write_apa102(self.pixel_buffer)
        end_time = time.time()
        #logging.debug("end render: " + str(end_time) + " elapsed: " + str(end_time - start_time))
        #import pdb
        #pdb.set_trace()

    def write_apa102(self, data):
        #start frame, 32 bits of zero
        self.spi.writebytes([0] * 4)

        #write RGB data
        #chunk the data out in 1024 byte blocks
        for i in range(0, len(data), 1024):
            length = len(data)
            if ((i + 1024) > length):
                #end = length - (i+1024 - length)
                chunk = data[i:]
            else:
                #end = i + 1024
                chunk = data[i:i + 1024]
            self.spi.writebytes(chunk)

        #write footer. This is total numnber of LEDS / 2 bits of 1's
        num_dwords = LEDS_PER_PANEL * NUM_PANELS / 32
        for i in range(num_dwords):
            self.spi.writebytes(
                [0xff, 0x00, 0x00, 0x00]
            )  #the datasheet calls for 1's here, but internet says 0s work better? the fast LED lib does both?

    def clear(self):
        self.pixel_buffer = [POWER, 0, 0, 0] * LEDS_PER_PANEL * NUM_PANELS

    def calculate_fps(self):
        now = time.time()
        delta = now - self.start_clock
        frame_time = delta / self.frame_count
        self.fps = 1 / frame_time
        logging.debug("elapsed seconds: " + str(delta) + " frame count: " +
                      str(self.frame_count) + " current fps: " + str(self.fps))

    def animate(self):

        if self.start_clock == None:
            self.frame_count = 0
            self.start_clock = time.time()

        elapsed_time = time.time() - self.start_clock
        num_animations = int(round(elapsed_time /
                                   (self.animation_time / 1000)))
        current_animation = int(num_animations) % len(self.animations)
        #logging.debug("elapsed time: " + str(elapsed_time) + " num animations:" + str(num_animations) + " current animation:" + str(current_animation))

        animation = self.animations[current_animation]

        frame = animation.get_next_frame()

        if frame == None:
            time.sleep(.001)
            return

        self.frame_count = self.frame_count + 1

        if self.frame_count % 100 == 0:
            self.calculate_fps()

        line_length = animation.width * 4

        for y in range(animation.height):
            frame_offset = y * line_length
            line = frame[frame_offset:frame_offset + line_length]
            buffer_offset = ((
                (int(animation.destination_y_offset) + y) * PANEL_X) +
                             int(animation.destination_x_offset)) * 4
            self.pixel_buffer[buffer_offset:buffer_offset + line_length] = line

    def render_loop(self):
        try:
            while 1:
                brightbar.animate()
                brightbar.render()
        except:
            print_exception(*sys.exc_info())

    def start(self):
        if STARTUP_SEQUENCE:
            startup_sequence(self)
        if self.render_thread == None:
            self.render_thread = threading.Thread(name="RenderThread",
                                                  target=self.render_loop)
        self.render_thread.start()

    def stop(self):
        self.render_thread.stop()
Esempio n. 17
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
Esempio n. 18
0
 # write to RDAC
spi.xfer(list(struct.unpack('BB', struct.pack('>H', 1 << 10 | 0))))

 # read RDAC
spi.xfer(list(struct.unpack('BB', struct.pack('>H', 0b10 << 10 | 0))))

 # read Control register
spi.xfer(list(struct.unpack('BB', struct.pack('>H', 0b111 << 10 | 0))))
spi.readbytes(2)

for i in range(1024):
    spi.xfer(list(struct.unpack('BB', struct.pack('>H', 1 << 10 | i))))
    time.sleep(.2)


spi.writebytes([0x0,0x0])
spi.writebytes([0x18,0x02])
spi.writebytes([0x05,0x00])
spi.writebytes([0x08,0x0])
spi.writebytes([0x0,0x0])
spi.writebytes([0x0,0x0])
spi.writebytes([0x0,0x0])

spi.xfer([0x0,0x0])
spi.xfer([0x18,0x02])
spi.xfer([0x05,0x00])
spi.xfer([0x08,0x0])
spi.xfer([0x0,0x0])


class voltage_divider:
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()
class EPD(object):
    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)

    def digital_write(self, pin, value):
        return GPIO.output(pin, value)

    def digital_read(self, pin):
        return GPIO.input(pin)

    def delay_ms(self, delaytime):
        time.sleep(delaytime / 1000.0)

    def send_command(self, command):
        self.digital_write(DC_PIN, GPIO.LOW)
        self.spi.writebytes([command])

    def send_data(self, data):
        self.digital_write(DC_PIN, GPIO.HIGH)
        self.spi.writebytes([data])

    def init(self):
        """ Preform the hardware initialization sequence """
        # Interface initialization:
        GPIO.setwarnings(False)
        GPIO.setup(RST_PIN, GPIO.OUT)
        GPIO.setup(DC_PIN, GPIO.OUT)
        GPIO.setup(CS_PIN, GPIO.OUT)
        GPIO.setup(BUSY_PIN, GPIO.IN)

        self.spi.msh = 2000000
        self.spi.mode = 0b00
        # EPD hardware init
        # The specifics of how this works or what "power optimization" actually means
        # are unclear to me, so I'm leaving it as-is.
        self.reset()
        self.send_command(POWER_SETTING)
        self.send_data(0x03)                  # VDS_EN, VDG_EN
        self.send_data(0x00)                  # VCOM_HV, VGHL_LV[1], VGHL_LV[0]
        self.send_data(0x2b)                  # VDH
        self.send_data(0x2b)                  # VDL
        self.send_data(0x09)                  # VDHR
        self.send_command(BOOSTER_SOFT_START)
        self.send_data(0x07)
        self.send_data(0x07)
        self.send_data(0x17)
        # Power optimization
        self.send_command(0xF8)
        self.send_data(0x60)
        self.send_data(0xA5)
        # Power optimization
        self.send_command(0xF8)
        self.send_data(0x89)
        self.send_data(0xA5)
        # Power optimization
        self.send_command(0xF8)
        self.send_data(0x90)
        self.send_data(0x00)
        # Power optimization
        self.send_command(0xF8)
        self.send_data(0x93)
        self.send_data(0x2A)
        # Power optimization
        self.send_command(0xF8)
        self.send_data(0xA0)
        self.send_data(0xA5)
        # Power optimization
        self.send_command(0xF8)
        self.send_data(0xA1)
        self.send_data(0x00)
        # Power optimization
        self.send_command(0xF8)
        self.send_data(0x73)
        self.send_data(0x41)
        self.send_command(PARTIAL_DISPLAY_REFRESH)
        self.send_data(0x00)
        self.send_command(POWER_ON)
        self.wait_until_idle()

        self.send_command(PANEL_SETTING)
        self.send_data(0xAF)        # KW-BF   KWR-AF    BWROTP 0f
        self.send_command(PLL_CONTROL)
        self.send_data(0x3A)        # 3A 100HZ   29 150Hz 39 200HZ    31 171HZ
        self.send_command(VCM_DC_SETTING_REGISTER)
        self.send_data(0x12)
        self.delay_ms(2)
        self.set_lut()
        # EPD hardware init end
        self._init_performed = True

    def wait_until_idle(self):
        """ Wait until screen is idle by polling the busy pin """
        while(self.digital_read(BUSY_PIN) == 0):      # 0: busy, 1: idle
            self.delay_ms(50)

    def reset(self):
        """ Module reset """
        self.digital_write(RST_PIN, GPIO.LOW)
        self.delay_ms(200)
        self.digital_write(RST_PIN, GPIO.HIGH)
        self.delay_ms(200)

    def set_lut(self, fast=False):
        """ Set LUT for the controller.
        If `fast` is srt to True, quick update LUTs from Ben Krasnow will be used"""
        lut_to_use = LUT if not fast else QuickLUT

        # Quick LUTs courtsey of Ben Krasnow:
        # http://benkrasnow.blogspot.co.il/2017/10/fast-partial-refresh-on-42-e-paper.html
        # https://www.youtube.com/watch?v=MsbiO8EAsGw

        self.send_command(LUT_FOR_VCOM)               # vcom
        for byte in lut_to_use.lut_vcom_dc:
            self.send_data(byte)

        self.send_command(LUT_WHITE_TO_WHITE)         # ww --
        for byte in lut_to_use.lut_ww:
            self.send_data(byte)

        self.send_command(LUT_BLACK_TO_WHITE)         # bw r
        for byte in lut_to_use.lut_bw:
            self.send_data(byte)

        self.send_command(LUT_WHITE_TO_BLACK)         # wb w
        for byte in lut_to_use.lut_wb:
            self.send_data(byte)

        self.send_command(LUT_BLACK_TO_BLACK)         # bb b
        for byte in lut_to_use.lut_bb:
            self.send_data(byte)

    def _get_frame_buffer(self, image):
        """ Get a full frame buffer from a PIL Image object """
        image_monocolor = image.convert('1')
        imwidth, imheight = image_monocolor.size
        if imwidth != self.width or imheight != self.height:
            raise ValueError('Image must be same dimensions as display \
                ({0}x{1}).' .format(self.width, self.height))
        return self._get_frame_buffer_for_size(image_monocolor, self.height, self.width)

    def _get_frame_buffer_for_size(self, image_monocolor, height, width):
        """ Get a frame buffer object from a PIL Image object assuming a specific size"""
        buf = [0x00] * (width * height // 8)
        pixels = image_monocolor.load()
        for y in range(height):
            for x in range(width):
                # Set the bits for the column of pixels at the current position
                if pixels[x, y] != 0:
                    buf[(x + y * width) // 8] |= (0x80 >> (x % 8))
        return buf

    def display_frame(self, image):
        """ Display a full frame, doing a full screen refresh """
        if not self._init_performed:
            # Initialize the hardware if it wasn't already initialized
            self.init()
        self.set_lut()
        frame_buffer = self._get_frame_buffer(image)
        self.send_command(DATA_START_TRANSMISSION_1)
        self.delay_ms(2)
        for _ in range(0, self.width * self.height // 8):
            self.send_data(0xFF)
        self.delay_ms(2)
        self.send_command(DATA_START_TRANSMISSION_2)
        self.delay_ms(2)
        for i in range(0, self.width * self.height // 8):
            self.send_data(frame_buffer[i])
        self.delay_ms(2)
        self.send_command(DISPLAY_REFRESH)
        self.wait_until_idle()
        self._last_frame = image.copy()
        self._partial_refresh_count = 0  # reset the partial refreshes counter

    def _send_partial_frame_dimensions(self, x, y, l, w):
        self.send_data(x >> 8)
        self.send_data(x & 0xf8)
        self.send_data(y >> 8)
        self.send_data(y & 0xff)
        self.send_data(w >> 8)
        self.send_data(w & 0xf8)
        self.send_data(l >> 8)
        self.send_data(l & 0xff)

    def display_partial_frame(self, image, x, y, h, w, fast=False):
        """ Display a partial frame, only refreshing the changed area.

        `image` is a Pillow Image object
        `x` and `y` are the top left coordinates
        `h` is the height of the area to update
        `w` is the width of the area to update.


        if `fast` is True, fast refresh lookup tables will be used.
        see `smart_update()` method documentation for details."""
        if fast:
            self.set_lut(fast=True)
            self.delay_ms(2)

        # According to the spec, x and w have to be multiples of 8.
        # round them up and down accordingly to make sure they fit the requirement
        # adding a few more pixels to the refreshed area.
        # This is mandatory, otherwise the display might get corrupted until
        # the next valid update that touches the same area.
        x = _nearest_mult_of_8(x, False)
        w = _nearest_mult_of_8(w)

        self.send_command(PARTIAL_DATA_START_TRANSMISSION_1)
        self.delay_ms(2)

        self._send_partial_frame_dimensions(x, y, h, w)
        self.delay_ms(2)

        # Send the old values, as per spec
        old_image = self._last_frame.crop((x, y, x+w, y+h))
        old_fb = self._get_frame_buffer_for_size(old_image, h, w)
        for i in range(0, w * h // 8):
            self.send_data(old_fb[i])
        self.delay_ms(2)

        self.send_command(PARTIAL_DATA_START_TRANSMISSION_2)
        self.delay_ms(2)

        self._send_partial_frame_dimensions(x, y, h, w)

        # Send new data
        self._last_frame = image.copy()
        image = image.crop((x, y, x+w, y+h))
        new_fb = self._get_frame_buffer_for_size(image, h, w)
        for i in range(0, w * h // 8):
            self.send_data(new_fb[i])
        self.delay_ms(2)

        self.send_command(PARTIAL_DISPLAY_REFRESH)
        self.delay_ms(2)
        self._send_partial_frame_dimensions(x, y, h, w)
        self.wait_until_idle()
        if fast:
            self.set_lut()  # restore LUT to normal mode
        self._partial_refresh_count += 1

    def smart_update(self, image):
        """ Display a frame, automatically deciding which refresh method to use.
        If `fast_frefresh` is enabled, it would use optimized LUTs that shorten
        the refresh cycle, and don't do the full "inverse,black,white,black again,
        then draw" flush cycle.

        The fast refresh mode is much faster, but causes the image to apper
        gray instead of black, and can cause burn-in if it's overused.

        It's recommended to do a full flush "soon" after using the fast mode,
        to avoid degrading the panel. You can tweak `partial_refresh_limit`
        or
        """
        if self._last_frame is None or self._partial_refresh_count == self.partial_refresh_limit:
            # Doing a full refresh when:
            # - No frame has been displayed in this run, do a full refresh
            # - The display has been partially refreshed more than LIMIT times
            # the last full refresh (to prevent burn-in)
            self.display_frame(image)
        else:
            # Partial update. Let's start by figuring out the bounding box
            # of the changed area
            difference = ImageChops.difference(self._last_frame, image)
            bbox = difference.getbbox()
            if bbox is not None:
                # the old picture and new picture are different, partial
                # update is needed.
                # Get the update area. x and w have to be multiples of 8
                # as per the spec, so round down for x, and round up for w
                x = _nearest_mult_of_8(bbox[0], False)
                y = bbox[1]
                w = _nearest_mult_of_8(bbox[2] - x)
                if w > self.width:
                    w = self.width
                h = bbox[3] - y
                if h > self.height:
                    h = self.height
                # now let's figure out if fast mode is an option.
                # If the area was all white before - fast mode will be used.
                # otherwise, a slow refresh will be used (to avoid ghosting).
                # Since the image only has one color, meaning each pixel is either
                # 0 or 255, the following convinent one liner can be used
                fast = 0 not in self._last_frame.crop(bbox).getdata() and self.fast_refresh
                self.display_partial_frame(image, x, y, h, w, fast)

    def sleep(self):
        """Put the chip into a deep-sleep mode to save power.
        The deep sleep mode would return to standby by hardware reset.
        Use EPD.reset() to awaken and use EPD.init() to initialize. """
        self.send_command(DEEP_SLEEP)
        self.delay_ms(2)
        self.send_data(0xa5)  # deep sleep requires 0xa5 as a "check code" parameter
Esempio n. 21
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)
Esempio n. 22
0
class Enrf24():
    __bus = None
    __device = None

    __rf_status = 0
    __rf_addr_width = 5
    __lastirq = None
    __readpending = 0
    __lastTXfailed = False
    __txbuf_len = 0
    __txbuf = []

    # Internal IRQ handling
    __ENRF24_IRQ_TX = 0x20
    __ENRF24_IRQ_RX = 0x40
    __ENRF24_IRQ_TXFAILED = 0x10
    __ENRF24_IRQ_MASK = 0x70

    __ENRF24_CFGMASK_IRQ = 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 = ""

    def begin(self, datarate=1000000, channel=0):  # Specify bitrate & channel
        GPIO.setup(self.cePin, GPIO.OUT)
        GPIO.output(self.cePin, GPIO.LOW)
        GPIO.setup(self.csnPin, GPIO.OUT)
        GPIO.output(self.csnPin, GPIO.HIGH)
        GPIO.setup(self.irqPin,
                   GPIO.IN)  # No pullups; the transceiver provides this!
        self.spi.writebytes([0x00
                             ])  # Strawman transfer, fixes USCI issue on G2553
        #self.spi.writebytes([0xCF, 0x00])

        # Is the transceiver present/alive?
        if (not self.__isAlive()):
            return False  # Nothing more to do here...

        # Wait 100ms for module to initialize
        time.sleep(0.1)

        # Init certain registers
        self.__writeReg(RF24_CONFIG,
                        0x00)  # Deep power-down, everything disabled
        self.__writeReg(RF24_EN_AA, 0x03)
        self.__writeReg(RF24_EN_RXADDR, 0x03)
        self.__writeReg(RF24_RF_SETUP, 0x00)
        self.__writeReg(RF24_STATUS, self.__ENRF24_IRQ_MASK)  # Clear all IRQs
        self.__writeReg(RF24_DYNPD, 0x03)
        self.__writeReg(RF24_FEATURE,
                        RF24_EN_DPL)  # Dynamic payloads enabled by default

        # Set all parameters
        if (channel > 125):
            channel = 125

        self.deepsleep()
        self.__issueCmd(RF24_FLUSH_TX)
        self.__issueCmd(RF24_FLUSH_RX)
        self.__readpending = 0
        self.__irq_clear(self.__ENRF24_IRQ_MASK)
        self.setChannel(channel)
        self.setSpeed(datarate)
        self.setTXpower()
        self.setAutoAckParams()
        self.setAddressLength(self.__rf_addr_width)
        self.setCRC(True)  # Default = CRC on, 8-bit
        return True

    def end(self):  # Shut it off, clear the library's state
        self.__txbuf_len = 0
        self.__rf_status = 0
        self.__rf_addr_width = 5

        if (not self.__isAlive()):
            return

        self.deepsleep()
        self.__issueCmd(RF24_FLUSH_TX)
        self.__issueCmd(RF24_FLUSH_RX)
        self.readpending = 0
        self.__irq_clear(self.__ENRF24_IRQ_MASK)
        GPIO.output(self.cePin, GPIO.LOW)
        GPIO.output(self.csnPin, GPIO.HIGH)

    # I/O
    def available(
            self,
            checkIrq=False):  # Check if incoming data is ready to be read
        #print(checkIrq and GPIO.input(self.irqPin) and self.__readpending == 0)
        if (checkIrq and GPIO.input(self.irqPin) and self.__readpending == 0):
            return False
        self.__maintenanceHook()
        if ((not self.__readReg(RF24_FIFO_STATUS)) & RF24_RX_EMPTY):
            return True

        if (self.__readpending):
            return True

        return False

    def read(self, maxlen=32):  # Read contents of RX buffer up to
        buf = None
        plwidth = 0
        res = ""

        self.__maintenanceHook()
        self.__readpending = 0
        if ((self.__readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) or maxlen < 1):
            return 0

        plwidth = self.__readCmdPayload(RF24_R_RX_PL_WID, plwidth, 1, 1)[0]
        buf = self.__readCmdPayload(RF24_R_RX_PAYLOAD, buf, plwidth, maxlen)
        if (self.__irq_derivereason() and self.__ENRF24_IRQ_RX):
            self.__irq_clear(self.__ENRF24_IRQ_RX)

        for i in buf:
            res += chr(i)

        self.last_payload = res
        return res  # 'maxlen' bytes, return final length.
        # 'inbuf' should be maxlen+1 since a
        # null '\0' is tacked onto the end.

    def getMessage(self):
        return self.last_payload

    def write(self, data):
        if (self.__txbuf_len == 32
            ):  # If we're trying to stuff an already-full buffer...
            self.flush()  # Blocking OTA TX

        txbuf = []
        data = list(data)
        for i in data:
            txbuf.append(ord(i))
        self.__txbuf = txbuf
        self.__txbuf_len = len(txbuf)

        return 1

    def flush(self):  # Force transmission of TX ring buffer contents
        reg = None
        addrbuf = []
        enaa = False
        origrx = False

        if (self.__txbuf_len == 0):
            return  # Zero-length buffer?  Nothing to send!

        reg = self.__readReg(RF24_FIFO_STATUS)
        if (
                reg & BITS["BIT5"]
        ):  # RF24_TX_FULL #define is BIT0, which is not the correct bit for FIFO_STATUS.
            # Seen this before with a user whose CE pin was messed up.
            self.__issueCmd(RF24_FLUSH_TX)
            self.__txbuf_len = 0
            return  # Should never happen, but nonetheless a precaution to take.

        self.__maintenanceHook()

        if (reg & RF24_TX_REUSE):
            # If somehow TX_REUSE is enabled, we need to flush the TX queue before loading our new payload.
            self.__issueCmd(RF24_FLUSH_TX)

        if (self.__readReg(RF24_EN_AA) & 0x01
                and (self.__readReg(RF24_RF_SETUP) & 0x28) != 0x20):
            # AutoACK enabled, must write TX addr to RX pipe#0
            # Note that 250Kbps doesn't support auto-ack, so we check RF24_RF_SETUP to verify that.
            enaa = True
            self.__readTXaddr(addrbuf)
            self.__writeRXaddrP0(addrbuf)

        reg = self.__readReg(RF24_CONFIG)
        if (not (reg & RF24_PWR_UP)):
            #digitalWrite(_cePin, HIGH);  // Workaround for SI24R1 knockoff chips
            self.__writeReg(
                RF24_CONFIG, self.__ENRF24_CFGMASK_IRQ
                | self.__ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP)
            time.sleep(.05)  # 5ms delay required for nRF24 oscillator start-up
            #digitalWrite(_cePin, LOW);

        if (reg & RF24_PRIM_RX):
            origrx = True
            GPIO.output(self.cePin, GPIO.LOW)
            self.__writeReg(
                RF24_CONFIG, self.__ENRF24_CFGMASK_IRQ
                | self.__ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP)

        self.__txbuf = self.__issueCmdPayload(RF24_W_TX_PAYLOAD, self.__txbuf)
        GPIO.output(self.cePin, GPIO.HIGH)
        time.sleep(0.1)
        GPIO.output(self.cePin, GPIO.LOW)

        self.__txbuf_len = 0  # Reset TX ring buffer

        while (GPIO.input(self.irqPin)):  # Wait until IRQ fires
            pass

        # IRQ fired
        self.__maintenanceHook()  # Handle/clear IRQ

        # Purge Pipe#0 address (set to module's power-up default)
        if (enaa):
            addrbuf = [0xE7, 0xE7, 0xE7, 0xE7, 0xE7]
            self.__writeRXaddrP0(addrbuf)

        # If we were in RX mode before writing, return back to RX mode.
        if (origrx):
            self.enableRX()

    def purge(
            self):  # Ignore TX ring buffer contents, return ring pointer to 0.
        self.__txbuf_len = 0

    # Power-state related stuff-
    def radioState(
        self
    ):  # Evaluate current state of the transceiver (see ENRF24_STATE_* defines)
        if not self.__isAlive():
            return ENRF24_STATE_NOTPRESENT

        counter = 15
        reg = self.__readReg(RF24_CONFIG)
        if reg == 0:
            while reg == 0 and counter < 15:
                reg = self.__readReg(RF24_CONFIG)
                counter += 1

        if (not (reg & RF24_PWR_UP)):
            return ENRF24_STATE_DEEPSLEEP

        # At this point it's either Standby-I, II or PRX.
        if (reg & RF24_PRIM_RX):
            if (GPIO.input(self.cePin)):
                return ENRF24_STATE_PRX
            # PRIM_RX=1 but CE=0 is a form of idle state.
            return ENRF24_STATE_IDLE

        # Check if TX queue is empty, if so it's idle, if not it's PTX.
        if (self.__readReg(RF24_FIFO_STATUS) & RF24_TX_EMPTY):
            return ENRF24_STATE_IDLE
        return ENRF24_STATE_PTX

    def printRadioState(self):
        status = self.radioState()
        sys.stdout.write("Enrf24 radio transceiver status: ")
        if status == ENRF24_STATE_NOTPRESENT:
            print("NO TRANSCEIVER PRESENT")

        elif status == ENRF24_STATE_DEEPSLEEP:
            print("DEEP SLEEP <1uA power consumption")

        elif status == ENRF24_STATE_IDLE:
            print("IDLE module powered up w/ oscillators running")

        elif status == ENRF24_STATE_PTX:
            print("Actively Transmitting")

        elif status == ENRF24_STATE_PRX:
            print("Receive Mode")

        else:
            print("UNKNOWN STATUS CODE")

    def printStatus(self):
        status = self.__readReg(RF24_STATUS)
        data_ready = str(hex(status & 0x40))
        data_sent = str(hex(status & 0x20))
        max_tx_retries = str(hex(status & 0x10))

        if status & 0x0E == 0x0E:
            rx_pipe_no = "RX FIFO Empty"
        elif status & 0x02 == 0x02:
            rx_pipe_no = 1
        elif status & 0x04 == 0x04:
            rx_pipe_no = 2
        elif status & 0x06 == 0x06:
            rx_pipe_no = 3
        elif status & 0x08 == 0x08:
            rx_pipe_no = 4
        elif status & 0x0A == 0x0A:
            rx_pipe_no = 5
        elif ~status & 0x0E:
            rx_pipe_no = 0
        else:
            rx_pipe_no = "Error"

        rx_pipe_no = str(rx_pipe_no)
        tx_fifo_full = str(status & 0x01)

        status = str(hex(status))

        sys.stdout.write("STATUS=")
        sys.stdout.write(status)
        sys.stdout.write("\tRX_DR=")
        sys.stdout.write(data_ready)
        sys.stdout.write(" TX_DS=")
        sys.stdout.write(data_sent)
        sys.stdout.write(" MAX_RT=")
        sys.stdout.write(max_tx_retries)
        sys.stdout.write(" RX_P_NO=")
        sys.stdout.write(rx_pipe_no)
        sys.stdout.write(" TX_FULL=")
        print(tx_fifo_full)
        print("")

    def printDetails(self):
        self.printStatus()

        buf = []
        sys.stdout.write("RX_ADDR_P0=")
        buf = self.__readRegMultiLSB(RF24_RX_ADDR_P0, buf,
                                     self.__rf_addr_width)
        for i in buf:
            sys.stdout.write(hex(i) + " ")
        print("")
        sys.stdout.write("RX_ADDR_P1=")
        buf = self.__readRegMultiLSB(RF24_RX_ADDR_P1, buf,
                                     self.__rf_addr_width)
        for i in buf:
            sys.stdout.write(hex(i) + " ")
        print("")
        sys.stdout.write("RX_ADDR_P2=")
        buf = self.__readRegMultiLSB(RF24_RX_ADDR_P2, buf,
                                     self.__rf_addr_width)
        for i in buf:
            sys.stdout.write(hex(i) + " ")
        print("")
        sys.stdout.write("RX_ADDR_P3=")
        buf = self.__readRegMultiLSB(RF24_RX_ADDR_P3, buf,
                                     self.__rf_addr_width)
        for i in buf:
            sys.stdout.write(hex(i) + " ")
        print("")
        sys.stdout.write("RX_ADDR_P4=")
        buf = self.__readRegMultiLSB(RF24_RX_ADDR_P4, buf,
                                     self.__rf_addr_width)
        for i in buf:
            sys.stdout.write(hex(i) + " ")
        print("")
        sys.stdout.write("RX_ADDR_P5=")
        buf = self.__readRegMultiLSB(RF24_RX_ADDR_P5, buf,
                                     self.__rf_addr_width)
        for i in buf:
            sys.stdout.write(hex(i) + " ")
        print("")
        print("")

        sys.stdout.write("TX_ADDR=")
        buf = self.__readRegMultiLSB(RF24_TX_ADDR, buf, self.__rf_addr_width)
        for i in buf:
            sys.stdout.write(hex(i) + " ")
        print("")
        print("")

        sys.stdout.write("RX_PW_P0=")
        print(hex(self.__readReg(RF24_RX_PW_P0)))

        sys.stdout.write("RX_PW_P1=")
        print(hex(self.__readReg(RF24_RX_PW_P1)))

        sys.stdout.write("RX_PW_P2=")
        print(hex(self.__readReg(RF24_RX_PW_P2)))

        sys.stdout.write("RX_PW_P3=")
        print(hex(self.__readReg(RF24_RX_PW_P3)))

        sys.stdout.write("RX_PW_P4=")
        print(hex(self.__readReg(RF24_RX_PW_P4)))

        sys.stdout.write("RX_PW_P5=")
        print(hex(self.__readReg(RF24_RX_PW_P5)))
        print("")

        sys.stdout.write("EN_AA=")
        print(bin(self.__readReg(RF24_EN_AA)))

        sys.stdout.write("EN_RXADDR=")
        print(bin(self.__readReg(RF24_EN_RXADDR)))

        sys.stdout.write("RF_CH=")
        print(hex(self.__readReg(RF24_RF_CH)))

        sys.stdout.write("RF_SETUP=")
        print(bin(self.__readReg(RF24_RF_SETUP)))

        sys.stdout.write("CONFIG=")
        print(bin(self.__readReg(RF24_CONFIG)))

        sys.stdout.write("DYNPD=")
        print(bin(self.__readReg(RF24_DYNPD)))

        sys.stdout.write("FEATURE=")
        print(bin(self.__readReg(RF24_FEATURE)))
        print("")

        sys.stdout.write("Data Rate=")
        print(self.getSpeed())

        sys.stdout.write("CRC Length=")
        print(self.getCRC())

        sys.stdout.write("PA Power=")
        print(self.getTXpower())

    def deepsleep(self):  # Enter POWERDOWN mode, ~0.9uA power consumption
        reg = self.__readReg(RF24_CONFIG)
        if (reg & (RF24_PWR_UP | RF24_PRIM_RX)):
            self.__writeReg(
                RF24_CONFIG,
                self.__ENRF24_CFGMASK_IRQ | self.__ENRF24_CFGMASK_CRC(reg))

        GPIO.output(self.cePin, GPIO.LOW)

    def enableRX(self):  # Enter PRX mode (~14mA)
        reg = self.__readReg(RF24_CONFIG)
        self.__writeReg(
            RF24_CONFIG, self.__ENRF24_CFGMASK_IRQ
            | self.__ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP | RF24_PRIM_RX)
        self.__writeReg(RF24_RX_PW_P0, 0x20)
        self.__writeReg(RF24_RX_PW_P1, 0x20)
        GPIO.output(self.cePin, GPIO.HIGH)

        if (
                not (reg & RF24_PWR_UP)
        ):  # Powering up from deep-sleep requires 5ms oscillator start delay
            time.sleep(0.05)

    def disableRX(self):  # Disable PRX mode (PRIM_RX bit in CONFIG register)
        # Note this won't necessarily push the transceiver into deep sleep, but rather
        # an idle standby mode where its internal oscillators are ready & running but
        # the RF transceiver PLL is disabled.  ~26uA power consumption.
        GPIO.output(self.cePin, GPIO.LOW)

        reg = self.__readReg(RF24_CONFIG)
        if (
                reg & RF24_PWR_UP
        ):  # Keep us in standby-I if we're coming from RX mode, otherwise stay
            # in deep-sleep if we call this while already in PWR_UP=0 mode.

            self.__writeReg(
                RF24_CONFIG, self.__ENRF24_CFGMASK_IRQ
                | self.__ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP)
        else:
            self.__writeReg(
                RF24_CONFIG,
                self.__ENRF24_CFGMASK_IRQ | self.__ENRF24_CFGMASK_CRC(reg))

    # Custom tweaks to RF parameters, packet parameters
    def autoAck(self,
                onoff=True
                ):  # Enable/disable auto-acknowledgements (enabled by default)
        reg = self.__readReg(RF24_EN_AA)
        if (onoff):
            if (not (reg & 0x01) or not (reg & 0x02)):
                self.__writeReg(RF24_EN_AA, 0x03)

        else:
            if (reg & 0x03):
                self.__writeReg(RF24_EN_AA, 0x00)

    def setChannel(self, channel):
        if (channel > 125):
            channel = 125
        self.__writeReg(RF24_RF_CH, channel)

    def setTXpower(
            self,
            dBm=0
    ):  # Only a few values supported by this (0, -6, -12, -18 dBm)
        reg = self.__readReg(
            RF24_RF_SETUP) & 0xF8  # preserve RF speed settings
        pwr = 0x06
        if (dBm >= 7):
            pwr = 0x07
        if (dBm < 0):
            pwr = 0x04
        if (dBm < -6):
            pwr = 0x02
        if (dBm < -12):
            pwr = 0x00
        self.__writeReg(RF24_RF_SETUP, reg | pwr)

    def setSpeed(self, rfspeed):  # Set 250000, 1000000, 2000000 speeds.
        reg = self.__readReg(
            RF24_RF_SETUP) & 0xD7  # preserve RF power settings
        spd = 0x01
        if (rfspeed < 2000000):
            spd = 0x00
        if (rfspeed < 1000000):
            spd = 0x04
        self.__writeReg(RF24_RF_SETUP, reg | (spd << 3))

    def setCRC(self,
               onoff,
               crc16bit=False):  # Enable/disable CRC usage inside nRF24's
        # hardware packet engine, specify 8 or
        # 16-bit CRC.
        crcbits = 0

        reg = self.__readReg(
            RF24_CONFIG) & 0xF3  # preserve IRQ mask, PWR_UP/PRIM_RX settings
        if (onoff):
            crcbits |= RF24_EN_CRC
        if (crc16bit):
            crcbits |= RF24_CRCO
        self.__writeReg(RF24_CONFIG, (reg | crcbits))

    # Set AutoACK retry count, timeout params (0-15, 250-4000 respectively)
    def setAutoAckParams(self, autoretry_count=15, autoretry_timeout=2000):
        setup_retr = 0

        setup_retr = autoretry_count & 0x0F
        autoretry_timeout -= 250
        setup_retr |= ((autoretry_timeout / 250) & 0x0F) << 4
        self.__writeReg(RF24_SETUP_RETR, setup_retr)

    # Protocol addressing -- receive, transmit addresses
    def setAddressLength(self,
                         len):  # Valid parameters = 3, 4 or 5.  Defaults to 5.
        if (len < 3):
            len = 3
        if (len > 5):
            len = 5

        self.__writeReg(RF24_SETUP_AW, len - 2)
        self.__rf_addr_width = len

    def setRXaddress(self, rxaddr):  # 3-5 byte RX address loaded into pipe#1
        self.__writeRegMultiLSB(RF24_RX_ADDR_P1, rxaddr)

    def setTXaddress(
            self, txaddr):  # 3-5 byte TX address loaded into TXaddr register
        self.__writeRegMultiLSB(RF24_TX_ADDR, txaddr)

    # Miscellaneous feature
    def rfSignalDetected(
        self
    ):  # Read RPD register to determine if transceiver has presently detected an RF signal
        # of -64dBm or greater.  Only works in PRX (enableRX()) mode.
        rpd = self.__readReg(RF24_RPD)
        return rpd

    # Query current parameters
    def getChannel(self):
        return self.__readReg(RF24_RF_CH)

    def getSpeed(self):
        reg = self.__readReg(RF24_RF_SETUP) & 0x28

        if (reg == 0x00):
            return 1000000
        elif (reg == 0x08):
            return 2000000
        elif (reg == 0x20):
            return 250000
        else:
            return 0

    def getTXpower(self):
        reg = self.__readReg(RF24_RF_SETUP) & 0x07

        if (reg & 0x01):
            return 7  # SI24R1-only +7dBm mode
        elif (reg == 0x02):
            return -12
        elif (reg == 0x04):
            return -6
        elif (reg == 0x06):
            return 0
        else:
            return -18

    def getAddressLength(self):
        return self.__rf_addr_width

    def getRXaddress(self):
        buf = []
        buf = self.__readRegMultiLSB(RF24_RX_ADDR_P1, buf,
                                     self.__rf_addr_width)
        return buf

    def getTXaddress(self):
        buf = []
        buf = self.__readRegMultiLSB(RF24_TX_ADDR, buf, rf_addr_width)
        return buf

    def getAutoAck(self):
        reg = self.__readReg(RF24_EN_AA)

        if (reg):
            return True
        else:
            return False

    def getCRC(self):
        reg = self.__readReg(RF24_CONFIG) & 0x0C

        if (reg == 0x08):
            return 8
        elif (reg == 0x0C):
            return 16
        else:
            return 0

    def __readReg(self, addr):
        GPIO.output(self.csnPin, GPIO.LOW)
        result = self.spi.xfer2([(RF24_R_REGISTER | addr), RF24_NOP])
        self.__rf_status = result[0]
        GPIO.output(self.csnPin, GPIO.HIGH)
        return result[1]

    def __readRegMultiLSB(self, addr, buf, length):
        txbuf = [(RF24_R_REGISTER | addr)]
        for i in range(length):
            txbuf.append(RF24_NOP)
        GPIO.output(self.csnPin, GPIO.LOW)
        buf = self.spi.xfer2(txbuf)
        self.__rf_status = buf[0]
        status = []
        for i in range(1, len(buf) + 1):
            status.append(buf[-i])
        status.pop()
        GPIO.output(self.csnPin, GPIO.HIGH)
        return status

    def __writeReg(self, addr, val):
        GPIO.output(self.csnPin, GPIO.LOW)
        res = self.spi.xfer2([(RF24_W_REGISTER | addr), val])
        GPIO.output(self.csnPin, GPIO.HIGH)

    def __writeRegMultiLSB(self, addr, buf):
        txbuf = [(RF24_W_REGISTER | addr)]
        for i in range(1, len(buf) + 1):
            txbuf.append(buf[-i])
        GPIO.output(self.csnPin, GPIO.LOW)
        status = self.spi.xfer2(txbuf)
        GPIO.output(self.csnPin, GPIO.HIGH)

    def __issueCmd(self, cmd):
        GPIO.output(self.csnPin, GPIO.LOW)
        self.spi.writebytes([cmd])
        GPIO.output(self.csnPin, GPIO.HIGH)

    def __readCmdPayload(self, cmd, buf, length, maxlen):
        GPIO.output(self.csnPin, GPIO.LOW)
        messg = []
        txbuf = [cmd]
        for i in range(maxlen):
            txbuf.append(RF24_NOP)
        buf = self.spi.xfer2(
            txbuf)  # Beyond maxlen bytes, just discard the remaining data.
        self.__rf_status = buf[0]
        for i in range(1, length + 1):
            messg.append(buf[i])
        GPIO.output(self.csnPin, GPIO.HIGH)
        return messg

    def __issueCmdPayload(self, cmd, buf):
        payload = []
        payload.append(cmd)
        for i in buf:
            payload.append(i)
        GPIO.output(self.csnPin, GPIO.LOW)
        res = self.spi.xfer2(payload)
        GPIO.output(self.csnPin, GPIO.HIGH)

    def __irq_getreason(self):
        self.__lastirq = self.__readReg(RF24_STATUS) & self.__ENRF24_IRQ_MASK

    def __irq_derivereason(
            self
    ):  # Get IRQ status from rf_status w/o querying module over SPI.
        self.__lastirq = self.__rf_status & self.__ENRF24_IRQ_MASK

    def __irq_clear(self, irq):
        self.__writeReg(RF24_STATUS, (irq & self.__ENRF24_IRQ_MASK))

    def __isAlive(self):
        self.spi.writebytes([0x00])
        aw = self.__readReg(RF24_SETUP_AW)
        return ((aw & 0xFC) == 0x00 and (aw & 0x03) != 0x00)

    def __readTXaddr(self, buf):
        self.__readRegMultiLSB(RF24_TX_ADDR, buf, self.__rf_addr_width)

    def __writeRXaddrP0(self, buf):
        self.__writeRegMultiLSB(RF24_RX_ADDR_P0, buf)

    def __maintenanceHook(
        self
    ):  # Handles IRQs and purges RX queue when erroneous contents exist.
        i = 0

        self.__irq_getreason()

        if (self.__lastirq & self.__ENRF24_IRQ_TXFAILED):
            self.__lastTXfailed = True
            self.__issueCmd(RF24_FLUSH_TX)
            self.__irq_clear(self.__ENRF24_IRQ_TXFAILED)

        if (self.__lastirq & self.__ENRF24_IRQ_TX):
            self.__lastTXfailed = False
            self.__irq_clear(self.__ENRF24_IRQ_TX)

        if (self.__lastirq & self.__ENRF24_IRQ_RX):
            if ((not self.__readReg(RF24_FIFO_STATUS))
                    & RF24_RX_FULL):  # Don't feel it's necessary
                # to be notified of new
                # incoming packets if the RX
                # queue is full.
                self.__irq_clear(self.__ENRF24_IRQ_RX)

        # Check if RX payload is 0-byte or >32byte (erroneous conditions)
        # Also check if data was received on pipe#0, which we are ignoring.
        # The reason for this is pipe#0 is needed for receiving AutoACK acknowledgements,
        # its address gets reset to the module's default and we do not care about data
        # coming in to that address...

            i = self.__readCmdPayload(RF24_R_RX_PL_WID, i, 1, 1)[0]

            if (i == 0 or i > 32 or ((self.__rf_status & 0x0E) >> 1) == 0):
                # Zero-width RX payload is an error that happens a lot
                # with non-AutoAck, and must be cleared with FLUSH_RX.
                # Erroneous >32byte packets are a similar phenomenon.
                self.__issueCmd(RF24_FLUSH_RX)
                self.__irq_clear(self.__ENRF24_IRQ_RX)
                self.__readpending = 0
            else:
                self.__readpending = 1

            # Actual scavenging of RX queues is performed by user-directed use of read().

    def __ENRF24_CFGMASK_CRC(self, a):
        return (a & (RF24_EN_CRC | RF24_CRCO))
Esempio n. 23
0
class DAC:
    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()
        # server

    def reset_dac(self):
        GPIO.output("P8_18", 1)
        print('Reseting DAC')
        self.spi.close()
        self.spi = SPI(1, 0)
        GPIO.output("P8_18", 0)  # returns it back to 0

    def __del__(self):
        self.reset_dac()  # reset voltage
        self.spi.close()  # spi close

    def initializeDAC(
            self
    ):  # we can always change the initialize and make it more flexible
        GPIO.output("P8_17", GPIO.HIGH)
        self.spi.writebytes([0b00100000, 0b00000000, 0b00100010])
        GPIO.output("P8_17", GPIO.LOW)

    def registerValue(self):
        self.initializeDAC()
        if self.act_val != 0:
            temp = self.convertComplement_DAC(self.act_val, 20)
            string1 = self.DAC_SEND + temp[0:4]
            string2 = temp[4:12]
            string3 = temp[12:]
            GPIO.output("P8_17", GPIO.HIGH)
            self.spi.writebytes(
                [int(string1, 2),
                 int(string2, 2),
                 int(string3, 2)])
            print('Sending to the DAC: ', string1 + string2 + string3)
            GPIO.output("P8_17", GPIO.LOW)
        else:
            self.reset_dac()
            return

    @staticmethod
    def convertComplement_DAC(value, width=20):
        #        Return the binary representation of the input number as a string.
        #        If width is not given it is assumed to be 20. If width is given, the two's complement of the number is
        #        returned, with respect to that width.
        #        In a two's-complement system negative numbers are represented by the two's
        #        complement of the absolute value. This is the most common method of
        #        representing signed integers on computers. A N-bit two's-complement
        #        system can represent every integer in the range [-2^(N-1),2^(N-1)-1]

        def warning(widt, width_bin):

            # the function checks if the width is a good value for input number, if not (f.e smaller) returning
            # default 20

            if widt != 20 and (widt <= 0 or width < width_bin):
                print("Bad width, returning default\n")
                return width_bin
            elif widt == 20 and widt < width_bin:
                return width_bin
            else:
                return widt

        if value > 0:
            binar = bin(
                int(value))[2:]  # take binary representation of input value
            real_width = warning(width, len(binar))  # check width
            if real_width > len(
                    binar):  # add zeros if width is bigger that binary length
                for x1 in range(0, real_width - len(binar)):
                    binar = "0" + binar
            return binar

        elif value == 0:  # all zeros
            binar = ""
            for x2 in range(0, width):
                binar = "0" + binar

        elif value < 0:
            binar = bin(
                abs(int(value))
            )[2:]  # because of the minus sign at the beginning we take absolute value
            real_width = warning(width, len(binar))
            if abs(value) == pow(2, real_width - 1):
                return binar
            if real_width > len(
                    binar
            ):  # with bigger length we have to add zeros at the beginning
                for x3 in range(0, real_width - len(binar)):
                    binar = "0" + binar
            strin = ""  # empty temporary string
            for x in range(0, real_width):
                if int(binar[x]) == 1:
                    temp = 0  # negating for the 2's complement
                else:
                    temp = 1
                strin = strin + str(temp)
            temp_add = int(strin, 2)
            temp_add = temp_add + 1
            binar = bin(temp_add)[2:]
            return binar
Esempio n. 24
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)
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()
Esempio n. 26
0
class DACRef:

    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

    def setDACAddress(self, list):
        self.dacAddress = list
        GPIO.setup("P9_15", self.dacAddress[0])  # P0
        GPIO.setup("P9_11", self.dacAddress[1])  # P1
        GPIO.setup("P9_12", self.dacAddress[2])  # P2
        GPIO.setup("P9_13", self.dacAddress[3])  # P3
        GPIO.setup("P9_14", self.dacAddress[4])  # P4

    def chooseDAC(self, dacNum=0, board=0):

        if board == 0:
            p2 = 0
            p3 = 0
            p4 = 0
        elif board == 1:
            p2 = 0
            p3 = 0
            p4 = 1
        elif board == 2:
            p2 = 0
            p3 = 1
            p4 = 0
        elif board == 3:
            p2 = 0
            p3 = 1
            p4 = 1
        else:
            print("WRONG NUMBER, SETTING 0")
            p2 = 0
            p3 = 0
            p4 = 0

        GPIO.output("P9_12", p2)
        GPIO.output("P9_13", p3)
        GPIO.output("P9_14", p4)

        if dacNum == 0:
            p0 = 0
            p1 = 0
        elif dacNum == 1:
            p0 = 0
            p1 = 1
        elif dacNum == 2:
            p0 = 1
            p1 = 0
        elif dacNum == 3:
            p0 = 1
            p1 = 1
        GPIO.output("P9_15", p0)
        GPIO.output("P9_11", p1)
        self.dacAddress = [p0, p1, p2, p3, p4]

    def setLDAC(self, ldac):
        self.ldac = ldac
        GPIO.output("P8_17", self.ldac)

    def resetDAC(self):
        self.reset = 1
        GPIO.output("P8_18", self.reset)
        GPIO.output("P8_18", 0)  # returns it back to 0

    def setValueRaw(self, raw):
        if self.max_raw_plus >= int(raw) >= self.max_raw_minus:
            self.actVal = int(raw)
            print("Actual value is: " + str(self.actVal))
        else:
            self.actVal = 0  # if we go out of range we get 0
            print("Out of range[-1,1] or 0.")
           # print("Actual value is: " + str(self.actVal))
        self.registerValue()

    def setValueNorm(self, norm):
        if 0 < norm <= 1:
            self.actVal = int(self.max_raw_plus * norm)
            print("Actual value is: " + str(self.actVal))
        elif 0 > norm >= -1:
            self.actVal = int(-self.max_raw_minus * norm)
           # print("Actual value is: " + str(self.actVal))
        else:
            self.actVal = 0
            print("Out of range[-1,1] or 0.")
           # print("Actual value is: " + str(self.actVal))
        self.registerValue()

    def setValHelp(self, address):
        val = input("Write the value from [-524288,524287]: ")
        if val <= self.max_raw_plus and val >= self.max_raw_minus:
            self.setDACAddress(address)
            self.setValueNorm(int(val))
        else:
            print("Wrong number, doing nothing")
            return

    def initializeDAC(self):  # we can always change the initialize and make it more flexible
        GPIO.output("P8_17", GPIO.HIGH)
        self.spi.writebytes([0b00100000, 0b00000000, 0b00100010])
        GPIO.output("P8_17", GPIO.LOW)

    def registerValue(self):

        self.initializeDAC()
        if self.actVal != 0:
            temp = convertComplement_DAC(self.actVal, 20)
            string1 = self.dacSend + temp[0:4]
            string2 = temp[4:12]
            string3 = temp[12:]
            GPIO.output("P8_17", GPIO.HIGH)
            self.spi.writebytes([int(string1, 2), int(string2, 2), int(string3, 2)])
            GPIO.output("P8_17", GPIO.LOW)
        else:
            self.resetDAC()

    def __del__(self):
        self.resetDAC()
        self.spi.close()
Esempio n. 27
0

controlReglAddress			= 0x0D
statusRegAddress			= 0x0E
trickleChargerRegAddress    = 0x0F

agingOffsetAddress		    = 0x10
temperatureMSBAddress	    = 0x11
temperatureLSBAddress	    = 0x12



seconds 		= 0x00
minutes 		= 0x00
hours			= 0x00
dayOfWeek		= 00000XXX
dayOfMonth		= 00NNXXXX
monthCentury	= 0x00
year			= 0x00
control			= 00011000 #Enable 1Hz or 00?
status			= 0x00
agingOffset		= 0x00
temperatureMSB	= 0x00
temperatureLSB	= 0x00

SetHeatBeat     = 0x00#For  control register



spi.writebytes([controlReglAddress, SetHeatBeat ])
Esempio n. 28
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)
Esempio n. 29
0
class RFM69HCW():
    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

    def _io_setup(self):
        GPIO.setup(BLUE_LEDPIN, GPIO.OUT)
        GPIO.setup(MODULE_EN, GPIO.OUT)
        GPIO.setup(MODULE_RST, GPIO.OUT)
        GPIO.setup(G0_PIN, GPIO.IN)
        GPIO.setup(G1_PIN, GPIO.OUT)
        GPIO.setup(G2_PIN, GPIO.OUT)
        # GPIO.add_event_detect(G0_PIN, GPIO.FALLING, callback=g0int)
        GPIO.add_event_detect(G0_PIN, GPIO.RISING, callback=g0int)

    def _check_register(self, addr, value):
        vals = self.RFM_SPI.xfer2([addr, 0x0])
        if vals[1] != value:
            str = "addr: " + hex(addr) + "(" + inv_sx1231_reg[
                addr] + ")" + " should be: " + hex(value) + " got: " + hex(
                    vals[1])
            raise CheckError(str)
        print "Reg{", hex(addr), "}(", inv_sx1231_reg[addr], ")\t\t=", hex(
            vals[1])

    def write_register(self, reg, val, checkit=False):
        addr = reg
        reg = reg | 0x80
        # print "reg is: ", bin(reg)
        # print "val is: " , bin(val)
        # RFM_SPI.writebytes([reg, val])
        self.RFM_SPI.xfer2([reg, val])
        if checkit == True:
            self._check_register(addr, val)
        return

    def read_register(self, reg):
        regval = self.RFM_SPI.xfer2([reg, 0x0])
        return regval[1]

    def reset_radio(self):
        #self.blue_blink(2)
        GPIO.output(MODULE_EN, GPIO.HIGH)
        GPIO.output(MODULE_RST, GPIO.LOW)
        time.sleep(0.5)
        GPIO.output(MODULE_RST, GPIO.HIGH)
        time.sleep(0.5)
        GPIO.output(MODULE_RST, GPIO.LOW)
        time.sleep(0.5)

    def blue_invert(self):
        if (self.LED_STATE) == True:
            self.blue_off()
        else:
            self.blue_on()

    def blue_off(self):
        self.LED_STATE = False
        GPIO.output(BLUE_LEDPIN, GPIO.HIGH)
        return

    def blue_on(self):
        self.LED_STATE = True
        GPIO.output(BLUE_LEDPIN, GPIO.LOW)
        return

    def blue_blink(self, n=3):
        for num in range(0, n * 2):
            self.blue_invert()
            time.sleep(0.25)
        return

    def report_setup(self):
        print 'LED_STATE is:\t', self.LED_STATE
        print 'Fxosc is:    \t', self.Fxosc
        print 'Fstep is:    \t', self.Fstep
        print 'Callsign is: \t', self.callsign
        return

    # Facts:
    #   Fxosc = 32Mhz
    #   Fstep = 32e6/2^9  =  61.03515625
    #   Frf   = int(carrier_hz/Fstep)
    def write_carrier_freq(self, carrier_hz=436500000):
        frf = int(carrier_hz / self.Fstep)

        # vals = RFM_SPI.xfer2([RegFrfMsb, 0x0, 0x0, 0x0])
        # print "Pre: vals=\t", hex(vals[0]), "\t", hex(vals[1]), "\t", hex(vals[2]), "\t", hex(vals[3])

        frfmsb = (frf >> 16) & 0xff
        frfmid = (frf >> 8) & 0xff
        frflsb = frf & 0xff

        wbuf = [(sx1231_reg["RegFrfMsb"] | 0x80),
                int(frfmsb),
                int(frfmid),
                int(frflsb)]
        self.RFM_SPI.writebytes(wbuf)

        vals = self.RFM_SPI.xfer2([sx1231_reg["RegFrfMsb"], 0x0, 0x0, 0x0])
        # print "Post: vals=\t", hex(vals[0]), "\t", hex(vals[1]), "\t", hex(vals[2]), "\t", hex(vals[3])
        return

    def set_freq_deviation(self, freq_dev_hz=20000):
        freqdev = int(freq_dev_hz / self.Fstep)

        wbuf = [(sx1231_reg["RegFdevMsb"] | 0x80), (int(freqdev >> 8) & 0x3f),
                int(freqdev & 0xff)]
        self.RFM_SPI.writebytes(wbuf)
        # print "fdev_msb:\t",
        # check_register(sx1231_reg["RegFdevMsb"], (int(freqdev>>8) & 0x3f))
        # print "\nfdev_lsb:\t",
        # check_register(sx1231_reg["RegFdevLsb"], (int(freqdev & 0xff)))
        # print "\n"
        return

    def set_bitrate(self, bitrate_hz=1200):
        rate = int(self.Fxosc / bitrate_hz)

        wbuf = [(sx1231_reg["RegBitrateMsb"] | 0x80), (int(rate >> 8) & 0xff),
                int(rate & 0xff)]
        self.RFM_SPI.writebytes(wbuf)

    def set_sync_value(fourbytelist):
        wbuf = [(sx1231_reg["RegSyncValue1"] | 0x80)] + fourbytelist
        self.RFM_SPI.writebytes(wbuf)

    def set_preamble(twobytelist):
        wbuf = [(sx1231_reg["RegPreambleMsb"] | 0x80)] + twobytelist
        self.RFM_SPI.writebytes(wbuf)

    """
    Experiment with automodes 
    """

    def config_packet(self, pa, node_id=0x33, network_id=0x77):
        # Begin with sequencer on, listen off, and in standby
        self.write_register(sx1231_reg["RegOpMode"],
                            OPMODE_SEQUENCER_ON | OPMODE_LISTEN_OFF, True)
        self.set_mode(OPMODE_STANDBY)

        # Automodes - Finish Emptying fifo while in STBY
        self.write_register(
            sx1231_reg["RegAutoModes"], AUTOMODE_ENTER_CRC_OK
            | AUTOMODE_EXIT_FIFO_NOT_EMPTY | AUTOMODE_INTERM_STDBY, True)

        # Packet Mode, FSK, No Shaping
        self.write_register(
            sx1231_reg["RegDataModul"],
            DATAMODUL_Packet | DATAMODUL_FSK | DATAMODUL_NoShaping)

        self.write_carrier_freq(self.carrier_freq)
        self.set_freq_deviation(self.carrier_dev)
        self.set_bitrate(self.bitrate)

        # PA Output Power
        self.write_register(sx1231_reg["RegPaLevel"], PAOutputCfg(
            PA0, 0x1F))  # keep at PA0 until end of initialize

        # DIO Mappings
        g0_flag = False
        g1_flag = False
        g2_flag = False
        g3_flag = False
        g4_flag = False
        g5_flag = False
        #  (DccFreq|RxBwMant|RxBwExp) Table 13
        self.write_register(sx1231_reg["RegRxBw"],
                            (010 << 5 | 0x10 << 3 | 100 << 0))  # 20.8kHz?

        # DIO_0 initialize to PAYLOAD ready in RX
        self.write_register(
            sx1231_reg["RegDioMapping1"],
            ((self.read_register(sx1231_reg["RegDioMapping1"]) &
              (~(0b11 << DIO_0_POS))) | DIO0_PAYLOADREADY << DIO_0_POS), True)
        # DIO_1 is RX TIMEOUT
        self.write_register(
            sx1231_reg["RegDioMapping1"],
            ((self.read_register(sx1231_reg["RegDioMapping1"]) &
              (~(0b11 << DIO_1_POS))) | DIO1_RX_TIMEOUT << DIO_1_POS), True)

        # DIO_4 is Clkout
        self.write_register(sx1231_reg["RegDioMapping2"],
                            (DIO4_RXRDY << DIO_4_POS | DIO_CLK_DIV32), True)

        # Clear IRQFLAG and reset FIFO
        self.write_register(sx1231_reg["RegIrqFlags2"], IRQFLAGS2_FIFOOVERRUN)

        # RSSI Thresh
        self.write_register(sx1231_reg["RegRssiThresh"], 0xdc,
                            True)  # -220/2 = -110dBm?

        # Preamble length (0xaa..N)
        self.write_register(sx1231_reg["RegPreambleLsb"], 0xf, True)

        # Sync Config
        self.write_register(
            sx1231_reg["RegSyncConfig"],
            SYNCCFG_SYNC_ON | SYNCCFG_FILL_FIFO_INTR | SYNCCFG_SIZE_2, True)

        # Sync Word
        self.write_register(sx1231_reg["RegSyncValue1"], node_id, True)
        self.write_register(sx1231_reg["RegSyncValue2"], network_id, True)

        # Packet config 1
        self.write_register(
            sx1231_reg["RegPacketConfig1"], PACKET1_FORMAT_FIXED
            | PACKET1_DCFREE_NONE
            | PACKET1_CRC_ON
            | PACKET1_CRCAUTOCLEAR_ON
            | PACKET1_ADDRESS_FILTERING_BOTH, True)

        # Payload Length
        self.write_register(sx1231_reg["RegPayloadLength"],
                            default_Payload_bytes, True)

        # Node address:
        self.write_register(sx1231_reg["RegNodeAdrs"], self.node_id, True)
        self.write_register(sx1231_reg["RegBroadcastAdrs"], self.node_id + 1,
                            True)

        # Fifothresh? Only for TX
        self.write_register(sx1231_reg["RegFifoThresh"],
                            FIFOTHRESH_NOT_EMPTY | FIFOTHRESH_THRESHOLD_15,
                            True)

        # Packet config 2
        self.write_register(sx1231_reg["RegPacketConfig2"],
                            PACKET2_AUTORX_RESTART_ON, True)

        # Magic numbers
        self.write_register(
            sx1231_reg["RegPaRamp"], 0b0011, True
        )  # 500uS   close to 1/2400 bps ... see PacketConfig2 InterPacketRxDelay Must match the tx PA Ramp-down time
        # self.write_register(sx1231_reg["RegAfcCtrl"],0x40 | (0b1<<5) , True ) # AfcLowBetaOn  - Manual misprint....bits 7-6 read as 0b01  not 0b00
        self.write_register(
            sx1231_reg["RegAfcCtrl"], (0b1 << 5), True
        )  # AfcLowBetaOn  - Manual misprint....bits 7-6 read as 0b01  not 0b00
        self.write_register(sx1231_reg["RegTestDagc"], 0x20,
                            True)  # page 74 for AfcLowBetaOn=1
        self.write_register(sx1231_reg["RegPaLevel"], pa)
        return

    def set_mode(self, mode):
        if (mode == self._mode):
            return

        if (mode == OPMODE_SLEEP):
            self.write_register(
                sx1231_reg["RegDioMapping1"],
                ((self.read_register(sx1231_reg["RegDioMapping1"]) &
                  (~(0b11 << DIO_0_POS))) | DIO0_PAYLOADREADY << DIO_0_POS))
            self.write_register(
                sx1231_reg["RegOpMode"],
                (self.read_register(sx1231_reg["RegOpMode"]) & 0xe3)
                | OPMODE_SLEEP)
            self._mode = OPMODE_SLEEP
        elif (mode == OPMODE_STANDBY):
            self.write_register(
                sx1231_reg["RegDioMapping1"],
                ((self.read_register(sx1231_reg["RegDioMapping1"]) &
                  (~(0b11 << DIO_0_POS))) | DIO0_PAYLOADREADY << DIO_0_POS))
            self.write_register(
                sx1231_reg["RegOpMode"],
                (self.read_register(sx1231_reg["RegOpMode"]) & 0xe3)
                | OPMODE_STANDBY)
            self._mode = OPMODE_STANDBY
        elif (mode == OPMODE_FS_SYNTH):
            self.write_register(
                sx1231_reg["RegOpMode"],
                (self.read_register(sx1231_reg["RegOpMode"]) & 0xe3)
                | OPMODE_FS_SYNTH)
            self._mode = OPMODE_FS_SYNTH
        elif (mode == OPMODE_TX):
            self.write_register(
                sx1231_reg["RegDioMapping1"],
                ((self.read_register(sx1231_reg["RegDioMapping1"]) &
                  (~(0b11 << DIO_0_POS))) | DIO0_PACKETSENT << DIO_0_POS))
            self.write_register(
                sx1231_reg["RegOpMode"],
                (self.read_register(sx1231_reg["RegOpMode"]) & 0xe3)
                | OPMODE_TX)
            self._mode = OPMODE_TX
        elif (mode == OPMODE_RX):
            self.write_register(
                sx1231_reg["RegDioMapping1"],
                ((self.read_register(sx1231_reg["RegDioMapping1"]) &
                  (~(0b11 << DIO_0_POS))) | DIO0_PAYLOADREADY << DIO_0_POS))
            self.write_register(
                sx1231_reg["RegOpMode"],
                (self.read_register(sx1231_reg["RegOpMode"]) & 0xe3)
                | OPMODE_RX)
            self._mode = OPMODE_RX
        else:
            raise ValueError('Unrecognized Mode')

        while ((self.read_register(sx1231_reg["RegIrqFlags1"])
                & IRQFLAGS1_MODEREADY) == 0x00):
            pass
        return

    def RSSI(self):
        # write trigger
        self.write_register(sx1231_reg["RegRssiConfig"], 0b1)
        while ((self.read_register(sx1231_reg["RegRssiConfig"])
                & RSSI_DONE) == 0x0):
            pass
        rssival = -self.read_register(sx1231_reg["RegRssiValue"])
        rssival = rssival / 2
        return rssival

    # call when g0flag goes true
    def read_fifo(self):
        global g0_flag
        self.standby()
        fifolist = self.RFM_SPI.readbytes(default_Payload_bytes + 1)

        #debugging
        # value = True
        # while value:
        # print "* ";
        # value = self.read_register(sx1231_reg["RegIrqFlags2"]) & IRQFLAGS2_PAYLOADREADY
        # garbage=self.RFM_SPI.readbytes(default_Payload_bytes+1)

        value = self.read_register(
            sx1231_reg["RegIrqFlags2"]) & IRQFLAGS2_PAYLOADREADY
        if value == 0:
            g0_flag = False
        return fifolist

    def standby(self):
        self.set_mode(OPMODE_STANDBY)
        return

    def receive(self):
        self.set_mode(OPMODE_RX)

        g0_flag = False
        return

    def send(self, bytelist):
        self.set_mode(OPMODE_STANDBY)
        if len(bytelist) > MAX_PACKET_LEN:
            raise ValueError('Max Packet Len Exceeded')

        #bytelist  = [self.node_id+1]+[self.node_id] + bytelist
        # bytelist  = [self.node_id] + [self.node_id+1] + bytelist
        # bytelist  = [self.node_id] + bytelist
        bytelist = [self.node_id] + bytelist
        print "\tbytelist: ", bytelist
        wbuf = [(sx1231_reg["RegFifo"] | 0x80)] + bytelist

        self.RFM_SPI.writebytes(wbuf)
        start_time = time.time()
        self.set_mode(OPMODE_TX)

        # Read pin or register...
        # value = GPIO.input(G0_PIN)
        value = self.read_register(
            sx1231_reg["RegIrqFlags2"]) & IRQFLAGS2_PACKETSENT
        #print "Start send:\t", start_time
        while value == 0:
            # value = GPIO.input(G0_PIN)
            value = self.read_register(
                sx1231_reg["RegIrqFlags2"]) & IRQFLAGS2_PACKETSENT
            elapsed_time = time.time() - start_time
            if (elapsed_time > 10):
                break

        #print "Stop send:\t", elapsed_time
        self.set_mode(OPMODE_STANDBY)
        return

    def stop(self):
        return
Esempio n. 30
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

Esempio n. 31
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]
		self._unselect()
		return result

	def _writeReg(self, addr, 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.readRSSI() < 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.readRSSI()

	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]
		]

		while self._readReg(REG_SYNCVALUE1) != 0xaa:
			self._writeReg(REG_SYNCVALUE1, 0xaa)
		while self._readReg(REG_SYNCVALUE1) != 0x55:
			self._writeReg(REG_SYNCVALUE1, 0x55)

		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