refactoring

This commit is contained in:
Stefan Seegel 2020-01-23 21:23:04 +01:00
parent 7aa238d029
commit dcbdbeec0b
5 changed files with 209 additions and 159 deletions

View file

@ -1 +0,0 @@
from .raspyrfm import *

View file

@ -1,30 +1,30 @@
#!/usr/bin/env python2.7
import RaspyRFM
from raspyrfm import *
import sensors
from sensors import rawsensor
import sys
import time
import threading
if RaspyRFM.RaspyRFM.Test(1):
if raspyrfm_test(2, RFM69):
print("Found RaspyRFM twin")
rfm = RaspyRFM.RaspyRFM(1, 24) #when using the RaspyRFM twin
elif RaspyRFM.RaspyRFM.Test(0):
rfm = RaspyRFM(2, RFM69) #when using the RaspyRFM twin
elif raspyrfm_test(1, RFM69):
print("Found RaspyRFM single")
rfm = RaspyRFM.RaspyRFM() #when using a single single 868 MHz RaspyRFM
rfm = RaspyRFM(1, RFM69) #when using a single single 868 MHz RaspyRFM
else:
print("No RFM69 module found!")
exit()
rfm.SetParams(
Freq = 868.30, #MHz center frequency
Datarate = 9.579, #kbit/s baudrate
ModulationType = RaspyRFM.FSK, #modulation
Deviation = 30, #kHz frequency deviation
SyncPattern = [0x2d, 0xd4], #syncword
Bandwidth = 150, #kHz bandwidth
RssiThresh = -105, #dBm RSSI threshold
rfm.set_params(
Freq = 868.30, #MHz center frequency
Datarate = 9.579, #kbit/s baudrate
ModulationType = rfm69.FSK, #modulation
Deviation = 30, #kHz frequency deviation
SyncPattern = [0x2d, 0xd4], #syncword
Bandwidth = 150, #kHz bandwidth
RssiThresh = -105, #dBm RSSI threshold
)
class BaudChanger(threading.Thread):
@ -40,7 +40,7 @@ class BaudChanger(threading.Thread):
else:
dr = 17.241
print "Switch baudrate to " + str(dr) + " kbit/s"
rfm.SetParams(Datarate = dr)
rfm.set_params(Datarate = dr)
self.baud = not self.baud
baudChanger = BaudChanger()
@ -49,7 +49,7 @@ baudChanger.start()
print "Waiting for sensors..."
while 1:
data = rfm.ReceivePacket(5)
data = rfm.receive_packet(5)
if data == None:
continue

48
raspyrfm/__init__.py Normal file
View file

@ -0,0 +1,48 @@
import rfm69
RFM69 = 1
RFM9x = 2
def __get_hw_params(mod):
if mod == 1:
dio0 = 25
elif mod == 2:
dio0 = 24
elif mod == 3:
dio0 = 1
elif mod == 4:
dio0 = 18
else:
return
return (mod - 1, dio0)
def RaspyRFM(mod, type):
""" Create a RaspyRFM object.
Parameters:
mod (int):
Number of the module.
Always 1 for a single RaspyRFM
1-2 for a dual RaspyRFM
1-4 for a quad RaspyRFM
type (int):
type of the module (RFM69 or RFM9x)
Returns:
Rfm69 or Rfm9x object if successful, otherwise None
"""
s = __get_hw_params(mod)
if s:
if type == RFM69:
return rfm69.Rfm69(s[0], s[1])
else:
print("Not yet implemented.")
def raspyrfm_test(mod, type):
s = __get_hw_params(mod)
if s:
return rfm69.Rfm69.test(s[0], s[1])

View file

@ -11,53 +11,53 @@ FSTEP = FXOSC / (1<<19)
# Connect to pins 17-26 on raspberry pi
#-------------------------------------------------#
# Raspi | Raspi | Raspi | RFM69 | RFM12 | PCB con #
# Name | GPIO | Pin | Name | Name | Pin #
# Name | GPIO | Pin | Name | Name | Pin #
#-------------------------------------------------#
# 3V3 | - | 17 | 3.3V | VDD | 1 #
# - | 24 | 18 | DIO1 | FFIT | 2 # only when PCB jumper closed
# MOSI | 10 | 19 | MOSI | SDI | 3 #
# GND | - | 20 | GND | GND | 4 #
# MISO | 9 | 21 | MISO | SDO | 5 #
# - | 25 | 22 | DIO0 | nIRQ | 6 #
# SCKL | 11 | 23 | SCK | SCK | 7 #
# CE0 | 8 | 24 | NSS | nSEL | 8 #
# CE1 | 7 | 26 | DIO2 | nFFS | 10 # only when PCB jumper closed
# 3V3 | - | 17 | 3.3V | VDD | 1 #
# - | 24 | 18 | DIO1 | FFIT | 2 # only when PCB jumper closed
# MOSI | 10 | 19 | MOSI | SDI | 3 #
# GND | - | 20 | GND | GND | 4 #
# MISO | 9 | 21 | MISO | SDO | 5 #
# - | 25 | 22 | DIO0 | nIRQ | 6 #
# SCKL | 11 | 23 | SCK | SCK | 7 #
# CE0 | 8 | 24 | NSS | nSEL | 8 #
# CE1 | 7 | 26 | DIO2 | nFFS | 10 # only when PCB jumper closed
#-------------------------------------------------#
# RaspyRFM twin module with 10-pin connector
# Connect to pins 17-26 on raspberry pi
#-------------------------------------------------#
# Raspi | Raspi | Raspi | RFM69 | RFM12 | PCB con #
# Name | GPIO | Pin | Name | Name | Pin #
# Name | GPIO | Pin | Name | Name | Pin #
#-------------------------------------------------#
# 3V3 | - | 17 | 3.3V | VDD | 1 #
# - | 24 | 18 | DIO0_2| FFIT | 2 #
# MOSI | 10 | 19 | MOSI | SDI | 3 #
# GND | - | 20 | GND | GND | 4 #
# MISO | 9 | 21 | MISO | SDO | 5 #
# - | 25 | 22 | DIO0_1| nIRQ | 6 #
# SCKL | 11 | 23 | SCK | SCK | 7 #
# CE0 | 8 | 24 | NSS1 | nSEL | 8 #
# CE1 | 7 | 26 | NSS2 | nFFS | 10 #
# 3V3 | - | 17 | 3.3V | VDD | 1 #
# - | 24 | 18 | DIO0_2| FFIT | 2 #
# MOSI | 10 | 19 | MOSI | SDI | 3 #
# GND | - | 20 | GND | GND | 4 #
# MISO | 9 | 21 | MISO | SDO | 5 #
# - | 25 | 22 | DIO0_1| nIRQ | 6 #
# SCKL | 11 | 23 | SCK | SCK | 7 #
# CE0 | 8 | 24 | NSS1 | nSEL | 8 #
# CE1 | 7 | 26 | NSS2 | nFFS | 10 #
#-------------------------------------------------#
# RaspyRFM twin module with 12-pin connector
# Connect to pins 15-26 on raspberry pi
#-------------------------------------------------#
# Raspi | Raspi | Raspi | RFM69 | RFM12 | PCB con #
# Name | GPIO | Pin | Name | Name | Pin #
# Name | GPIO | Pin | Name | Name | Pin #
#-------------------------------------------------#
# - | 22 | 15 | DIO2_2| | 1 #
# - | 23 | 16 | DIO2_1| | 2 #
# 3V3 | - | 17 | 3.3V | VDD | 3 #
# - | 24 | 18 | DIO0_2| FFIT | 4 #
# MOSI | 10 | 19 | MOSI | SDI | 5 #
# GND | - | 20 | GND | GND | 6 #
# MISO | 9 | 21 | MISO | SDO | 7 #
# - | 25 | 22 | DIO0_1| nIRQ | 8 #
# SCKL | 11 | 23 | SCK | SCK | 9 #
# CE0 | 8 | 24 | NSS1 | nSEL | 10 #
# CE1 | 7 | 26 | NSS2 | nFFS | 12 #
# - | 22 | 15 | DIO2_2| | 1 #
# - | 23 | 16 | DIO2_1| | 2 #
# 3V3 | - | 17 | 3.3V | VDD | 3 #
# - | 24 | 18 | DIO0_2| FFIT | 4 #
# MOSI | 10 | 19 | MOSI | SDI | 5 #
# GND | - | 20 | GND | GND | 6 #
# MISO | 9 | 21 | MISO | SDO | 7 #
# - | 25 | 22 | DIO0_1| nIRQ | 8 #
# SCKL | 11 | 23 | SCK | SCK | 9 #
# CE0 | 8 | 24 | NSS1 | nSEL | 10 #
# CE1 | 7 | 26 | NSS2 | nFFS | 12 #
#-------------------------------------------------#
#RFM69 registers
@ -152,15 +152,15 @@ DIO0_PM_SENT = 0
DIO0_PM_TXDONE = 1
DIO0_PM_PLLLOCK = 3
class RaspyRFM(threading.Thread):
class Rfm69(threading.Thread):
@staticmethod
def Test(cs):
def test(cs, gpio_dio0):
spi = spidev.SpiDev()
spi.open(0, cs)
spi.max_speed_hz = 5000
#Testing presence of module
err = False
for i in range(0, 8):
for i in range(8):
spi.xfer2([(RegSyncValue1 + i) | 0x80, 0x55])
test = spi.xfer2([(RegSyncValue1 + i), 0x00])[1]
if test != 0x55:
@ -174,9 +174,8 @@ class RaspyRFM(threading.Thread):
spi.close()
return not err
def __init__(self, cs = 0, gpio_int = 25):
if not self.Test(cs):
if not self.test(cs, gpio_int):
print("ERROR! RFM69 not found")
return
@ -192,9 +191,9 @@ class RaspyRFM(threading.Thread):
print("RFM69 found on CS " + str(cs))
GPIO.setmode(GPIO.BCM)
GPIO.setup(gpio_int, GPIO.IN)
GPIO.add_event_detect(gpio_int, GPIO.RISING, callback=self.__RfmIrq)
GPIO.add_event_detect(gpio_int, GPIO.RISING, callback=self.__rfm_irq)
self.__SetMode(MODE_STDBY)
self.__set_mode(MODE_STDBY)
config = {}
#SET DEFAULTS
@ -256,9 +255,9 @@ class RaspyRFM(threading.Thread):
config[RegPacketConfig1] = 0x00 #Fixed length, CRC off, no adr
for key in config:
self.__WriteReg(key, config[key])
self.__write_reg(key, config[key])
self.ModeStandBy()
self.mode_standby()
threading.Thread.__init__(self)
print("Init complete.")
@ -266,82 +265,82 @@ class RaspyRFM(threading.Thread):
while True:
time.sleep(0.5)
def __RfmIrq(self, ch):
def __rfm_irq(self, ch):
self.__event.set()
def __WriteReg(self, reg, val):
def __write_reg(self, reg, val):
temp = self.__spi.xfer2([(reg & 0x7F) | 0x80, val & 0xFF])
def __WriteRegWord(self, reg, val):
self.__WriteReg(reg, (val >> 8) & 0xFF)
self.__WriteReg(reg + 1, val & 0xFF)
def __write_reg_word(self, reg, val):
self.__write_reg(reg, (val >> 8) & 0xFF)
self.__write_reg(reg + 1, val & 0xFF)
def __SetReg(self, reg, mask, val):
temp = self.ReadReg(reg) & (~mask)
def __set_reg(self, reg, mask, val):
temp = self.read_reg(reg) & (~mask)
temp |= val & mask
self.__WriteReg(reg, temp)
self.__write_reg(reg, temp)
def __SetDioMapping(self, dio, mapping):
def __set_dio_mapping(self, dio, mapping):
if ((dio >= 0) and (dio <=3)):
self.__SetReg(RegDioMapping1, 0xC0 >> (dio * 2), mapping << (6 - dio * 2))
self.__set_reg(RegDioMapping1, 0xC0 >> (dio * 2), mapping << (6 - dio * 2))
elif (dio == 5):
self.__SetReg(RegDioMapping2, 0x03 << 4, mapping << 4)
self.__set_reg(RegDioMapping2, 0x03 << 4, mapping << 4)
def __SetMode(self, mode):
self.__WriteReg(RegOpMode, mode << 2)
def __set_mode(self, mode):
self.__write_reg(RegOpMode, mode << 2)
self.__mode = mode
while ((self.ReadReg(RegIrqFlags1) & (1<<7)) == 0):
while ((self.read_reg(RegIrqFlags1) & (1<<7)) == 0):
pass
def ReadReg(self, reg):
def read_reg(self, reg):
temp = self.__spi.xfer2([reg & 0x7F, 0x00])
return temp[1]
def ReadFifoBurst(self, len):
def read_fifo_burst(self, len):
temp = self.__spi.xfer2([0x00] + [0x00] * len)
return temp[1:]
def WriteFifoBurst(self, data):
def write_fifo_burst(self, data):
self.__spi.xfer2([0x80] + list(data))
def ReadRegWord(self, reg):
def read_reg_word(self, reg):
temp = self.__spi.xfer2([reg & 0x7F, 0x00, 0x00])
return (temp[1] << 8) | (temp[2])
def ReadRssiValue(self):
return self.ReadReg(RegRssiValue)
def read_rssi_value(self):
return self.read_reg(RegRssiValue)
def ModeStandBy(self):
self.__SetMode(MODE_STDBY)
def mode_standby(self):
self.__set_mode(MODE_STDBY)
def SetParams(self, **params):
def set_params(self, **params):
self.__mutex.acquire()
self.__event.set()
for key in params:
value = params[key]
if key == "Freq":
fword = int(round(value * 1E6 / FSTEP))
self.__WriteReg(RegFrfMsb, fword >> 16)
self.__WriteReg(RegFrfMid, fword >> 8)
self.__WriteReg(RegFrfLsb, fword)
self.__write_reg(RegFrfMsb, fword >> 16)
self.__write_reg(RegFrfMid, fword >> 8)
self.__write_reg(RegFrfLsb, fword)
elif key == "TXPower":
elif key == "TxPower":
pwr = int(value + 18)
self.__WriteReg(RegPaLevel, 0x80 | (pwr & 0x1F))
self.__write_reg(RegPaLevel, 0x80 | (pwr & 0x1F))
elif key == "Datarate":
rate = int(round(FXOSC / (value * 1000)))
self.__WriteRegWord(RegBitrateMsb, rate)
self.__write_reg_word(RegBitrateMsb, rate)
elif key == "Deviation":
dev = int(round(value * 1000 / FSTEP))
self.__WriteRegWord(RegFdevMsb, dev)
self.__write_reg_word(RegFdevMsb, dev)
elif key == "ModulationType":
self.__SetReg(RegDataModul, 0x18, value << 3)
self.__set_reg(RegDataModul, 0x18, value << 3)
elif key == "ModulationsShaping":
self.__SetReg(RegDataModul, 0x03, value)
elif key == "ModulationShaping":
self.__set_reg(RegDataModul, 0x03, value)
elif key == "SyncPattern":
conf = 0
@ -351,9 +350,9 @@ class RaspyRFM(threading.Thread):
conf |= 1<<7
else:
conf = 1<<6
self.__WriteReg(RegSyncConfig, conf)
self.__write_reg(RegSyncConfig, conf)
for i, d in enumerate(value):
self.__WriteReg(RegSyncValue1 + i, d)
self.__write_reg(RegSyncValue1 + i, d)
elif key == "Bandwidth":
RxBw = FXOSC / value / 1000 / 4
@ -364,7 +363,7 @@ class RaspyRFM(threading.Thread):
RxBw = RxBw / 4 - 4
RxBw = max(RxBw, 0)
m = int(RxBw)
self.__SetReg(RegRxBw, 0x1F, m<<3 | e)
self.__set_reg(RegRxBw, 0x1F, m<<3 | e)
elif key == "AfcBandwidth":
RxBw = FXOSC / value / 1000 / 4
@ -375,46 +374,46 @@ class RaspyRFM(threading.Thread):
RxBw = RxBw / 4 - 4
RxBw = max(RxBw, 0)
m = int(RxBw)
self.__SetReg(RegAfcBw, 0x1F, m<<3 | e)
self.__set_reg(RegAfcBw, 0x1F, m<<3 | e)
elif key == "Preamble":
self.__WriteRegWord(RegPreambleMsb, value)
self.__write_reg_word(RegPreambleMsb, value)
elif key == "LnaGain":
self.__SetReg(RegLna, 0x07, value)
self.__set_reg(RegLna, 0x07, value)
elif key == "RssiThresh":
th = -(value * 2)
self.__WriteReg(RegRssiThresh, th)
self.__write_reg(RegRssiThresh, th)
elif key == "Dagc":
self.__WriteReg(RegDagc, value)
self.__write_reg(RegDagc, value)
elif key == "AfcFei":
self.__WriteReg(RegAfcFei, value)
self.__write_reg(RegAfcFei, value)
elif key == "Callback":
self.__Callback = value
self.__callback = value
elif key == "DcFree":
self.__SetReg(RegPacketConfig1, 3<<5, value<<5)
self.__set_reg(RegPacketConfig1, 3<<5, value<<5)
elif key == "OokThreshType":
self.__SetReg(RegOokPeak, 3<<6, value<<6)
self.__set_reg(RegOokPeak, 3<<6, value<<6)
elif key == "OokFixedThresh":
self.__WriteReg(RegOokFix, value)
self.___write_reg(RegOokFix, value)
elif key == "OokPeakThreshDec":
self.__SetReg(RegOokPeak, 7<<0, value)
self.__set_reg(RegOokPeak, 7<<0, value)
else:
print("Unrecognized option >>" + key + "<<")
self.ModeStandBy();
self.mode_standby();
self.__mutex.release()
def __WaitInt(self):
def __wait_int(self):
self.__event.clear()
if GPIO.input(self.__gpio_int):
return
@ -422,7 +421,7 @@ class RaspyRFM(threading.Thread):
if GPIO.input(self.__gpio_int):
break
def WhitenHope(self, data):
def whiten_hope(self, data):
lfsr = 0x3fe
for i, d in enumerate(data):
data[i] = data[i] ^ ((lfsr >> 2) & 0xFF)
@ -433,7 +432,7 @@ class RaspyRFM(threading.Thread):
lfsr <<= 1
lfsr &= 0x3ff
def WhitenTI(self, data):
def whiten_ti(self, data):
lfsr = 0x1ff
for i, d in enumerate(data):
data[i] = data[i] ^ (lfsr & 0xFF)
@ -442,30 +441,30 @@ class RaspyRFM(threading.Thread):
lfsr |= 1<<9
lfsr >>= 1
def SendPacket(self, data):
def send_packet(self, data):
self.__mutex.acquire()
self.__event.set()
self.ModeStandBy()
self.mode_standby()
#flush FIFO
status = self.ReadReg(RegIrqFlags2)
status = self.read_reg(RegIrqFlags2)
while (status & 0x40 == 0x40):
self.ReadReg(RegFifo)
status = self.ReadReg(RegIrqFlags2)
self.read_reg(RegFifo)
status = self.read_reg(RegIrqFlags2)
self.__WriteReg(RegPayloadLength, 0) #unlimited length
self.__WriteReg(RegFifoThresh, 0x80 | self.__fifothresh) #start TX with 1st byte in FIFO
self.__SetDioMapping(0, DIO0_PM_SENT) #DIO0 -> PacketSent
self.__SetMode(MODE_TX)
self.__write_reg(RegPayloadLength, 0) #unlimited length
self.__write_reg(RegFifoThresh, 0x80 | self.__fifothresh) #start TX with 1st byte in FIFO
self.__set_dio_mapping(0, DIO0_PM_SENT) #DIO0 -> PacketSent
self.__set_mode(MODE_TX)
l = min(len(data), 64)
while True:
self.WriteFifoBurst(data[:l])
self.write_fifo_burst(data[:l])
data = data[l:]
if len(data) == 0:
break
while True:
status = self.ReadReg(RegIrqFlags2)
status = self.read_reg(RegIrqFlags2)
if (status & (1<<5)) == 0: #below fifothresh
l = min(len(data), self.__fifothresh)
break
@ -473,38 +472,38 @@ class RaspyRFM(threading.Thread):
l = 1
break
self.__WaitInt()
self.ModeStandBy()
self.__wait_int()
self.mode_standby()
self.__mutex.release()
def ReadFifoWait(self, length):
def read_fifo_wait(self, length):
ret = []
while length > 0:
flags = self.ReadReg(RegIrqFlags2)
flags = self.read_reg(RegIrqFlags2)
if ((flags & (1<<5)) != 0) and (length >= 32): #FIFO level?
ret += self.ReadFifoBurst(self.__fifothresh)
ret += self.read_fifo_burst(self.__fifothresh)
length -= self.__fifothresh
if (flags & (1<<6)) != 0: #FIFO not empty?
ret.append(self.ReadReg(RegFifo))
ret.append(self.read_reg(RegFifo))
length -= 1
return ret
def GetNoiseFloor(self):
self.__mutex.acquire()
#save values
rssithresh = self.ReadReg(RegRssiThresh)
ookthresh = self.ReadReg(RegOokFix)
sync = self.ReadReg(RegSyncConfig)
rssithresh = self.read_reg(RegRssiThresh)
ookthresh = self.read_reg(RegOokFix)
sync = self.read_reg(RegSyncConfig)
self.__WriteReg(RegRssiThresh, 240)
self.__WriteReg(RegSyncConfig, 1<<6) #no sync, always fill FIFO
self.__WriteReg(RegPayloadLength, 0) #unlimited length
self.__SetMode(MODE_RX)
self.__write_reg(RegRssiThresh, 240)
self.__write_reg(RegSyncConfig, 1<<6) #no sync, always fill FIFO
self.__write_reg(RegPayloadLength, 0) #unlimited length
self.__set_mode(MODE_RX)
thresh = 40
while True:
self.__WriteReg(RegOokFix, thresh)
self.__write_reg(RegOokFix, thresh)
for i in range(150):
b = self.ReadFifoWait()
b = self.read_fifo_wait()
if b != 0:
thresh += 1
break;
@ -512,47 +511,46 @@ class RaspyRFM(threading.Thread):
break;
#restore registers
self.__WriteReg(RegRssiThresh, rssithresh)
self.__WriteReg(RegOokFix, ookthresh)
self.__WriteReg(RegSyncConfig, sync)
self.ModeStandBy()
self.__write_reg(RegRssiThresh, rssithresh)
self.__write_reg(RegOokFix, ookthresh)
self.__write_reg(RegSyncConfig, sync)
self.mode_standby()
self.__mutex.release()
return thresh
def __StartRx(self):
self.__SetDioMapping(2, 1) #DIO2 -> DATA
def __start_rx(self):
self.__mutex.acquire()
while True:
self.__WriteReg(RegPayloadLength, 0) #unlimited length
self.__WriteReg(RegFifoThresh, self.__fifothresh)
self.__write_reg(RegPayloadLength, 0) #unlimited length
self.__write_reg(RegFifoThresh, self.__fifothresh)
if self.__syncsize > 0:
self.__SetDioMapping(0, DIO0_PM_SYNC) #DIO0 -> SyncAddress
self.__set_dio_mapping(0, DIO0_PM_SYNC) #DIO0 -> SyncAddress
else:
self.__SetDioMapping(0, DIO0_PM_RSSI) #DIO0 -> RSSI
self.__SetMode(MODE_RX)
self.__set_dio_mapping(0, DIO0_PM_RSSI) #DIO0 -> RSSI
self.__set_mode(MODE_RX)
self.__mutex.release()
self.__WaitInt()
self.__wait_int()
self.__mutex.acquire()
if self.__mode == MODE_RX:
break;
def StartRx(self, cb):
self.__StartRx()
def start_rx(self, cb):
self.__start_rx()
cb()
self.ModeStandBy()
self.mode_standby()
self.__mutex.release()
def ReceivePacket(self, length):
self.__StartRx()
result = self.ReadFifoWait(length)
def receive_packet(self, length):
self.__start_rx()
result = self.read_fifo_wait(length)
rssi = -self.ReadReg(RegRssiValue) / 2
afc = self.ReadReg(RegAfcMsb) << 8
afc = afc | self.ReadReg(RegAfcLsb)
rssi = -self.read_reg(RegRssiValue) / 2
afc = self.read_reg(RegAfcMsb) << 8
afc = afc | self.read_reg(RegAfcLsb)
if afc >= 0x8000:
afc = afc - 0x10000
self.ModeStandBy()
self.mode_standby()
self.__mutex.release()
return (result, rssi, afc)

View file

@ -2,12 +2,17 @@
import setuptools
setuptools.setup(
name="RaspyRFM",
name="raspyrfm",
version="1.1",
author="S. Seegel",
author_email="post@seegel-systeme.de",
description="Package for interfacing the RaspyRFM module",
packages=["RaspyRFM"],
keywords="RFM69 radio IOT wireless remote hope",
description="Package for interfacing the RaspyRFM radiomodule",
url="https://github.com/Phunkafizer/RaspyRFM",
project_urls={
"Examples": "https://www.seegel-systeme.de/2015/09/02/ein-funkmodul-fuer-den-raspberry-raspyrfm/"
},
packages=["raspyrfm"],
license="MIT",
zip_safe=False,
install_requires=[