Compare commits

...

21 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 0c62afe3c8 Merge branch 'master' into kc4upr. Fixing a 4.1.55 merge issue. 2020-04-29 22:25:05 -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 eb4380695c Merge branch 'master' into kc4upr. Updating to quisk-4.1.54. 2020-04-29 22:10:33 -05:00
Rob French cf8aaa5ae0 Merge branch 'master' into kc4upr. Updating to quisk-4.1.53 in order to ensure that gpiokeyer etc is maintained current. 2020-04-29 22:02:56 -05:00
Rob French 92602fdbb6 Minor comments update. 2020-04-03 12:47:55 -05:00
Rob French 63483dabcd Fixed gpiokeyer.c by adding a forward declaration of the quisk_..._hangtime() function that is also used internaly. 2020-03-14 11:58:54 -05:00
Rob French fba22c95f7 Tweaked the GPIO keyer code, made a more flexible keyer startup: can use 2-5 input parameters (e.g. "gpio:a,b", "gpio:a,b,c", etc.). 2020-03-10 00:06:13 -05:00
Rob French 9a343877e5 Updated the GPIO keyer to take a 5th (optional) argument, hangtime. Sets the number of milliseconds for a semi-QSK delay (i.e. stay in transmit for # of msecs after last CW symbol). 2020-03-09 23:54:28 -05:00
Rob French 8a58f0dba8 Comments, various minor "productionization" changes. 2020-03-01 23:11:29 -06:00
Rob French e440b07548 (1) Allowed use of the internal key state at the same time as the GPIO Keyer, in order to enable easy switching between CW and other modes.
(2) Clean comments in the code.
Remaining effort:
- Cleanup GPIO Keyer for release.
- Eventually, add PTT button and possibly separate straight key input to GPIO Keyer.
2020-02-29 23:18:03 -06:00
Rob French c7125fe21d Added quisk_close_key to the list of publicly available functions, so I can close the existing key and open a new one if desired. Also added some debug updates to the GPIO keyer. 2020-02-29 01:29:30 -06:00
Rob French 39293c4130 Updated GPIO keyer with enable/disable functionality. 2020-02-28 23:34:44 -06:00
Rob French 1b4775f452 Removed Ultimatic keyer mode. Added digital outputs for keyer and PTT (T/R switch) lines. Streamlined the code for the semaphores. Made it more configurable / less #defines. 2020-02-26 21:28:59 -06:00
Rob French 9892ccb1a4 Stupid error on the input. Fixed. Ultimatic keyer still not working. Iambic appear to be fine. 2020-02-24 00:41:24 -06:00
Rob French 924dce5426 Attempting to add the controls, not working as well. Need to fix ultimatic keyer, possibly semaphore related? 2020-02-24 00:21:43 -06:00
Rob French 4b1207c31f Successfully merged in N1GP keyer code! It appears to transmit correctly! No controls implemented yet (i.e. can't modify keyer parameters). Also, I'm not sure about the threading/semaphores aspect.
I think there is some further work to be done there to be technically correct.
2020-02-23 23:04:34 -06:00
25 changed files with 4158 additions and 5 deletions

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).

862
gpiokeyer.c Normal file
View File

@ -0,0 +1,862 @@
/***********************************************************************
* gpiokeyer.c
* by Robert A. French (KC4UPR)
*
* This file implements a General Purpose Input Output (GPIO) based
* Morse Code / Continuous Wave (CW) keyer for Quisk. This was derived
* from Richard (N1GP) Koch's Raspberry Pi iambic keyer code, available
* at: github.com/n1gp/iambic-keyer
*
* Modifications included:
* - Removing the GPIO sidetone functionality. Quisk will be creating
* both the sidetone and the actual quadrature CW signal to feed to
* the SDR.
* - Modifying the keying logic (state machine) slightly. I don't know
* if I improved it or not, but changes were based on my tracing thru
* the code and updating things that seemed reasonable.
* - Implementing GPIO key and T/R switching outputs, that could be
* used to drive both an external CW generator, as well a T/R
* switching with a configurable QSK/semi-QSK delay.
* - Making parameters configurable/updateable during runtime by calls
* from Quisk.
* - Making the GPIO pins configurable at startup.
* - Incorporating the keyer into Quisk's overall keying logic logic.
*
* Original N1GP changelog and licensing are below, as well as the notes
* from the even previous source, a Verilog keyer for Hermes Lite.
**********************************************************************/
/*
3/1/2020, Rob French / KC4UPR, I converted the code for use as a
component of Quisk.
10/12/2016, Rick Koch / N1GP, I adapted Phil's verilog code from
the openHPSDR Hermes iambic.v implementation to build
and run on a raspberry PI 3.
1/7/2017, N1GP, adapted to work with Jack Audio, much better
timing.
------------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
------------------------------------------------------------------------
------------------------------------------------------------------------
Copywrite (C) Phil Harman VK6PH May 2014
------------------------------------------------------------------------
The code implements an Iambic CW keyer. The following features are supported:
* Variable speed control from 1 to 60 WPM
* Dot and Dash memory
* Straight, Bug, Iambic Mode A or B Modes
* Variable character weighting
* Automatic Letter spacing
* Paddle swap
Dot and Dash memory works by registering an alternative paddle closure whilst a paddle is pressed.
The alternate paddle closure can occur at any time during a paddle closure and is not limited to being
half way through the current dot or dash. This feature could be added if required.
In Straight mode, closing the DASH paddle will result in the output following the input state. This enables a
straight morse key or external Iambic keyer to be connected.
In Bug mode closing the dot paddle will send repeated dots.
The difference between Iambic Mode A and B lies in what the keyer does when both paddles are released. In Mode A the
keyer completes the element being sent when both paddles are released. In Mode B the keyer sends an additional
element opposite to the one being sent when the paddles are released.
This only effects letters and characters like C, period or AR.
Automatic Letter Space works as follows: When enabled, if you pause for more than one dot time between a dot or dash
the keyer will interpret this as a letter-space and will not send the next dot or dash until the letter-space time has been met.
The normal letter-space is 3 dot periods. The keyer has a paddle event memory so that you can enter dots or dashes during the
inter-letter space and the keyer will send them as they were entered.
Speed calculation - Using standard PARIS timing, dot_period(mS) = 1200/WPM
*/
//#define DEBUG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <poll.h>
#include <sched.h>
#include <time.h>
#include <sys/mman.h>
#include <pthread.h>
#include <signal.h>
#include <semaphore.h>
#include <wiringPi.h>
/***********************************************************************
* Constants
**********************************************************************/
#define NSEC_PER_SEC (1000000000)
#define CW_HANGTIME_DEFAULT (250)
#define NUM_PARMS (5)
/***********************************************************************
* Types
**********************************************************************/
/* KC4UPR: I added an enumeration for the keyer modes, instead of a
* macro. Probably superfluous.
*/
enum {
KEYER_STRAIGHT = 0,
KEYER_MODE_A,
KEYER_MODE_B,
NUM_KEYER_MODES
};
/* KC4UPR: Enumeration of the states in the iambic keyer state machine.
* I added the HANGTIME state, which is used to differentiate between
* the end of the last CW symbol, and the end of the transmission delay
* for QSK/semi-QSK operations.
*/
enum {
CHECK = 0,
PREDOT,
PREDASH,
SENDDOT,
SENDDASH,
DOTDELAY,
DASHDELAY,
DOTHELD,
DASHHELD,
LETTERSPACE,
HANGTIME,
EXITLOOP
};
/***********************************************************************
* Function Prototypes
*
* These are only prototypes for the internal functions... the functions
* that are callable from quisk.c and/or Python are all declared in
* quisk.h, and then defined at the end of this file.
**********************************************************************/
static void keyer_update(void);
static void keyer_event(int, int, uint32_t);
static void keyer_event_left(void);
static void keyer_event_right(void);
static void clear_memory(void);
static void set_keyer_out(int);
static void* keyer_thread(void *);
/* quisk_set_gpio_keyer_hangtime() - defining this in here since we do
* call it internally a few times.
*/
void quisk_set_gpio_keyer_hangtime(int) ;
/***********************************************************************
* Variables
**********************************************************************/
/* GPIO Pins
*
* KC4UPR: Converted the GPIO pin definitions from macros to variables,
* so that we can set them dynamically at runtime.
*/
static int left_paddle_gpio = 22;
static int right_paddle_gpio = 27;
static int keyer_out_gpio = 23;
static int tr_switch_gpio = 24;
/* Keyer Configuration
*/
static int cw_keyer_mode = KEYER_MODE_A;
static int cw_keyer_speed = 20;
static int cw_keyer_weight = 55;
static int cw_keys_reversed = 0;
static int cw_keyer_spacing = 0;
static int cw_keyer_enabled = 1;
static int cw_hangtime_msec = CW_HANGTIME_DEFAULT;
static int cw_active_state = 0; // not currently (re-)configurable
/* Current Paddle State
*/
static int kcwl = 0; // left paddle
static int kcwr = 0; // right paddle
static int *kdot; // dots - point to either left or right
static int *kdash; // dashes - point to either right or left
/* Internal Keyer State
*/
static int dot_memory = 0;
static int dash_memory = 0;
static int key_state = 0;
static int kdelay = 0;
static int dot_delay = 0;
static int dash_delay = 0;
static int running, keyer_out = 0;
/* Thread Variables
*/
static pthread_t keyer_thread_id;
static sem_t cw_event;
#if defined(DEBUG)
static int cw_event_value;
#endif
/***********************************************************************
* Internal functions
**********************************************************************/
/* KC4UPR: Update the keyer, i.e. calculate its internal values based
* on current settings. This is called once at keyer open, and then
* again any time certain settings are updated.
*/
static void keyer_update() {
dot_delay = 1200 / cw_keyer_speed;
// will be 3 * dot length at standard weight
dash_delay = (dot_delay * 3 * cw_keyer_weight) / 50;
if (cw_keys_reversed) {
kdot = &kcwr;
kdash = &kcwl;
} else {
kdot = &kcwl;
kdash = &kcwr;
}
/* NOTE: need to actually dynamically set this at some point...
* Currently, based on the code below, there is a hardcoded 250ms
* semi-QSK delay. ~250ms after the end of the last symbol, the
* T/R switch will be disabled.
*/
// cw_hangtime_msec = (int)(0.25f * 1000.0f);
}
/* KC4UPR: The "actual" event handler. Updates the value of the
* currently depressed/released paddle.
*/
static void keyer_event(int gpio, int level, uint32_t tick) {
// cw_active_state is for the logic level (active high vs low).
int state = (cw_active_state == 0) ? (level == 0) : (level != 0);
if (gpio == left_paddle_gpio)
kcwl = state;
else // RIGHT_PADDLE_GPIO
kcwr = state;
/* Post (increment) the semaphore. Why? Because the keyer thread
* may be waiting on it, so this lets the keyer thread begin running
* the state machine if it was currently between sequences.
*/
if (state)
sem_post(&cw_event);
}
/* KC4UPR: Helper function added to support WiringPi instead of PiGPIO.
* PiGPIO supports using the same callback for multiple pins, because
* the pin is one of the parameters to the interrupt handler. However,
* I needed to use WiringPi instead of PiGPIO due to PiGPIO not working
* with my soundcard "hat" for the Raspberry Pi.
*/
static void keyer_event_left()
{
int level = digitalRead(left_paddle_gpio);
keyer_event(left_paddle_gpio, level, 0);
#if defined(DEBUG)
/* KC4UPR: I added current value of the semaphore because I was
* curious as to how many times this ISR is getting called. For
* whatever reason, despite my debounce circuit on this pin,
* this is getting called a lot...
*/
sem_getvalue(&cw_event, &cw_event_value);
fprintf(stdout, "[GPIO Keyer] left paddle pressed; semaphore value: %d\n", cw_event_value);
#endif
}
/* KC4UPR: Helper function added to support WiringPi instead of PiGPIO.
* PiGPIO supports using the same callback for multiple pins, because
* the pin is one of the parameters to the interrupt handler. However,
* I needed to use WiringPi instead of PiGPIO due to PiGPIO not working
* with my soundcard "hat" for the Raspberry Pi.
*/
static void keyer_event_right()
{
int level = digitalRead(right_paddle_gpio);
keyer_event(right_paddle_gpio, level, 0);
#if defined(DEBUG)
/* KC4UPR: I added current value of the semaphore because I was
* curious as to how many times this ISR is getting called. For
* whatever reason, despite my debounce circuit on this pin,
* this is getting called a lot...
*/
sem_getvalue(&cw_event, &cw_event_value);
fprintf(stdout, "[GPIO Keyer] right paddle pressed; semaphore value: %d\n", cw_event_value);
#endif
}
/* KC4UPR: Clear the dot and dash memory of the iambic keyer.
*/
static void clear_memory() {
dot_memory = 0;
dash_memory = 0;
}
/* KC4UPR: Set the keyer output (which will be read by the function
* is_key_down_gpiokeyer(), when called by Quisk). Also writes the
* digital output GPIO pins, if they are being used.
*/
static void set_keyer_out(int state) {
/* First, write to the hardware T/R switch, if we are using it, and
* if the specific keyer state is key_down. A logical AND is used
* here instead of bitwise, because tr_switch_gpio could have
* multiple valid values.
*/
if (state && tr_switch_gpio)
digitalWrite(tr_switch_gpio, 1 & cw_keyer_enabled);
/* Set the key state. This is what will be read by Quisk.
*/
keyer_out = state;
/* Finally, write to the hardware CW key line, if it was specified.
*/
if (keyer_out_gpio)
digitalWrite(keyer_out_gpio, keyer_out & cw_keyer_enabled);
}
/* KC4UPR: Keyer thread, which processes the key state and moves
* through the state machines.
*/
static void* keyer_thread(void *arg) {
struct timespec loop_delay;
int interval = 1000000; // 1 ms
int hangtime_elapsed = 0;
while (running) {
#if defined(DEBUG)
/* KC4UPR: Writing out the current semaphore value because
* I was curious at the impact of bouncing on how often the
* interrupt handler was getting called.
*/
sem_getvalue(&cw_event, &cw_event_value);
fprintf(stdout, "[GPIO Keyer] waiting; semaphore value: %d\n", cw_event_value);
#endif
sem_wait(&cw_event);
key_state = CHECK;
while (key_state != EXITLOOP) {
/* Anytime the keyer output is set (i.e. we are transmitting
* a symbol), reset the elapsed hangtime. Once we complete
* sending the current symbol (dit/dah/straight key out), we
* will start the hangtime counter for the T/R switch.
*/
if (keyer_out)
hangtime_elapsed = 0;
switch(key_state) {
case HANGTIME:
if (hangtime_elapsed >= cw_hangtime_msec) {
if (tr_switch_gpio) {
#if defined(DEBUG)
sem_getvalue(&cw_event, &cw_event_value);
fprintf(stdout, "[GPIO Keyer] hangtime complete, %d msec; semaphore value: %d\n", cw_hangtime_msec, cw_event_value);
#endif
digitalWrite(tr_switch_gpio, 0);
key_state = EXITLOOP;
}
}
/* KC4UPR: The HANGTIME state is intentionally first in
* the switch() statement, and it intentionally does NOT
* have a break at the end of it. I want it to fall-
* through into the CHECK state logic, so it can look to
* see if there are any switch actuations, which would
* then interrupt the HANGTIME state and start the state
* machine over. This is probably terrible coding
* practice...
*/
case CHECK: // check for key press
if (cw_keyer_mode == KEYER_STRAIGHT) { // Straight/External key or bug
if (*kdash) { // send manual dashes
if (!keyer_out) {
set_keyer_out(1);
key_state = HANGTIME; //EXITLOOP;
}
}
else if (*kdot) // and automatic dots
key_state = PREDOT;
else if (key_state == HANGTIME) {
if (keyer_out)
set_keyer_out(0);
} else {
key_state = EXITLOOP;
}
}
else {
if (*kdot)
key_state = PREDOT;
else if (*kdash)
key_state = PREDASH;
else if (key_state != HANGTIME) {
key_state = EXITLOOP;
}
}
break;
case PREDOT: // need to clear any pending dots or dashes
clear_memory();
key_state = SENDDOT;
break;
case PREDASH:
clear_memory();
key_state = SENDDASH;
break;
// dot paddle pressed so set keyer_out high for time dependant on speed
// also check if dash paddle is pressed during this time
case SENDDOT:
set_keyer_out(1);
if (kdelay == dot_delay) {
kdelay = 0;
set_keyer_out(0);
key_state = DOTDELAY; // add inter-character spacing of one dot length
}
else kdelay++;
// if Mode A and both paddels are relesed then clear dash memory
if (cw_keyer_mode == KEYER_MODE_A) {
if (!*kdot & !*kdash)
dash_memory = 0;
}
if (*kdash) { // set dash memory
dash_memory = 1;
}
break;
// dash paddle pressed so set keyer_out high for time dependant on 3 x dot delay and weight
// also check if dot paddle is pressed during this time
case SENDDASH:
set_keyer_out(1);
if (kdelay == dash_delay) {
kdelay = 0;
set_keyer_out(0);
key_state = DASHDELAY; // add inter-character spacing of one dot length
}
else kdelay++;
// if Mode A and both padles are relesed then clear dot memory
if (cw_keyer_mode == KEYER_MODE_A) {
if (!*kdot & !*kdash)
dot_memory = 0;
}
if (*kdot) { // set dot memory
dot_memory = 1;
}
break;
// add dot delay at end of the dot and check for dash memory, then check if paddle still held
case DOTDELAY:
if (kdelay == dot_delay) {
kdelay = 0;
if(!*kdot && cw_keyer_mode == KEYER_STRAIGHT) // just return if in bug mode
key_state = HANGTIME;
else if (dash_memory) // dash has been set during the dot so service
key_state = PREDASH;
else key_state = DOTHELD; // dot is still active so service
}
else kdelay++;
if (*kdash) { // set dash memory
dash_memory = 1;
}
break;
// add dot delay at end of the dash and check for dot memory, then check if paddle still held
case DASHDELAY:
if (kdelay == dot_delay) {
kdelay = 0;
if (dot_memory) // dot has been set during the dash so service
key_state = PREDOT;
else key_state = DASHHELD; // dash is still active so service
}
else kdelay++;
if (*kdot) { // set dot memory
dot_memory = 1;
}
break;
// check if dot paddle is still held, if so repeat the dot. Else check if Letter space is required
case DOTHELD:
if (*kdot) // dot has been set during the dash so service
key_state = PREDOT;
else if (*kdash) // has dash paddle been pressed
key_state = PREDASH;
else if (cw_keyer_spacing) { // Letter space enabled so clear any pending dots or dashes
clear_memory();
key_state = LETTERSPACE;
}
else key_state = HANGTIME;
break;
// check if dash paddle is still held, if so repeat the dash. Else check if Letter space is required
case DASHHELD:
if (*kdash) // dash has been set during the dot so service
key_state = PREDASH;
else if (*kdot) // has dot paddle been pressed
key_state = PREDOT;
else if (cw_keyer_spacing) { // Letter space enabled so clear any pending dots or dashes
clear_memory();
key_state = LETTERSPACE;
}
else key_state = HANGTIME;
break;
// Add letter space (3 x dot delay) to end of character and check if a paddle is pressed during this time.
// Actually add 2 x dot_delay since we already have a dot delay at the end of the character.
case LETTERSPACE:
if (kdelay == 2 * dot_delay) {
kdelay = 0;
if (dot_memory) // check if a dot or dash paddle was pressed during the delay.
key_state = PREDOT;
else if (dash_memory)
key_state = PREDASH;
else key_state = HANGTIME; // no memories set so restart
}
else kdelay++;
// save any key presses during the letter space delay
if (*kdot) dot_memory = 1;
if (*kdash) dash_memory = 1;
break;
default:
key_state = EXITLOOP;
}
/* If the key out state is 0 (not sending), increment the
* hangtime elapsed timer. This will continue incrementing
* while we are in the HANGTIME state, until either the
* timer completes, or keyer out goes to 1.
*/
if (!keyer_out)
hangtime_elapsed++;
if (key_state != EXITLOOP) {
clock_gettime(CLOCK_MONOTONIC, &loop_delay);
loop_delay.tv_nsec += interval;
while (loop_delay.tv_nsec >= NSEC_PER_SEC) {
loop_delay.tv_nsec -= NSEC_PER_SEC;
loop_delay.tv_sec++;
}
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &loop_delay, NULL);
}
}
}
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] thread should be ending now\n");
#endif
return arg; // did this to ditch compiler warnings... bad idea?
}
/***********************************************************************
* is_key_down.c functions
*
* These functions are called from is_key_down.c, and implement the
* method-specific open/close/set functions for the keyer.
**********************************************************************/
/* KC4UPR: Open the GPIO keyer. Its name must start with "gpio". The
* overall format is:
* gpio:left,right,keyer_out,tr_switch
* where:
* left - GPIO input pin for the left paddle
* right - GPIO input pin for the right paddle
* keyer_out - GPIO output pin for the key (actual CW) signal
* (unlike the tr_switch line, this is only keyed
* for the actual dits and dahs)
* (set to zero to not use this)
* tr_switch - GPIO output pin for T/R switching (this is
* enabled any time keyer_out is enabled, plus a
* short, configurable delay after the last time
* the keyer output was set)
* (set to zero to not use this)
* NOTE: The pin numbers to be used are GPIO pin numbers, NOT WiringPi
* pin numbers even though WiringPi is used!!!
*/
int open_key_gpiokeyer(const char * name)
{
int i;
int parm[NUM_PARMS];
/* KC4UPR: Read the GPIO keyer name, and parse out the pins for
* left paddle, right paddle, keyer out, T/R switch, and "hang time"
* in milliseconds. 'Keyer out' and 'T/R switch' pins two can be
* zero if that functionality is not desired.
*/
switch(sscanf(name, "gpio:%d,%d,%d,%d,%d", &parm[0], &parm[1], &parm[2], &parm[3], &parm[4])) {
case 5: // v0.2
left_paddle_gpio = parm[0];
right_paddle_gpio = parm[1];
keyer_out_gpio = parm[2];
tr_switch_gpio = parm[3];
quisk_set_gpio_keyer_hangtime(parm[4]);
break;
case 4: // v0.1
/* KC4UPR: matched the first 4 inputs - original v0.1 interface.
*/
left_paddle_gpio = parm[0];
right_paddle_gpio = parm[1];
keyer_out_gpio = parm[2];
tr_switch_gpio = parm[3];
quisk_set_gpio_keyer_hangtime(CW_HANGTIME_DEFAULT);
break;
case 3: // v0.2
/* KC4UPR: three inputs--no discrete outputs, but hangtime set.
*/
left_paddle_gpio = parm[0];
right_paddle_gpio = parm[1];
keyer_out_gpio = 0;
tr_switch_gpio = 0;
quisk_set_gpio_keyer_hangtime(parm[2]);
break;
case 2: // v0.2
/* KC4UPR: only two inputs--the discrete outputs won't be used.
*/
left_paddle_gpio = parm[0];
right_paddle_gpio = parm[1];
keyer_out_gpio = 0;
tr_switch_gpio = 0;
quisk_set_gpio_keyer_hangtime(CW_HANGTIME_DEFAULT);
break;
default:
fprintf(stderr, "[GPIO Keyer] insufficient parameters: %s\n", name);
return -1;
}
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] configuration:\n - left paddle GPIO: %d\n - right paddle GPIO: %d\n - keyer out GPIO: %d\n - T/R switch GPIO: %d\n",
left_paddle_gpio, right_paddle_gpio, keyer_out_gpio, tr_switch_gpio);
#endif
/* KC4UPR: Setup WiringPi. Note that I have specified using the
* GPIO pin names rather than the WiringPi pin names.
*/
if (wiringPiSetupGpio () < 0) {
fprintf(stderr, "[GPIO Keyer] unable to setup wiringPi: %s\n", strerror(errno));
return -1;
}
/* KC4UPR: Setup the right paddle pin for input. An interrupt will
* be triggered on both key down and key up.
*/
pinMode(right_paddle_gpio, INPUT);
pullUpDnControl(right_paddle_gpio, PUD_UP);
usleep(100000);
wiringPiISR(right_paddle_gpio, INT_EDGE_BOTH, keyer_event_right);
/* KC4UPR: Setup the left paddle pin for input. An interrupt will
* be triggered on both key down and key up.
*/
pinMode(left_paddle_gpio, INPUT);
pullUpDnControl(left_paddle_gpio, PUD_UP);
usleep(100000);
wiringPiISR(left_paddle_gpio, INT_EDGE_BOTH, keyer_event_left);
/* KC4UPR: Setup the keyer output pin as an output pin, IF the
* value is not 0. If the pin value is 0, then this output is
* disabled.
*/
if (keyer_out_gpio) {
pinMode(keyer_out_gpio, OUTPUT);
digitalWrite(keyer_out_gpio, 0);
}
/* KC4UPR: Setup the T/R switch pin as an output pin, IF the
* value is not 0. If the pin value is 0, then this output is
* disabled.
*/
if (tr_switch_gpio) {
pinMode(tr_switch_gpio, OUTPUT);
digitalWrite(tr_switch_gpio, 0);
}
keyer_update();
i = sem_init(&cw_event, 0, 0);
running = 1;
i |= pthread_create(&keyer_thread_id, NULL, keyer_thread, NULL);
if(i < 0) {
fprintf(stderr,"[GPIO Keyer] pthread_create for keyer_thread failed %d\n", i);
return -1;
}
return 0;
}
/* KC4UPR: Close the GPIO keyer. This sets the running flag for the
* keyer thread to false, posts the semaphore (to ensure the keyer
* thread gets off of a semaphore wait), and then joins the thread to
* close it.
*
* NOTE: If Quisk is not closed after closing the GPIO keyer, the
* interrupt handlers for the GPIO pins remain present. I think I can
* possibly fix this by assigning a NULL ISR???
*/
void close_key_gpiokeyer(void)
{
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] closing keyer\n");
#endif
running = 0;
sem_post(&cw_event);
pthread_join(keyer_thread_id, 0);
sem_destroy(&cw_event);
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] keyer closed\n");
#endif
}
/* KC4UPR: Return the state of the keyer. This is a logic AND of the
* current keyer_out state, and the cw_keyer_enabled signal.
*/
int is_key_down_gpiokeyer(void)
{
static int retval;
retval = keyer_out & cw_keyer_enabled;
return retval;
}
/***********************************************************************
* Externally callable functions
*
* These functions are callable from Quisk proper, as well as from any
* Quisk Python modules. They are declared in quisk.h, and are used to
* (re-)configure various keyer parameters.
**********************************************************************/
/* KC4UPR: Set the keyer mode. Keyer modes are defined as an
* enumeration in this file. Current enums are:
* KEYER_STRAIGHT = 0
* KEYER_MODE_A = 1
* KEYER_MODE_B = 2
* If the requested mode is out of bounds, nothing happens...
*/
void quisk_set_gpio_keyer_mode(int mode)
{
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] mode change: %d - %s\n", mode,
((mode>-1)&&(mode<NUM_KEYER_MODES))?"success":"failed ");
#endif
if ((mode > -1) && (mode < NUM_KEYER_MODES))
cw_keyer_mode = mode;
}
/* KC4UPR: Set the keyer speed in WPM. Valid from 1-60 WPM.
*/
void quisk_set_gpio_keyer_speed(int wpm)
{
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] speed change: %d - %s\n", wpm,
((wpm>0)&&(wpm<61))?"success":"failed ");
#endif
if ((wpm > 0) && (wpm < 61)) {
cw_keyer_speed = wpm;
keyer_update();
}
}
/* KC4UPR: Set the keyer weight in percent (?). Valid from 33-66.
*/
void quisk_set_gpio_keyer_weight(int weight)
{
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] weight change: %d - %s\n", weight,
((weight>32)&&(weight<67))?"success":"failed ");
#endif
if ((weight > 32) && (weight < 67)) {
cw_keyer_weight = weight;
keyer_update();
}
}
/* KC4UPR: Reverse the paddles. Default: left = dit, right = dah.
*/
void quisk_set_gpio_keyer_reversed(int flag)
{
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] reverse paddles: %s\n",
flag==0?"false":"true ");
#endif
cw_keys_reversed = (flag == 0 ? 0 : 1);
keyer_update();
}
/* KC4UPR: Set strict character spacing. Default: off.
*/
void quisk_set_gpio_keyer_strict(int flag)
{
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] strict spacing: %s\n",
flag==0?"false":"true ");
#endif
cw_keyer_spacing = (flag == 0 ? 0 : 1);
}
/* KC4UPR: Enable/disable the keyer. If disabled, then regardless of
* state, nothing will be output.
*/
void quisk_set_gpio_keyer_enabled(int flag)
{
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] enabled: %s\n",
flag==0?"false":"true ");
#endif
cw_keyer_enabled = (flag == 0 ? 0 : 1);
}
/* KC4UPR: Set the keyer "hangtime". This is the delay that the T/R
* switch remains set after the last symbol was transmitted (the default
* is 250 msec, if this is never called). Can be set from 0 to 1000
* msec.
*/
void quisk_set_gpio_keyer_hangtime(int msec)
{
#if defined(DEBUG)
fprintf(stdout, "[GPIO Keyer] hangtime: %d msec\n", msec)
#endif
if ((msec > -1) && (msec < 1001)) {
cw_hangtime_msec = msec;
}
}
/***********************************************************************
* EOF
**********************************************************************/

