Compare commits

...

15 Commits

Author SHA1 Message Date
Rob French f35984a5f6 Added README.md 2020-10-27 15:05:48 -05:00
Rob French 94267ab4b6 Added the hardware and widgets files (sadly, I
forgot to store their history).  Also, added
some hardware schematics showing the workings of
the interface hat for the CW key (and the key
line to the RS-HFIQ).
2020-10-27 14:57:47 -05:00
Rob French f8ccc3dd18 Added fix from: https://groups.io/g/n2adr-sdr/message/550?p=,,,20,0,0,0::Created,,bug+small+screen,20,2,0,72901711 2020-05-01 20:41:58 -05:00
Rob French a7975ab23f Fixed broken setup.py... again... 2020-04-29 23:24:27 -05:00
Rob French 2252cded4c Fixed setup.py to resolve merge conflict. 2020-04-29 22:44:01 -05:00
Rob French e2909d3c38 Updated to quisk-4.1.56. 2020-04-29 22:26:41 -05:00
Rob French 0c62afe3c8 Merge branch 'master' into kc4upr. Fixing a 4.1.55 merge issue. 2020-04-29 22:25:05 -05:00
Rob French 0da9087a5c Correctly updated to quisk-4.1.55 2020-04-29 22:23:47 -05:00
Rob French a52cd31615 Revert "Updated to quisk-4.1.55"
This reverts commit 742cc489ed.
2020-04-29 22:22:43 -05:00
Rob French 89c9a8b596 Revert "Updated to quisk-4.1.56."
This reverts commit c4f85f3262.
2020-04-29 22:22:14 -05:00
Rob French c4f85f3262 Updated to quisk-4.1.56. 2020-04-29 22:18:38 -05:00
Rob French 270b6863a6 Merge branch 'master' into kc4upr. Updating to quisk-4.1.55. 2020-04-29 22:15:57 -05:00
Rob French 742cc489ed Updated to quisk-4.1.55 2020-04-29 22:15:22 -05:00
Rob French eb4380695c Merge branch 'master' into kc4upr. Updating to quisk-4.1.54. 2020-04-29 22:10:33 -05:00
Rob French 65732f3d1a Updated local repository to 4.1.54 2020-04-29 22:09:06 -05:00
42 changed files with 4260 additions and 39 deletions

View File

@ -1,3 +1,24 @@
Quisk Version 4.1.56 April 2020
================================
For Linux, if the file /usr/include/portaudio.h is absent, portaudio will not be included in Quisk.
This change makes portaudio optional. The change was needed because portaudio breaks wine. Quisk now
restores the correct frequency for the 60 meter band. There were some other bug fixes.
Quisk Version 4.1.55 April 2020
================================
The new Sdr Micron radio was missing from the Windows version of Quisk. There are reports that the item
Hermes_BandDictTx is damaged in the quisk_settings.json file. Quisk will now fix this itself. The item is
the "Tx IO Bus" on the Hermes Bands configuration screen.
Quisk Version 4.1.54 March 2020
================================
There are now two new radios available in Quisk. David Fainitski contributed code for the Sdr Micron,
and Andrea Montefusco IW0HDV contributed code for the Perseus SDR. The radios should appear on the
list of supported radios in Config/Radios screen. Check the Config/radio/Hardware screen to see if you
need any more options. Please test these radios to make sure everything is working.
I added a general way to add new radios to the configuration screens. See docs.html under Custom Hardware.
Quisk Version 4.1.53 March 2020
================================
I changed the Afedri radio module to be compatible with Python3. The graph Zoom feature now is available
@ -8,7 +29,7 @@ noise floor such as PlutoSDR. You will have to readjust your waterfall colors.
I added a hardware setting for the LNA gain during transmit for the HL2. I made some changes to the CW
and PTT hardware interface for the HL2. These work great with the HL2, but test the new code if you have
diferent Hermes hardware such as Red Pitaya.
different Hermes hardware such as Red Pitaya.
Quisk Version 4.1.52 December 2019
===================================

View File

@ -7,4 +7,6 @@ graft n2adr
graft sdriqpkg
graft softrock
graft soapypkg
graft sdrmicronpkg
graft perseuspkg
global-exclude *.pyc

View File

@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: quisk
Version: 4.1.53
Version: 4.1.56
Summary: QUISK is a Software Defined Radio (SDR) transceiver that can control various radio hardware.
Home-page: http://james.ahlstrom.name/quisk/
Author: James C. Ahlstrom

8
README.md Normal file
View File

@ -0,0 +1,8 @@
NOTE: This project/branch is not actively maintained. I inadvertantly fried (at least) the final amp on my RS-HFIQ, and so until I can figure out how to repair that, I am not actively working on my Quisk branch.
Things that this code is intended to do:
- Provide control of the RS-HFIQ hardware (note, originally derived from other code; attribution in source).
- Provide a built-in iambic keyer with low latency, derived from the N1GP keyer. Use Raspberry Pi GPIO.
- Provide hardware keying (vs. serial keying) of the RS-HFIQ using the front panel connector (intended for min latency CW).
- Provide some additional UI elements (adjust keyer, adjust power, etc).

View File

@ -1 +1 @@
#Quisk version 4.1.53
#Quisk version 4.1.56

View File

