Skip to content

Commit

Permalink
Merge pull request #677 from SmackleFunky/master
Browse files Browse the repository at this point in the history
Virtual Serial Port - and a Layout that uses that virtual serial port for Plover
  • Loading branch information
jackhumbert authored Aug 23, 2016
2 parents fb4452c + 7009112 commit a920548
Show file tree
Hide file tree
Showing 9 changed files with 695 additions and 4 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
endif

ifeq ($(strip $(VIRTSER_ENABLE)), yes)
OPT_DEFS += -DVIRTSER_ENABLE
endif

ifeq ($(strip $(AUDIO_ENABLE)), yes)
OPT_DEFS += -DAUDIO_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
Expand Down
3 changes: 3 additions & 0 deletions keyboards/ergodox/ez/keymaps/steno/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
VIRTSER_ENABLE = yes
# Not enough interupts, so something has to go
MOUSEKEY_ENABLE = no
324 changes: 324 additions & 0 deletions keyboards/ergodox/ez/keymaps/steno/keymap.c

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions keyboards/ergodox/ez/keymaps/steno/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# ErgoDox EZ Steno Configuration

This layout has a layer that uses the TxBolt Stenograph protocol over a Virtual Serial port. It requires something like Plover in order to function.

In Plover, you can select TX Bolt as the Stenotype Machine, and find the COM port that was assigned. In this way, your regular keyboard will still function normally, and you can switch back and forth between the Steno and Keyboard layers.

<pre><code>
/* Keymap 0: Basic layer
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | Del | Q | W | E | R | T | L1 | | TX | Y | U | I | O | P | \ |
* |--------+------+------+------+------+------| | | BOLT |------+------+------+------+------+--------|
* | BkSp | A | S | D | F | G |------| |------| H | J | K | L |; / L2|' / Cmd |
* |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
* | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | App | LGui | | Alt |Ctrl/Esc|
* ,------|------|------| |------+--------+------.
* | | | Home | | PgUp | | |
* | Space|Backsp|------| |------| Tab |Enter |
* | |ace | End | | PgDn | | |
* `--------------------' `----------------------'
*/
/* Keymap 1: Symbol Layer
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* |Version | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | | | | | | | | . | 0 | = | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*/
/* Keymap 2: Media keys
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | RESET | | | | | | | | | | | | | | |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | | | | | | | | | | | | | | | |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | | | | | |------| |------| | | | | | Play |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | | | | | | | | | | | Prev | Next | | |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | | | | | | |VolUp |VolDn | Mute | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | |Brwser|
* | | |------| |------| |Back |
* | | | | | | | |
* `--------------------' `--------------------'
*/
/* Keymap 3: TxBolt (Serial)
*
* ,--------------------------------------------------. ,--------------------------------------------------.
* | BKSPC | | | | | | | | | | | | | | |
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
* | | # | # | # | # | # | | | | # | # | # | # | # | # |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | S | T | P | H | * |------| |------| * | F | P | L | T | D |
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
* | | S | K | W | R | * | | | | * | R | B | G | S | Z |
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
* | | | | | | | | | | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | A | O |------| |------| E | U |
* | | | | | | | |
* `--------------------' `--------------------'
*/
</code></pre>
10 changes: 10 additions & 0 deletions tmk_core/common/virtser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef _VIRTSER_H_
#define _VIRTSER_H_

/* Define this function in your code to process incoming bytes */
void virtser_recv(const uint8_t ch);

/* Call this to send a character over the Virtual Serial Device */
void virtser_send(const uint8_t byte);

#endif
4 changes: 4 additions & 0 deletions tmk_core/protocol/lufa.mk
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
$(TMK_DIR)/protocol/serial_uart.c
endif

ifeq ($(strip $(VIRTSER_ENABLE)), yes)
LUFA_SRC += $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c
endif

SRC += $(LUFA_SRC)

# Search Path
Expand Down
112 changes: 111 additions & 1 deletion tmk_core/protocol/lufa/descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,15 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},

.USBSpecification = VERSION_BCD(1,1,0),
#if VIRTSER_ENABLE
.Class = USB_CSCP_IADDeviceClass,
.SubClass = USB_CSCP_IADDeviceSubclass,
.Protocol = USB_CSCP_IADDeviceProtocol,
#else
.Class = USB_CSCP_NoDeviceClass,
.SubClass = USB_CSCP_NoDeviceSubclass,
.Protocol = USB_CSCP_NoDeviceProtocol,
#endif

.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,

Expand Down Expand Up @@ -643,8 +649,112 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =

.TotalEmbeddedJacks = 0x01,
.AssociatedJackID = {0x03}
}
},
#endif

#ifdef VIRTSER_ENABLE
.CDC_Interface_Association =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},

.FirstInterfaceIndex = CCI_INTERFACE,
.TotalInterfaces = 2,