View File

@ -59,12 +59,28 @@ static void close_key_enet(void);
static int is_key_down_pport(void);
static int is_key_down_serport(void);
static int is_key_down_enet(void);
#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Headers for new functions to implement the GPIO Keyer. They
* are not defined as static here, because I implemented the functions
* in a separate source file (gpiokeyer.c).
*/
int open_key_gpiokeyer(const char * name);
void close_key_gpiokeyer(void);
int is_key_down_gpiokeyer(void);
#endif
static enum { // The key access method
None, // Return the internal state; default key is always up
ParPort, // Use the parallel port
SerPort, // Use the serial port
Udp // Use UDP Ethernet
#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Define a new hardware keyer type: a GPIO Keyer that
* implements straight, bug, and iambic keyer functionality, can be
* configured to use different pins on a Raspberry Pi.
*/
, GpioKeyer // Use Raspberry Pi GPIO keyer based on N1GP code
#endif
} key_method = None;
static int fd = -1; // File descriptor to read the parallel or serial port
@ -91,6 +107,30 @@ int quisk_open_key(const char * name)
key_method = Udp;
ret = open_key_enet(name);
}
#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Check if the GPIO Keyer was requested, and if so, open
* it. Its name must start with "gpio". The overall format is:
* gpio:left,right,keyer_out,tr_switch
* where:
* left - GPIO input pin for the left paddle
* right - GPIO input pin for the right paddle
* keyer_out - GPIO output pin for the key (actual CW) signal
* (unlike the tr_switch line, this is only keyed
* for the actual dits and dahs)
* (set to zero to not use this)
* tr_switch - GPIO output pin for T/R switching (this is
* enabled any time keyer_out is enabled, plus a
* short, configurable delay after the last time
* the keyer output was set)
* (set to zero to not use this)
* NOTE: The pin numbers to be used are GPIO pin numbers, NOT
* WiringPi pin numbers even though WiringPi is used!!!
*/
else if (!strncmp(name, "gpio", 4)){ // Raspberry Pi GPIO keyer
key_method = GpioKeyer;
ret = open_key_gpiokeyer(name);
}
#endif
else {
ret = 5;
}
@ -111,6 +151,13 @@ void quisk_close_key(void)
case Udp:
close_key_enet();
break;
#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Self-explanatory--close the GPIO Keyer.
*/
case GpioKeyer:
close_key_gpiokeyer();
break;
#endif
}
return;
}
@ -126,6 +173,18 @@ int quisk_is_key_down(void)
return is_key_down_pport();
case Udp:
return is_key_down_enet();
#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Check if the GPIO Keyer key is down. This also checks
* the state of the internal key. I included this to allow use of
* the quisk_set_key_down() function in conjunction with the GPIO
* Keyer, for example in the case of digimodes. This could probably
* also reasonably be applied to the other hardware key methods
* above, but I decided to try to restrict my changes to things
* explicitly involving the GPIO Keyer.
*/
case GpioKeyer:
return is_key_down_gpiokeyer() | key_is_down;
#endif
}
return 0;
}

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)