@ -157,8 +157,16 @@ class Configuration:
try:
if fmt4 == 'text': # Note: JSON returns Unicode strings !!!
setattr(conf, k, v)
elif fmt4 in ('dict', 'list'):
setattr(conf, k, v)
elif fmt4 == 'dict':
if isinstance(v, dict):
setattr(conf, k, v)
else:
raise ValueError()
elif fmt4 == 'list':
if isinstance(v, list):
setattr(conf, k, v)
else:
raise ValueError()
elif fmt4 == 'inte':
setattr(conf, k, int(v, base=0))
elif fmt4 == 'numb':
@ -183,6 +191,8 @@ class Configuration:
else:
print ("Unknown format for", k, fmt)
except:
del radio_dict[k]
self.settings_changed = True
errors = errors + "Failed to set %s to %s using format %s\n" % (k, v, fmt)
#traceback.print_exc()
if conf.color_scheme == 'B':
@ -277,7 +287,7 @@ class Configuration:
def GetWidgets(self, app, hardware, conf, frame, gbs, vertBox): # Called fifth
if Settings[1] == "ConfigFileRadio":
return False
path = self.GetRadioDict()["widgets_file_name"]
path = self.GetRadioDict().get("widgets_file_name", '')
path = self.NormPath(path)
if os.path.isfile(path):
dct = {}
@ -448,13 +458,27 @@ class Configuration:
# Then some help text starting with "# "
# Then a list of possible value#explain with the default first
# Then a blank line to end.
self.format4name = {}
self.format4name['hardware_file_type'] = 'text'
self._ParserConf('quisk_conf_defaults.py')
# Read any user-defined radio types
for dirname in os.listdir('.'):
if not os.path.isdir(dirname) or dirname[-3:] != 'pkg':
continue
if dirname in ('freedvpkg', 'sdriqpkg', 'soapypkg'):
continue
filename = os.path.join(dirname, 'quisk_hardware.py')
if not os.path.isfile(filename):
continue
try:
self._ParserConf(filename)
except:
traceback.print_exc()
def _ParserConf(self, filename):
re_AeqB = re.compile("^#?(\w+)\s*=\s*([^#]+)#*(.*)") # item values "a = b"
section = None
data_name = None
fp = open("quisk_conf_defaults.py", "r")
fp = open(filename, "r")
for line in fp:
line = line.strip()
if not line:
@ -486,7 +510,7 @@ class Configuration:
value_list = []
if data_name in self.format4name:
if self.format4name[data_name] != fmt:
print ("Inconsistent format for", data_name, self.format4name[data_name], fmt)
print (filename, ": Inconsistent format for", data_name, self.format4name[data_name], fmt)
else:
self.format4name[data_name] = fmt
section_data.append([data_name, dspl, fmt, '', value_list])
@ -495,7 +519,7 @@ class Configuration:
mo = re_AeqB.match(line)
if mo:
if data_name != mo.group(1):
print ("Parse error for", data_name)
print (filename, ": Parse error for", data_name)
continue
value = mo.group(2).strip()
expln = mo.group(3).strip()
@ -1120,7 +1144,7 @@ class BaseWindow(wx.ScrolledWindow):
return ok
def EvalItem(self, value, fmt4): # Return Python integer, number, boolean, text
# return is (item_is_ok, evaluated_item)
if fmt4 in ('text', 'rfil'): # text items are always OK
if fmt4 not in ('inte', 'numb', 'bool'): # only certain formats are evaluated
return True, value
jj = value.find('#')
if jj > 0:
@ -1136,7 +1160,7 @@ class BaseWindow(wx.ScrolledWindow):
else:
v = False
else:
return False, None
raise ValueError
except:
dlg = wx.MessageDialog(None,
"Can not set item with format %s to value %s" % (fmt4, value),

View File

@ -50,6 +50,7 @@ div.contents {
<li><a href="#Configuration">Configuration</a></li>
<li><a href="#SoundCards">Sound Cards</a></li>
<li><a href="#SDRIQ">SDR-IQ</a></li>
<li><a href="#Perseus">Perseus</a></li>
<li><a href="#Timing">Timing</a></li>
<li><a href="#USBControl">USB Control</a></li>
<li><a href="#CustomHardware">Custom Hardware</a></li>
@ -80,6 +81,7 @@ complete transceiver. Quisk works with this hardware:
<li>SoftRock connected to the sound card</li>
<li>Many other SDR's connected to the sound card</li>
<li>SDR-IQ connected by USB</li>
<li>Perseus connected by USB</li>
<li>N2ADR hardware connected by Ethernet and IP</li>
<li>HiQSDR hardware connected by Ethernet and IP</li>
<li>The Hermes-Lite project at <a href="http://hermeslite.com">hermeslite.com</a></li>
@ -253,7 +255,7 @@ sudo apt-get install libfftw3-dev
<br>
sudo apt-get install libasound2-dev
<br>
sudo apt-get install portaudio19-dev
sudo apt-get install portaudio19-dev # Optional, if you want portaudio support
<br>
sudo apt-get install libpulse-dev
<br>
@ -449,7 +451,7 @@ _quisk.so and _quisk.pyd.
</ul>
<ul>
<li>sound_portaudio.c is the sound card access code for PortAudio. </li>
<li>sound_portaudio.c is the sound card access code for PortAudio. PortAudio is optional.</li>
</ul>
<ul>
@ -691,15 +693,9 @@ more information.
<br>
<br>
The
PortAudio
interface is newer, may be easier to get working, and may be used to
connect Quisk to other programs (I have not tried this). But for
CW, ALSA
has
lower latency. Run "python portaudio.py" in a terminal window to
see a list of available names, or use
a different PortAudio tool. Here are some PortAudio names:
The PortAudio interface is now optional. Many users are changing to PulseAudio.
You can run "python portaudio.py" in a terminal window to
see a list of available PortAudio names. Here are some PortAudio names:
<br>
<pre>"portaudio:(hw:0,0)" First sound card.
"portaudio:(hw:1,0)" Second sound card, etc.
@ -874,6 +870,35 @@ In earlier versions of Windows, port names are COM1, COM2 etc. and use the "USB
Windows should find this driver by itself.
</p>
<br>
<h2 id="Perseus">Perseus as Input </h2>
<p>
Quisk can use an Perseus HF receiver from Microtelecom instead of a sound card as input.
Set up a radio of type Perseus. The Perseus uses a native USB interface to connect to Quisk.
The Quisk perseuspkg extension relies on <a href="http://github.com/Microtelecom/libpserseus-sdr">libperseus-sdr</a>
open source library to manage Perseus hardware and receive the I/Q samples stream.
</p>
<br>
<p>
Follow the instruction into GitHub repository to compile and install the library.
On Suse distribution the library is available as binary package.
Next compile the perseuspkg using the command:
</p>
<br>
<pre>
make perseus3
</pre>
</br>
<p>
The several sample rates can be selected opening Config panel: in
the Config tab there is the Samples rates dropdown.
</p>
The input analog filter can be switched in using the button Wideband.<br>
The input attenuator is operate via the button RF, that allows to select
the four attenuator steps.<br>
The ADC commands for dithering and preamplifier are found on
left bottom corner as ADC Dither and ADC Preamp.<br>
</p>
<br>
<h2 id="Timing">Timing </h2>
<br>
There are several configuration parameters devoted to tuning; read the
@ -988,6 +1013,7 @@ can put code there to poll a serial port or to perform other
housekeeping functions (try to be efficient). The two remaining
functions deserve more documentation.
<br>
<br>
<h3 id="g0.8.1">ChangeFrequency(self, tune, vfo, source='', band='', event=None)</h3>
Quisk calls the ChangeFrequency() function when the user changes the Tx
frequency with a mouse click on the graph or waterfall, with the entry
@ -1117,6 +1143,29 @@ return the new frequencies from ReturnFrequency() or else Quisk will be
unaware of the change.
<br>
<br>
<h3 id="g0.8.3">Adding Custom Hardware to the Config/Radios Screen</h3>
Once you write your own hardware file for your custom hardware, you still need to add it to the
list of available radio types, and add its configuration options to its Config/radios/Hardware screen.
First create a subdirectory of the Quisk directory with a name ending in "pkg"; for example,
"myradiopkg". Then put your hardware file in this subdirectory with the name "quisk_hardware.py".
You will need at least one configuration option to specify the hardware file name.
Add this code (all comments) near the top of quisk_hardware.py:
<pre>
# Define the name of the hardware and the items on the hardware screen (see quisk_conf_defaults.py):
################ Receivers MyRadio, The special radio that I own
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'myradiopkg/quisk_hardware.py'
</pre>
Of course, change the names of the radio and subdirectory as appropriate. Your radio of general type "MyRadio"
will now appear in the list of radios on the Config/Radios screen, and its configuration items will appear
on the Config/radio/Hardware screen. You can add additional items. See quisk_conf_defaults.py and the *pkg
subdirectories for examples.
<br>
<br>
<h2 id="ExtensionPackages">Extension Packages </h2>
Quisk comes with two extension packages. The freedvpkg package

View File

@ -0,0 +1,286 @@
EESchema-LIBRARY Version 2.4
#encoding utf-8
#
# Connector_AudioJack3_Switch
#
DEF Connector_AudioJack3_Switch J 0 20 Y Y 1 F N
F0 "J" 0 450 50 H V C CNN
F1 "Connector_AudioJack3_Switch" 0 350 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Jack*
$ENDFPLIST
DRAW
S -200 -200 -250 -300 0 1 10 F
S 100 250 -200 -350 0 1 10 f
P 2 0 1 0 -50 190 -40 170 N
P 2 0 1 0 20 -10 30 -30 N
P 2 0 1 0 70 -210 80 -230 N
P 4 0 1 10 0 -200 25 -225 50 -200 100 -200 N
P 4 0 1 0 100 -300 70 -300 70 -210 60 -230 N
P 4 0 1 0 100 -100 20 -100 20 -10 10 -30 N
P 4 0 1 0 100 100 -50 100 -50 190 -60 170 N
P 5 0 1 10 -75 -200 -50 -225 -25 -200 -25 0 100 0 N
P 5 0 1 10 100 200 -100 200 -100 -200 -125 -225 -150 -200 N
X ~ R 200 0 100 L 50 50 1 1 P
X ~ RN 200 -100 100 L 50 50 1 1 P
X ~ S 200 200 100 L 50 50 1 1 P
X ~ SN 200 100 100 L 50 50 1 1 P
X ~ T 200 -200 100 L 50 50 1 1 P
X ~ TN 200 -300 100 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Connector_Generic_Conn_02x20_Odd_Even
#
DEF Connector_Generic_Conn_02x20_Odd_Even J 0 40 Y N 1 F N
F0 "J" 50 1000 50 H V C CNN
F1 "Connector_Generic_Conn_02x20_Odd_Even" 50 -1100 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Connector*:*_2x??_*
$ENDFPLIST
DRAW
S -50 -995 0 -1005 1 1 6 N
S -50 -895 0 -905 1 1 6 N
S -50 -795 0 -805 1 1 6 N
S -50 -695 0 -705 1 1 6 N
S -50 -595 0 -605 1 1 6 N
S -50 -495 0 -505 1 1 6 N
S -50 -395 0 -405 1 1 6 N
S -50 -295 0 -305 1 1 6 N
S -50 -195 0 -205 1 1 6 N
S -50 -95 0 -105 1 1 6 N
S -50 5 0 -5 1 1 6 N
S -50 105 0 95 1 1 6 N
S -50 205 0 195 1 1 6 N
S -50 305 0 295 1 1 6 N
S -50 405 0 395 1 1 6 N
S -50 505 0 495 1 1 6 N
S -50 605 0 595 1 1 6 N
S -50 705 0 695 1 1 6 N
S -50 805 0 795 1 1 6 N
S -50 905 0 895 1 1 6 N
S -50 950 150 -1050 1 1 10 f
S 150 -995 100 -1005 1 1 6 N
S 150 -895 100 -905 1 1 6 N
S 150 -795 100 -805 1 1 6 N
S 150 -695 100 -705 1 1 6 N
S 150 -595 100 -605 1 1 6 N
S 150 -495 100 -505 1 1 6 N
S 150 -395 100 -405 1 1 6 N
S 150 -295 100 -305 1 1 6 N
S 150 -195 100 -205 1 1 6 N
S 150 -95 100 -105 1 1 6 N
S 150 5 100 -5 1 1 6 N
S 150 105 100 95 1 1 6 N
S 150 205 100 195 1 1 6 N
S 150 305 100 295 1 1 6 N
S 150 405 100 395 1 1 6 N
S 150 505 100 495 1 1 6 N
S 150 605 100 595 1 1 6 N
S 150 705 100 695 1 1 6 N
S 150 805 100 795 1 1 6 N
S 150 905 100 895 1 1 6 N
X Pin_1 1 -200 900 150 R 50 50 1 1 P
X Pin_10 10 300 500 150 L 50 50 1 1 P
X Pin_11 11 -200 400 150 R 50 50 1 1 P
X Pin_12 12 300 400 150 L 50 50 1 1 P
X Pin_13 13 -200 300 150 R 50 50 1 1 P
X Pin_14 14 300 300 150 L 50 50 1 1 P
X Pin_15 15 -200 200 150 R 50 50 1 1 P
X Pin_16 16 300 200 150 L 50 50 1 1 P
X Pin_17 17 -200 100 150 R 50 50 1 1 P
X Pin_18 18 300 100 150 L 50 50 1 1 P
X Pin_19 19 -200 0 150 R 50 50 1 1 P
X Pin_2 2 300 900 150 L 50 50 1 1 P
X Pin_20 20 300 0 150 L 50 50 1 1 P
X Pin_21 21 -200 -100 150 R 50 50 1 1 P
X Pin_22 22 300 -100 150 L 50 50 1 1 P
X Pin_23 23 -200 -200 150 R 50 50 1 1 P
X Pin_24 24 300 -200 150 L 50 50 1 1 P
X Pin_25 25 -200 -300 150 R 50 50 1 1 P
X Pin_26 26 300 -300 150 L 50 50 1 1 P
X Pin_27 27 -200 -400 150 R 50 50 1 1 P
X Pin_28 28 300 -400 150 L 50 50 1 1 P
X Pin_29 29 -200 -500 150 R 50 50 1 1 P
X Pin_3 3 -200 800 150 R 50 50 1 1 P
X Pin_30 30 300 -500 150 L 50 50 1 1 P
X Pin_31 31 -200 -600 150 R 50 50 1 1 P
X Pin_32 32 300 -600 150 L 50 50 1 1 P
X Pin_33 33 -200 -700 150 R 50 50 1 1 P
X Pin_34 34 300 -700 150 L 50 50 1 1 P
X Pin_35 35 -200 -800 150 R 50 50 1 1 P
X Pin_36 36 300 -800 150 L 50 50 1 1 P
X Pin_37 37 -200 -900 150 R 50 50 1 1 P
X Pin_38 38 300 -900 150 L 50 50 1 1 P
X Pin_39 39 -200 -1000 150 R 50 50 1 1 P
X Pin_4 4 300 800 150 L 50 50 1 1 P
X Pin_40 40 300 -1000 150 L 50 50 1 1 P
X Pin_5 5 -200 700 150 R 50 50 1 1 P
X Pin_6 6 300 700 150 L 50 50 1 1 P
X Pin_7 7 -200 600 150 R 50 50 1 1 P
X Pin_8 8 300 600 150 L 50 50 1 1 P
X Pin_9 9 -200 500 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Device_C
#
DEF Device_C C 0 10 N Y 1 F N
F0 "C" 25 100 50 H V L CNN
F1 "Device_C" 25 -100 50 H V L CNN
F2 "" 38 -150 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
C_*
$ENDFPLIST
DRAW
P 2 0 1 20 -80 -30 80 -30 N
P 2 0 1 20 -80 30 80 30 N
X ~ 1 0 150 110 D 50 50 1 1 P
X ~ 2 0 -150 110 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Device_R_US
#
DEF Device_R_US R 0 0 N Y 1 F N
F0 "R" 100 0 50 V V C CNN
F1 "Device_R_US" -100 0 50 V V C CNN
F2 "" 40 -10 50 V I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
R_*
$ENDFPLIST
DRAW
P 2 0 1 0 0 -90 0 -100 N
P 2 0 1 0 0 90 0 100 N
P 5 0 1 0 0 -30 40 -45 0 -60 -40 -75 0 -90 N
P 5 0 1 0 0 30 40 15 0 0 -40 -15 0 -30 N
P 5 0 1 0 0 90 40 75 0 60 -40 45 0 30 N
X ~ 1 0 150 50 D 50 50 1 1 P
X ~ 2 0 -150 50 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# IO-Hat-rescue_Mounting_Hole-Mechanical
#
DEF IO-Hat-rescue_Mounting_Hole-Mechanical MK 0 40 Y Y 1 F N
F0 "MK" 0 200 50 H V C CNN
F1 "IO-Hat-rescue_Mounting_Hole-Mechanical" 0 125 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Mounting?Hole*
Hole*
$ENDFPLIST
DRAW
C 0 0 50 0 1 50 N
ENDDRAW
ENDDEF
#
# Isolator_LTV-847
#
DEF Isolator_LTV-847 U 0 40 Y Y 4 F N
F0 "U" -200 200 50 H V L CNN
F1 "Isolator_LTV-847" 0 200 50 H V L CNN
F2 "Package_DIP:DIP-16_W7.62mm" -200 -200 50 H I L CIN
F3 "" 0 0 50 H I L CNN
ALIAS LTV-847
$FPLIST
DIP*W7.62mm*
$ENDFPLIST
DRAW
S -200 150 200 -150 0 1 10 f
P 2 0 1 10 -125 -25 -75 -25 N
P 2 0 1 0 100 25 175 100 N
P 2 0 1 0 175 -100 100 -25 F
P 2 0 1 0 175 -100 200 -100 N
P 2 0 1 0 175 100 200 100 N
P 3 0 1 0 -100 -25 -100 -100 -200 -100 N
P 3 0 1 20 100 75 100 -75 100 -75 N
P 4 0 1 0 -200 100 -100 100 -100 -50 -100 25 N
P 4 0 1 10 -100 -25 -125 25 -75 25 -100 -25 N
P 5 0 1 0 -20 -20 30 -20 15 -25 15 -15 30 -20 N
P 5 0 1 0 -20 20 30 20 15 15 15 25 30 20 N
P 5 0 1 0 120 -65 140 -45 160 -85 120 -65 120 -65 F
X ~ 1 -300 100 100 R 50 50 1 1 P
X ~ 15 300 -100 100 L 50 50 1 1 P
X ~ 16 300 100 100 L 50 50 1 1 P
X ~ 2 -300 -100 100 R 50 50 1 1 P
X ~ 13 300 -100 100 L 50 50 2 1 P
X ~ 14 300 100 100 L 50 50 2 1 P
X ~ 3 -300 100 100 R 50 50 2 1 P
X ~ 4 -300 -100 100 R 50 50 2 1 P
X ~ 11 300 -100 100 L 50 50 3 1 P
X ~ 12 300 100 100 L 50 50 3 1 P
X ~ 5 -300 100 100 R 50 50 3 1 P
X ~ 6 -300 -100 100 R 50 50 3 1 P
X ~ 10 300 100 100 L 50 50 4 1 P
X ~ 7 -300 100 100 R 50 50 4 1 P
X ~ 8 -300 -100 100 R 50 50 4 1 P
X ~ 9 300 -100 100 L 50 50 4 1 P
ENDDRAW
ENDDEF
#
# power_+3.3V
#
DEF power_+3.3V #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -150 50 H I C CNN
F1 "power_+3.3V" 0 140 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
ALIAS +3.3V
DRAW
P 2 0 1 0 -30 50 0 100 N
P 2 0 1 0 0 0 0 100 N
P 2 0 1 0 0 100 30 50 N
X +3V3 1 0 0 0 U 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# power_+5V
#
DEF power_+5V #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -150 50 H I C CNN
F1 "power_+5V" 0 140 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
P 2 0 1 0 -30 50 0 100 N
P 2 0 1 0 0 0 0 100 N
P 2 0 1 0 0 100 30 50 N
X +5V 1 0 0 0 U 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# power_GND
#
DEF power_GND #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -250 50 H I C CNN
F1 "power_GND" 0 -150 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
X GND 1 0 0 0 D 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# power_GNDA
#
DEF power_GNDA #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -250 50 H I C CNN
F1 "power_GNDA" 0 -150 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
X GNDA 1 0 0 0 D 50 50 1 1 W N
ENDDRAW
ENDDEF
#
#End Library

View File

@ -0,0 +1,3 @@
EESchema-DOCLIB Version 2.0
#
#End Doc Library

View File

@ -0,0 +1,20 @@
EESchema-LIBRARY Version 2.4
#encoding utf-8
#
# Mounting_Hole-Mechanical
#
DEF Mounting_Hole-Mechanical MK 0 40 Y Y 1 F N
F0 "MK" 0 200 50 H V C CNN
F1 "Mounting_Hole-Mechanical" 0 125 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Mounting?Hole*
Hole*
$ENDFPLIST
DRAW
C 0 0 50 0 1 50 N
ENDDRAW
ENDDEF
#
#End Library

43
kc4upr/IO Hat/IO Hat.cmp Normal file
View File

@ -0,0 +1,43 @@
Cmp-Mod V01 Created by PcbNew date = Mon 04 Sep 2017 07:48:59 AM CDT
BeginCmp
TimeStamp = 580CBA7A
Path = /5834FB2E
Reference = MK1;
ValeurCmp = M2.5;
IdModule = Mounting_Holes:MountingHole_2-5mm;
EndCmp
BeginCmp
TimeStamp = 580CBAAE
Path = /5834FC19
Reference = MK2;
ValeurCmp = M2.5;
IdModule = Mounting_Holes:MountingHole_2-5mm;
EndCmp
BeginCmp
TimeStamp = 580CBAC8
Path = /5834FBEF
Reference = MK3;
ValeurCmp = M2.5;
IdModule = Mounting_Holes:MountingHole_2-5mm;
EndCmp
BeginCmp
TimeStamp = 580C7F66
Path = /580C18BB
Reference = P1;
ValeurCmp = CONN_02X20;
IdModule = Socket_Strips:Socket_Strip_Straight_2x20;
EndCmp
BeginCmp
TimeStamp = 580CBAD7
Path = /5834FC4F
Reference = MK4;
ValeurCmp = M2.5;
IdModule = Mounting_Holes:MountingHole_2-5mm;
EndCmp
EndListe

BIN
kc4upr/IO Hat/IO Hat.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

View File

@ -0,0 +1,424 @@
(kicad_pcb (version 20171130) (host pcbnew no-vcs-found-c6d0075~61~ubuntu16.04.1)
(general
(thickness 1.6)
(drawings 39)
(tracks 0)
(zones 0)
(modules 5)
(nets 32)
)
(page A3)
(title_block
(date "15 nov 2012")
)
(layers
(0 F.Cu signal)
(31 B.Cu signal)
(32 B.Adhes user)
(33 F.Adhes user)
(34 B.Paste user)
(35 F.Paste user)
(36 B.SilkS user)
(37 F.SilkS user)
(38 B.Mask user)
(39 F.Mask user)
(40 Dwgs.User user)
(41 Cmts.User user)
(42 Eco1.User user)
(43 Eco2.User user)
(44 Edge.Cuts user)
)
(setup
(last_trace_width 0.2)
(trace_clearance 0.2)
(zone_clearance 0.508)
(zone_45_only no)
(trace_min 0.1524)
(segment_width 0.1)
(edge_width 0.1)
(via_size 0.9)
(via_drill 0.6)
(via_min_size 0.8)
(via_min_drill 0.5)
(uvia_size 0.5)
(uvia_drill 0.1)
(uvias_allowed no)
(uvia_min_size 0.5)
(uvia_min_drill 0.1)
(pcb_text_width 0.3)
(pcb_text_size 1 1)
(mod_edge_width 0.15)
(mod_text_size 1 1)
(mod_text_width 0.15)
(pad_size 2.5 2.5)
(pad_drill 2.5)
(pad_to_mask_clearance 0)
(aux_axis_origin 200 150)
(grid_origin 200 150)
(visible_elements 7FFFFFFF)
(pcbplotparams
(layerselection 0x00030_80000001)
(usegerberextensions true)
(usegerberattributes false)
(usegerberadvancedattributes false)
(creategerberjobfile false)
(excludeedgelayer true)
(linewidth 0.150000)
(plotframeref false)
(viasonmask false)
(mode 1)
(useauxorigin false)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15)
(psnegative false)
(psa4output false)
(plotreference true)
(plotvalue true)
(plotinvisibletext false)
(padsonsilk false)
(subtractmaskfromsilk false)
(outputformat 1)
(mirror false)
(drillshape 1)
(scaleselection 1)
(outputdirectory ""))
)
(net 0 "")
(net 1 +3V3)
(net 2 +5V)
(net 3 GND)
(net 4 /ID_SD)
(net 5 /ID_SC)
(net 6 /GPIO5)
(net 7 /GPIO6)
(net 8 /GPIO26)
(net 9 "/GPIO2(SDA1)")
(net 10 "/GPIO3(SCL1)")
(net 11 "/GPIO4(GCLK)")
(net 12 "/GPIO14(TXD0)")
(net 13 "/GPIO15(RXD0)")
(net 14 "/GPIO17(GEN0)")
(net 15 "/GPIO27(GEN2)")
(net 16 "/GPIO22(GEN3)")
(net 17 "/GPIO23(GEN4)")
(net 18 "/GPIO24(GEN5)")
(net 19 "/GPIO25(GEN6)")
(net 20 "/GPIO18(GEN1)(PWM0)")
(net 21 "/GPIO10(SPI0_MOSI)")
(net 22 "/GPIO9(SPI0_MISO)")
(net 23 "/GPIO11(SPI0_SCK)")
(net 24 "/GPIO8(SPI0_CE_N)")
(net 25 "/GPIO7(SPI1_CE_N)")
(net 26 "/GPIO12(PWM0)")
(net 27 "/GPIO13(PWM1)")
(net 28 "/GPIO19(SPI1_MISO)")
(net 29 /GPIO16)
(net 30 "/GPIO20(SPI1_MOSI)")
(net 31 "/GPIO21(SPI1_SCK)")
(net_class Default "This is the default net class."
(clearance 0.2)
(trace_width 0.2)
(via_dia 0.9)
(via_drill 0.6)
(uvia_dia 0.5)
(uvia_drill 0.1)
(add_net +3V3)
(add_net +5V)
(add_net "/GPIO10(SPI0_MOSI)")
(add_net "/GPIO11(SPI0_SCK)")
(add_net "/GPIO12(PWM0)")
(add_net "/GPIO13(PWM1)")
(add_net "/GPIO14(TXD0)")
(add_net "/GPIO15(RXD0)")
(add_net /GPIO16)
(add_net "/GPIO17(GEN0)")
(add_net "/GPIO18(GEN1)(PWM0)")
(add_net "/GPIO19(SPI1_MISO)")
(add_net "/GPIO2(SDA1)")
(add_net "/GPIO20(SPI1_MOSI)")
(add_net "/GPIO21(SPI1_SCK)")
(add_net "/GPIO22(GEN3)")
(add_net "/GPIO23(GEN4)")
(add_net "/GPIO24(GEN5)")
(add_net "/GPIO25(GEN6)")
(add_net /GPIO26)
(add_net "/GPIO27(GEN2)")
(add_net "/GPIO3(SCL1)")
(add_net "/GPIO4(GCLK)")
(add_net /GPIO5)
(add_net /GPIO6)
(add_net "/GPIO7(SPI1_CE_N)")
(add_net "/GPIO8(SPI0_CE_N)")
(add_net "/GPIO9(SPI0_MISO)")
(add_net /ID_SC)
(add_net /ID_SD)
(add_net GND)
)
(net_class Power ""
(clearance 0.2)
(trace_width 0.5)
(via_dia 1)
(via_drill 0.7)
(uvia_dia 0.5)
(uvia_drill 0.1)
)
(module Connector_PinSocket_2.54mm:PinSocket_2x20_P2.54mm_Vertical (layer B.Cu) (tedit 5A19A433) (tstamp 5A793E9F)
(at 208.37 98.77 270)
(descr "Through hole straight socket strip, 2x20, 2.54mm pitch, double cols (from Kicad 4.0.7), script generated")
(tags "Through hole socket strip THT 2x20 2.54mm double row")
(path /59AD464A)
(fp_text reference P1 (at 2.208 1.512) (layer B.SilkS)
(effects (font (size 1 1) (thickness 0.15)) (justify mirror))
)
(fp_text value Conn_02x20_Odd_Even (at -1.27 -51.03 270) (layer B.Fab)
(effects (font (size 1 1) (thickness 0.15)) (justify mirror))
)
(fp_line (start -3.81 1.27) (end 0.27 1.27) (layer B.Fab) (width 0.1))
(fp_line (start 0.27 1.27) (end 1.27 0.27) (layer B.Fab) (width 0.1))
(fp_line (start 1.27 0.27) (end 1.27 -49.53) (layer B.Fab) (width 0.1))
(fp_line (start 1.27 -49.53) (end -3.81 -49.53) (layer B.Fab) (width 0.1))
(fp_line (start -3.81 -49.53) (end -3.81 1.27) (layer B.Fab) (width 0.1))
(fp_line (start -3.87 1.33) (end -1.27 1.33) (layer B.SilkS) (width 0.12))
(fp_line (start -3.87 1.33) (end -3.87 -49.59) (layer B.SilkS) (width 0.12))
(fp_line (start -3.87 -49.59) (end 1.33 -49.59) (layer B.SilkS) (width 0.12))
(fp_line (start 1.33 -1.27) (end 1.33 -49.59) (layer B.SilkS) (width 0.12))
(fp_line (start -1.27 -1.27) (end 1.33 -1.27) (layer B.SilkS) (width 0.12))
(fp_line (start -1.27 1.33) (end -1.27 -1.27) (layer B.SilkS) (width 0.12))
(fp_line (start 1.33 1.33) (end 1.33 0) (layer B.SilkS) (width 0.12))
(fp_line (start 0 1.33) (end 1.33 1.33) (layer B.SilkS) (width 0.12))
(fp_line (start -4.34 1.8) (end 1.76 1.8) (layer B.CrtYd) (width 0.05))
(fp_line (start 1.76 1.8) (end 1.76 -50) (layer B.CrtYd) (width 0.05))
(fp_line (start 1.76 -50) (end -4.34 -50) (layer B.CrtYd) (width 0.05))
(fp_line (start -4.34 -50) (end -4.34 1.8) (layer B.CrtYd) (width 0.05))
(fp_text user %R (at -1.27 -24.13 180) (layer B.Fab)
(effects (font (size 1 1) (thickness 0.15)) (justify mirror))
)
(pad 1 thru_hole rect (at 0 0 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 1 +3V3))
(pad 2 thru_hole oval (at -2.54 0 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 2 +5V))
(pad 3 thru_hole oval (at 0 -2.54 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 9 "/GPIO2(SDA1)"))
(pad 4 thru_hole oval (at -2.54 -2.54 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 2 +5V))
(pad 5 thru_hole oval (at 0 -5.08 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 10 "/GPIO3(SCL1)"))
(pad 6 thru_hole oval (at -2.54 -5.08 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 GND))
(pad 7 thru_hole oval (at 0 -7.62 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 11 "/GPIO4(GCLK)"))
(pad 8 thru_hole oval (at -2.54 -7.62 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 12 "/GPIO14(TXD0)"))
(pad 9 thru_hole oval (at 0 -10.16 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 GND))
(pad 10 thru_hole oval (at -2.54 -10.16 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 13 "/GPIO15(RXD0)"))
(pad 11 thru_hole oval (at 0 -12.7 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 14 "/GPIO17(GEN0)"))
(pad 12 thru_hole oval (at -2.54 -12.7 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 20 "/GPIO18(GEN1)(PWM0)"))
(pad 13 thru_hole oval (at 0 -15.24 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 15 "/GPIO27(GEN2)"))
(pad 14 thru_hole oval (at -2.54 -15.24 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 GND))
(pad 15 thru_hole oval (at 0 -17.78 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 16 "/GPIO22(GEN3)"))
(pad 16 thru_hole oval (at -2.54 -17.78 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 17 "/GPIO23(GEN4)"))
(pad 17 thru_hole oval (at 0 -20.32 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 1 +3V3))
(pad 18 thru_hole oval (at -2.54 -20.32 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 18 "/GPIO24(GEN5)"))
(pad 19 thru_hole oval (at 0 -22.86 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 21 "/GPIO10(SPI0_MOSI)"))
(pad 20 thru_hole oval (at -2.54 -22.86 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 GND))
(pad 21 thru_hole oval (at 0 -25.4 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 22 "/GPIO9(SPI0_MISO)"))
(pad 22 thru_hole oval (at -2.54 -25.4 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 19 "/GPIO25(GEN6)"))
(pad 23 thru_hole oval (at 0 -27.94 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 23 "/GPIO11(SPI0_SCK)"))
(pad 24 thru_hole oval (at -2.54 -27.94 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 24 "/GPIO8(SPI0_CE_N)"))
(pad 25 thru_hole oval (at 0 -30.48 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 GND))
(pad 26 thru_hole oval (at -2.54 -30.48 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 25 "/GPIO7(SPI1_CE_N)"))
(pad 27 thru_hole oval (at 0 -33.02 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 4 /ID_SD))
(pad 28 thru_hole oval (at -2.54 -33.02 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 5 /ID_SC))
(pad 29 thru_hole oval (at 0 -35.56 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 6 /GPIO5))
(pad 30 thru_hole oval (at -2.54 -35.56 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 GND))
(pad 31 thru_hole oval (at 0 -38.1 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 7 /GPIO6))
(pad 32 thru_hole oval (at -2.54 -38.1 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 26 "/GPIO12(PWM0)"))
(pad 33 thru_hole oval (at 0 -40.64 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 27 "/GPIO13(PWM1)"))
(pad 34 thru_hole oval (at -2.54 -40.64 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 GND))
(pad 35 thru_hole oval (at 0 -43.18 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 28 "/GPIO19(SPI1_MISO)"))
(pad 36 thru_hole oval (at -2.54 -43.18 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 29 /GPIO16))
(pad 37 thru_hole oval (at 0 -45.72 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 8 /GPIO26))
(pad 38 thru_hole oval (at -2.54 -45.72 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 30 "/GPIO20(SPI1_MOSI)"))
(pad 39 thru_hole oval (at 0 -48.26 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 GND))
(pad 40 thru_hole oval (at -2.54 -48.26 270) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 31 "/GPIO21(SPI1_SCK)"))
(model ${KISYS3DMOD}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_2x20_P2.54mm_Vertical.wrl
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(module MountingHole:MountingHole_2.7mm_M2.5 (layer F.Cu) (tedit 56D1B4CB) (tstamp 5A793E98)
(at 261.5 146.5)
(descr "Mounting Hole 2.7mm, no annular, M2.5")
(tags "mounting hole 2.7mm no annular m2.5")
(path /5834FC4F)
(attr virtual)
(fp_text reference MK4 (at 0 -3.7) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value M2.5 (at 0 3.7) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 2.95 0) (layer F.CrtYd) (width 0.05))
(fp_circle (center 0 0) (end 2.7 0) (layer Cmts.User) (width 0.15))
(fp_text user %R (at 0.3 0) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 np_thru_hole circle (at 0 0) (size 2.7 2.7) (drill 2.7) (layers *.Cu *.Mask))
)
(module MountingHole:MountingHole_2.7mm_M2.5 (layer F.Cu) (tedit 56D1B4CB) (tstamp 5A793E91)
(at 203.5 146.5)
(descr "Mounting Hole 2.7mm, no annular, M2.5")
(tags "mounting hole 2.7mm no annular m2.5")
(path /5834FBEF)
(attr virtual)
(fp_text reference MK3 (at 0 -3.7) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value M2.5 (at 0 3.7) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text user %R (at 0.3 0) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 2.7 0) (layer Cmts.User) (width 0.15))
(fp_circle (center 0 0) (end 2.95 0) (layer F.CrtYd) (width 0.05))
(pad 1 np_thru_hole circle (at 0 0) (size 2.7 2.7) (drill 2.7) (layers *.Cu *.Mask))
)
(module MountingHole:MountingHole_2.7mm_M2.5 (layer F.Cu) (tedit 56D1B4CB) (tstamp 5A793E8A)
(at 261.5 97.5 180)
(descr "Mounting Hole 2.7mm, no annular, M2.5")
(tags "mounting hole 2.7mm no annular m2.5")
(path /5834FC19)
(attr virtual)
(fp_text reference MK2 (at 0 -3.7 180) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value M2.5 (at 0 3.7 180) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 2.95 0) (layer F.CrtYd) (width 0.05))
(fp_circle (center 0 0) (end 2.7 0) (layer Cmts.User) (width 0.15))
(fp_text user %R (at 0.3 0 180) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 np_thru_hole circle (at 0 0 180) (size 2.7 2.7) (drill 2.7) (layers *.Cu *.Mask))
)
(module MountingHole:MountingHole_2.7mm_M2.5 (layer F.Cu) (tedit 56D1B4CB) (tstamp 5A793E83)
(at 203.5 97.5 180)
(descr "Mounting Hole 2.7mm, no annular, M2.5")
(tags "mounting hole 2.7mm no annular m2.5")
(path /5834FB2E)
(attr virtual)
(fp_text reference MK1 (at 0 -3.7 180) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value M2.5 (at 0 3.7 180) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text user %R (at 0.3 0 180) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 2.7 0) (layer Cmts.User) (width 0.15))
(fp_circle (center 0 0) (end 2.95 0) (layer F.CrtYd) (width 0.05))
(pad 1 np_thru_hole circle (at 0 0 180) (size 2.7 2.7) (drill 2.7) (layers *.Cu *.Mask))
)
(gr_line (start 244 146) (end 244 131) (layer Edge.Cuts) (width 0.1))
(gr_line (start 246 131) (end 246 146) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 245 131) (end 244 131) (angle 180) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 245 146) (end 246 146) (angle 180) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 200.5 131) (end 200 131) (angle 89.9) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 204.5 130) (end 205 130) (angle 90) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 200.5 113) (end 200.5 113.5) (angle 90) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 204.5 114) (end 204.5 113.5) (angle 90) (layer Edge.Cuts) (width 0.1))
(gr_line (start 200 113) (end 200 131) (layer Dwgs.User) (width 0.1))
(gr_line (start 200 97) (end 200 113) (layer Edge.Cuts) (width 0.1))
(gr_text DISPLAY (at 202.5 122 90) (layer Dwgs.User) (tstamp 580CBBFF)
(effects (font (size 1 1) (thickness 0.15)))
)
(gr_text CAMERA (at 245 139 90) (layer Dwgs.User)
(effects (font (size 1 1) (thickness 0.15)))
)
(gr_text RJ45 (at 276.2 139.84) (layer Dwgs.User) (tstamp 580CBBEB)
(effects (font (size 2 2) (thickness 0.15)))
)
(gr_text USB (at 277.724 121.552) (layer Dwgs.User) (tstamp 580CBBE9)
(effects (font (size 2 2) (thickness 0.15)))
)
(gr_text USB (at 278.232 102.248) (layer Dwgs.User)
(effects (font (size 2 2) (thickness 0.15)))
)
(gr_arc (start 262 97) (end 262 94) (angle 90) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 262 147) (end 265 147) (angle 90) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 203 147) (end 203 150) (angle 90) (layer Edge.Cuts) (width 0.1))
(gr_arc (start 203 97) (end 200 97) (angle 90) (layer Edge.Cuts) (width 0.1))
(gr_line (start 269.9 114.45) (end 287 114.45) (layer Dwgs.User) (width 0.1))
(gr_line (start 262 94) (end 203 94) (layer Edge.Cuts) (width 0.1))
(gr_line (start 269.9 127.55) (end 269.9 114.45) (layer Dwgs.User) (width 0.1))
(gr_line (start 287 127.55) (end 269.9 127.55) (layer Dwgs.User) (width 0.1))
(gr_line (start 287 114.45) (end 287 127.55) (layer Dwgs.User) (width 0.1))
(gr_line (start 204.5 130.5) (end 200.5 130.5) (layer Edge.Cuts) (width 0.1))
(gr_line (start 205 114) (end 205 130) (layer Edge.Cuts) (width 0.1))
(gr_line (start 200.5 113.5) (end 204.5 113.5) (layer Edge.Cuts) (width 0.1))
(gr_line (start 266 147.675) (end 266 131.825) (layer Dwgs.User) (width 0.1))
(gr_line (start 287 147.675) (end 266 147.675) (layer Dwgs.User) (width 0.1))
(gr_line (start 287 131.825) (end 287 147.675) (layer Dwgs.User) (width 0.1))
(gr_line (start 266 131.825) (end 287 131.825) (layer Dwgs.User) (width 0.1))
(gr_line (start 265 147) (end 265 97) (layer Edge.Cuts) (width 0.1))
(gr_line (start 203 150) (end 262 150) (layer Edge.Cuts) (width 0.1))
(gr_line (start 200 131) (end 200 147) (layer Edge.Cuts) (width 0.1))
(gr_line (start 269.9 109.455925) (end 269.9 96.355925) (layer Dwgs.User) (width 0.1))
(gr_line (start 287 109.455925) (end 269.9 109.455925) (layer Dwgs.User) (width 0.1))
(gr_line (start 287 96.355925) (end 287 109.455925) (layer Dwgs.User) (width 0.1))
(gr_line (start 269.9 96.355925) (end 287 96.355925) (layer Dwgs.User) (width 0.1))
(gr_text "RASPBERRY-PI 40-PIN ADDON BOARD\nVIEW FROM TOP\nNOTE: P1 SHOULD BE FITTED ON THE REVERSE OF THE BOARD\n\nADD EDGE CUTS FROM CAMERA AND DISPLAY PORTS AS REQUIRED" (at 200 160.16) (layer Dwgs.User)
(effects (font (size 2 1.7) (thickness 0.12)) (justify left))
)
)