.Class = CDC_CSCP_CDCClass,
.SubClass = CDC_CSCP_ACMSubclass,
.Protocol = CDC_CSCP_ATCommandProtocol,

.IADStrIndex = NO_DESCRIPTOR,
},

.CDC_CCI_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},

.InterfaceNumber = CCI_INTERFACE,
.AlternateSetting = 0,

.TotalEndpoints = 1,

.Class = CDC_CSCP_CDCClass,
.SubClass = CDC_CSCP_ACMSubclass,
.Protocol = CDC_CSCP_ATCommandProtocol,

.InterfaceStrIndex = NO_DESCRIPTOR
},

.CDC_Functional_Header =
{
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
.Subtype = 0x00,

.CDCSpecification = VERSION_BCD(1,1,0),
},

.CDC_Functional_ACM =
{
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
.Subtype = 0x02,

.Capabilities = 0x02,
},

.CDC_Functional_Union =
{
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
.Subtype = 0x06,

.MasterInterfaceNumber = CCI_INTERFACE,
.SlaveInterfaceNumber = CDI_INTERFACE,
},

.CDC_NotificationEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},

.EndpointAddress = CDC_NOTIFICATION_EPADDR,
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = CDC_NOTIFICATION_EPSIZE,
.PollingIntervalMS = 0xFF
},

.CDC_DCI_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},

.InterfaceNumber = CDI_INTERFACE,
.AlternateSetting = 0,

.TotalEndpoints = 2,

.Class = CDC_CSCP_CDCDataClass,
.SubClass = CDC_CSCP_NoDataSubclass,
.Protocol = CDC_CSCP_NoDataProtocol,

.InterfaceStrIndex = NO_DESCRIPTOR
},

.CDC_DataOutEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},

.EndpointAddress = CDC_OUT_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = CDC_EPSIZE,
.PollingIntervalMS = 0x05
},

.CDC_DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},

.EndpointAddress = CDC_IN_EPADDR,
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = CDC_EPSIZE,
.PollingIntervalMS = 0x05
},
#endif

};


Expand Down
43 changes: 40 additions & 3 deletions tmk_core/protocol/lufa/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ typedef struct
USB_MIDI_Descriptor_Jack_Endpoint_t MIDI_Out_Jack_Endpoint_SPC;
#endif

#ifdef VIRTSER_ENABLE
USB_Descriptor_Interface_Association_t CDC_Interface_Association;

// CDC Control Interface
USB_Descriptor_Interface_t CDC_CCI_Interface;
USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;

// CDC Data Interface
USB_Descriptor_Interface_t CDC_DCI_Interface;
USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
#endif
} USB_Descriptor_Configuration_t;


Expand Down Expand Up @@ -141,8 +156,15 @@ typedef struct
# define AS_INTERFACE NKRO_INTERFACE
#endif

#ifdef VIRTSER_ENABLE
# define CCI_INTERFACE (AS_INTERFACE + 1)
# define CDI_INTERFACE (AS_INTERFACE + 2)
#else
# define CDI_INTERFACE AS_INTERFACE
#endif

/* nubmer of interfaces */
#define TOTAL_INTERFACES AS_INTERFACE + 1
#define TOTAL_INTERFACES (CDI_INTERFACE + 1)


// Endopoint number and size
Expand Down Expand Up @@ -180,11 +202,24 @@ typedef struct
# define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 2)
# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM)
# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM)
#else
# define MIDI_STREAM_OUT_EPNUM NKRO_IN_EPNUM
#endif

#ifdef VIRTSER_ENABLE
# define CDC_NOTIFICATION_EPNUM (MIDI_STREAM_OUT_EPNUM + 1)
# define CDC_IN_EPNUM (MIDI_STREAM_OUT_EPNUM + 2)
# define CDC_OUT_EPNUM (MIDI_STREAM_OUT_EPNUM + 3)
# define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM)
# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM)
# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM)
#else
# define CDC_OUT_EPNUM MIDI_STREAM_OUT_EPNUM
#endif


#if defined(__AVR_ATmega32U2__) && MIDI_STREAM_OUT_EPADDR > 4
# error "Endpoints are not available enough to support all functions. Remove some in Makefile.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI)"
#if defined(__AVR_ATmega32U2__) && CDC_OUT_EPNUM > 4
# error "Endpoints are not available enough to support all functions. Remove some in Makefile.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, SERIAL)"
#endif

#define KEYBOARD_EPSIZE 8
Expand All @@ -193,6 +228,8 @@ typedef struct
#define CONSOLE_EPSIZE 32
#define NKRO_EPSIZE 16
#define MIDI_STREAM_EPSIZE 64
#define CDC_NOTIFICATION_EPSIZE 8
#define CDC_EPSIZE 16


uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
Expand Down
Loading

0 comments on commit a920548

Please sign in to comment.