kopia lustrzana https://github.com/projecthorus/wenet
Added RFM22B initialisation functions, fixed Ctrl-C exiting of test tx scripts.
rodzic
0e66fcc8ff
commit
0018fbcb4a
|
@ -14,6 +14,8 @@ from time import sleep
|
|||
from threading import Thread
|
||||
import numpy as np
|
||||
|
||||
# Alternate output module, which writes transmitted data as one-bit-per-char (i.e. 0 = 0x00, 1 = 0x01)
|
||||
# to a file. Very useful for debugging.
|
||||
class BinaryDebug(object):
|
||||
def __init__(self):
|
||||
self.f = open("debug.bin",'wb')
|
||||
|
@ -42,7 +44,7 @@ class PacketTX(object):
|
|||
|
||||
|
||||
def __init__(self,serial_port="/dev/ttyAMA0", serial_baud=115200, payload_length=256, debug = False):
|
||||
|
||||
# WARNING: 115200 baud is ACTUALLY 115386.834 baud, as measured using a freq counter.
|
||||
if debug == True:
|
||||
self.s = BinaryDebug()
|
||||
self.debug = True
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# RFM22B Initialisation for Horus High Speed Telemetry
|
||||
#
|
||||
# 2016-03-13 Mark Jessop <vk5qi@rfhead.net>
|
||||
#
|
||||
# A mash together of a few different libraries, including:
|
||||
# https://github.com/MaxBaex/raspi_rfm22
|
||||
# https://github.com/omcaree/rfm22b/blob/master/src/rfm22b.cpp
|
||||
#
|
||||
# Uses spidev for SPI comms.
|
||||
#
|
||||
# Note: This is fairly limited, and was only intended to get a RFM22B
|
||||
# into direct-async TX mode.
|
||||
# Lots of functions (i.e. anything to do with packets) are unimplemented.
|
||||
#
|
||||
# Electrical Connections:
|
||||
# GPIO0 <-> TX_ANT
|
||||
# GPIO1 <-> RX_ANT
|
||||
# SDN <-> GND (Not sure if this is a good thing, not being about to hard reset it..)
|
||||
# GPIO2 <-> UART TXD (for direct mode TX)
|
||||
# SPI - connected to CE1 (can change this when instantiating the object.)
|
||||
#
|
||||
|
||||
import spidev, sys, time
|
||||
|
||||
class REG:
|
||||
DEVICE_TYPE = 0x00
|
||||
DEVICE_VERSION = 0x01
|
||||
DEVICE_STATUS = 0x02
|
||||
INTERRUPT_STATUS_1 = 0x03
|
||||
INTERRUPT_STATUS_2 = 0x04
|
||||
INTERRUPT_ENABLE_1 = 0x05
|
||||
INTERRUPT_ENABLE_2 = 0x06
|
||||
OPERATING_FUNCTION_CONTROL_1 = 0x07
|
||||
OPERATING_FUNCTION_CONTROL_2 = 0x08
|
||||
CRYSTAL_OSCILLATOR_LOAD = 0x09
|
||||
MICROCONTROLLER_CLOCK_OUTPUT = 0x0A
|
||||
GPIO0_CONFIGURATION = 0x0B
|
||||
GPIO1_CONFIGURATION = 0x0C
|
||||
GPIO2_CONFIGURATION = 0x0D
|
||||
I_O_PORT_CONFIGURATION = 0x0E
|
||||
ADC_CONFIGURATION = 0x0F
|
||||
ADC_SENSOR_AMPLIFIER_OFFSET = 0x10
|
||||
ADC_VALUE = 0x11
|
||||
TEMPERATURE_SENSOR_CONTROL = 0x12
|
||||
TEMPERATURE_VALUE_OFFSET = 0x13
|
||||
WAKE_UP_TIMER_PERIOD_1 = 0x14
|
||||
WAKE_UP_TIMER_PERIOD_2 = 0x15
|
||||
WAKE_UP_TIMER_PERIOD_3 = 0x16
|
||||
WAKE_UP_TIMER_VALUE_1 = 0x17
|
||||
WAKE_UP_TIMER_VALUE_2 = 0x18
|
||||
LOW_DUTY_CYCLE_MODE_DURATION = 0x19
|
||||
LOW_BATTERY_DETECTION_THRESHOLD = 0x1A
|
||||
BATTERY_VOLTAGE_LEVEL = 0x1B
|
||||
IF_FILTER_BANDWIDTH = 0x1C
|
||||
AFC_LOOP_GEARSHIFT_OVERRIDE = 0x1D
|
||||
AFC_TIMING_CONTROL = 0x1E
|
||||
CLOCK_RECOVERY_GEARSHIFT_OVERRIDE = 0x1F
|
||||
CLOCK_RECOVERY_OVERSAMPLING_RATIO = 0x20
|
||||
CLOCK_RECOVERY_OFFSET_2 = 0x21
|
||||
CLOCK_RECOVERY_OFFSET_1 = 0x22
|
||||
CLOCK_RECOVERY_OFFSET_0 = 0x23
|
||||
CLOCK_RECOVERY_TIMING_LOOP_GAIN_1 = 0x24
|
||||
CLOCK_RECOVERY_TIMING_LOOP_GAIN_0 = 0x25
|
||||
RECEIVED_SIGNAL_STRENGTH_INDICATOR = 0x26
|
||||
RSSI_THRESSHOLF_FOR_CLEAR_CHANNEL_INDICATOR = 0x27
|
||||
ANTENNA_DIVERSITY_REGISTER_1 = 0x28
|
||||
ANTENNA_DIVERSITY_REGISTER_2 = 0x29
|
||||
AFC_LIMITER = 0x2A
|
||||
AFC_CORRECTION_READ = 0x2B
|
||||
OOK_COUNTER_VALUE_1 = 0x2C
|
||||
OOK_COUNTER_VALUE_2 = 0x2D
|
||||
SLICER_PEAK_HOLD = 0x2E
|
||||
# Register 0x2F reserved
|
||||
DATA_ACCESS_CONTROL = 0x30
|
||||
EzMAC_STATUS = 0x31
|
||||
HEADER_CONTROL_1 = 0x32
|
||||
HEADER_CONTROL_2 = 0x33
|
||||
PREAMBLE_LENGTH = 0x34
|
||||
PREAMBLE_DETECTION_CONTROL = 0x35
|
||||
SYNC_WORD_3 = 0x36
|
||||
SYNC_WORD_2 = 0x37
|
||||
SYNC_WORD_1 = 0x38
|
||||
SYNC_WORD_0 = 0x39
|
||||
TRANSMIT_HEADER_3 = 0x3A
|
||||
TRANSMIT_HEADER_2 = 0x3B
|
||||
TRANSMIT_HEADER_1 = 0x3C
|
||||
TRANSMIT_HEADER_0 = 0x3D
|
||||
TRANSMIT_PACKET_LENGTH = 0x3E
|
||||
CHECK_HEADER_3 = 0x3F
|
||||
CHECK_HEADER_2 = 0x40
|
||||
CHECK_HEADER_1 = 0x41
|
||||
CHECK_HEADER_0 = 0x42
|
||||
HEADER_ENABLE_3 = 0x43
|
||||
HEADER_ENABLE_2 = 0x44
|
||||
HEADER_ENABLE_1 = 0x45
|
||||
HEADER_ENABLE_0 = 0x46
|
||||
RECEIVED_HEADER_3 = 0x47
|
||||
RECEIVED_HEADER_2 = 0x48
|
||||
RECEIVED_HEADER_1 = 0x49
|
||||
RECEIVED_HEADER_0 = 0x4A
|
||||
RECEIVED_PACKET_LENGTH = 0x4B
|
||||
# Registers 0x4C-4E reserved
|
||||
ADC8_CONTROL = 0x4F
|
||||
# Registers 0x50-5F reserved
|
||||
CHANNEL_FILTER_COEFFICIENT_ADDRESS = 0x60
|
||||
# Register 0x61 reserved
|
||||
CRYSTAL_OSCILLATOR_CONTROL_TEST = 0x62
|
||||
# Registers 0x63-68 reserved
|
||||
AGC_OVERRIDE_1 = 0x69
|
||||
# Registers 0x6A-0x6C reserved
|
||||
TX_POWER = 0x6D
|
||||
TX_DATA_RATE_1 = 0x6E
|
||||
TX_DATA_RATE_0 = 0x6F
|
||||
MODULATION_MODE_CONTROL_1 = 0x70
|
||||
MODULATION_MODE_CONTROL_2 = 0x71
|
||||
FREQUENCY_DEVIATION = 0x72
|
||||
FREQUENCY_OFFSET_1 = 0x73
|
||||
FREQUENCY_OFFSET_2 = 0x74
|
||||
FREQUENCY_BAND_SELECT = 0x75
|
||||
NOMINAL_CARRIER_FREQUENCY_1 = 0x76
|
||||
NOMINAL_CARRIER_FREQUENCY_0 = 0x77
|
||||
# Register 0x78 reserved
|
||||
FREQUENCY_HOPPING_CHANNEL_SELECT = 0x79
|
||||
FREQUENCY_HOPPING_STEP_SIZE = 0x7A
|
||||
# Register 0x7B reserved
|
||||
TX_FIFO_CONTROL_1 = 0x7C
|
||||
TX_FIFO_CONTROL_2 = 0x7D
|
||||
RX_FIFO_CONTROL = 0x7E
|
||||
FIFO_ACCESS = 0x7F
|
||||
|
||||
class MODE:
|
||||
IDLE = 0
|
||||
RX = 1
|
||||
TX = 2
|
||||
|
||||
class TXPOW:
|
||||
TXPOW_1DBM = 0x00
|
||||
TXPOW_2DBM = 0x01
|
||||
TXPOW_5DBM = 0x02
|
||||
TXPOW_8DBM = 0x03
|
||||
TXPOW_11DBM = 0x04
|
||||
TXPOW_14DBM = 0x05
|
||||
TXPOW_17DBM = 0x06
|
||||
TXPOW_20DBM = 0x07
|
||||
|
||||
class CONFIGS:
|
||||
# Register: 1c, 1f, 20, 21, 22, 23, 24, 25, 2c, 2d, 2e, 58, 69, 6e, 6f, 70, 71, 72
|
||||
REGISTERS = [0x1C,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x2C,0x2D,0x2E,0x58,0x69,0x6E,0x6F,0x70,0x71,0x72]
|
||||
DIRECT_120K = [0x8a, 0x03, 0x60, 0x01, 0x55, 0x55, 0x02, 0xad, 0x40, 0x0a, 0x50, 0x80, 0x60, 0x20, 0x00, 0x00, 0x02, 0x60]
|
||||
|
||||
class RFM22B(object):
|
||||
|
||||
def __init__(self,device=1):
|
||||
self.spi = spidev.SpiDev()
|
||||
self.spi.open(0,device)
|
||||
|
||||
if not self.check_connection():
|
||||
print("Init Failed!")
|
||||
self.spi.close()
|
||||
sys.exit(1)
|
||||
|
||||
self.setup_basic()
|
||||
|
||||
print("Init Complete!")
|
||||
|
||||
def close(self):
|
||||
self.spi.close()
|
||||
|
||||
def read_register(self,address):
|
||||
return self.spi.xfer([address,0])[1]
|
||||
|
||||
def write_register(self,address,data):
|
||||
return self.spi.xfer([address | 0x80, data])
|
||||
|
||||
def check_connection(self):
|
||||
device_type = self.read_register(REG.DEVICE_TYPE)
|
||||
device_version = self.read_register(REG.DEVICE_VERSION)
|
||||
|
||||
print("Device Type:\t %d" % device_type)
|
||||
print("Device Version:\t %d" % device_version)
|
||||
|
||||
if (device_type != 8) or (device_version != 6):
|
||||
print("Wrong Device?!")
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
# 441.2E6 = HBSEL: 0 FB: 20 FBS: 84 FC: 7679 NCF1: 29, NCF0: 255
|
||||
def set_frequency(self, freq_hz):
|
||||
if (freq_hz<240E6) or (freq_hz>960E6):
|
||||
print("Invalid Frequency!")
|
||||
return False
|
||||
|
||||
hbsel = 1 if (freq_hz>= 480E6) else 0
|
||||
|
||||
fb = int(freq_hz/10E6/(hbsel+1) - 24)
|
||||
fbs = (1<<6) | (hbsel<<5) | fb
|
||||
fc = int((freq_hz/(10.0E6 * (hbsel+1)) - fb - 24) * 64000)
|
||||
|
||||
ncf1 = fc>>8
|
||||
ncf0 = fc & 0xFF
|
||||
|
||||
print("hbsel: %d, fb: %d, fbs: %d, fc: %d, ncf1: %d, ncf0: %d" % (hbsel,fb,fbs,fc,ncf1,ncf0))
|
||||
|
||||
self.write_register(REG.FREQUENCY_BAND_SELECT,fbs)
|
||||
self.write_register(REG.NOMINAL_CARRIER_FREQUENCY_1,ncf1)
|
||||
self.write_register(REG.NOMINAL_CARRIER_FREQUENCY_0,ncf0)
|
||||
|
||||
# Read back registers.
|
||||
fbs_read = self.read_register(REG.FREQUENCY_BAND_SELECT)
|
||||
ncf1_read = self.read_register(REG.NOMINAL_CARRIER_FREQUENCY_1)
|
||||
ncf0_read = self.read_register(REG.NOMINAL_CARRIER_FREQUENCY_0)
|
||||
|
||||
if (fbs == fbs_read) and (ncf1 == ncf1_read) and (ncf0 == ncf0_read):
|
||||
print("Frequency set OK!")
|
||||
return True
|
||||
else:
|
||||
print("Frequency not set correctly!")
|
||||
return False
|
||||
|
||||
def setup_basic(self):
|
||||
# Software reset.
|
||||
self.write_register(REG.OPERATING_FUNCTION_CONTROL_1,0x80)
|
||||
time.sleep(0.1)
|
||||
# Interrupts
|
||||
self.write_register(REG.INTERRUPT_ENABLE_1,0x87)
|
||||
# Switch to ready mode.
|
||||
self.write_register(REG.OPERATING_FUNCTION_CONTROL_1,0x01)
|
||||
self.write_register(REG.CRYSTAL_OSCILLATOR_LOAD,0x7f)
|
||||
# Configure GPIO 0 and 1 settings.
|
||||
self.write_register(REG.GPIO0_CONFIGURATION, 0x12) # TX State, physically wired into TX_ANT pin.
|
||||
self.write_register(REG.GPIO1_CONFIGURATION, 0x15) # RX State, physically wired into RX_ANT pin.
|
||||
|
||||
# Program a bulk set of registers.
|
||||
# I'm using this to set a bunch of different registers at one time, to load up pre-calculated configs.
|
||||
def set_bulk(self,registers,data):
|
||||
if len(registers) != len(data):
|
||||
print("Array length mismatch!")
|
||||
return False
|
||||
|
||||
for k in xrange(len(registers)):
|
||||
self.write_register(registers[k],data[k])
|
||||
|
||||
def set_tx_power(self,power):
|
||||
self.write_register(REG.TX_POWER,power)
|
||||
|
||||
def set_mode(self,mode):
|
||||
self.write_register(REG.OPERATING_FUNCTION_CONTROL_1,mode)
|
||||
|
||||
if __name__ == '__main__':
|
||||
rfm = RFM22B()
|
||||
rfm.set_tx_power(TXPOW.TXPOW_14DBM | 0x08)
|
||||
rfm.set_frequency(441.2E6)
|
||||
rfm.write_register(REG.GPIO2_CONFIGURATION,0x30) # TX Data In
|
||||
rfm.set_bulk(CONFIGS.REGISTERS,CONFIGS.DIRECT_120K)
|
||||
rfm.set_mode(0x09)
|
||||
rfm.close()
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Known bits Transmitter Script
|
||||
# Transmit a fixed packet repeatedly. Useful for BER testing.
|
||||
#
|
||||
# Mark Jessop <vk5qi@rfhead.net>
|
||||
#
|
||||
|
||||
import PacketTX, sys, os, time
|
||||
import numpy as np
|
||||
|
||||
payload = np.arange(0,256,1).astype(np.uint8).tostring() # 0->255
|
||||
|
||||
debug_output = False # If True, packet bits are saved to debug.bin as one char per bit.
|
||||
|
||||
|
||||
tx = PacketTX.PacketTX(debug=debug_output)
|
||||
tx.start_tx()
|
||||
|
||||
try:
|
||||
while True:
|
||||
tx.tx_packet(payload)
|
||||
except KeyboardInterrupt:
|
||||
tx.close()
|
||||
print("Closing")
|
|
@ -36,10 +36,13 @@ def transmit_file(filename, tx_object):
|
|||
|
||||
tx = PacketTX.PacketTX(debug=debug_output)
|
||||
tx.start_tx()
|
||||
|
||||
for img in image_numbers:
|
||||
filename = file_path % img
|
||||
print("\nTXing: %s" % filename)
|
||||
transmit_file(filename,tx)
|
||||
|
||||
tx.close()
|
||||
print("TX Started. Press Ctrl-C to stop.")
|
||||
try:
|
||||
while True:
|
||||
for img in image_numbers:
|
||||
filename = file_path % img
|
||||
print("\nTXing: %s" % filename)
|
||||
transmit_file(filename,tx)
|
||||
except KeyboardInterrupt:
|
||||
print("Closing...")
|
||||
tx.close()
|
||||
|
|
Ładowanie…
Reference in New Issue