152
kc4upr/IO Hat/IO Hat.net Normal file
View File

@ -0,0 +1,152 @@
(export (version D)
(design
(source /home/ashton/repo/kicad-library/template/raspberrypi-gpio-40pin/raspberrypi-gpio-40pin.sch)
(date "Mon 04 Sep 2017 07:54:14 AM CDT")
(tool "Eeschema (2017-02-21 revision 35a8d78)-master")
(sheet (number 1) (name /) (tstamps /)
(title_block
(title)
(company)
(rev)
(date "15 nov 2012")
(source raspberrypi-gpio-40pin.sch)
(comment (number 1) (value ""))
(comment (number 2) (value ""))
(comment (number 3) (value ""))
(comment (number 4) (value "")))))
(components
(comp (ref P1)
(value Conn_02x20_Odd_Even)
(libsource (lib conn) (part Conn_02x20_Odd_Even))
(sheetpath (names /) (tstamps /))
(tstamp 59AD464A)))
(libparts
(libpart (lib conn) (part Conn_02x20_Odd_Even)
(description "Generic connector, double row, 02x20, odd/even pin numbering scheme (row 1 odd numbers, row 2 even numbers)")
(docs ~)
(footprints
(fp Connector*:*2x??x*mm*)
(fp Connector*:*2x???Pitch*)
(fp Pin_Header_Straight_2X*)
(fp Pin_Header_Angled_2X*)
(fp Socket_Strip_Straight_2X*)
(fp Socket_Strip_Angled_2X*))
(fields
(field (name Reference) J)
(field (name Value) Conn_02x20_Odd_Even))
(pins
(pin (num 1) (name Pin_1) (type passive))
(pin (num 2) (name Pin_2) (type passive))
(pin (num 3) (name Pin_3) (type passive))
(pin (num 4) (name Pin_4) (type passive))
(pin (num 5) (name Pin_5) (type passive))
(pin (num 6) (name Pin_6) (type passive))
(pin (num 7) (name Pin_7) (type passive))
(pin (num 8) (name Pin_8) (type passive))
(pin (num 9) (name Pin_9) (type passive))
(pin (num 10) (name Pin_10) (type passive))
(pin (num 11) (name Pin_11) (type passive))
(pin (num 12) (name Pin_12) (type passive))
(pin (num 13) (name Pin_13) (type passive))
(pin (num 14) (name Pin_14) (type passive))
(pin (num 15) (name Pin_15) (type passive))
(pin (num 16) (name Pin_16) (type passive))
(pin (num 17) (name Pin_17) (type passive))
(pin (num 18) (name Pin_18) (type passive))
(pin (num 19) (name Pin_19) (type passive))
(pin (num 20) (name Pin_20) (type passive))
(pin (num 21) (name Pin_21) (type passive))
(pin (num 22) (name Pin_22) (type passive))
(pin (num 23) (name Pin_23) (type passive))
(pin (num 24) (name Pin_24) (type passive))
(pin (num 25) (name Pin_25) (type passive))
(pin (num 26) (name Pin_26) (type passive))
(pin (num 27) (name Pin_27) (type passive))
(pin (num 28) (name Pin_28) (type passive))
(pin (num 29) (name Pin_29) (type passive))
(pin (num 30) (name Pin_30) (type passive))
(pin (num 31) (name Pin_31) (type passive))
(pin (num 32) (name Pin_32) (type passive))
(pin (num 33) (name Pin_33) (type passive))
(pin (num 34) (name Pin_34) (type passive))
(pin (num 35) (name Pin_35) (type passive))
(pin (num 36) (name Pin_36) (type passive))
(pin (num 37) (name Pin_37) (type passive))
(pin (num 38) (name Pin_38) (type passive))
(pin (num 39) (name Pin_39) (type passive))
(pin (num 40) (name Pin_40) (type passive)))))
(libraries
(library (logical conn)
(uri /home/ashton/repo/kicad-library/library/conn.lib)))
(nets
(net (code 1) (name "/GPIO4(GCLK)")
(node (ref P1) (pin 7)))
(net (code 2) (name "/GPIO3(SCL1)")
(node (ref P1) (pin 5)))
(net (code 3) (name +5V)
(node (ref P1) (pin 2))
(node (ref P1) (pin 4)))
(net (code 4) (name "/GPIO2(SDA1)")
(node (ref P1) (pin 3)))
(net (code 5) (name +3V3)
(node (ref P1) (pin 1))
(node (ref P1) (pin 17)))
(net (code 6) (name "/GPIO14(TXD0)")
(node (ref P1) (pin 8)))
(net (code 7) (name "/GPIO15(RXD0)")
(node (ref P1) (pin 10)))
(net (code 8) (name "/GPIO21(SPI1_SCK)")
(node (ref P1) (pin 40)))
(net (code 9) (name /GPIO5)
(node (ref P1) (pin 29)))
(net (code 10) (name "/GPIO20(SPI1_MOSI)")
(node (ref P1) (pin 38)))
(net (code 11) (name /ID_SC)
(node (ref P1) (pin 28)))
(net (code 12) (name "/GPIO24(GEN5)")
(node (ref P1) (pin 18)))
(net (code 13) (name /GPIO26)
(node (ref P1) (pin 37)))
(net (code 14) (name /ID_SD)
(node (ref P1) (pin 27)))
(net (code 15) (name /GPIO16)
(node (ref P1) (pin 36)))
(net (code 16) (name "/GPIO7(SPI1_CE_N)")
(node (ref P1) (pin 26)))
(net (code 17) (name "/GPIO23(GEN4)")
(node (ref P1) (pin 16)))
(net (code 18) (name "/GPIO19(SPI1_MISO)")
(node (ref P1) (pin 35)))
(net (code 19) (name "/GPIO8(SPI0_CE_N)")
(node (ref P1) (pin 24)))
(net (code 20) (name "/GPIO13(PWM1)")
(node (ref P1) (pin 33)))
(net (code 21) (name "/GPIO11(SPI0_SCK)")
(node (ref P1) (pin 23)))
(net (code 22) (name "/GPIO12(PWM0)")
(node (ref P1) (pin 32)))
(net (code 23) (name "/GPIO25(GEN6)")
(node (ref P1) (pin 22)))
(net (code 24) (name "/GPIO18(GEN1)(PWM0)")
(node (ref P1) (pin 12)))
(net (code 25) (name /GPIO6)
(node (ref P1) (pin 31)))
(net (code 26) (name "/GPIO9(SPI0_MISO)")
(node (ref P1) (pin 21)))
(net (code 27) (name GND)
(node (ref P1) (pin 9))
(node (ref P1) (pin 6))
(node (ref P1) (pin 20))
(node (ref P1) (pin 25))
(node (ref P1) (pin 39))
(node (ref P1) (pin 34))
(node (ref P1) (pin 14))
(node (ref P1) (pin 30)))
(net (code 28) (name "/GPIO10(SPI0_MOSI)")
(node (ref P1) (pin 19)))
(net (code 29) (name "/GPIO22(GEN3)")
(node (ref P1) (pin 15)))
(net (code 30) (name "/GPIO27(GEN2)")
(node (ref P1) (pin 13)))
(net (code 31) (name "/GPIO17(GEN0)")
(node (ref P1) (pin 11)))))

BIN
kc4upr/IO Hat/IO Hat.pdf Normal file

Binary file not shown.

85
kc4upr/IO Hat/IO Hat.pro Normal file
View File

@ -0,0 +1,85 @@
update=Mon 04 May 2020 10:25:03 PM CDT
version=1
last_client=eeschema
[cvpcb]
version=1
NetITyp=0
NetIExt=.net
PkgIExt=.pkg
NetDir=
LibDir=
NetType=0
[cvpcb/libraries]
EquName1=devcms
[pcbnew]
version=1
PadDrlX=320
PadDimH=600
PadDimV=600
PadForm=1
PadMask=14745599
ViaDiam=450
ViaDril=250
Isol=60
Countlayer=2
Lpiste=170
RouteTo=15
RouteBo=0
TypeVia=3
Segm45=1
Racc45=1
Unite=0
SegFill=1
SegAffG=0
NewAffG=1
PadFill=1
PadAffG=1
PadSNum=1
ModAffC=0
ModAffT=0
PcbAffT=0
SgPcb45=1
TxtPcbV=800
TxtPcbH=600
TxtModV=600
TxtModH=600
TxtModW=120
HPGLnum=1
HPGdiam=15
HPGLSpd=20
HPGLrec=2
HPGLorg=0
GERBmin=15
VEgarde=100
DrawLar=150
EdgeLar=150
TxtLar=120
MSegLar=150
ForPlot=1
WpenSer=10
UserGrX=0,01
UserGrY=0,01
UserGrU=1
DivGrPc=1
TimeOut=600
MaxLnkS=3
ShowRat=0
ShowMRa=1
[pcbnew/libraries]
LibDir=
LibName1=sockets
[general]
version=1
[eeschema]
version=1
LibDir=
[schematic_editor]
version=1
PageLayoutDescrFile=
PlotDirectoryName=
SubpartIdSeparator=0
SubpartFirstId=65
NetFmtName=
SpiceAjustPassiveValues=0
LabSize=50
ERC_TestSimilarLabels=1

602
kc4upr/IO Hat/IO Hat.sch Normal file
View File

