# -*- coding: utf-8 -*- # Copyright (C) 2009 Donald L. Dietmeyer (dldietmeyer@charter.net) # Copyright (C) 2011 DF9DQ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. You may view a copy of the # GNU GPL at http://www.gnu.org/copyleft/gpl.html or Google GNU GPL. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # This driver is for the FiFi-SDR receiver. For more info visit # the website at http://o28.sischa.net/fifisdr/trac/wiki # If you want to use this hardware module, then specify it in your # .quisk_conf.py file with: # import quisk_hardware_fifisdr as quisk_hardware from quisk_hardware_model import Hardware as BaseHardware import usb # Provide USB access to Python # Ubuntu: load python-usb 0.4.1-ubuntu1 # Web: http://sourceforge.net/projects/pyusb/ USBDEV_VENDOR = 0x16C0 USBDEV_PRODUCT = 0x05DC VENDOR_NAME = "www.ov-lennestadt.de" PRODUCT_NAME = "FiFi-SDR" MULTIPLIER = 4 CONVERT_11_21 = 2097152.0 # 11.21 format CONVERT = MULTIPLIER * CONVERT_11_21 CONVERT_8_24 = 16777216.0 MEGA = 1000000.0 GET_VERSION = 0x00 SET_FREQ = 0x32 SET_XTAL_FREQ = 0x33 SET_STARTUP_FREQ = 0x34 GET_SUB_MULT = 0x39 GET_FREQ = 0x3A GET_STARTUP_FREQ = 0x3C GET_XTAL_FREQ = 0x3D SET_PTT = 0x50 GET_FIFI_EXTRA = 0xAB SET_FIFI_EXTRA = 0xAC EXTRA_READ_SVN_VERSION = 0 EXTRA_WRITE_PREAMP = 19 DEVICE2HOST = 0xC0 # Device to Host, Vendor, to Device HOST2DEVICE = 0x40 # Host to Device, Vendor, to Device class Hardware(BaseHardware): def __init__(self, app, conf): BaseHardware.__init__(self, app, conf) self.conf = conf self.frequency = 7e6 self.tune = self.frequency self.handle = None self.TUNEMAX = self.conf.sample_rate / 2 - 1000 self.looffset = 0 # LO offset (see GET_SUB_MULT command) self.rf_gain_labels = ('0 dB', '-6 dB') # 0/-6 dB switch in ADC def open(self): # Called once to open the Hardware for bus in usb.busses(): for dev in bus.devices: h = dev.open() if (dev.idVendor == USBDEV_VENDOR) and (dev.idProduct == USBDEV_PRODUCT): print("Connected to FiFi-SDR") self.handle = h self.looffset = self.getLoOffset() self.getStartup() self.getSoftrockVersion() self.getSvnVersion() self.frequency = self.getFrequency() self.tune = self.frequency + MULTIPLIER*12000 self.getXtal() return print("Can't open the FiFi-SDR") exit() def close(self): # Called once to close the Hardware self.handle = self.handle.reset() def ChangeFrequency(self, tune, vfo, source='', band='', event=None): # Change and return the tuning and VFO frequency in Hertz. The VFO frequency is the # frequency in the center of the display; that is, the RF frequency corresponding to an # audio frequency of zero Hertz. The tuning frequency is the RF frequency indicated by # the tuning line on the display, and is equivalent to the transmit frequency. The quisk # receive frequency is the tuning frequency plus the RIT (receive incremental tuning). # If your hardware will not change to the requested frequencies, return different # frequencies. # The source is a string indicating the source of the change: # BtnBand A band button # BtnUpDown The band Up/Down buttons # FreqEntry The user entered a frequency in the box # MouseBtn1 Left mouse button press # MouseBtn3 Right mouse button press # MouseMotion The user is dragging with the left button # MouseWheel The mouse wheel up/down # For "BtnBand", the string band is in the band argument. # For the mouse events, the handler event is in the event argument. # If you drag the cursor to the far left or right, # adapt the the center frequency by +/- 10 kHz. if abs(tune - vfo) >= self.TUNEMAX: if tune > vfo: vfo = vfo + 10000 tune = vfo + self.TUNEMAX - 10000 else: vfo = vfo - 10000 tune = vfo - self.TUNEMAX + 10000 self.tune = tune if vfo != self.frequency: self.frequency = vfo v = vfo / MEGA # Make it MHz vset = v + self.looffset # Account for the programmed offset if (vset >= 0.04) and (vset <= 200.0): try: n = self.handle.controlMsg(requestType = HOST2DEVICE, request = SET_FREQ, buffer = self.pack4(int(vset * CONVERT)), value=0, index=0, timeout=100) if (vset != v): print("LO set to %f MHz (real: %f MHz)" % (v, vset)) else: print("LO set to %f MHz" % v) except usb.USBError: print("FiFi-SDR communication error") exit() else: print("Desired frequency (%f) is out of range!" % vset) return 0, 0 return tune, self.frequency def pack1(self, integer): buf = '' int = integer for i in range(1): buf += chr(int & 0xff) int >>= 8 return buf def pack4(self, integer): buf = '' int = integer for i in range(4): buf += chr(int & 0xff) int >>= 8 return buf def ReturnFrequency(self): # Return the current tuning and VFO frequency. If neither have changed, # you can return (None, None). This is called at about 10 Hz by the main. # return (tune, vfo) # return changed frequencies return self.tune, self.frequency def ChangeMode(self, mode): # Change the tx/rx mode # mode is a string: "USB", "AM", etc. pass def ChangeBand(self, band): # Change the band # band is a string: "60", "40", "WWV", etc. pass def HeartBeat(self): # Called at about 10 Hz by the main pass def getFrequency(self): res = self.handle.controlMsg(requestType = DEVICE2HOST, request = GET_FREQ, buffer = 4, value=0, index=0, timeout=100) f = ((((((res[3]<<8) + res[2])<<8) + res[1])<<8) + res[0]) / CONVERT f = f - self.looffset print("LO frequency is %f MHz" % f) return int(f * MEGA) # In Hz def getStartup(self): res = self.handle.controlMsg(requestType = DEVICE2HOST, request = GET_STARTUP_FREQ, buffer = 4, value=0, index=0, timeout=100) f = ((((((res[3]<<8) + res[2])<<8) + res[1])<<8) + res[0]) / CONVERT print("Startup frequency is %f MHz" % f) return int(f * MEGA) # In Hz def getXtal(self): res = self.handle.controlMsg(requestType = DEVICE2HOST, request = GET_XTAL_FREQ, buffer = 4, value=0, index=0, timeout=100) f = ((((((res[3]<<8) + res[2])<<8) + res[1])<<8) + res[0]) / CONVERT_8_24 print("Crystal frequency is %f MHz" % f) return int(f * MEGA) # In Hz def getLoOffset(self): res = self.handle.controlMsg(requestType = DEVICE2HOST, request = GET_SUB_MULT, buffer = 8, value=0, index=0, timeout=100) sub = ((((((res[3]<<8) + res[2])<<8) + res[1])<<8) + res[0]) if (sub & 0x80000000): # Check int32 sign bit sub = sub - 0x100000000 sub = sub / CONVERT_11_21 sub = sub / MULTIPLIER print("LO offset is %f kHz" % (sub * 1000)) return sub def getSoftrockVersion(self): res = self.handle.controlMsg(requestType = DEVICE2HOST, request = GET_VERSION, buffer = 2, value=0, index=0, timeout=100) major = res[1] minor = res[0] print("Softrock compatibility version is %d.%d" % (major, minor)) return def getSvnVersion(self): try: res = self.handle.controlMsg(requestType = DEVICE2HOST, request = GET_FIFI_EXTRA, buffer = 4, value=0, index=EXTRA_READ_SVN_VERSION, timeout=100) svn = (((((res[3]<<8) + res[2])<<8) + res[1])<<8) + res[0] print("FiFi-SDR firmware version (SVN) is %d" % svn) return svn except usb.USBError: print("Cannot determine FiFi-SDR firmware version") return 0 def OnButtonRfGain(self, event, name=None): if event is not None: win = event.GetEventObject() name = win.GetLabel() value = -1 if name == '0 dB': value = 1 if name == '-6 dB': value = 0 if value >= 0: self.handle.controlMsg(requestType = HOST2DEVICE, request = SET_FIFI_EXTRA, buffer = self.pack1(int(value)), value=0, index=EXTRA_WRITE_PREAMP, timeout=100) return def OnButtonPTT(self, event): button = event.GetEventObject() if button.GetValue(): self.ptt = 1 else: self.ptt = 0 res = self.handle.controlMsg(requestType = DEVICE2HOST, request = SET_PTT, buffer = 2, value = self.ptt, index = 0, timeout = 100) return