133
quisk.c
View File

@ -3045,6 +3045,24 @@ static PyObject * open_key(PyObject * self, PyObject * args)
return PyInt_FromLong(quisk_open_key(name));
}
/* KC4UPR: Added this function to be able to close the current key from
* Python scripts. The intent was to be able to close the current key
* and open a new one, primarily to switch from hardware-generated CW to
* Fldigi-generated digital. This is a cumbersome way to do this, and
* I've moved away from it for the GPIO Keyer. However, this still
* seems like a reasonable function to have available to Python (like
* open_key() is), so I added it and didn't restrict it to cases where
* ENABLE_GPIO_KEYER is defined.
*/
static PyObject * close_key(PyObject * self, PyObject * args)
{
if (!PyArg_ParseTuple (args, ""))
return NULL;
quisk_close_key();
Py_INCREF (Py_None);
return Py_None;
}
static void close_udp(void)
{
short msg = 0x7373; // shutdown
@ -5163,6 +5181,107 @@ static PyObject * set_sample_bytes(PyObject * self, PyObject * args)
return Py_None;
}
#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Set the GPIO Keyer mode from Python. Mode definitions are
* available in gpiokeyer.c.
*/
static PyObject * set_gpio_keyer_mode(PyObject * self, PyObject * args)
{
int mode;
if (!PyArg_ParseTuple (args, "i", &mode))
return NULL;
quisk_set_gpio_keyer_mode(mode);
Py_INCREF (Py_None);
return Py_None;
}
/* KC4UPR: Set the GPIO Keyer speed in WPM from Python. Valid range is
* 1-60 WPM.
*/
static PyObject * set_gpio_keyer_speed(PyObject * self, PyObject * args)
{
int wpm;
if (!PyArg_ParseTuple (args, "i", &wpm))
return NULL;
quisk_set_gpio_keyer_speed(wpm);
Py_INCREF (Py_None);
return Py_None;
}
/* KC4UPR: Set the GPIO Keyer dot-dash weight from Python. Valid range
* is 33-66.
*/
static PyObject * set_gpio_keyer_weight(PyObject * self, PyObject * args)
{
int weight;
if (!PyArg_ParseTuple (args, "i", &weight))
return NULL;
quisk_set_gpio_keyer_weight(weight);
Py_INCREF (Py_None);
return Py_None;
}
/* KC4UPR: Reverse the left/right paddle functions (dot/dash is by
* default). '0' to keep default, anything else to reverse.
*/
static PyObject * set_gpio_keyer_reversed(PyObject * self, PyObject * args)
{
int rev;
if (!PyArg_ParseTuple (args, "i", &rev))
return NULL;
quisk_set_gpio_keyer_reversed(rev);
Py_INCREF (Py_None);
return Py_None;
}
/* KC4UPR: Set strict character spacing mode. '0' to keep default,
* anything else to set strict spacing.
*/
static PyObject * set_gpio_keyer_strict(PyObject * self, PyObject * args)
{
int strict;
if (!PyArg_ParseTuple (args, "i", &strict))
return NULL;
quisk_set_gpio_keyer_strict(strict);
Py_INCREF (Py_None);
return Py_None;
}
/* KC4UPR: Enable (!= 0) or disable (== 0) the keyer. Note that if the
* keyer is disabled, then the left and right paddles will not generate
* a CW signal or switch T/R. However, set_key_down() can be used to
* set the internal key state.
*/
static PyObject * set_gpio_keyer_enabled(PyObject * self, PyObject * args)
{
int enabled;
if (!PyArg_ParseTuple (args, "i", &enabled))
return NULL;
quisk_set_gpio_keyer_enabled(enabled);
Py_INCREF (Py_None);
return Py_None;
}
/* KC4UPR: Set the GPIO keyer hangtime: the number of milliseconds to
* leave the T/R switch in "transmit" after the last CW symbol.
*/
static PyObject * set_gpio_keyer_hangtime(PyObject * self, PyObject * args)
{
int hangtime;
if (!PyArg_ParseTuple (args, "i", &hangtime))
return NULL;
quisk_set_gpio_keyer_hangtime(hangtime);
Py_INCREF (Py_None);
return Py_None;
}
#endif
static PyMethodDef QuiskMethods[] = {
{"add_tone", add_tone, METH_VARARGS, "Add a test tone to the data."},
{"dft", dft, METH_VARARGS, "Calculate the discrete Fourier transform."},
@ -5252,6 +5371,9 @@ static PyMethodDef QuiskMethods[] = {
{"start_sound", start_sound, METH_VARARGS, "Start the soundcard."},
{"mixer_set", mixer_set, METH_VARARGS, "Set microphone mixer parameters such as volume."},
{"open_key", open_key, METH_VARARGS, "Open access to the state of the key (CW or PTT)."},
/* KC4UPR: As described above, added close_key() as a Python-callable function.
*/
{"close_key", close_key, METH_VARARGS, "Close the currently selected key."},
{"open_rx_udp", open_rx_udp, METH_VARARGS, "Open a UDP port for capture."},
{"close_rx_udp", close_rx_udp, METH_VARARGS, "Close the UDP port used for capture."},
{"add_rx_samples", add_rx_samples, METH_VARARGS, "Record the Rx samples received by Python code."},
@ -5264,6 +5386,17 @@ static PyMethodDef QuiskMethods[] = {
{"freedv_get_version", quisk_freedv_get_version, METH_VARARGS, "Return the codec2 API version."},
{"freedv_get_rx_char", quisk_freedv_get_rx_char, METH_VARARGS, "Get text characters received from freedv."},
{"freedv_set_options", (PyCFunction)quisk_freedv_set_options, METH_VARARGS|METH_KEYWORDS, "Set the freedv parameters."},
#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Allow the other GPIO Keyer settings to be configured from Python.
*/
{"set_gpio_keyer_mode", set_gpio_keyer_mode, METH_VARARGS, "Change the CW keyer mode."},
{"set_gpio_keyer_speed", set_gpio_keyer_speed, METH_VARARGS, "Change the CW keyer speed."},
{"set_gpio_keyer_weight", set_gpio_keyer_weight, METH_VARARGS, "Change the CW keyer symbol weight."},
{"set_gpio_keyer_reversed", set_gpio_keyer_reversed, METH_VARARGS, "Enabled/disable reversed paddles."},
{"set_gpio_keyer_strict", set_gpio_keyer_strict, METH_VARARGS, "Enable/disable strict character spacing."},
{"set_gpio_keyer_enabled", set_gpio_keyer_enabled, METH_VARARGS, "Enable/disable the CW keyer"},
{"set_gpio_keyer_hangtime", set_gpio_keyer_hangtime, METH_VARARGS, "Set number of msecs for semi-QSK delay"},
#endif
{NULL, NULL, 0, NULL} /* Sentinel */
};

View File

@ -7,6 +7,7 @@ WinQuisk.pyw
WinQuiskVna.pyw
__init__.py
__main__.py
_quisk.pyd
configure.py
defaults.html
docs.html
@ -18,6 +19,7 @@ filters.h
filters.py
freedv.c
freedv.h
gpiokeyer.c
help.html
help_conf.html
help_vna.html
@ -50,9 +52,11 @@ quisk_hardware_hamlib.py
quisk_hardware_model.py
quisk_hardware_sdr8600.py
quisk_hardware_sdriq.py
quisk_hardware_sdrmicron.py
quisk_utils.py
quisk_vna.py
quisk_widgets.py
setup.cfg
setup.py
softrock_tune_vfo.py
sound.c
@ -68,6 +72,7 @@ winsound.txt
./README.txt
./__init__.py
./__main__.py
./_quisk.so
./configure.py
./defaults.html
./docs.html
@ -97,6 +102,7 @@ winsound.txt
./quisk_hardware_model.py
./quisk_hardware_sdr8600.py
./quisk_hardware_sdriq.py
./quisk_hardware_sdrmicron.py
./quisk_utils.py
./quisk_vna.py
./quisk_widgets.py
@ -106,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
@ -156,6 +163,7 @@ winsound.txt
./sdriqpkg/README.txt
./sdriqpkg/__init__.py
./sdriqpkg/quisk_hardware.py
./sdriqpkg/sdriq.so
./sdrmicronpkg/__init__.py
./sdrmicronpkg/quisk_hardware.py
./soapypkg/__init__.py
@ -172,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
@ -239,6 +250,7 @@ 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

62
quisk.h
View File

@ -281,6 +281,25 @@ void quisk_udp_mic_error(char *);
void quisk_check_freedv_mode(void);
void quisk_calc_audio_graph(double, complex double *, double *, int, int);
int QuiskDeltaMsec(int);
#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Define some additional functions for the GPIO Keyer. These
* allow setting various parameters for the keyer.
* mode - straight/bug, Iambic A, Iambic B
* speed - speed in words-per-minute (WPM), 1-60
* weight - dot vs dash weight, in range 33-66
* reverse - reverse left/right paddles (dot/dash by default)
* strict - enforce strict character spacing
* enabled - enable/disable the keyer
* hangtime - msecs to transmit after last CW symbol
*/
void quisk_set_gpio_keyer_mode(int);
void quisk_set_gpio_keyer_speed(int);
void quisk_set_gpio_keyer_weight(int);
void quisk_set_gpio_keyer_reversed(int);
void quisk_set_gpio_keyer_strict(int);
void quisk_set_gpio_keyer_enabled(int);
void quisk_set_gpio_keyer_hangtime(int);
#endif
// Functions supporting digital voice codecs
typedef int (* ty_dvoice_codec_rx)(complex double *, double *, int, int);
@ -333,6 +352,20 @@ int import_quisk_api(void); // used to initialize Quisk_API
#define quisk_dvoice_freedv (*( void (*) (ty_dvoice_codec_rx, ty_dvoice_codec_tx) )Quisk_API[8])
#define quisk_is_key_down (*( int (*) (void) )Quisk_API[9])
#define quisk_sample_source4 (*( void (*) (ty_sample_start, ty_sample_stop, ty_sample_read, ty_sample_write) )Quisk_API[10])
//#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Provide API definitions for the GPIO Keyer functions.
* However... since this doesn't seem to be required for various other
* functions that are accessible from Python, I've commented it all out,
* since in truth I really don't know what it's for/how to use it.
*/
//#define quisk_set_gpio_keyer_mode (*( void (*) (int) )Quisk_API[11])
//#define quisk_set_gpio_keyer_speed (*( void (*) (int) )Quisk_API[12])
//#define quisk_set_gpio_keyer_weight (*( void (*) (int) )Quisk_API[13])
//#define quisk_set_gpio_keyer_reversed (*( void (*) (int) )Quisk_API[14])
//#define quisk_set_gpio_keyer_strict (*( void (*) (int) )Quisk_API[15])
//#define quisk_set_gpio_keyer_enabled (*( void (*) (int) )Quisk_API[16])
//#define quisk_set_gpio_keyer_hangtime (*( void (*) (int) )Quisk_API[17])
//#endif
#else
// Used to export symbols from _quisk in quisk.c
@ -347,12 +380,41 @@ void quisk_sample_source(ty_sample_start, ty_sample_stop, ty_sample_read);
void quisk_dvoice_freedv(ty_dvoice_codec_rx, ty_dvoice_codec_tx);
int quisk_is_key_down(void);
void quisk_sample_source4(ty_sample_start, ty_sample_stop, ty_sample_read, ty_sample_write);
//#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Provide API definitions for the GPIO Keyer functions.
* However... since this doesn't seem to be required for various other
* functions that are accessible from Python, I've commented it all out,
* since in truth I really don't know what it's for/how to use it.
*/
//void quisk_set_gpio_keyer_mode(int);
//void quisk_set_gpio_keyer_speed(int);
//void quisk_set_gpio_keyer_weight(int);
//void quisk_set_gpio_keyer_reversed(int);
//void quisk_set_gpio_keyer_strict(int);
//void quisk_set_gpio_keyer_enabled(int);
//void quisk_set_gpio_keyer_hangtime(int);
//#endif
//#if defined(ENABLE_GPIO_KEYER)
/* KC4UPR: Provide API definitions for the GPIO Keyer functions.
* However... since this doesn't seem to be required for various other
* functions that are accessible from Python, I've commented it all out,
* since in truth I really don't know what it's for/how to use it.
*/
//#define QUISK_API_INIT { \
// &quisk_sound_state, &QuiskGetConfigInt, &QuiskGetConfigDouble, &QuiskGetConfigString, &QuiskTimeSec, \
// &QuiskSleepMicrosec, &QuiskPrintTime, &quisk_sample_source, &quisk_dvoice_freedv, &quisk_is_key_down, \
// &quisk_sample_source4, &quisk_set_gpio_keyer_mode, &quisk_set_gpio_keyer_speed, \
// &quisk_set_gpio_keyer_weight, &quisk_set_gpio_keyer_reversed, &quisk_set_gpio_keyer_strict, \
// &quisk_set_gpio_keyer_enabled, &quisk_set_gpio_keyer_hangtime \
// }
//#else
#define QUISK_API_INIT { \
&quisk_sound_state, &QuiskGetConfigInt, &QuiskGetConfigDouble, &QuiskGetConfigString, &QuiskTimeSec, \
&QuiskSleepMicrosec, &QuiskPrintTime, &quisk_sample_source, &quisk_dvoice_freedv, &quisk_is_key_down, \
&quisk_sample_source4 \
}
//#endif
#endif

View File

@ -1291,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)

View File

@ -17,6 +17,12 @@ fp.close()
is_64bit = struct.calcsize("P") == 8
have_portaudio = False
# KC4UPR: Added some lists to grab extra libraries, sources and macros.
extra_libraries = []
extra_sources = []
extra_macros = []
if sys.platform != "win32":
try:
import wx
@ -30,12 +36,21 @@ if sys.platform != "win32":
have_portaudio = True
if not os.path.isdir("/usr/include/pulse"):
print ("please install the package libpulse-dev")
libraries = ['asound', 'pulse', 'fftw3', 'm']
# KC4UPR: Added this section to build the GPIO Keyer, in the event
# that wiringPi.h is available.
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']
define_macros = []
'filter.c', 'extdemod.c', 'freedv.c'] + extra_sources
define_macros = [] + extra_macros
if have_portaudio:
libraries.append('portaudio')
sources.append('sound_portaudio.c')