@ -0,0 +1,602 @@
EESchema Schematic File Version 4
EELAYER 30 0
EELAYER END
$Descr USLetter 11000 8500
encoding utf-8
Sheet 1 1
Title "I/O Hat for Raspberry Pi and SDR"
Date "2020-05-04"
Rev "A"
Comp ""
Comment1 ""
Comment2 ""
Comment3 ""
Comment4 ""
$EndDescr
$Comp
L power:+5V #PWR01
U 1 1 580C1B61
P 3100 950
F 0 "#PWR01" H 3100 800 50 0001 C CNN
F 1 "+5V" H 3100 1090 50 0000 C CNN
F 2 "" H 3100 950 50 0000 C CNN
F 3 "" H 3100 950 50 0000 C CNN
1 3100 950
1 0 0 -1
$EndComp
Wire Wire Line
3100 950 3100 1100
Wire Wire Line
3100 1100 2900 1100
Wire Wire Line
3100 1200 2900 1200
Connection ~ 3100 1100
$Comp
L power:GND #PWR02
U 1 1 580C1D11
P 3000 3150
F 0 "#PWR02" H 3000 2900 50 0001 C CNN
F 1 "GND" H 3000 3000 50 0000 C CNN
F 2 "" H 3000 3150 50 0000 C CNN
F 3 "" H 3000 3150 50 0000 C CNN
1 3000 3150
1 0 0 -1
$EndComp
Wire Wire Line
3000 1300 3000 1700
Wire Wire Line
3000 2700 2900 2700
Wire Wire Line
3000 2500 2900 2500
Connection ~ 3000 2700
Wire Wire Line
3000 2000 2900 2000
Connection ~ 3000 2500
Wire Wire Line
3000 1700 2900 1700
Connection ~ 3000 2000
$Comp
L power:GND #PWR03
U 1 1 580C1E01
P 2300 3150
F 0 "#PWR03" H 2300 2900 50 0001 C CNN
F 1 "GND" H 2300 3000 50 0000 C CNN
F 2 "" H 2300 3150 50 0000 C CNN
F 3 "" H 2300 3150 50 0000 C CNN
1 2300 3150
1 0 0 -1
$EndComp
Wire Wire Line
2300 3000 2400 3000
Wire Wire Line
2300 1500 2300 2300
Wire Wire Line
2300 2300 2400 2300
Connection ~ 2300 3000
Connection ~ 2200 1100
Wire Wire Line
2200 1900 2400 1900
Wire Wire Line
2200 1100 2400 1100
Wire Wire Line
2200 950 2200 1100
$Comp
L power:+3.3V #PWR04
U 1 1 580C1BC1
P 2200 950
F 0 "#PWR04" H 2200 800 50 0001 C CNN
F 1 "+3.3V" H 2200 1090 50 0000 C CNN
F 2 "" H 2200 950 50 0000 C CNN
F 3 "" H 2200 950 50 0000 C CNN
1 2200 950
1 0 0 -1
$EndComp
Wire Wire Line
2300 1500 2400 1500
Connection ~ 2300 2300
Wire Wire Line
2400 1200 1250 1200
Wire Wire Line
1250 1300 2400 1300
Wire Wire Line
1250 1400 2400 1400
Wire Wire Line
2400 1600 1250 1600
Wire Wire Line
2400 2000 1250 2000
Wire Wire Line
1250 2100 2400 2100
Wire Wire Line
1250 2200 2400 2200
Wire Wire Line
2400 2400 1250 2400
Wire Wire Line
1250 2600 2400 2600
Wire Wire Line
2400 2700 1250 2700
Wire Wire Line
1250 2800 2400 2800
Wire Wire Line
1250 2900 2400 2900
Wire Wire Line
2900 2800 3950 2800
Wire Wire Line
2900 2300 3950 2300
Wire Wire Line
2900 2400 3950 2400
Wire Wire Line
2900 2100 3950 2100
Wire Wire Line
2900 1800 3950 1800
Wire Wire Line
2900 1500 3950 1500
Wire Wire Line
2900 1600 3950 1600
Wire Wire Line
2900 1400 3950 1400
Wire Wire Line
2900 2600 3950 2600
Text Label 1250 1200 0 50 ~ 0
GPIO2(SDA1)
Text Label 1250 1300 0 50 ~ 0
GPIO3(SCL1)
Text Label 1250 1400 0 50 ~ 0
GPIO4(GCLK)
Text Label 1250 1600 0 50 ~ 0
GPIO17(GEN0)
Text Label 1250 1700 0 50 ~ 0
GPIO27(GEN2)
Text Label 1250 1800 0 50 ~ 0
GPIO22(GEN3)
Text Label 1250 2000 0 50 ~ 0
GPIO10(SPI0_MOSI)
Text Label 1250 2100 0 50 ~ 0
GPIO9(SPI0_MISO)
Text Label 1250 2200 0 50 ~ 0
GPIO11(SPI0_SCK)
Text Label 1250 2400 0 50 ~ 0
ID_SD
Text Label 1250 2500 0 50 ~ 0
GPIO5
Text Label 1250 2600 0 50 ~ 0
GPIO6
Text Label 1250 2700 0 50 ~ 0
GPIO13(PWM1)
Text Label 1250 2800 0 50 ~ 0
GPIO19(SPI1_MISO)
Text Label 1250 2900 0 50 ~ 0
GPIO26
Text Label 3950 2900 2 50 ~ 0
GPIO20(SPI1_MOSI)
Text Label 3950 2800 2 50 ~ 0
GPIO16
Text Label 3950 2600 2 50 ~ 0
GPIO12(PWM0)
Text Label 3950 2400 2 50 ~ 0
ID_SC
Text Label 3950 2300 2 50 ~ 0
GPIO7(SPI1_CE_N)
Text Label 3950 2200 2 50 ~ 0
GPIO8(SPI0_CE_N)
Text Label 3950 2100 2 50 ~ 0
GPIO25(GEN6)
Text Label 3950 1900 2 50 ~ 0
GPIO24(GEN5)
Text Label 3950 1800 2 50 ~ 0
GPIO23(GEN4)
Text Label 3950 1600 2 50 ~ 0
GPIO18(GEN1)(PWM0)
Text Label 3950 1500 2 50 ~ 0
GPIO15(RXD0)
Text Label 3950 1400 2 50 ~ 0
GPIO14(TXD0)
Wire Wire Line
3000 1300 2900 1300
Connection ~ 3000 1700
Text Notes 650 7600 0 50 ~ 0
ID_SD and ID_SC PINS:\nThese pins are reserved for HAT ID EEPROM.\n\nAt boot time this I2C interface will be\ninterrogated to look for an EEPROM\nthat identifes the attached board and\nallows automagic setup of the GPIOs\n(and optionally, Linux drivers).\n\nDO NOT USE these pins for anything other\nthan attaching an I2C ID EEPROM. Leave\nunconnected if ID EEPROM not required.
$Comp
L IO-Hat-rescue:Mounting_Hole-Mechanical MK1
U 1 1 5834FB2E
P 3000 7200
F 0 "MK1" H 3100 7246 50 0000 L CNN
F 1 "M2.5" H 3100 7155 50 0000 L CNN
F 2 "MountingHole:MountingHole_2.7mm_M2.5" H 3000 7200 60 0001 C CNN
F 3 "" H 3000 7200 60 0001 C CNN
1 3000 7200
1 0 0 -1
$EndComp
$Comp
L IO-Hat-rescue:Mounting_Hole-Mechanical MK3
U 1 1 5834FBEF
P 3450 7200
F 0 "MK3" H 3550 7246 50 0000 L CNN
F 1 "M2.5" H 3550 7155 50 0000 L CNN
F 2 "MountingHole:MountingHole_2.7mm_M2.5" H 3450 7200 60 0001 C CNN
F 3 "" H 3450 7200 60 0001 C CNN
1 3450 7200
1 0 0 -1
$EndComp
$Comp
L IO-Hat-rescue:Mounting_Hole-Mechanical MK2
U 1 1 5834FC19
P 3000 7400
F 0 "MK2" H 3100 7446 50 0000 L CNN
F 1 "M2.5" H 3100 7355 50 0000 L CNN
F 2 "MountingHole:MountingHole_2.7mm_M2.5" H 3000 7400 60 0001 C CNN
F 3 "" H 3000 7400 60 0001 C CNN
1 3000 7400
1 0 0 -1
$EndComp
$Comp
L IO-Hat-rescue:Mounting_Hole-Mechanical MK4
U 1 1 5834FC4F
P 3450 7400
F 0 "MK4" H 3550 7446 50 0000 L CNN
F 1 "M2.5" H 3550 7355 50 0000 L CNN
F 2 "MountingHole:MountingHole_2.7mm_M2.5" H 3450 7400 60 0001 C CNN
F 3 "" H 3450 7400 60 0001 C CNN
1 3450 7400
1 0 0 -1
$EndComp
Text Notes 3000 7050 0 50 ~ 0
Mounting Holes
$Comp
L Connector_Generic:Conn_02x20_Odd_Even P1
U 1 1 59AD464A
P 2600 2000
F 0 "P1" H 2650 3117 50 0000 C CNN
F 1 "Conn_02x20_Odd_Even" H 2650 3026 50 0000 C CNN
F 2 "Connector_PinSocket_2.54mm:PinSocket_2x20_P2.54mm_Vertical" H -2250 1050 50 0001 C CNN
F 3 "" H -2250 1050 50 0001 C CNN
1 2600 2000
1 0 0 -1
$EndComp
Wire Wire Line
2900 3000 3950 3000
Text Label 3950 3000 2 50 ~ 0
GPIO21(SPI1_SCK)
Wire Wire Line
3100 1100 3100 1200
Wire Wire Line
3000 2700 3000 3150
Wire Wire Line
3000 2500 3000 2700
Wire Wire Line
3000 2000 3000 2500
Wire Wire Line
2300 3000 2300 3150
Wire Wire Line
2200 1100 2200 1900
Wire Wire Line
2300 2300 2300 3000
Wire Wire Line
3000 1700 3000 2000
$Comp
L Isolator:LTV-847 U1
U 2 1 5EB15A6C
P 5750 5950
F 0 "U1" H 5750 6275 50 0000 C CNN
F 1 "LTV-847" H 5750 6184 50 0000 C CNN
F 2 "Package_DIP:DIP-16_W7.62mm" H 5550 5750 50 0001 L CIN
F 3 "http://optoelectronics.liteon.com/upload/download/DS-70-96-0016/LTV-8X7%20series.PDF" H 5750 5950 50 0001 L CNN
2 5750 5950
1 0 0 -1
$EndComp
$Comp
L Isolator:LTV-847 U1
U 1 1 5EB0E8CA
P 5750 5200
F 0 "U1" H 5750 5525 50 0000 C CNN
F 1 "LTV-847" H 5750 5434 50 0000 C CNN
F 2 "Package_DIP:DIP-16_W7.62mm" H 5550 5000 50 0001 L CIN
F 3 "http://optoelectronics.liteon.com/upload/download/DS-70-96-0016/LTV-8X7%20series.PDF" H 5750 5200 50 0001 L CNN
1 5750 5200
1 0 0 -1
$EndComp
Wire Wire Line
4250 5850 5150 5850
Wire Wire Line
6050 5850 6500 5850
Wire Wire Line
6500 5850 6500 5300
Wire Wire Line
5450 5300 5100 5300
Wire Wire Line
5100 5300 5100 6050
Wire Wire Line
5100 6050 5450 6050
$Comp
L power:GNDA #PWR?
U 1 1 5EB51B80
P 6750 6100
F 0 "#PWR?" H 6750 5850 50 0001 C CNN
F 1 "GNDA" H 6755 5927 50 0000 C CNN
F 2 "" H 6750 6100 50 0001 C CNN
F 3 "" H 6750 6100 50 0001 C CNN
1 6750 6100
1 0 0 -1
$EndComp
Wire Wire Line
6050 5300 6150 5300
Wire Wire Line
6150 5300 6150 6050
Wire Wire Line
6150 6050 6050 6050
Wire Wire Line
6750 5500 6750 6050
Wire Wire Line
6950 5500 6750 5500
Wire Wire Line
6500 5300 6950 5300
$Comp
L Connector:AudioJack3_Switch J3
U 1 1 5EB469C1
P 7150 5300
F 0 "J3" H 6870 5208 50 0000 R CNN
F 1 "AudioJack3_Switch" H 6870 5299 50 0000 R CNN
F 2 "" H 7150 5300 50 0001 C CNN
F 3 "~" H 7150 5300 50 0001 C CNN
1 7150 5300
-1 0 0 1
$EndComp
Wire Wire Line
6050 5100 6950 5100
Wire Wire Line
6150 6050 6750 6050
Connection ~ 6150 6050
Connection ~ 6750 6050
Wire Wire Line
6750 6050 6750 6100
Wire Wire Line
1250 2900 1250 5100
Wire Wire Line
1250 5100 5150 5100
$Comp
L power:GND #PWR?
U 1 1 5EBBBEBE
P 5100 6100
F 0 "#PWR?" H 5100 5850 50 0001 C CNN
F 1 "GND" H 5105 5927 50 0000 C CNN
F 2 "" H 5100 6100 50 0001 C CNN
F 3 "" H 5100 6100 50 0001 C CNN
1 5100 6100
1 0 0 -1
$EndComp
Wire Wire Line
5100 6100 5100 6050
Connection ~ 5100 6050
Wire Wire Line
750 3900 750 1700
Wire Wire Line
750 1700 2400 1700
Wire Wire Line
950 1800 2400 1800
$Comp
L Device:R_US R5
U 1 1 5EB1B0EE
P 5300 5100
F 0 "R5" V 5095 5100 50 0000 C CNN
F 1 "330" V 5186 5100 50 0000 C CNN
F 2 "" V 5340 5090 50 0001 C CNN
F 3 "~" H 5300 5100 50 0001 C CNN
1 5300 5100
0 1 1 0
$EndComp
$Comp
L Device:R_US R6
U 1 1 5EB26DC1
P 5300 5850
F 0 "R6" V 5095 5850 50 0000 C CNN
F 1 "330" V 5186 5850 50 0000 C CNN
F 2 "" V 5340 5840 50 0001 C CNN
F 3 "~" H 5300 5850 50 0001 C CNN
1 5300 5850
0 1 1 0
$EndComp
Wire Wire Line
2200 1100 1850 1100
Wire Wire Line
1850 1100 1850 550
Wire Wire Line
1850 550 5500 550
Text Notes 7600 5850 0 50 ~ 0
J3 - Keyer output discretes (isolated from Raspberry Pi)\nTip - CW output (dits and dahs)\nRing - T/R switching (includes "hang time" after last dit/dah)\nSleeve - Rig ground
Wire Wire Line
3950 2200 2900 2200
Wire Wire Line
2900 2900 3950 2900
Wire Wire Line
1250 2500 2400 2500
Wire Wire Line
4250 1900 4250 5850
Wire Wire Line
2900 1900 4250 1900
Text Notes 7600 2800 0 50 ~ 0
J1 - Paddles\nTip - Left paddle\nRing - Right paddle\nSleeve - Ground
Wire Wire Line
5500 1100 5500 1500
Connection ~ 5500 1100
Wire Wire Line
6050 1100 6050 1300
Wire Wire Line
5500 1100 6050 1100
Wire Wire Line
5500 550 5500 1100
Wire Wire Line
5650 2800 6800 2800
Connection ~ 5650 2800
Wire Wire Line
5650 2750 5650 2800
Wire Wire Line
5100 2800 5650 2800
Wire Wire Line
5100 2800 5100 2750
Wire Wire Line
5100 2450 5100 2400
Wire Wire Line
5650 2450 5650 2000
Wire Wire Line
6800 2800 6800 2850
Connection ~ 6800 2800
Wire Wire Line
6800 2400 6800 2800
$Comp
L Device:C C2
U 1 1 5EC3E208
P 5100 2600
F 0 "C2" H 5215 2646 50 0000 L CNN
F 1 "0.01" H 5215 2555 50 0000 L CNN
F 2 "" H 5138 2450 50 0001 C CNN
F 3 "~" H 5100 2600 50 0001 C CNN
1 5100 2600
1 0 0 -1
$EndComp
Wire Wire Line
5500 2450 5500 2400
Wire Wire Line
5150 2400 5100 2400
$Comp
L Device:R_US R2
U 1 1 5EBD72CB
P 5850 2000
F 0 "R2" V 5645 2000 50 0000 C CNN
F 1 "4700" V 5736 2000 50 0000 C CNN
F 2 "" V 5890 1990 50 0001 C CNN
F 3 "~" H 5850 2000 50 0001 C CNN
1 5850 2000
0 1 1 0
$EndComp
Wire Wire Line
6050 2000 6950 2000
Wire Wire Line
6050 2000 6000 2000
Wire Wire Line
5700 2000 5650 2000
$Comp
L Device:C C1
U 1 1 5EC41670
P 5650 2600
F 0 "C1" H 5765 2646 50 0000 L CNN
F 1 "0.01" H 5765 2555 50 0000 L CNN
F 2 "" H 5688 2450 50 0001 C CNN
F 3 "~" H 5650 2600 50 0001 C CNN
1 5650 2600
1 0 0 -1
$EndComp
Wire Wire Line
6950 2400 6800 2400
$Comp
L power:GND #PWR?
U 1 1 5EC39345
P 6800 2850
F 0 "#PWR?" H 6800 2600 50 0001 C CNN
F 1 "GND" H 6805 2677 50 0000 C CNN
F 2 "" H 6800 2850 50 0001 C CNN
F 3 "" H 6800 2850 50 0001 C CNN
1 6800 2850
1 0 0 -1
$EndComp
Connection ~ 5500 2400
Wire Wire Line
6400 2200 6950 2200
Wire Wire Line
6400 2400 6400 2200
Wire Wire Line
5500 2400 6400 2400
Wire Wire Line
5500 2400 5450 2400
Connection ~ 6050 2000
Wire Wire Line
5500 1800 5500 2400
Wire Wire Line
6050 1600 6050 2000
$Comp
L Device:R_US R4
U 1 1 5EBD594A
P 5300 2400
F 0 "R4" V 5095 2400 50 0000 C CNN
F 1 "4700" V 5186 2400 50 0000 C CNN
F 2 "" V 5340 2390 50 0001 C CNN
F 3 "~" H 5300 2400 50 0001 C CNN
1 5300 2400
0 1 1 0
$EndComp
$Comp
L Device:R_US R3
U 1 1 5EBD3F7C
P 5500 1650
F 0 "R3" H 5568 1696 50 0000 L CNN
F 1 "4700" H 5568 1605 50 0000 L CNN
F 2 "" V 5540 1640 50 0001 C CNN
F 3 "~" H 5500 1650 50 0001 C CNN
1 5500 1650
1 0 0 -1
$EndComp
$Comp
L Device:R_US R1
U 1 1 5EBD1D33
P 6050 1450
F 0 "R1" H 6118 1496 50 0000 L CNN
F 1 "4700" H 6118 1405 50 0000 L CNN
F 2 "" V 6090 1440 50 0001 C CNN
F 3 "~" H 6050 1450 50 0001 C CNN
1 6050 1450
1 0 0 -1
$EndComp
$Comp
L Connector:AudioJack3_Switch J1
U 1 1 5EBC04A3
P 7150 2200
F 0 "J1" H 6870 2108 50 0000 R CNN
F 1 "AudioJack3_Switch" H 6870 2199 50 0000 R CNN
F 2 "" H 7150 2200 50 0001 C CNN
F 3 "~" H 7150 2200 50 0001 C CNN
1 7150 2200
-1 0 0 1
$EndComp
Wire Wire Line
750 3900 4900 3900
Wire Wire Line
4900 3900 4900 2400
Wire Wire Line
4900 2400 5100 2400
Connection ~ 5100 2400
Wire Wire Line
5650 2000 4750 2000
Wire Wire Line
4750 2000 4750 3750
Wire Wire Line
4750 3750 950 3750
Wire Wire Line
950 1800 950 3750
Connection ~ 5650 2000
$Comp
L Connector:AudioJack3_Switch J2
U 1 1 5ED38DA2
P 7150 3850
F 0 "J2" H 6870 3758 50 0000 R CNN
F 1 "AudioJack3_Switch" H 6870 3849 50 0000 R CNN
F 2 "" H 7150 3850 50 0001 C CNN
F 3 "~" H 7150 3850 50 0001 C CNN
1 7150 3850
-1 0 0 1
$EndComp
$Comp
L power:GND #PWR?
U 1 1 5ED3DFCB
P 6800 4300
F 0 "#PWR?" H 6800 4050 50 0001 C CNN
F 1 "GND" H 6805 4127 50 0000 C CNN
F 2 "" H 6800 4300 50 0001 C CNN
F 3 "" H 6800 4300 50 0001 C CNN
1 6800 4300
1 0 0 -1
$EndComp
Wire Wire Line
6950 4050 6800 4050
Wire Wire Line
6800 4050 6800 4300
Text Notes 7600 4400 0 50 ~ 0
J2 - Growth\nTip - TBD\nRing - TBD\nSleeve - Ground
$EndSCHEMATC

View File

@ -0,0 +1,602 @@
EESchema Schematic File Version 4
EELAYER 30 0
EELAYER END
$Descr USLetter 11000 8500
encoding utf-8
Sheet 1 1
Title "I/O Hat for Raspberry Pi and SDR"
Date "2020-05-04"
Rev "-"
Comp ""
Comment1 ""
Comment2 ""
Comment3 ""
Comment4 ""
$EndDescr
$Comp
L power:+5V #PWR01
U 1 1 580C1B61
P 3100 950
F 0 "#PWR01" H 3100 800 50 0001 C CNN
F 1 "+5V" H 3100 1090 50 0000 C CNN
F 2 "" H 3100 950 50 0000 C CNN
F 3 "" H 3100 950 50 0000 C CNN
1 3100 950
1 0 0 -1
$EndComp
Wire Wire Line
3100 950 3100 1100
Wire Wire Line
3100 1100 2900 1100
Wire Wire Line
3100 1200 2900 1200
Connection ~ 3100 1100
$Comp
L power:GND #PWR02
U 1 1 580C1D11
P 3000 3150
F 0 "#PWR02" H 3000 2900 50 0001 C CNN
F 1 "GND" H 3000 3000 50 0000 C CNN
F 2 "" H 3000 3150 50 0000 C CNN
F 3 "" H 3000 3150 50 0000 C CNN
1 3000 3150
1 0 0 -1
$EndComp
Wire Wire Line
3000 1300 3000 1700
Wire Wire Line
3000 2700 2900 2700
Wire Wire Line
3000 2500 2900 2500
Connection ~ 3000 2700
Wire Wire Line
3000 2000 2900 2000
Connection ~ 3000 2500
Wire Wire Line
3000 1700 2900 1700
Connection ~ 3000 2000
$Comp
L power:GND #PWR03
U 1 1 580C1E01
P 2300 3150
F 0 "#PWR03" H 2300 2900 50 0001 C CNN
F 1 "GND" H 2300 3000 50 0000 C CNN
F 2 "" H 2300 3150 50 0000 C CNN
F 3 "" H 2300 3150 50 0000 C CNN
1 2300 3150
1 0 0 -1
$EndComp
Wire Wire Line
2300 3000 2400 3000
Wire Wire Line
2300 1500 2300 2300
Wire Wire Line
2300 2300 2400 2300
Connection ~ 2300 3000
Connection ~ 2200 1100
Wire Wire Line
2200 1900 2400 1900
Wire Wire Line
2200 1100 2400 1100
Wire Wire Line
2200 950 2200 1100
$Comp
L power:+3.3V #PWR04
U 1 1 580C1BC1
P 2200 950
F 0 "#PWR04" H 2200 800 50 0001 C CNN
F 1 "+3.3V" H 2200 1090 50 0000 C CNN
F 2 "" H 2200 950 50 0000 C CNN
F 3 "" H 2200 950 50 0000 C CNN
1 2200 950
1 0 0 -1
$EndComp
Wire Wire Line
2300 1500 2400 1500
Connection ~ 2300 2300
Wire Wire Line
2400 1200 1250 1200
Wire Wire Line
1250 1300 2400 1300
Wire Wire Line
1250 1400 2400 1400
Wire Wire Line
2400 1600 1250 1600
Wire Wire Line
2400 2000 1250 2000
Wire Wire Line
1250 2100 2400 2100
Wire Wire Line
1250 2200 2400 2200
Wire Wire Line
2400 2400 1250 2400
Wire Wire Line
1250 2600 2400 2600
Wire Wire Line
2400 2700 1250 2700
Wire Wire Line
1250 2800 2400 2800
Wire Wire Line
1250 2900 2400 2900
Wire Wire Line
2900 2800 3950 2800
Wire Wire Line
2900 2300 3950 2300
Wire Wire Line
2900 2400 3950 2400
Wire Wire Line
2900 2100 3950 2100
Wire Wire Line
2900 1800 3950 1800
Wire Wire Line
2900 1500 3950 1500
Wire Wire Line
2900 1600 3950 1600
Wire Wire Line
2900 1400 3950 1400
Wire Wire Line
2900 2600 3950 2600
Text Label 1250 1200 0 50 ~ 0
GPIO2(SDA1)
Text Label 1250 1300 0 50 ~ 0
GPIO3(SCL1)
Text Label 1250 1400 0 50 ~ 0
GPIO4(GCLK)
Text Label 1250 1600 0 50 ~ 0
GPIO17(GEN0)
Text Label 1250 1700 0 50 ~ 0
GPIO27(GEN2)
Text Label 1250 1800 0 50 ~ 0
GPIO22(GEN3)
Text Label 1250 2000 0 50 ~ 0
GPIO10(SPI0_MOSI)
Text Label 1250 2100 0 50 ~ 0
GPIO9(SPI0_MISO)
Text Label 1250 2200 0 50 ~ 0
GPIO11(SPI0_SCK)
Text Label 1250 2400 0 50 ~ 0
ID_SD
Text Label 1250 2500 0 50 ~ 0
GPIO5
Text Label 1250 2600 0 50 ~ 0
GPIO6
Text Label 1250 2700 0 50 ~ 0
GPIO13(PWM1)
Text Label 1250 2800 0 50 ~ 0
GPIO19(SPI1_MISO)
Text Label 1250 2900 0 50 ~ 0
GPIO26
Text Label 3950 2900 2 50 ~ 0
GPIO20(SPI1_MOSI)
Text Label 3950 2800 2 50 ~ 0
GPIO16
Text Label 3950 2600 2 50 ~ 0
GPIO12(PWM0)
Text Label 3950 2400 2 50 ~ 0
ID_SC
Text Label 3950 2300 2 50 ~ 0
GPIO7(SPI1_CE_N)
Text Label 3950 2200 2 50 ~ 0
GPIO8(SPI0_CE_N)
Text Label 3950 2100 2 50 ~ 0
GPIO25(GEN6)
Text Label 3950 1900 2 50 ~ 0
GPIO24(GEN5)
Text Label 3950 1800 2 50 ~ 0
GPIO23(GEN4)
Text Label 3950 1600 2 50 ~ 0
GPIO18(GEN1)(PWM0)
Text Label 3950 1500 2 50 ~ 0
GPIO15(RXD0)
Text Label 3950 1400 2 50 ~ 0
GPIO14(TXD0)
Wire Wire Line
3000 1300 2900 1300
Connection ~ 3000 1700
Text Notes 650 7600 0 50 ~ 0
ID_SD and ID_SC PINS:\nThese pins are reserved for HAT ID EEPROM.\n\nAt boot time this I2C interface will be\ninterrogated to look for an EEPROM\nthat identifes the attached board and\nallows automagic setup of the GPIOs\n(and optionally, Linux drivers).\n\nDO NOT USE these pins for anything other\nthan attaching an I2C ID EEPROM. Leave\nunconnected if ID EEPROM not required.
$Comp
L IO-Hat-rescue:Mounting_Hole-Mechanical MK1
U 1 1 5834FB2E
P 3000 7200
F 0 "MK1" H 3100 7246 50 0000 L CNN
F 1 "M2.5" H 3100 7155 50 0000 L CNN
F 2 "MountingHole:MountingHole_2.7mm_M2.5" H 3000 7200 60 0001 C CNN
F 3 "" H 3000 7200 60 0001 C CNN
1 3000 7200
1 0 0 -1
$EndComp
$Comp
L IO-Hat-rescue:Mounting_Hole-Mechanical MK3
U 1 1 5834FBEF
P 3450 7200
F 0 "MK3" H 3550 7246 50 0000 L CNN
F 1 "M2.5" H 3550 7155 50 0000 L CNN
F 2 "MountingHole:MountingHole_2.7mm_M2.5" H 3450 7200 60 0001 C CNN
F 3 "" H 3450 7200 60 0001 C CNN
1 3450 7200
1 0 0 -1
$EndComp
$Comp
L IO-Hat-rescue:Mounting_Hole-Mechanical MK2
U 1 1 5834FC19
P 3000 7400
F 0 "MK2" H 3100 7446 50 0000 L CNN
F 1 "M2.5" H 3100 7355 50 0000 L CNN
F 2 "MountingHole:MountingHole_2.7mm_M2.5" H 3000 7400 60 0001 C CNN
F 3 "" H 3000 7400 60 0001 C CNN
1 3000 7400
1 0 0 -1
$EndComp
$Comp
L IO-Hat-rescue:Mounting_Hole-Mechanical MK4
U 1 1 5834FC4F
P 3450 7400
F 0 "MK4" H 3550 7446 50 0000 L CNN
F 1 "M2.5" H 3550 7355 50 0000 L CNN
F 2 "MountingHole:MountingHole_2.7mm_M2.5" H 3450 7400 60 0001 C CNN
F 3 "" H 3450 7400 60 0001 C CNN
1 3450 7400
1 0 0 -1
$EndComp
Text Notes 3000 7050 0 50 ~ 0
Mounting Holes
$Comp
L Connector_Generic:Conn_02x20_Odd_Even P1
U 1 1 59AD464A
P 2600 2000
F 0 "P1" H 2650 3117 50 0000 C CNN
F 1 "Conn_02x20_Odd_Even" H 2650 3026 50 0000 C CNN
F 2 "Connector_PinSocket_2.54mm:PinSocket_2x20_P2.54mm_Vertical" H -2250 1050 50 0001 C CNN
F 3 "" H -2250 1050 50 0001 C CNN
1 2600 2000
1 0 0 -1
$EndComp
Wire Wire Line
2900 3000 3950 3000
Text Label 3950 3000 2 50 ~ 0
GPIO21(SPI1_SCK)
Wire Wire Line
3100 1100 3100 1200
Wire Wire Line
3000 2700 3000 3150
Wire Wire Line
3000 2500 3000 2700
Wire Wire Line
3000 2000 3000 2500
Wire Wire Line
2300 3000 2300 3150
Wire Wire Line
2200 1100 2200 1900
Wire Wire Line
2300 2300 2300 3000
Wire Wire Line
3000 1700 3000 2000
$Comp
L Isolator:LTV-847 U1
U 2 1 5EB15A6C
P 5750 5950
F 0 "U1" H 5750 6275 50 0000 C CNN
F 1 "LTV-847" H 5750 6184 50 0000 C CNN
F 2 "Package_DIP:DIP-16_W7.62mm" H 5550 5750 50 0001 L CIN
F 3 "http://optoelectronics.liteon.com/upload/download/DS-70-96-0016/LTV-8X7%20series.PDF" H 5750 5950 50 0001 L CNN
2 5750 5950
1 0 0 -1
$EndComp
$Comp
L Isolator:LTV-847 U1
U 1 1 5EB0E8CA
P 5750 5200
F 0 "U1" H 5750 5525 50 0000 C CNN
F 1 "LTV-847" H 5750 5434 50 0000 C CNN
F 2 "Package_DIP:DIP-16_W7.62mm" H 5550 5000 50 0001 L CIN
F 3 "http://optoelectronics.liteon.com/upload/download/DS-70-96-0016/LTV-8X7%20series.PDF" H 5750 5200 50 0001 L CNN
1 5750 5200
1 0 0 -1
$EndComp
Wire Wire Line
4250 5850 5150 5850
Wire Wire Line
6050 5850 6500 5850
Wire Wire Line
6500 5850 6500 5300
Wire Wire Line
5450 5300 5100 5300
Wire Wire Line
5100 5300 5100 6050
Wire Wire Line
5100 6050 5450 6050
$Comp
L power:GNDA #PWR?
U 1 1 5EB51B80
P 6750 6100
F 0 "#PWR?" H 6750 5850 50 0001 C CNN
F 1 "GNDA" H 6755 5927 50 0000 C CNN
F 2 "" H 6750 6100 50 0001 C CNN
F 3 "" H 6750 6100 50 0001 C CNN
1 6750 6100
1 0 0 -1
$EndComp
Wire Wire Line
6050 5300 6150 5300
Wire Wire Line
6150 5300 6150 6050
Wire Wire Line
6150 6050 6050 6050
Wire Wire Line
6750 5500 6750 6050
Wire Wire Line
6950 5500 6750 5500
Wire Wire Line
6500 5300 6950 5300
$Comp
L Connector:AudioJack3_Switch J3
U 1 1 5EB469C1
P 7150 5300
F 0 "J3" H 6870 5208 50 0000 R CNN
F 1 "AudioJack3_Switch" H 6870 5299 50 0000 R CNN
F 2 "" H 7150 5300 50 0001 C CNN
F 3 "~" H 7150 5300 50 0001 C CNN
1 7150 5300
-1 0 0 1
$EndComp
Wire Wire Line
6050 5100 6950 5100
Wire Wire Line
6150 6050 6750 6050
Connection ~ 6150 6050
Connection ~ 6750 6050
Wire Wire Line
6750 6050 6750 6100
Wire Wire Line
1250 2900 1250 5100
Wire Wire Line
1250 5100 5150 5100
$Comp
L power:GND #PWR?
U 1 1 5EBBBEBE
P 5100 6100
F 0 "#PWR?" H 5100 5850 50 0001 C CNN
F 1 "GND" H 5105 5927 50 0000 C CNN
F 2 "" H 5100 6100 50 0001 C CNN
F 3 "" H 5100 6100 50 0001 C CNN
1 5100 6100
1 0 0 -1
$EndComp
Wire Wire Line
5100 6100 5100 6050
Connection ~ 5100 6050
Wire Wire Line
750 3900 750 1700
Wire Wire Line
750 1700 2400 1700
Wire Wire Line
950 1800 2400 1800
$Comp
L Device:R_US R5
U 1 1 5EB1B0EE
P 5300 5100
F 0 "R5" V 5095 5100 50 0000 C CNN
F 1 "330" V 5186 5100 50 0000 C CNN
F 2 "" V 5340 5090 50 0001 C CNN
F 3 "~" H 5300 5100 50 0001 C CNN
1 5300 5100
0 1 1 0
$EndComp
$Comp
L Device:R_US R6
U 1 1 5EB26DC1
P 5300 5850
F 0 "R6" V 5095 5850 50 0000 C CNN
F 1 "330" V 5186 5850 50 0000 C CNN
F 2 "" V 5340 5840 50 0001 C CNN
F 3 "~" H 5300 5850 50 0001 C CNN
1 5300 5850
0 1 1 0
$EndComp
Wire Wire Line
2200 1100 1850 1100
Wire Wire Line
1850 1100 1850 550
Wire Wire Line
1850 550 5500 550
Text Notes 7600 5850 0 50 ~ 0
J2 - Keyer output discretes (isolated from Raspberry Pi)\nTip - CW output (dits and dahs)\nRing - T/R switching (includes "hang time" after last dit/dah)\nSleeve - Rig ground
Wire Wire Line
3950 2200 2900 2200
Wire Wire Line
2900 2900 3950 2900
Wire Wire Line
1250 2500 2400 2500
Wire Wire Line
4250 1900 4250 5850
Wire Wire Line
2900 1900 4250 1900
Text Notes 7600 2800 0 50 ~ 0
J1 - Paddles\nTip - Left paddle\nRing - Right paddle\nSleeve - Ground
Wire Wire Line
5500 1100 5500 1500
Connection ~ 5500 1100
Wire Wire Line
6050 1100 6050 1300
Wire Wire Line
5500 1100 6050 1100
Wire Wire Line
5500 550 5500 1100
Wire Wire Line
5650 2800 6800 2800
Connection ~ 5650 2800
Wire Wire Line
5650 2750 5650 2800
Wire Wire Line
5100 2800 5650 2800
Wire Wire Line
5100 2800 5100 2750
Wire Wire Line
5100 2450 5100 2400
Wire Wire Line
5650 2450 5650 2000
Wire Wire Line
6800 2800 6800 2850
Connection ~ 6800 2800
Wire Wire Line
6800 2400 6800 2800
$Comp
L Device:C C2
U 1 1 5EC3E208
P 5100 2600
F 0 "C2" H 5215 2646 50 0000 L CNN
F 1 "0.01" H 5215 2555 50 0000 L CNN
F 2 "" H 5138 2450 50 0001 C CNN
F 3 "~" H 5100 2600 50 0001 C CNN
1 5100 2600
1 0 0 -1
$EndComp
Wire Wire Line
5500 2450 5500 2400
Wire Wire Line
5150 2400 5100 2400
$Comp
L Device:R_US R2
U 1 1 5EBD72CB
P 5850 2000
F 0 "R2" V 5645 2000 50 0000 C CNN
F 1 "4700" V 5736 2000 50 0000 C CNN
F 2 "" V 5890 1990 50 0001 C CNN
F 3 "~" H 5850 2000 50 0001 C CNN
1 5850 2000
0 1 1 0
$EndComp
Wire Wire Line
6050 2000 6950 2000
Wire Wire Line
6050 2000 6000 2000
Wire Wire Line
5700 2000 5650 2000
$Comp
L Device:C C1
U 1 1 5EC41670
P 5650 2600
F 0 "C1" H 5765 2646 50 0000 L CNN
F 1 "0.01" H 5765 2555 50 0000 L CNN
F 2 "" H 5688 2450 50 0001 C CNN
F 3 "~" H 5650 2600 50 0001 C CNN
1 5650 2600
1 0 0 -1
$EndComp
Wire Wire Line
6950 2400 6800 2400
$Comp
L power:GND #PWR?
U 1 1 5EC39345
P 6800 2850
F 0 "#PWR?" H 6800 2600 50 0001 C CNN
F 1 "GND" H 6805 2677 50 0000 C CNN
F 2 "" H 6800 2850 50 0001 C CNN
F 3 "" H 6800 2850 50 0001 C CNN
1 6800 2850
1 0 0 -1
$EndComp
Connection ~ 5500 2400
Wire Wire Line
6400 2200 6950 2200
Wire Wire Line
6400 2400 6400 2200
Wire Wire Line
5500 2400 6400 2400
Wire Wire Line
5500 2400 5450 2400
Connection ~ 6050 2000
Wire Wire Line
5500 1800 5500 2400
Wire Wire Line
6050 1600 6050 2000
$Comp
L Device:R_US R4
U 1 1 5EBD594A
P 5300 2400
F 0 "R4" V 5095 2400 50 0000 C CNN
F 1 "4700" V 5186 2400 50 0000 C CNN
F 2 "" V 5340 2390 50 0001 C CNN
F 3 "~" H 5300 2400 50 0001 C CNN
1 5300 2400
0 1 1 0
$EndComp
$Comp
L Device:R_US R3
U 1 1 5EBD3F7C
P 5500 1650
F 0 "R3" H 5568 1696 50 0000 L CNN
F 1 "4700" H 5568 1605 50 0000 L CNN
F 2 "" V 5540 1640 50 0001 C CNN
F 3 "~" H 5500 1650 50 0001 C CNN
1 5500 1650
1 0 0 -1
$EndComp
$Comp
L Device:R_US R1
U 1 1 5EBD1D33
P 6050 1450
F 0 "R1" H 6118 1496 50 0000 L CNN
F 1 "4700" H 6118 1405 50 0000 L CNN
F 2 "" V 6090 1440 50 0001 C CNN
F 3 "~" H 6050 1450 50 0001 C CNN
1 6050 1450
1 0 0 -1
$EndComp
$Comp
L Connector:AudioJack3_Switch J1
U 1 1 5EBC04A3
P 7150 2200
F 0 "J1" H 6870 2108 50 0000 R CNN
F 1 "AudioJack3_Switch" H 6870 2199 50 0000 R CNN
F 2 "" H 7150 2200 50 0001 C CNN
F 3 "~" H 7150 2200 50 0001 C CNN
1 7150 2200
-1 0 0 1
$EndComp
Wire Wire Line
750 3900 4900 3900
Wire Wire Line
4900 3900 4900 2400
Wire Wire Line
4900 2400 5100 2400
Connection ~ 5100 2400
Wire Wire Line
5650 2000 4750 2000
Wire Wire Line
4750 2000 4750 3750
Wire Wire Line
4750 3750 950 3750
Wire Wire Line
950 1800 950 3750
Connection ~ 5650 2000
$Comp
L Connector:AudioJack3_Switch J2
U 1 1 5ED38DA2
P 7150 3850
F 0 "J2" H 6870 3758 50 0000 R CNN
F 1 "AudioJack3_Switch" H 6870 3849 50 0000 R CNN
F 2 "" H 7150 3850 50 0001 C CNN
F 3 "~" H 7150 3850 50 0001 C CNN
1 7150 3850
-1 0 0 1
$EndComp
$Comp
L power:GND #PWR?
U 1 1 5ED3DFCB
P 6800 4300
F 0 "#PWR?" H 6800 4050 50 0001 C CNN
F 1 "GND" H 6805 4127 50 0000 C CNN
F 2 "" H 6800 4300 50 0001 C CNN
F 3 "" H 6800 4300 50 0001 C CNN
1 6800 4300
1 0 0 -1
$EndComp
Wire Wire Line
6950 4050 6800 4050
Wire Wire Line
6800 4050 6800 4300
Text Notes 7600 4400 0 50 ~ 0
J1 - Growth\nTip - TBD\nRing - TBD\nSleeve - Ground
$EndSCHEMATC

1
kc4upr/IO Hat/IO Hat.stf Normal file
View File

@ -0,0 +1 @@
comp = "P1" module = "HE10_26D"

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,166 @@
EESchema-LIBRARY Version 2.3
#encoding utf-8
#
# +3V3
#
DEF +3V3 #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -150 50 H I C CNN
F1 "+3V3" 0 140 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
ALIAS +3.3V
DRAW
P 2 0 1 0 -30 50 0 100 N
P 2 0 1 0 0 0 0 100 N
P 2 0 1 0 0 100 30 50 N
X +3V3 1 0 0 0 U 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# +5V
#
DEF +5V #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -150 50 H I C CNN
F1 "+5V" 0 140 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
DRAW
P 2 0 1 0 -30 50 0 100 N
P 2 0 1 0 0 0 0 100 N
P 2 0 1 0 0 100 30 50 N
X +5V 1 0 0 0 U 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# CONN_02X20
#
DEF CONN_02X20 P 0 1 Y N 1 F N
F0 "P" 0 1050 50 H V C CNN
F1 "CONN_02X20" 0 0 50 V V C CNN
F2 "" 0 -950 50 H V C CNN
F3 "" 0 -950 50 H V C CNN
$FPLIST
Pin_Header_Straight_2X20
Pin_Header_Angled_2X20
Socket_Strip_Straight_2X20
Socket_Strip_Angled_2X20
$ENDFPLIST
DRAW
S -100 -945 -50 -955 0 1 0 N
S -100 -845 -50 -855 0 1 0 N
S -100 -745 -50 -755 0 1 0 N
S -100 -645 -50 -655 0 1 0 N
S -100 -545 -50 -555 0 1 0 N
S -100 -445 -50 -455 0 1 0 N
S -100 -345 -50 -355 0 1 0 N
S -100 -245 -50 -255 0 1 0 N
S -100 -145 -50 -155 0 1 0 N
S -100 -45 -50 -55 0 1 0 N
S -100 55 -50 45 0 1 0 N
S -100 155 -50 145 0 1 0 N
S -100 255 -50 245 0 1 0 N
S -100 355 -50 345 0 1 0 N
S -100 455 -50 445 0 1 0 N
S -100 555 -50 545 0 1 0 N
S -100 655 -50 645 0 1 0 N
S -100 755 -50 745 0 1 0 N
S -100 855 -50 845 0 1 0 N
S -100 955 -50 945 0 1 0 N
S -100 1000 100 -1000 0 1 0 N
S 50 -945 100 -955 0 1 0 N
S 50 -845 100 -855 0 1 0 N
S 50 -745 100 -755 0 1 0 N
S 50 -645 100 -655 0 1 0 N
S 50 -545 100 -555 0 1 0 N
S 50 -445 100 -455 0 1 0 N
S 50 -345 100 -355 0 1 0 N
S 50 -245 100 -255 0 1 0 N
S 50 -145 100 -155 0 1 0 N
S 50 -45 100 -55 0 1 0 N
S 50 55 100 45 0 1 0 N
S 50 155 100 145 0 1 0 N
S 50 255 100 245 0 1 0 N
S 50 355 100 345 0 1 0 N
S 50 455 100 445 0 1 0 N
S 50 555 100 545 0 1 0 N
S 50 655 100 645 0 1 0 N
S 50 755 100 745 0 1 0 N
S 50 855 100 845 0 1 0 N
S 50 955 100 945 0 1 0 N
X P1 1 -250 950 150 R 50 50 1 1 P
X P2 2 250 950 150 L 50 50 1 1 P
X P3 3 -250 850 150 R 50 50 1 1 P
X P4 4 250 850 150 L 50 50 1 1 P
X P5 5 -250 750 150 R 50 50 1 1 P
X P6 6 250 750 150 L 50 50 1 1 P
X P7 7 -250 650 150 R 50 50 1 1 P
X P8 8 250 650 150 L 50 50 1 1 P
X P9 9 -250 550 150 R 50 50 1 1 P
X P10 10 250 550 150 L 50 50 1 1 P
X P20 20 250 50 150 L 50 50 1 1 P
X P30 30 250 -450 150 L 50 50 1 1 P
X P40 40 250 -950 150 L 50 50 1 1 P
X P11 11 -250 450 150 R 50 50 1 1 P
X P21 21 -250 -50 150 R 50 50 1 1 P
X P31 31 -250 -550 150 R 50 50 1 1 P
X P12 12 250 450 150 L 50 50 1 1 P
X P22 22 250 -50 150 L 50 50 1 1 P
X P32 32 250 -550 150 L 50 50 1 1 P
X P13 13 -250 350 150 R 50 50 1 1 P
X P23 23 -250 -150 150 R 50 50 1 1 P
X P33 33 -250 -650 150 R 50 50 1 1 P
X P14 14 250 350 150 L 50 50 1 1 P
X P24 24 250 -150 150 L 50 50 1 1 P
X P34 34 250 -650 150 L 50 50 1 1 P
X P15 15 -250 250 150 R 50 50 1 1 P
X P25 25 -250 -250 150 R 50 50 1 1 P
X P35 35 -250 -750 150 R 50 50 1 1 P
X P16 16 250 250 150 L 50 50 1 1 P
X P26 26 250 -250 150 L 50 50 1 1 P
X P36 36 250 -750 150 L 50 50 1 1 P
X P17 17 -250 150 150 R 50 50 1 1 P
X P27 27 -250 -350 150 R 50 50 1 1 P
X P37 37 -250 -850 150 R 50 50 1 1 P
X P18 18 250 150 150 L 50 50 1 1 P
X P28 28 250 -350 150 L 50 50 1 1 P
X P38 38 250 -850 150 L 50 50 1 1 P
X P19 19 -250 50 150 R 50 50 1 1 P
X P29 29 -250 -450 150 R 50 50 1 1 P
X P39 39 -250 -950 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# GND
#
DEF GND #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -250 50 H I C CNN
F1 "GND" 0 -150 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
DRAW
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
X GND 1 0 0 0 D 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# MOUNTING_HOLE
#
DEF MOUNTING_HOLE MH 0 40 Y Y 1 F N
F0 "MH" 0 150 50 H V C CNN
F1 "MOUNTING_HOLE" 375 -50 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
DRAW
S -100 100 100 0 0 1 0 N
S -50 0 50 -150 0 1 0 N
P 2 0 1 0 -50 -150 50 -125 N
P 2 0 1 0 50 -100 -50 -125 N
P 2 0 1 0 50 -75 -50 -100 N
P 2 0 1 0 50 -50 -50 -75 N
P 2 0 1 0 50 -25 -50 -50 N
P 2 0 1 0 50 0 -50 -25 N
X ~ 1 -100 -150 50 R 50 50 1 1 I
ENDDRAW
ENDDEF
#
#End Library

View File

@ -0,0 +1,3 @@
(sym_lib_table
(lib (name IO-Hat-rescue)(type Legacy)(uri "${KIPRJMOD}/IO Hat-rescue.lib")(options "")(descr ""))
)

503
kc4upr/hardware_pihfiq.py Normal file
View File

@ -0,0 +1,503 @@
########################################################################
# Pi-HFIQ hardware control module for Quisk.
#
# Original 'hardware_usbserial.py' for RS-HFIQ hardware by _____.
#
# Adapted into the "Pi-HFIQ" configuration by Rob French, KC4UPR.
#
# This file provides for USB control of the HobbyPCB RS-HFIQ SDR
# transceiver, in conjunction with a Raspberry Pi for control. The
# Raspberry Pi provides ADC/DAC of the RX and TX I/Q signals, as well as
# input methods for audio, digital, and CW modes.
#
# TODO as of 2020-04-21:
# (1) Implement all/most of the keyer parameters as user-controllable
# items in the configuration file, widgets, and/or config menu.
# (2) Make power level settings automatically get stored/restored per
# band, mode, and possibly even frequency ("nearest 10 KHz" or
# something like that... memory is cheap). This is due to the
# fact that I get the RS-HFIQ "CLIP" light coming on with different
# output volumes depending on mode, CW vs digital, etc.
# (3) Clean up more comments.
# (4) Add an automatic device finder... so you don't have to edit
# /dev/ttyUSB0, ...USB1, etc.
#
########################################################################
from __future__ import print_function
import math
import psutil
import serial
import serial.tools.list_ports
import struct
import sys
import threading
import time
import traceback
from quisk_hardware_model import Hardware as BaseHardware
import _quisk as QS
DEBUG = 1
KEYER_MODE_LIST = (('Keyer', None), ('Bug', None), ('Iambic A', None), ('Iambic B', None))
DEFAULT_KEYER_MODE = 2
DEFAULT_KEYER_WPM = 15
########################################################################
def dprint(*args, **kwargs):
print(*args, file=sys.stdout, **kwargs)
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
########################################################################
# RSHFIQ class
#
# An object that encapsulates all of the functionality associated with
# the RS-HFIQ serial interface. It provides methods and/or properties
# for each of the commands in the RS-HFIQ interface command list, and
# performs all of the necessary serial port operations.
########################################################################
class Hardware(BaseHardware):
def __init__(self, app, conf, debug=DEBUG):
BaseHardware.__init__(self, app, conf)
# serial port for the transceiver (rig) -- RS-HFIQ
self.rig = RSHFIQ(device="/dev/ttyUSB0", debug=DEBUG)
self.debug = debug
self.vfo = None
self.ptt_button = 0
self.is_cw = False
self.key_thread = None
self.mon_thread = None
self.keyer_mode_list = [x[0] for x in KEYER_MODE_LIST]
self.keyer_mode = DEFAULT_KEYER_MODE
self.keyer_wpm = DEFAULT_KEYER_WPM
self.SetKeyerMode(self.keyer_mode)
self.SetKeyerWPM(self.keyer_wpm)
def open(self): # Called once to open the Hardware
if self.rig.open():
version = self.rig.version
if version[0:7] == "RS-HFIQ":
if self.conf.name_of_mic_play and self.conf.key_poll_msec:
self.key_thread = KeyThread(self.rig, self.conf.key_poll_msec / 1000.0, self.conf.key_hang_time)
self.key_thread.start()
self.mon_thread = StatusThread(self.rig)
self.mon_thread.start()
return version
else:
eprint("[Pi-HFIQ] could not find the RS-HFIQ device -- terminating")
exit()
else:
return "[Pi-HFIQ] unable to open device"
def close(self): # Called once to close the Hardware
if self.key_thread:
self.key_thread.stop()
self.key_thread = None
if self.mon_thread:
self.mon_thread.stop()
self.mon_thread = None
self.rig.serial.close()
return "[Pi-HFIQ] closed"
def HeartBeat(self):
if self.application.bottom_widgets:
self.application.bottom_widgets.UpdateText(
"Rig: %.0fC, CPU: %.0fC, Proc: %.0f%%, Mem: %.0f%%" % (
self.mon_thread.rig_temp,
self.mon_thread.cpu_temp,
self.mon_thread.cpu_load,
self.mon_thread.mem_load))
pass
def ReturnFrequency(self):
return None, self.rig.frequency
def ChangeFrequency(self, tune, vfo, source='', band='', event=None):
if self.vfo <> vfo :
self.vfo = vfo
self.rig.frequency = self.vfo
# probably need to check that this actually worked!
return tune, self.vfo
def OnButtonPTT(self, event=None):
if event:
if event.GetEventObject().GetValue():
if self.debug: dprint("[Pi-HFIQ] PTT pressed")
self.ptt_button = 1
else:
if self.debug: dprint("[Pi-HFIQ] PTT released")
self.ptt_button = 0
if self.key_thread and self.is_cw:
# keyer thread exists--it handles PTT
# Also temporarily using this only for CW, because digimodes
# aren't working with the keyer thread...
if self.debug: dprint("[Pi-HFIQ] PTT handled by keyer thread")
self.key_thread.OnPTT(self.ptt_button)
else:
# no keyer thread--PTT handled here
if self.debug: dprint("[Pi-HFIQ] PTT state not handled by keyer thread")
self.rig.transmit = (self.ptt_button == 1)
QS.set_key_down(event.GetEventObject().GetValue())
# if self.is_cw:
# QS.set_key_down(0)
# QS.set_transmit_mode(self.ptt_button)
# else:
# QS.set_key_down(self.ptt_button)
def ChangeMode(self, mode): # Change the tx/rx mode
# mode is a string: "USB", "AM", etc.
if mode in ('CWU', 'CWL'):
self.is_cw = True
QS.set_gpio_keyer_enabled(1)
else:
self.is_cw = False
QS.set_gpio_keyer_enabled(0)
if self.key_thread:
self.key_thread.IsCW(self.is_cw)
elif hasattr(self, 'OnButtonPTT'):
# what is this for?
self.OnButtonPTT()
def OnSpot(self, level):
if self.key_thread:
self.key_thread.OnSpot(level)
def SetKeyerMode(self, value):
self.keyer_mode = value
if (self.keyer_mode == 0):
QS.set_gpio_keyer_enabled(0)
else:
QS.set_gpio_keyer_enabled(1)
QS.set_gpio_keyer_mode(self.keyer_mode - 1)
def SetKeyerWPM(self, value):
self.keyer_wpm = value
QS.set_gpio_keyer_speed(self.keyer_wpm)
class KeyThread(threading.Thread):
"""Create a thread to monitor the key state."""
def __init__(self, rig, poll_secs, key_hang_time):
self.rig = rig
self.poll_secs = poll_secs
self.key_hang_time = key_hang_time
self.ptt_button = 0
self.spot_level = -1 # level is -1 for Spot button Off; else the Spot level 0 to 1000.
self.currently_in_tx = 0
self.is_cw = False
self.key_timer = 0
self.key_transmit = 0
threading.Thread.__init__(self)
self.doQuit = threading.Event()
self.doQuit.clear()
def run(self):
while not self.doQuit.isSet():
key_down = QS.is_key_down() # get the internal Quisk key state
# in the future, we can have the CW section handled by the H/W key
# line to the RS-HFIQ
if self.is_cw:
pass # this needs to be configurable; however, commenting
# everything below out to test key down via discrete
# if self.spot_level >= 0 or key_down: # key is down
# self.key_transmit = 1
# self.key_timer = time.time() # QSK/semi-QSK, as applicable
# else: # key is up
# #QS.set_key_down(0)
# if self.key_transmit and time.time() - self.key_timer > self.key_hang_time:
# self.key_transmit = 0
# if self.key_transmit != self.currently_in_tx:
# QS.set_transmit_mode(self.key_transmit)
# self.rig.transmit = (self.key_transmit == 1)
# self.currently_in_tx = self.key_transmit # success
# if DEBUG: print ("Change CW currently_in_tx", self.currently_in_tx)
# modes other than CW -- only allow the PTT button (and CAT?)
elif False: # temporarily disabled this chunk...
if self.ptt_button:
self.key_transmit = 1
if self.debug: dprint("[Pi-HFIQ Keyer Thread] non-CW transmit ON")
else:
self.key_transmit = 0
if self.debug: dprint("[Pi-HFIQ Keyer Thread] non-CW transmit OFF")
if self.key_transmit != self.currently_in_tx:
#QS.set_transmit_mode(self.key_transmit)
QS.set_key_down(self.key_transmit)
self.rig.transmit = (self.key_transmit == 1)
self.currently_in_tx = self.key_transmit # success
if DEBUG: print ("Change CW currently_in_tx", self.currently_in_tx)
time.sleep(self.poll_secs)
def stop(self):
"""Set a flag to indicate that the thread should end."""
self.doQuit.set()
def OnPTT(self, ptt):
self.ptt_button = ptt
def OnSpot(self, level):
self.spot_level = level
def IsCW(self, is_cw):
self.is_cw = is_cw
class StatusThread(threading.Thread):
"""Create a thread to monitor various parameters."""
def __init__(self, rig, poll_secs=0.5):
self.rig = rig
self.poll_secs = poll_secs
self.__rig_temp = 0
self.__cpu_temp = 0
self.__cpu_load = 0
self.__mem_load = 0
threading.Thread.__init__(self)
self.doQuit = threading.Event()
self.doQuit.clear()
def run(self):
while not self.doQuit.isSet():
self.__rig_temp = self.rig.temperature
self.__cpu_temp = psutil.sensors_temperatures()['cpu-thermal'][0].current
self.__cpu_load = psutil.cpu_percent()
self.__mem_load = psutil.virtual_memory().percent
time.sleep(self.poll_secs)
def stop(self):
"""Set a flag to indicate that the thread should end."""
self.doQuit.set()
@property
def rig_temp(self):
return self.__rig_temp
@property
def cpu_temp(self):
return self.__cpu_temp
@property
def cpu_load(self):
return self.__cpu_load
@property
def mem_load(self):
return self.__mem_load
########################################################################
# RSHFIQ class
#
# An object that encapsulates all of the functionality associated with
# the RS-HFIQ serial interface. It provides methods and/or properties
# for each of the commands in the RS-HFIQ interface command list, and
# performs all of the necessary serial port operations.
########################################################################
RSHFIQ_OUTPUT_LEVEL = ("off", "2 ma", "4 ma", "6 ma", "8 ma")
class RSHFIQ(object):
def __init__(self, device="/dev/ttyUSB0", output_level=2, debug=0):
"""Create a new RS-HFIQ object, associated with the specified
serial port. Optionally set output level of the VFO, as well as
debug level.
"""
self.serial = serial.Serial()
self.serial.port = device
self.serial.baudrate = 57600
self.serial.bytesize = serial.EIGHTBITS # number of bits per byte
self.serial.parity = serial.PARITY_NONE # set parity check: no parity
self.serial.stopbits = serial.STOPBITS_ONE # number of stop bits
self.serial.timeout = 1 # non-block read
self.serial.rtscts = False
self.debug = debug
self.__version = None
self.__output = output_level
self.__transmit = False
self.__lock = threading.Lock()
if self.debug: dprint("[RS-HFIQ] created new object: ", self.serial.port)
#===================================================================
def open(self):
"""Open the serial port associated with the RS-HFIQ, clear the
input, retrieve the version info, and configure for use.
"""
try:
self.serial.open()
except Exception, e:
print(e)
raise Exception
if self.serial.isOpen():
if self.debug: dprint("[RS-HFIQ] opened device: ", self.serial.port)
self.serial.flushInput() # flush input buffer, discarding all its contents
self.serial.flushOutput() # flush output buffer, aborting current output
# and discard all that is in buffer
time.sleep(1) # wait a moment for init to finish
# BUG: For some reason, I have to set a parameter to the
# RS-HFIQ before I can successfully read version info???
# But I don't have to do this if I just login to the RS-HFIQ
# via a serial terminal...
self.output_level = self.__output
self.transmit = False
if self.debug: dprint("[RS-HFIQ] getting version info")
# TODO: Make this it's own method... retrieving the version.
self.__lock.acquire()
self.serial.write("*W\r")
self.__version = self.serial.readline().strip()
self.__lock.release()
if self.debug: dprint("[RS-HFIQ] firmware version: ", self.__version)
return True
else:
return False
#===================================================================
def close(self):
"""Close the serial port associated with the RS-HFIQ.
"""
if self.serial.isOpen():
self.serial.close()
return True
else:
return False
#-------------------------------------------------------------------
# version - read-only property, returns the version of the RS-HFIQ.
#-------------------------------------------------------------------
@property
def version(self):
if self.debug: dprint("[RS-HFIQ] firmware version: ", self.__version)
return self.__version
#-------------------------------------------------------------------
# frequency - read-write property, sets the tuned frequency (VFO) of
# the RS-HFIQ as specified.
#-------------------------------------------------------------------
@property
def frequency(self):
if self.serial.isOpen():
self.__lock.acquire()
self.serial.write("*F?\r")
freq = self.serial.readline().strip()
self.__lock.release()
if self.debug: dprint("[RS-HFIQ] current tuned frequency: ", freq)
return freq
else:
return None
@frequency.setter
def frequency(self, freq):
if self.serial.isOpen():
self.__lock.acquire()
self.serial.write("*F" + str(freq) + "\r")
self.__lock.release()
if self.debug: dprint("[RS-HFIQ] setting tuned frequency: ", str(freq))
else:
pass
#-------------------------------------------------------------------
# output_level - read-write property, sets output level of the
# RS-HFIQ tuner frequency per the interface definition:
# 0 = off
# 1 = 2 ma drive
# 2 = 4 ma drive
# 3 = 6 ma drive
# 4 = 8 ma drive
#-------------------------------------------------------------------
@property
def output_level(self):
# should probably do some bounds checking on the debug statement
if self.debug: dprint("[RS-HFIQ] current output level: ", RSHFIQ_OUTPUT_LEVEL[self.__output])
return self.__output
@output_level.setter
def output_level(self, output_level):
if self.serial.isOpen():
self.__output = output_level
self.__lock.acquire()
self.serial.write("*OF" + str(self.__output) + "\r")
self.__lock.release()
if self.debug: dprint("[RS-HFIQ] set output level: ", RSHFIQ_OUTPUT_LEVEL[self.__output])
else:
pass
#-------------------------------------------------------------------
# transmit - read-write property, True/False sets the transmit state
# of the RS-HFIQ to ON/OFF.
#-------------------------------------------------------------------
@property
def transmit(self):
if self.debug: dprint("[RS-HFIQ] current transmit state ", "ON" if self.__transmit else "OFF")
return self.__transmit
@transmit.setter
def transmit(self, state):
if self.serial.isOpen():
if state:
self.__lock.acquire()
self.serial.write("*X1\r")
self.__lock.release()
self.__transmit = True
if self.debug: dprint("[RS-HFIQ] set transmit ON")
else:
self.__lock.acquire()
self.serial.write("*X0\r")
self.__lock.release()
self.__transmit = False
if self.debug: dprint("[RS-HFIQ] set transmit OFF")
else:
pass
#-------------------------------------------------------------------
# temperature - read-only property, read from the RS-HFIQ
#-------------------------------------------------------------------
@property
def temperature(self):
if self.serial.isOpen():
self.__lock.acquire()
self.serial.write("*T\r")
temp = self.serial.readline().strip()[:-1]
self.__lock.release()
if self.debug: dprint("[RS-HFIQ] current temperature: ", temp)
return float(temp)
else:
return None
########################################################################
# EOF
########################################################################

111
kc4upr/widgets_pihfiq.py Normal file
View File

@ -0,0 +1,111 @@
########################################################################
# Pi-HFIQ widgets module for Quisk.
#
# Original 'funcube_widget.py' for RS-HFIQ hardware by _____.
#
# Adapted into the "Pi-HFIQ" configuration by Rob French, KC4UPR.
#
# This file provides custom widgets for display in the Quisk window when
# used with an RS-HFIQ. This was specifically defined for the "Pi-HFIQ"
# in which a Raspberry Pi is used with the RS-HFIQ, and Quisk has been
# modified with the GPIO Keyer patch.
#
# TODO as of 2020-04-21:
# (1) Make keyer parameter(s) (mode, speed) saved to a config file auto-
# matically on exit.
# (2) Convert the horizontal sliders to popup sliders. This is mainly
# to fix the goofy cell sizing I get with the GridBagSizer.
#
########################################################################
from __future__ import print_function
import math
import wx
from quisk_widgets import *
import _quisk as QS
class BottomWidgets: # Add extra widgets to the bottom of the screen
def __init__(self, app, hardware, conf, frame, gbs, vertBox):
self.config = conf
self.hardware = hardware
self.application = app
self.start_row = app.widget_row # The first available row
self.start_col = app.button_start_col # The start of the button columns
self.num_rows_added = 1
start_row = self.start_row
bt = app.QuiskCycleCheckbutton(frame, self.OnKeyerMode, hardware.keyer_mode_list)
b = WrapSlider(bt, self.OnKeyerWPM, slider_value=self.hardware.keyer_wpm, slider_min=1, slider_max=60, display=True)
bw, bh = b.GetMinSize()
bt.SetIndex(self.hardware.keyer_mode)
gbs.Add(b, (start_row, self.start_col), (1, 2), flag=wx.EXPAND)
#b = app.SliderBoxHH(frame, '%d wpm', 15, 1, 60, self.OnKeyerWPM, True)
#b.SetValue(self.hardware.keyer_wpm)
#gbs.Add(b, (start_row, self.start_col+2), (1, 3), flag=wx.EXPAND)
b = app.SliderBoxHH(frame, 'Output: %d%%', conf.mic_out_volume, 0, 100, self.OnOutputLevel, True)
b.SetValue(70)
gbs.Add(b, (start_row, self.start_col+2), (1, 3), flag=wx.EXPAND)
self.status_text = app.QuiskText(frame, 'Rig: 100C, CPU: 100C, Proc: 100%, Mem: 100%', bh, wx.ALIGN_CENTER, True)
gbs.Add(self.status_text, (start_row, self.start_col+5), (1, 4), flag=wx.EXPAND)
def OnKeyerMode(self, event):
index = event.GetEventObject().index
self.hardware.SetKeyerMode(index)
def OnKeyerWPM(self, event):
btn = event.GetEventObject()
value = btn.slider_value
print('Keyer WPM: ', value)
self.hardware.SetKeyerWPM(value)
def OnOutputLevel(self, event):
btn = event.GetEventObject()
value = btn.GetValue()
print('Output Level: ', value)
QS.set_mic_out_volume(value)
def UpdateText(self, text):
self.status_text.SetLabel(text)
# lna = app.QuiskCheckbutton(frame, self.OnLNA, 'LNA')
# lna.SetValue( self.hardware.lna )
# gbs.Add(lna, (start_row, self.start_col), (1, 2), flag=wx.EXPAND)
# mixer = app.QuiskCheckbutton(frame, self.OnMixer, 'Mixer gain')
# mixer.SetValue( self.hardware.mixer )
# gbs.Add(mixer, (start_row, self.start_col+2), (1, 2), flag=wx.EXPAND)
# gain = app.SliderBoxHH(frame, 'If gain %d dB', 0, 0, 59, self.OnIF, True)
# gain.SetValue(self.hardware.ifgain)
# gbs.Add(gain,(start_row, self.start_col+4),(1,4), flag=wx.EXPAND)
# def OnLNA(self, event):
# btn = event.GetEventObject()
# if btn.GetValue() :
# value = 1
# else :
# value = 0
# print('LNA: ',value)
# self.hardware.SetLNA(value)
# def OnMixer(self, event):
# btn = event.GetEventObject()
# if btn.GetValue() :
# value = 1
# else :
# value = 0
# print('Mixer: ',value)
# self.hardware.SetMixer(value)
# def OnIF(self,event) :
# btn = event.GetEventObject()
# value = btn.GetValue()
# print('IF: ', value )
# self.hardware.SetIfGain(value)

View File

@ -7,11 +7,13 @@ quisk2:
python2 setup.py build_ext --force --inplace
@echo
@echo 'Use "make soapy2" to make the Python2 soapy module'
@echo 'Use "make perseus2" to make the Python2 perseus package'
quisk3:
python3 setup.py build_ext --force --inplace
@echo
@echo 'Use "make soapy3" to make the Python3 soapy module'
@echo 'Use "make perseus3" to make the Python3 perseus package'
soapy2:
(cd soapypkg; make soapy2)
@ -19,5 +21,11 @@ soapy2:
soapy3:
(cd soapypkg; make soapy3)
perseus2:
(cd perseuspkg; make perseus2)
perseus3:
(cd perseuspkg; make perseus3)
macports:
env ARCHFLAGS="-arch x86_64" python setup.py build_ext --force --inplace -D USE_MACPORTS

10
perseuspkg/README.txt Executable file
View File

@ -0,0 +1,10 @@
Microtelecom Perseus HF receiver
Prerequisite are:
libusb-1.0-0-dev (found in all major Linux distro)
libperseus-sdr as found in https://github.com/Microtelecom/libperseus-sdr/archive/master.zip

1
perseuspkg/__init__.py Executable file
View File

@ -0,0 +1 @@
#

7
perseuspkg/makefile Executable file
View File

@ -0,0 +1,7 @@
perseus2:
python2 setup.py build_ext --force --inplace
perseus3:
python3 setup.py build_ext --force --inplace

498
perseuspkg/perseus.c Executable file
View File

@ -0,0 +1,498 @@
/*
*
* Microtelecom perseus HF receiver
*
* access module: exposes Python functions needed in quisk_hardware.py
* to control hardware
*
*/
#include <Python.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <complex.h>
#include <perseus-sdr.h>
#define IMPORT_QUISK_API
#include "quisk.h"
#include "filter.h"
// This module was written by Andrea Montefusco IW0HDV.
typedef union {
struct {
int32_t i;
int32_t q;
} __attribute__((__packed__)) iq;
struct {
uint8_t i1;
uint8_t i2;
uint8_t i3;
uint8_t i4;
uint8_t q1;
uint8_t q2;
uint8_t q3;
uint8_t q4;
} __attribute__((__packed__)) ;
} iq_sample;
// buffer size for libperseus-sdr
const static int nb = 6;
const static int bs = 1024;
// This module uses the Python interface to import symbols from the parent _quisk
// extension module. It must be linked with import_quisk_api.c. See the documentation
// at the start of import_quisk_api.c.
#define DEBUG 1
static int num_perseus = 0;
static perseus_descr *descr = 0;
static int sr = 48000;
static float freq = 7050000.0;
static int adc_dither = 0;
static int adc_preamp = 0;
static void quisk_stop_samples(void);
static const char *fname = "/tmp/quiskperseus";
static int rfd = 0;
static int wfd = 0;
static int running = 0;
static int wb_filter = 0;
// Called in a loop to read samples; called from the sound thread.
static int quisk_read_samples(complex double * cSamples)
{
//fprintf (stderr, "r"); fflush(stderr);
int n = read(rfd, cSamples, sizeof(complex double)*SAMP_BUFFER_SIZE);
//fprintf(stderr, "%d ", n);
if (n >= 0)
return n/sizeof(complex double); // return number of samples
else
return 0;
}
// Called in a loop to write samples; called from the sound thread.
static int quisk_write_samples(complex double * cSamples, int nSamples)
{
return 0;
}
//
// callback that writes in the output pipe IQ values as
// complex floating point
//
static int user_data_callback_c_f(void *buf, int buf_size, void *extra)
{
// The buffer received contains 24-bit IQ samples (6 bytes per sample)
// Here we save the received IQ samples as 32 bit
// (msb aligned) integer IQ samples.
uint8_t *samplebuf = (uint8_t*)buf;
int nSamples = buf_size/6;
int k;
iq_sample s;
// the 24 bit data is scaled to a 32bit value (so that the machine's
// natural signed arithmetic will work)
for (k=0; k < nSamples; k++) {
s.i1 = s.q1 = 0;
s.i2 = *samplebuf++;
s.i3 = *samplebuf++;
s.i4 = *samplebuf++;
s.q2 = *samplebuf++;
s.q3 = *samplebuf++;
s.q4 = *samplebuf++;
// move I/Q to complex number
complex double x = (double)(s.iq.i)*10 + (double)(s.iq.q)*10 * _Complex_I;
if (wfd > 0) {
int n = write(wfd, &x, sizeof(complex double));
if (n<0 && ! -EAGAIN )
fprintf(stderr, "perseus c: Can't write output file: %s, descriptor: %d\n", strerror(errno), wfd);
}
}
return 0;
}
// Start sample capture; called from the sound thread.
static void quisk_start_samples(void)
{
fprintf (stderr, "perseus c: quisk_start_samples\n"); fflush(stderr);
int rc = mkfifo(fname, 0666);
if ((rc == -1) && (errno != EEXIST)) {
perror("perseus c: Error creating the named pipe");
}
rfd = open(fname, O_RDONLY|O_NONBLOCK);
if (rfd < 0) fprintf(stderr, "perseus c: Can't open read FIFO (%s)\n", strerror(errno));
else fprintf(stderr, "perseus c: read FIFO (%d)\n", rfd);
wfd = open(fname, O_WRONLY|O_NONBLOCK);
if (wfd < 0) fprintf(stderr, "perseus c: Can't open write FIFO (%s)\n", strerror(errno));
else fprintf(stderr, "perseus c: write FIFO (%d)\n", wfd);
if (perseus_set_sampling_rate(descr, sr) < 0) { // specify the sampling rate value in Samples/second
fprintf(stderr, "perseus c: fpga configuration error: %s\n", perseus_errorstr());
} else {
fprintf(stderr, "perseus c: sampling rate set to: %d\n", sr);
// Re-enable preselection filters (WB_MODE Off)
perseus_set_ddc_center_freq(descr, freq, wb_filter);
// start sampling ops
if (perseus_start_async_input(descr, nb*bs, user_data_callback_c_f, 0)<0) {
fprintf(stderr, "perseus c: start async input error: %s\n", perseus_errorstr());
} else
fprintf(stderr, "perseus c: start async input\n");
running = 1;
}
}
// Stop sample capture; called from the sound thread.
static void quisk_stop_samples(void)
{
fprintf (stderr, "perseus c: quisk_stop_samples\n"); fflush(stderr);
// We stop the acquisition...
fprintf(stderr, "perseus c: stopping async data acquisition...\n");
perseus_stop_async_input(descr);
running = 0;
// clearing FIFO...
close(rfd);
close(wfd);
unlink(fname);
}
// Called to close the sample source; called from the GUI thread.
static PyObject * close_device(PyObject * self, PyObject * args)
{
fprintf (stderr, "perseus c: close_device\n");
int sample_device; // for now one only Perseus can be managed
if (!PyArg_ParseTuple (args, "i", &sample_device))
return NULL;
if (descr) {
// We stop the acquisition...
if (running) {
perseus_stop_async_input(descr);
running = 0;
}
perseus_close(descr);
descr = 0;
}
Py_INCREF (Py_None);
return Py_None;
}
// Called to open the Perseus SDR device; called from the GUI thread.
static PyObject * open_device(PyObject * self, PyObject * args)
{
char buf128[128] = "Capture Microtelecom Perseus HF receiver";
eeprom_prodid prodid;
fprintf (stderr, "perseus c: open device (%d)\n", num_perseus); fflush(stderr);
// Check how many Perseus receivers are connected to the system
if (num_perseus == 0) num_perseus = perseus_init();
fprintf(stderr, "perseus c: %d Perseus receivers found\n",num_perseus);
if (num_perseus == 0) {
sprintf(buf128, "No Perseus receivers detected\n");
perseus_exit();
goto main_cleanup;
}
// Open the first one...
if ((descr = perseus_open(0)) == NULL) {
sprintf(buf128, "error: %s\n", perseus_errorstr());
fprintf(stderr, "perseus c: open error: %s\n", perseus_errorstr());
goto main_cleanup;
}
// Download the standard firmware to the unit
fprintf(stderr, "perseus c: Downloading firmware...\n");
if (perseus_firmware_download(descr,NULL)<0) {
sprintf(buf128, "perseus c: firmware download error: %s", perseus_errorstr());
goto main_cleanup;
}
// Dump some information about the receiver (S/N and HW rev)
if (perseus_is_preserie(descr, 0) == PERSEUS_SNNOTAVAILABLE)
fprintf(stderr, "perseus c: The device is a preserie unit");
else
if (perseus_get_product_id(descr,&prodid)<0)
fprintf(stderr, "perseus c: get product id error: %s", perseus_errorstr());
else
fprintf(stderr, "perseus c: Receiver S/N: %05d-%02hX%02hX-%02hX%02hX-%02hX%02hX - HW Release:%hd.%hd\n",
(uint16_t) prodid.sn,
(uint16_t) prodid.signature[5],
(uint16_t) prodid.signature[4],
(uint16_t) prodid.signature[3],
(uint16_t) prodid.signature[2],
(uint16_t) prodid.signature[1],
(uint16_t) prodid.signature[0],
(uint16_t) prodid.hwrel,
(uint16_t) prodid.hwver);
// Printing all sampling rates available .....
{
int buf[BUFSIZ];
if (perseus_get_sampling_rates (descr, buf, sizeof(buf)/sizeof(buf[0])) < 0) {
fprintf(stderr, "perseus c: get sampling rates error: %s\n", perseus_errorstr());
goto main_cleanup;
} else {
int i = 0;
while (buf[i]) {
fprintf(stderr, "perseus c: #%d: sample rate: %d\n", i, buf[i]);
i++;
}
}
}
// Configure the receiver for 2 MS/s operations
fprintf(stderr, "perseus c: Configuring FPGA...\n");
if (perseus_set_sampling_rate(descr, sr) < 0) { // specify the sampling rate value in Samples/second
//if (perseus_set_sampling_rate_n(descr, 0)<0) // specify the sampling rate value as ordinal in the vector
fprintf(stderr, "perseus c: fpga configuration error: %s\n", perseus_errorstr());
goto main_cleanup;
}
// ADC settings
perseus_set_adc (descr, adc_dither, adc_preamp);
// Disable preselection filters (WB_MODE On)
//perseus_set_ddc_center_freq(descr, freq, 0);
//sleep(1);
// Re-enable preselection filters (WB_MODE Off)
perseus_set_ddc_center_freq(descr, freq, wb_filter);
quisk_sample_source4(&quisk_start_samples, &quisk_stop_samples, &quisk_read_samples, &quisk_write_samples);
fprintf (stderr, "perseus c: quisk sample source callbacks established\n"); fflush(stderr);
goto exit_success;
main_cleanup:
return PyString_FromString("ERROR");
exit_success:
return PyString_FromString(buf128);
}
static PyObject * set_frequency(PyObject * self, PyObject * args) // Called from GUI thread
{
float param;
if (!PyArg_ParseTuple (args, "f", &param))
return NULL;
if (DEBUG)
fprintf (stderr, "perseus c: set DDC frequency%lf\n", param);
freq= param;
if (descr) perseus_set_ddc_center_freq(descr, freq, wb_filter == 0);
Py_INCREF (Py_None);
return Py_None;
}
static PyObject * set_input_filter(PyObject * self, PyObject * args) // Called from GUI thread
{
int param;
if (!PyArg_ParseTuple (args, "i", &param))
return NULL;
if (DEBUG)
fprintf (stderr, "perseus c: set input filter%d\n", param);
wb_filter = param;
if (descr) perseus_set_ddc_center_freq(descr, freq, wb_filter == 0);
Py_INCREF (Py_None);
return Py_None;
}
static PyObject * set_sampling_rate(PyObject * self, PyObject * args) // Called from GUI thread
{
int param;
if (!PyArg_ParseTuple (args, "i", &param))
return NULL;
fprintf (stderr, "perseus c: Set sampling rate %d\n", param);
if (param < 48000) sr = param * 1000;
else sr = param;
if (descr) {
if (running) {
fprintf(stderr, "perseus c: stop async input\n");
perseus_stop_async_input(descr);
}
// specify the sampling rate value in Samples/secon
if (perseus_set_sampling_rate(descr, sr) < 0) {
fprintf(stderr, "perseus c: fpga configuration error: %s\n", perseus_errorstr());
}
if (running) {
if (perseus_start_async_input(descr, nb*bs, user_data_callback_c_f, 0)<0) {
fprintf(stderr, "perseus c: start async input error: %s\n", perseus_errorstr());
} else
fprintf(stderr, "perseus c: start async input @%d\n", sr);
}
} else {
fprintf(stderr, "perseus c: tryng to start async input with no device open\n");
}
Py_INCREF (Py_None);
return Py_None;
}
static PyObject * set_attenuator(PyObject * self, PyObject * args) // Called from GUI thread
{ int param;
if (!PyArg_ParseTuple (args, "i", &param))
return NULL;
if (DEBUG)
fprintf (stderr, "perseus c: Set attenuator %d\n", param);
if (descr) {
// specify the sampling rate value in Samples/secon
if (perseus_set_attenuator_n(descr, (int)(param / -10)) < 0) {
fprintf(stderr, "perseus c: fpga configuration error: %s\n", perseus_errorstr());
}
}
Py_INCREF (Py_None);
return Py_None;
}
// Enable ADC Dither, Disable ADC Preamp
// perseus_set_adc(descr, true, false);
static PyObject * set_adc_dither (PyObject * self, PyObject * args) // Called from GUI thread
{ int dither_;
if (!PyArg_ParseTuple (args, "i", &dither_))
return NULL;
if (DEBUG)
fprintf (stderr, "perseus c: Set ADC: dither %d\n", dither_);
adc_dither = dither_;
if (descr) {
// specify the ADC dithering
if (perseus_set_adc(descr, adc_dither == 1, adc_preamp == 1) < 0) {
fprintf(stderr, "perseus c: ADC configuration error: %s\n", perseus_errorstr());
}
}
Py_INCREF (Py_None);
return Py_None;
}
static PyObject * set_adc_preamp (PyObject * self, PyObject * args) // Called from GUI thread
{ int preamp_;
if (!PyArg_ParseTuple (args, "i", &preamp_))
return NULL;
if (DEBUG)
fprintf (stderr, "perseus c: Set ADC: preamp: %d\n", preamp_);
adc_preamp = preamp_;
if (descr) {
// specify the sampling rate value in Samples/secon
if (perseus_set_adc(descr, adc_dither == 1, adc_preamp == 1) < 0) {
fprintf(stderr, "perseus c: ADC configuration error: %s\n", perseus_errorstr());
}
}
Py_INCREF (Py_None);
return Py_None;
}
static PyObject * deinit(PyObject * self, PyObject * args) // Called from dctor
{
perseus_exit();
Py_INCREF (Py_None);
return Py_None;
}
// Functions callable from Python are listed here:
static PyMethodDef QuiskMethods[] = {
{"open_device", open_device, METH_VARARGS, "Open the hardware."},
{"close_device", close_device, METH_VARARGS, "Close the hardware"},
{"set_frequency", set_frequency, METH_VARARGS, "set frequency"},
{"set_input_filter", set_input_filter, METH_VARARGS, "set input filter"},
{"set_sampling_rate", set_sampling_rate, METH_VARARGS, "set sampling rate"},
{"set_attenuator", set_attenuator, METH_VARARGS, "set attenuator"},
{"set_adc_dither", set_adc_dither, METH_VARARGS, "set ADC dither"},
{"set_adc_preamp", set_adc_preamp, METH_VARARGS, "set ADC preamplifier"},
{"deinit", deinit, METH_VARARGS, "deinit"},
// {"get_device_list", get_device_list, METH_VARARGS, "Return a list of Perseus SDR devices"},
{NULL, NULL, 0, NULL} /* Sentinel */
};
#if PY_MAJOR_VERSION < 3
// Python 2.7:
// Initialization, and registration of public symbol "initperseus":
PyMODINIT_FUNC initperseus (void)
{
if (Py_InitModule ("perseus", QuiskMethods) == NULL) {
fprintf(stderr, "perseus c: Py_InitModule failed!\n");
return;
}
// Import pointers to functions and variables from module _quisk
if (import_quisk_api()) {
fprintf(stderr, "perseus c: Failure to import pointers from _quisk\n");
return; //Error
}
}
// Python 3:
#else
static struct PyModuleDef perseusmodule = {
PyModuleDef_HEAD_INIT,
"perseus",
NULL,
-1,
QuiskMethods
} ;
PyMODINIT_FUNC PyInit_perseus(void)
{
PyObject * m;
m = PyModule_Create(&perseusmodule);
if (m == NULL)
return NULL;
// Import pointers to functions and variables from module _quisk
if (import_quisk_api()) {
fprintf(stderr, "perseus c: Failure to import pointers from _quisk\n");
return m; //Error
}
return m;
}
#endif

188
perseuspkg/quisk_hardware.py Executable file
View File

@ -0,0 +1,188 @@
# This is the hardware file to support radios accessed by the PerseusSDR interface.
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import socket, traceback, time, math
import _quisk as QS
try:
from perseuspkg import perseus
except:
#traceback.print_exc()
perseus = None
print ("Error: Perseus package not found.\n")
from quisk_hardware_model import Hardware as BaseHardware
DEBUG = 1
# Define the name of the hardware and the items on the hardware screen (see quisk_conf_defaults.py):
################ Receivers PerseusSDR, The PerseusSDR interface to multiple hardware SDRs.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'perseuspkg/quisk_hardware.py'
## widgets_file_name Widget file path, rfile
# This optional file adds additional controls for the radio.
#widgets_file_name = 'perseuspkg/quisk_widgets.py'
class Hardware(BaseHardware):
def __init__(self, app, conf):
BaseHardware.__init__(self, app, conf)
self.rf_gain_labels = ('RF +0', 'RF -10', 'RF -20', 'RF -30')
self.antenna_labels = ('Wide Band', 'Band Filter')
self.vardecim_index = 0
self.fVFO = 0.0 # Careful, this is a float
print ("__init__: %s" % conf)
self.rates = [ 48000, \
95000, \
96000, \
125000, \
192000, \
250000, \
500000, \
1000000, \
1600000, \
2000000 \
]
self.current_rate = 192000
self.att = 0;
self.wb = 0
def __del__(self):
# try to clear hardware
if perseus:
perseus.close()
perseus.deinit()
def get_hw (self):
return perseus
def pre_open(self):
print ("pre_open")
pass
def set_parameter(self, *args):
pass
def open(self): # Called once to open the Hardware
if not perseus:
return "Perseus module not available"
txt = perseus.open_device("perseus",2,3)
print ("perseus hardware: open")
return txt
def close(self): # Called once to close the Hardware
print ("perseus hardware: close")
if perseus:
perseus.close_device(1)
def ChangeGain(self, rxtx): # rxtx is '_rx' or '_tx'
if not perseus:
return
print ("perseus hardware: ChangeGain", rxtx)
pass
def OnButtonRfGain(self, event):
#btn = event.GetEventObject()
n = event.GetEventObject().index
self.att = n * -10
print ("perseus hardware: OnButtonRfGain: %d new attenuation: %d" % (n, self.att))
perseus.set_attenuator (self.att)
def ChangeFrequency(self, tune, vfo, source='', band='', event=None):
fVFO = float(vfo)
if self.fVFO != fVFO:
self.fVFO = fVFO
perseus.set_frequency(fVFO)
return tune, vfo
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 None, None # frequencies have not changed
def ReturnVfoFloat(self):
# Return the accurate VFO frequency as a floating point number.
# You can return None to indicate that the integer VFO frequency is valid.
return self.fVFO
# def OnBtnFDX(self, fdx): # fdx is 0 or 1
# pass
#
# def OnButtonPTT(self, event):
# pass
#
# def OnSpot(self, level):
# # level is -1 for Spot button Off; else the Spot level 0 to 1000.
# pass
#
# def ChangeMode(self, mode): # Change the tx/rx mode
# # mode is a string: "USB", "AM", etc.
# pass
#
# def ChangeBand(self, band):
# pass
#
# def HeartBeat(self): # Called at about 10 Hz by the main
# pass
def ImmediateChange(self, name, value):
print ("perseus hardware: ImmediateChange: perseus: name: %s value: %s" % (name, value))
if name == 'perseus_setSampleRate_rx':
value = int(value)
self.application.OnBtnDecimation(rate=value)
perseus.set_sampling_rate(value)
self.curren_dec = value
def VarDecimGetChoices(self): # Not used to set sample rate
print ("perseus hardware: VarDecimGetChoices")
return list(map(str, self.rates)) # convert integer to string
def VarDecimGetLabel(self): # Return a text label for the decimation control.
return 'Sample rates: '
def VarDecimGetIndex(self): # Return the index 0, 1, ... of the current decimation.
for i in range(len(self.rates)):
if self.rates[i] == self.current_rate:
return i
return 0
def VarDecimSet(self, index=None): # Called when the control is operated; if index==None, called on startup.
print ("perseus hardware: VarDecimSet: index: %s" % (index))
if index == None:
print ("perseus hardware: VarDecimSet: current sampling rate: %d" % self.current_rate)
new_rate = self.current_rate = self.application.vardecim_set
else:
new_rate = self.rates[index]
print ("perseus hardware: VarDecimSet: New sampling rate: %d" % new_rate)
perseus.set_sampling_rate(int(new_rate))
self.current_rate = int(new_rate)
return int(new_rate)
def VarDecimRange(self): # Return the lowest and highest sample rate.
print ("perseus hardware: VarDecimRange: %s" % self.rates)
return (self.rates[0], self.rates[-1])
def OnButtonAntenna(self, event):
btn = event.GetEventObject()
self.wb_filter = n = btn.index
print ("OnButtonAntenna: %d" % n)
perseus.set_input_filter (self.wb_filter)
# def StartSamples(self): # called by the sound thread
# print("perseus hardware: StartSamples")
# def StopSamples(self): # called by the sound thread
# print("perseus hardware: StopSamples")

37
perseuspkg/quisk_widgets.py Executable file
View File

@ -0,0 +1,37 @@
# Please do not change this widgets module for Quisk. Instead copy
# it to your own quisk_widgets.py and make changes there.
#
# This module is used to add extra widgets to the QUISK screen.
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import math, wx
class BottomWidgets: # Add extra widgets to the bottom of the screen
def __init__(self, app, hardware, conf, frame, gbs, vertBox):
self.config = conf
self.hardware = hardware
self.application = app
self.start_row = app.widget_row # The first available row
self.start_col = app.button_start_col # The start of the button columns
self.Widgets_0x06(app, hardware, conf, frame, gbs, vertBox)
def Widgets_0x06(self, app, hardware, conf, frame, gbs, vertBox):
self.num_rows_added = 1
start_row = self.start_row
b1 = app.QuiskCheckbutton(frame, self.OnADC_dither, 'ADC Dither')
gbs.Add(b1, (start_row, self.start_col), (1, 2), flag=wx.EXPAND)
b2 = app.QuiskCheckbutton(frame, self.OnADC_preamp, 'ADC Preamp')
gbs.Add(b2, (start_row, self.start_col + 2), (1, 2), flag=wx.EXPAND)
def OnADC_dither(self, event):
btn = event.GetEventObject()
value = btn.GetValue()
self.hardware.get_hw().set_adc_dither (value)
def OnADC_preamp(self, event):
btn = event.GetEventObject()
value = btn.GetValue()
self.hardware.get_hw().set_adc_preamp (value)

48
perseuspkg/setup.py Executable file
View File

@ -0,0 +1,48 @@
from distutils.core import setup, Extension
import sys
module2 = Extension ('perseus',
libraries = ['m', 'perseus-sdr'],
sources = ['../import_quisk_api.c', 'perseus.c'],
include_dirs = ['.', '..'],
)
modulew2 = Extension ('perseus',
sources = ['../import_quisk_api.c', 'perseus.c'],
include_dirs = ['.', '..'],
libraries = ['WS2_32', 'perseus-sdr'],
)
if sys.platform == "win32":
Modules = [modulew2]
else:
Modules = [module2]
setup (name = 'perseus',
version = '0.1',
description = 'perseus is an extension to Quisk to support Microtelecom Perseus SDR hardware',
long_description = """Microtelecom Perseus SDR HF receiver.
""",
author = 'Andrea Montefusco IW0HDV',
author_email = 'andrew@montefusco.com',
url = 'http://www.montefusco.com',
download_url = 'http://james.ahlstrom.name/quisk/',
packages = ['quisk.perseuspkg'],
package_dir = {'perseus' : '.'},
ext_modules = Modules,
classifiers = [
'Development Status :: 6 - Mature',
'Environment :: X11 Applications',
'Environment :: Win32 (MS Windows)',
'Intended Audience :: End Users/Desktop',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Natural Language :: English',
'Operating System :: POSIX :: Linux',
'Operating System :: Microsoft :: Windows',
'Programming Language :: Python',
'Programming Language :: C',
'Topic :: Communications :: Ham Radio',
],
)

View File

@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: quisk
Version: 4.1.53
Version: 4.1.56
Summary: QUISK is a Software Defined Radio (SDR) transceiver that can control various radio hardware.
Home-page: http://james.ahlstrom.name/quisk/
Author: James C. Ahlstrom

View File

@ -19,6 +19,7 @@ filters.h
filters.py
freedv.c
freedv.h
gpiokeyer.c
help.html
help_conf.html
help_vna.html
@ -55,6 +56,7 @@ quisk_hardware_sdrmicron.py
quisk_utils.py
quisk_vna.py
quisk_widgets.py
setup.cfg
setup.py
softrock_tune_vfo.py
sound.c
@ -70,6 +72,7 @@ winsound.txt
./README.txt
./__init__.py
./__main__.py
./_quisk.so
./configure.py
./defaults.html
./docs.html
@ -109,6 +112,7 @@ winsound.txt
./afedrinet/SOURCE.txt
./afedrinet/__init__.py
./afedrinet/afedri.py
./afedrinet/afedrinet_io.so
./afedrinet/quisk_conf.py
./afedrinet/quisk_conf_linux.py
./afedrinet/quisk_conf_mac.py
@ -151,9 +155,17 @@ winsound.txt
./n2adr/uhf_conf.py
./n2adr/uhf_hardware.py
./n2adr/uhf_widgets.py
./perseuspkg/README.txt
./perseuspkg/__init__.py
./perseuspkg/quisk_hardware.py
./perseuspkg/quisk_widgets.py
./perseuspkg/setup.py
./sdriqpkg/README.txt
./sdriqpkg/__init__.py
./sdriqpkg/quisk_hardware.py
./sdriqpkg/sdriq.so
./sdrmicronpkg/__init__.py
./sdrmicronpkg/quisk_hardware.py
./soapypkg/__init__.py
./soapypkg/quisk_hardware.py
./soapypkg/setup.py
@ -168,11 +180,14 @@ winsound.txt
./softrock/widgets_tx.py
afedrinet/SOURCE.txt
afedrinet/__init__.py
afedrinet/af_comp.bat
afedrinet/af_comp.bat.makeit
afedrinet/afe_library
afedrinet/afe_library.mac
afedrinet/afedri.py
afedrinet/afedrinet_io.c
afedrinet/afedrinet_io.pyd
afedrinet/afedrinet_io.so
afedrinet/quisk_conf.py
afedrinet/quisk_conf_linux.py
afedrinet/quisk_conf_mac.py
@ -217,6 +232,13 @@ n2adr/uhf_conf.py
n2adr/uhf_hardware.old
n2adr/uhf_hardware.py
n2adr/uhf_widgets.py
perseuspkg/README.txt
perseuspkg/__init__.py
perseuspkg/makefile
perseuspkg/perseus.c
perseuspkg/quisk_hardware.py
perseuspkg/quisk_widgets.py
perseuspkg/setup.py
quisk.egg-info/PKG-INFO
quisk.egg-info/SOURCES.txt
quisk.egg-info/dependency_links.txt
@ -228,6 +250,9 @@ sdriqpkg/quisk_hardware.py
sdriqpkg/sdriq.c
sdriqpkg/sdriq.h
sdriqpkg/sdriq.pyd
sdriqpkg/sdriq.so
sdrmicronpkg/__init__.py
sdrmicronpkg/quisk_hardware.py
soapypkg/__init__.py
soapypkg/makefile
soapypkg/quisk_hardware.py

View File

@ -3717,7 +3717,7 @@ class App(wx.App):
self.mode = conf.default_mode
self.color_list = None
self.color_index = 0
self.vardecim_set = None
self.vardecim_set = 48000
self.w_phase = None
self.zoom = 1.0
self.filter_bandwidth = 1000 # filter bandwidth
@ -3976,7 +3976,7 @@ The new code supports multiple corrections per band.""")
self.OpenSound()
tune, vfo = Hardware.ReturnFrequency() # Request initial frequency
if tune is None or vfo is None: # Set last-used frequency
self.bandBtnGroup.SetLabel(self.lastBand, do_cmd=True)
self.bandBtnGroup.SetLabel(self.lastBand, do_cmd=True, direction=0)
else: # Set requested frequency
self.BandFromFreq(tune)
self.ChangeDisplayFrequency(tune - vfo, vfo)

View File

@ -1670,7 +1670,7 @@ freedv_tx_msg = ''
# This is the list of FreeDV modes and their index number. The starting mode is the first listed.
freedv_modes = (('Mode 1600', 0), ('Mode 700', 1), ('Mode 700B', 2),
# ('Mode 2400A', 3), ('Mode 2400B', 4), ('Mode 800XA', 5),
('Mode 700C', 6), ('Mode 700D', 7), ('Future8', 8), ('Future9', 9))
('Mode 700C', 6), ('Mode 700D', 7), ('Mode 2020', 8), ('Future9', 9), ('Future10', 10))
# These are the filter bandwidths for each mode. Quisk has built-in optimized filters
# for these values, but you can change them if you want.

View File

@ -1101,7 +1101,7 @@ class RadioButtonGroup:
button.button.command = self.OnButton
else:
button.command = self.OnButton
def SetLabel(self, label, do_cmd=False):
def SetLabel(self, label, do_cmd=False, direction=None):
self.button = None
for b in self.buttons:
if self.button is not None:
@ -1116,6 +1116,8 @@ class RadioButtonGroup:
b.SetIndex(index)
self.button = b
b.SetValue(True)
if direction is not None:
b.direction = direction
elif b.GetLabel() == label:
b.SetValue(True)
self.button = b
@ -1289,7 +1291,7 @@ class RadioBtnPopup:
break
def GetLabel(self):
return self.first_button.GetLabel()
def SetLabel(self, label, do_cmd=False):
def SetLabel(self, label, do_cmd=False, direction=None):
self.first_button.SetLabel(label)
self.AddSecondButton(label)
self.RbDialog.RbGroup.SetLabel(label, False)

1
sdrmicronpkg/__init__.py Executable file
View File

@ -0,0 +1 @@
#

266
sdrmicronpkg/quisk_hardware.py Executable file
View File

@ -0,0 +1,266 @@
# -*- coding: cp1251 -*-
#
# It provides support for the SDR Micron
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import sys, wx, traceback
import ftd2xx as d2xx
import time
from quisk_hardware_model import Hardware as BaseHardware
DEBUG = 0
# https://github.com/Dfinitski/SDR-Micron
#
# RX control, to device, 32 bytes total
# Preamble + 'RX0' + enable + rate + 4 bytes frequency + attenuation + 14 binary zeroes
#
# where:
# Preamble is 7*0x55, 0xd5
# bytes:
# enable - binary 0 or 1, for enable receiver
# rate:
# binary
# 0 for 48 kHz
# 1 for 96 kHz
# 2 for 192 kHz
# 3 for 240 kHz
# 4 for 384 kHz
# 5 for 480 kHz
# 6 for 640 kHz
# 7 for 768 kHz
# 8 for 960 kHz
# 9 for 1536 kHz
# 10 for 1920 kHz
#
# frequency - 32 bits of tuning frequency, MSB is first
# attenuation - binary 0, 10, 20, 30 for needed attenuation
#
# RX data, to PC, 508 bytes total
# Preamble + 'RX0' + FW1 + FW2 + CLIP + 2 zeroes + 492 bytes IQ data
#
# Where:
# FW1 and FW2 - char digits firmware version number
# CLIP - ADC overflow indicator, 0 or 1 binary
# IQ data for 0 - 7 rate:
# 82 IQ pairs formatted as "I2 I1 I0 Q2 Q1 Q0.... ", MSB is first, 24 bits per sample
# IQ data for 8 - 10 rate:
# 123 IQ pairs formatted as "I1 I0 Q1 Q0..... ", MSB is first, 16 bits per sample
#
# Band Scope control, to device, 32 bytes total
# Preamble + 'BS0' + enable + period + 19 binary zeroes
#
# Where period is the full frame period in ms, from 50 to 255ms, 100ms is recommended
# for 10Hz refresh rate window.
#
# Band Scope data, to PC, 16384 16bit samples, 32768 bytes by 492 in each packet
# Preamble + 'BS0' + FW1 + FW2 + CLIP + PN + 1 zero + 492 bytes BS data
#
# Where PN is packet number 0, 1, 2, ..., 66
# BS data in format "BS1, BS0, BS1, BS0, ...", MSB is first
#
# 66 packets with PN = 0 - 65 contain 492 bytes each, and 67-th packet with PN = 66 contains
# the remaining 296 bytes of data and junk data to full 492 bytes size
#
# Define the name of the hardware and the items on the hardware screen (see quisk_conf_defaults.py):
################ Receivers SdrMicron, The SDR Micron project by David Fainitski.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'sdrmicronpkg/quisk_hardware.py'
class Hardware(BaseHardware):
sample_rates = [48, 96, 192, 240, 384, 480, 640 ,768, 960, 1536, 1920]
def __init__(self, app, conf):
BaseHardware.__init__(self, app, conf)
self.device = None
self.usb = None
self.rf_gain_labels = ('RF +10', 'RF 0', 'RF -10', 'RF -20')
self.index = 1
self.enable = 0
self.rate = 0
self.att = 10
self.freq = 7220000
self.old_freq = 0
self.sdrmicron_clock = 76800000
self.sdrmicron_decim = 1600
self.bscope_data = bytearray(0)
self.fw_ver = None
self.frame_msg = ''
if conf.fft_size_multiplier == 0:
conf.fft_size_multiplier = 3 # Set size needed by VarDecim
rx_bytes = 3 # rx_bytes is the number of bytes in each I or Q sample: 1, 2, 3, or 4
rx_endian = 1 # rx_endian is the order of bytes in the sample array: 0 == little endian; 1 == big endian
self.InitSamples(rx_bytes, rx_endian) # Initialize: read samples from this hardware file and send them to Quisk
bs_bytes = 2
bs_endian = 1
self.InitBscope(bs_bytes, bs_endian, self.sdrmicron_clock, 16384) # Initialize bandscope
def open(self): # This method must return a string showing whether the open succeeded or failed.
enum = d2xx.createDeviceInfoList() # quantity of FTDI devices
if(enum==0):
return 'Device was not found'
for i in range(enum): # Searching and openinq needed device
a = d2xx.getDeviceInfoDetail(i)
if(a['description']==b'SDR-Micron'):
try: self.usb = d2xx.openEx(a['serial'])
except:
return 'Device was not found'
Mode = 64 # Configure FT2232H into 0x40 Sync FIFO Mode
self.usb.setBitMode(255, 0) # reset
time.sleep(0.1)
self.usb.setBitMode(255, Mode) #configure FT2232H into Sync FIFO mode
self.usb.setTimeouts(100, 100) # read, write
self.usb.setLatencyTimer(2)
self.usb.setUSBParameters(32, 32) # in_tx_size, out_tx_size
time.sleep(1.5) # waiting for initialisation device
data = self.usb.read(self.usb.getQueueStatus()) # clean the usb data buffer
self.device = 'Opened'
self.frame_msg = a['description'].decode('utf-8') + ' S/N - ' + a['serial'].decode('utf-8')
return self.frame_msg
return 'Device was not found'
def close(self):
if(self.usb):
if(self.device=='Opened'):
enable = 0
self.device = None
self.rx_control_upd()
time.sleep(0.5)
self.usb.setBitMode(255, 0) # reset
self.usb.close()
def OnButtonRfGain(self, event):
btn = event.GetEventObject()
n = btn.index
self.att = n * 10
self.rx_control_upd()
def ChangeFrequency(self, tune, vfo, source='', band='', event=None):
if vfo:
self.freq = (vfo - self.transverter_offset)
if(self.freq!=self.old_freq):
self.old_freq = self.freq
self.rx_control_upd()
return tune, vfo
def ChangeBand(self, band):
# band is a string: "60", "40", "WWV", etc.
BaseHardware.ChangeBand(self, band)
btn = self.application.BtnRfGain
if btn:
if band in ('160', '80', '60', '40'):
btn.SetLabel('RF -10', True)
elif band in ('20',):
btn.SetLabel('RF 0', True)
else:
btn.SetLabel('RF +10', True)
def VarDecimGetChoices(self): # Return a list/tuple of strings for the decimation control.
return list(map(str, self.sample_rates)) # convert integer to string
def VarDecimGetLabel(self): # return a text label for the control
return "Sample rate ksps"
def VarDecimGetIndex(self): # return the current index
return self.index
def VarDecimSet(self, index=None): # return sample rate
if index is None: # initial call to set the sample rate before the call to open()
rate = self.application.vardecim_set
try:
self.index = self.sample_rates.index(rate // 1000)
except:
self.index = 0
else:
self.index = index
rate = self.sample_rates[self.index] * 1000
self.rate = self.index
if(rate>=960000):
rx_bytes = 2
rx_endian = 1
self.InitSamples(rx_bytes, rx_endian)
else:
rx_bytes = 3
rx_endian = 1
self.InitSamples(rx_bytes, rx_endian)
self.rx_control_upd()
return rate
def VarDecimRange(self): # Return the lowest and highest sample rate.
return (48000, 1920000)
def StartSamples(self): # called by the sound thread
self.enable = 1
self.rx_control_upd()
self.bscope_control_upd()
def StopSamples(self): # called by the sound thread
self.enable = 0
self.rx_control_upd()
self.bscope_control_upd()
def rx_control_upd(self):
if(self.device=='Opened'):
work = self.freq
freq4 = work & 0xFF
work = work >> 8
freq3 = work & 0xFF
work = work >> 8
freq2 = work & 0xFF
work = work >> 8
freq1 = work & 0xFF
if sys.version_info.major <= 2:
MESSAGE = 7*chr(0x55) + chr(0xd5) + 'RX0' + chr(self.enable) + chr(self.rate)
MESSAGE += chr(freq1) + chr(freq2) + chr(freq3) + chr(freq4) + chr(self.att) + 14*chr(0)
else:
MESSAGE = b"\x55\x55\x55\x55\x55\x55\x55\xd5RX0"
MESSAGE += bytes((self.enable, self.rate, freq1, freq2, freq3, freq4, self.att))
MESSAGE += bytes(14)
try: self.usb.write(MESSAGE)
except: print('Error while rx_control_upd')
def bscope_control_upd(self):
if self.device == 'Opened':
if sys.version_info.major <= 2:
MESSAGE = 7*chr(0x55) + chr(0xd5) + 'BS0' + chr(self.enable) + chr(100) + 19 * chr(0)
else:
MESSAGE = b"\x55\x55\x55\x55\x55\x55\x55\xd5BS0"
MESSAGE += bytes((self.enable, 100))
MESSAGE += bytes(19)
try: self.usb.write(MESSAGE)
except: None
def GetRxSamples(self): # Read all data from the SDR Micron and process it.
if self.device == None:
return
while (self.usb.getQueueStatus() >= 508):
data = self.usb.read(508)
data = bytearray(data)
if data[8:11] == bytearray(b'RX0'): # Rx I/Q data
if data[13]:
self.GotClip()
if self.fw_ver is None:
self.fw_ver = chr(data[11]) + '.' + chr(data[12])
self.frame_msg += ' F/W version - ' + self.fw_ver
self.application.main_frame.SetConfigText(self.frame_msg)
self.AddRxSamples(data[16:])
elif data[8:11] == bytearray(b'BS0'): # bandscope data
packet_number = data[14]
if packet_number == 0: # start of a block of data
self.bscope_data = data[16:] # 492 bytes
elif packet_number < 66:
self.bscope_data += data[16:] # 492 bytes
else: # end of a block of data, 296 bytes
self.bscope_data += data[16:312]
self.AddBscopeSamples(self.bscope_data)

View File

@ -8,7 +8,7 @@ import struct
# You must define the version here. A title string including
# the version will be written to __init__.py and read by quisk.py.
Version = '4.1.53'
Version = '4.1.56'
fp = open("__init__.py", "w") # write title string
fp.write("#Quisk version %s\n" % Version)
@ -16,7 +16,10 @@ fp.close()
is_64bit = struct.calcsize("P") == 8
# KC4UPR: Added some lists to grab extra sources and macros.
have_portaudio = False
# KC4UPR: Added some lists to grab extra libraries, sources and macros.
extra_libraries = []
extra_sources = []
extra_macros = []
@ -29,8 +32,8 @@ if sys.platform != "win32":
print ("Please install the package libfftw3-dev")
if not os.path.isdir("/usr/include/alsa"):
print ("Please install the package libasound2-dev")
if not os.path.isfile("/usr/include/portaudio.h"):
print ("Please install the package portaudio19-dev")
if os.path.isfile("/usr/include/portaudio.h"):
have_portaudio = True
if not os.path.isdir("/usr/include/pulse"):
print ("please install the package libpulse-dev")
# KC4UPR: Added this section to build the GPIO Keyer, in the event
@ -38,15 +41,26 @@ if sys.platform != "win32":
if not os.path.isfile("/usr/include/wiringPi.h"):
print("No wiringPi.h available--not building GPIO Keyer")
else:
extra_libraries.append('wiringPi')
extra_sources.append('gpiokeyer.c')
extra_macros.append(('ENABLE_GPIO_KEYER', '1'))
# KC4UPR: added suffix '+ extra...' to pull in extra items
libraries = ['asound', 'pulse', 'fftw3', 'm'] + extra_libraries
sources = ['quisk.c', 'sound.c', 'sound_alsa.c', 'sound_pulseaudio.c',
'is_key_down.c', 'microphone.c', 'utility.c',
'filter.c', 'extdemod.c', 'freedv.c'] + extra_sources
define_macros = [] + extra_macros
if have_portaudio:
libraries.append('portaudio')
sources.append('sound_portaudio.c')
else:
define_macros.append(("QUISK_NO_PORTAUDIO", None))
module1 = Extension ('quisk._quisk',
libraries = ['asound', 'portaudio', 'pulse', 'fftw3', 'm', 'pthread', 'rt', 'wiringPi'],
sources = ['quisk.c', 'sound.c', 'sound_alsa.c', 'sound_portaudio.c', 'sound_pulseaudio.c',
'is_key_down.c', 'microphone.c', 'utility.c',
'filter.c', 'extdemod.c', 'freedv.c'] + extra_sources,
define_macros = [] + extra_macros
libraries = libraries,
sources = sources,
define_macros = define_macros,
)
module2 = Extension ('quisk.sdriqpkg.sdriq',
@ -167,7 +181,7 @@ N1MM+ and software that uses Hamlib.
author_email = 'jahlstr@gmail.com',
url = 'http://james.ahlstrom.name/quisk/',
packages = ['quisk', 'quisk.sdriqpkg', 'quisk.n2adr', 'quisk.softrock', 'quisk.freedvpkg',
'quisk.hermes', 'quisk.hiqsdr', 'quisk.afedrinet', 'quisk.soapypkg'],
'quisk.hermes', 'quisk.hiqsdr', 'quisk.afedrinet', 'quisk.soapypkg', 'quisk.sdrmicronpkg', 'quisk.perseuspkg'],
package_dir = {'quisk' : '.'},
package_data = {'' : ['*.txt', '*.html', '*.so', '*.dll']},
entry_points = {'gui_scripts' : ['quisk = quisk.quisk:main', 'quisk_vna = quisk.quisk_vna:main']},

10
sound.c
View File

@ -433,7 +433,11 @@ int read_sound_interface(
switch( dev->driver )
{
case DEV_DRIVER_PORTAUDIO:
#ifdef QUISK_NO_PORTAUDIO
nSamples = 0;
#else
nSamples = quisk_read_portaudio(dev, cSamples);
#endif
break;
case DEV_DRIVER_ALSA:
nSamples = quisk_read_alsa(dev, cSamples);
@ -505,7 +509,9 @@ void play_sound_interface(
switch( dev->driver )
{
case DEV_DRIVER_PORTAUDIO:
#ifndef QUISK_NO_PORTAUDIO
quisk_play_portaudio(dev, nSamples, cSamples, report_latency, volume);
#endif
break;
case DEV_DRIVER_ALSA:
quisk_play_alsa(dev, nSamples, cSamples, report_latency, volume);
@ -860,7 +866,9 @@ void quisk_close_sound(void) // Called from sound thread
#ifdef MS_WINDOWS
int cleanup = radio_sound_socket != INVALID_SOCKET || radio_sound_mic_socket != INVALID_SOCKET;
#endif
#ifndef QUISK_NO_PORTAUDIO
quisk_close_sound_portaudio();
#endif
quisk_close_sound_alsa(CaptureDevices, PlaybackDevices);
quisk_close_sound_pulseaudio();
if (pt_sample_stop)
@ -1168,7 +1176,9 @@ void quisk_start_sound(void) // Called from sound thread
decide_drivers(PlaybackDevices);
// Let the drivers see the devices and start them up if appropriate
#ifndef QUISK_NO_PORTAUDIO
quisk_start_sound_portaudio(CaptureDevices, PlaybackDevices);
#endif
quisk_start_sound_pulseaudio(CaptureDevices, PlaybackDevices);
quisk_start_sound_alsa(CaptureDevices, PlaybackDevices);