* Initial palm_usb support * removing left over sun .c file * fixing licenses * actually adding updated files * fixing build error * more include cleanuppull/4568/head
@ -0,0 +1,120 @@ | |||
/* | |||
Copyright 2012 Jun Wako <wakojun@gmail.com> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/* This code makes use of cy384's Arduino USB HID adapter for the Palm Portable | |||
Keyboard, released under the BSD licence */ | |||
#pragma once | |||
#define CUSTOM_MATRIX 2 | |||
#define VENDOR_ID 0xFEED | |||
#define PRODUCT_ID 0x0001 | |||
#define DEVICE_VER 0x0100 | |||
#define MANUFACTURER QMK | |||
#define PRODUCT Stowaway converter | |||
#define DESCRIPTION USB converter for Stowaway keyboard | |||
// IO pins to serial | |||
// https://deskthority.net/wiki/Arduino_Pro_Micro for pin lookup | |||
#define VCC_PIN D1 // pro micro 2 | |||
#define RX_PIN D0 //pro micro 3 , was 8 on cy384 | |||
#define RTS_PIN C6 // 5 //[ was D4 // 4 on the cy384 | |||
#define DCD_PIN E6 //7 | |||
// if using the particular arduino pinout of CY384 | |||
#ifdef CY384 | |||
#define GND_PIN D7 //6 | |||
#define PULLDOWN_PIN B1 // 15 | |||
#endif | |||
#ifndef HANDSPRING | |||
// Set to 1 for Handspring or to disable RTS/DCD based handshake. | |||
#define HANDSPRING 0 | |||
#endif | |||
#define MAXDROP 10 // check if keyboard is connected every X polling cycles | |||
#define SLEEP_TIMEOUT 500000 // check keyboard/reset this many millis | |||
#define MATRIX_ROWS 12 | |||
#define MATRIX_COLS 8 | |||
/* key combination for command */ | |||
#define IS_COMMAND() ( \ | |||
keyboard_report->mods == (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) || \ | |||
keyboard_report->mods == (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI)) || \ | |||
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ | |||
) | |||
/* Serial(USART) configuration | |||
* asynchronous, negative logic, 9600baud, no flow control | |||
* 1-start bit, 8-data bit, non parity, 1-stop bit | |||
*/ | |||
#define SERIAL_SOFT_BAUD 9600 | |||
#define SERIAL_SOFT_PARITY_NONE | |||
#define SERIAL_SOFT_BIT_ORDER_LSB | |||
#if (HANDSPRING == 0) | |||
#define SERIAL_SOFT_LOGIC_NEGATIVE //RS232 logic | |||
#endif | |||
/* RXD Port */ | |||
#define SERIAL_SOFT_RXD_ENABLE | |||
// we are using Pro micro pin 3 / D0 as serial | |||
#define SERIAL_SOFT_RXD_DDR DDRD | |||
#define SERIAL_SOFT_RXD_PORT PORTD | |||
#define SERIAL_SOFT_RXD_PIN PIND | |||
#define SERIAL_SOFT_RXD_BIT 0 | |||
#define SERIAL_SOFT_RXD_VECT INT0_vect | |||
/* RXD Interupt */ | |||
#define SERIAL_SOFT_RXD_INIT() do { \ | |||
/* pin configuration: input with pull-up */ \ | |||
SERIAL_SOFT_RXD_DDR &= ~(1<<SERIAL_SOFT_RXD_BIT); \ | |||
SERIAL_SOFT_RXD_PORT |= (1<<SERIAL_SOFT_RXD_BIT); \ | |||
/* enable interrupt: INT0(rising edge) */ \ | |||
EICRA |= ((1<<ISC01)|(1<<ISC00)); \ | |||
EIMSK |= (1<<INT0); \ | |||
sei(); \ | |||
} while (0) | |||
#define SERIAL_SOFT_RXD_INT_ENTER() | |||
#define SERIAL_SOFT_RXD_INT_EXIT() do { \ | |||
/* clear interrupt flag */ \ | |||
EIFR = (1<<INTF0); \ | |||
} while (0) | |||
#define SERIAL_SOFT_RXD_READ() (SERIAL_SOFT_RXD_PIN&(1<<SERIAL_SOFT_RXD_BIT)) | |||
/* TXD Port */ | |||
#define SERIAL_SOFT_TXD_ENABLE | |||
#define SERIAL_SOFT_TXD_DDR DDRD | |||
#define SERIAL_SOFT_TXD_PORT PORTD | |||
#define SERIAL_SOFT_TXD_PIN PIND | |||
#define SERIAL_SOFT_TXD_BIT 3 | |||
#define SERIAL_SOFT_TXD_HI() do { SERIAL_SOFT_TXD_PORT |= (1<<SERIAL_SOFT_TXD_BIT); } while (0) | |||
#define SERIAL_SOFT_TXD_LO() do { SERIAL_SOFT_TXD_PORT &= ~(1<<SERIAL_SOFT_TXD_BIT); } while (0) | |||
#define SERIAL_SOFT_TXD_INIT() do { \ | |||
/* pin configuration: output */ \ | |||
SERIAL_SOFT_TXD_DDR |= (1<<SERIAL_SOFT_TXD_BIT); \ | |||
/* idle */ \ | |||
SERIAL_SOFT_TXD_ON(); \ | |||
} while (0) | |||
@ -0,0 +1,398 @@ | |||
/* | |||
Copyright 2018 milestogo | |||
with elements Copyright 2014 cy384 under a modified BSD license | |||
building on qmk structure Copyright 2012 Jun Wako <wakojun@gmail.com> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include QMK_KEYBOARD_H | |||
#include "protocol/serial.h" | |||
#include "timer.h" | |||
#include "pincontrol.h" | |||
/* | |||
* Matrix Array usage: | |||
* | |||
* ROW: 12(4bits) | |||
* COL: 8(3bits) | |||
* | |||
* +---------+ | |||
* 0|00 ... 07| | |||
* 1|00 ... 07| | |||
* :| ... | | |||
* :| ... | | |||
* A| | | |||
* B| | | |||
* +---------+ | |||
*/ | |||
static uint8_t matrix[MATRIX_ROWS]; | |||
// we're going to need a sleep timer | |||
static uint16_t last_activity ; | |||
// and a byte to track duplicate up events signalling all keys up. | |||
static uint16_t last_upKey ; | |||
// serial device can disconnect. Check every MAXDROP characters. | |||
static uint16_t disconnect_counter = 0; | |||
// bitmath masks. | |||
#define KEY_MASK 0b10000000 | |||
#define COL_MASK 0b00000111 | |||
#define ROW_MASK 0b01111000 | |||
#define ROW(code) (( code & ROW_MASK ) >>3) | |||
#define COL(code) ((code & COL_MASK) ) | |||
#define KEYUP(code) ((code & KEY_MASK) >>7 ) | |||
static bool is_modified = false; | |||
__attribute__ ((weak)) | |||
void matrix_init_kb(void) { | |||
matrix_init_user(); | |||
} | |||
__attribute__ ((weak)) | |||
void matrix_scan_kb(void) { | |||
matrix_scan_user(); | |||
} | |||
__attribute__ ((weak)) | |||
void matrix_init_user(void) { | |||
} | |||
__attribute__ ((weak)) | |||
void matrix_scan_user(void) { | |||
} | |||
inline | |||
uint8_t matrix_rows(void) | |||
{ | |||
return MATRIX_ROWS; | |||
} | |||
inline | |||
uint8_t matrix_cols(void) | |||
{ | |||
return MATRIX_COLS; | |||
} | |||
void pins_init(void) { | |||
// set pins for pullups, Rts , power &etc. | |||
//print ("pins setup\n"); | |||
pinMode(VCC_PIN, PinDirectionOutput); | |||
digitalWrite(VCC_PIN, PinLevelLow); | |||
#if ( HANDSPRING == 0) | |||
#ifdef CY835 | |||
pinMode(GND_PIN, PinDirectionOutput); | |||
digitalWrite(GND_PIN, PinLevelLow); | |||
pinMode(PULLDOWN_PIN, PinDirectionOutput); | |||
digitalWrite(PULLDOWN_PIN, PinLevelLow); | |||
#endif | |||
pinMode(DCD_PIN, PinDirectionInput); | |||
pinMode(RTS_PIN, PinDirectionInput); | |||
#endif | |||
/* check that the other side isn't powered up. | |||
test=digitalRead(DCD_PIN); | |||
xprintf("b%02X:", test); | |||
test=digitalRead(RTS_PIN); | |||
xprintf("%02X\n", test); | |||
*/ | |||
} | |||
uint8_t rts_reset(void) { | |||
static uint8_t firstread ; | |||
/* bounce RTS so device knows it is rebooted */ | |||
// On boot, we keep rts as input, then switch roles here | |||
// on leaving sleep, we toggle the same way | |||
firstread=digitalRead(RTS_PIN); | |||
// printf("r%02X:", firstread); | |||
pinMode(RTS_PIN, PinDirectionOutput); | |||
if (firstread == PinLevelHigh) { | |||
digitalWrite(RTS_PIN, PinLevelLow); | |||
} | |||
_delay_ms(10); | |||
digitalWrite(RTS_PIN, PinLevelHigh); | |||
/* the future is Arm | |||
if (palReadPad(RTS_PIN_IOPRT) == PinLevelLow) | |||
{ | |||
_delay_ms(10); | |||
palSetPadMode(RTS_PINn_IOPORT, PinDirectionOutput_PUSHPULL); | |||
palSetPad(RTS_PORT, RTS_PIN); | |||
} | |||
else | |||
{ | |||
palSetPadMode(RTS_PIN_RTS_PORT, PinDirectionOutput_PUSHPULL); | |||
palSetPad(RTS_PORT, RTS_PIN); | |||
palClearPad(RTS_PORT, RTS_PIN); | |||
_delay_ms(10); | |||
palSetPad(RTS_PORT, RTS_PIN); | |||
} | |||
*/ | |||
_delay_ms(5); | |||
//print("rts\n"); | |||
return 1; | |||
} | |||
uint8_t get_serial_byte(void) { | |||
static uint8_t code; | |||
while(1) { | |||
code = serial_recv(); | |||
if (code) { | |||
debug_hex(code); debug(" "); | |||
return code; | |||
} | |||
} | |||
} | |||
uint8_t palm_handshake(void) { | |||
// assumes something has seen DCD go high, we've toggled RTS | |||
// and we now need to verify handshake. | |||
// listen for up to 4 packets before giving up. | |||
// usually I get the sequence FF FA FD | |||
static uint8_t codeA=0; | |||
for (uint8_t i=0; i < 5; i++) { | |||
codeA=get_serial_byte(); | |||
if ( 0xFA == codeA) { | |||
if( 0xFD == get_serial_byte()) { | |||
return 1; | |||
} | |||
} | |||
} | |||
return 0; | |||
} | |||
uint8_t palm_reset(void) { | |||
print("@"); | |||
rts_reset(); // shouldn't need to power cycle. | |||
if ( palm_handshake() ) { | |||
last_activity = timer_read(); | |||
return 1; | |||
} else { | |||
print("failed reset"); | |||
return 0; | |||
} | |||
} | |||
uint8_t handspring_handshake(void) { | |||
// should be sent 15 ms after power up. | |||
// listen for up to 4 packets before giving up. | |||
static uint8_t codeA=0; | |||
for (uint8_t i=0; i < 5; i++) { | |||
codeA=get_serial_byte(); | |||
if ( 0xF9 == codeA) { | |||
if( 0xFB == get_serial_byte()) { | |||
return 1; | |||
} | |||
} | |||
} | |||
return 0; | |||
} | |||
uint8_t handspring_reset(void) { | |||
digitalWrite(VCC_PIN, PinLevelLow); | |||
_delay_ms(5); | |||
digitalWrite(VCC_PIN, PinLevelHigh); | |||
if ( handspring_handshake() ) { | |||
last_activity = timer_read(); | |||
disconnect_counter=0; | |||
return 1; | |||
} else { | |||
print("-HSreset"); | |||
return 0; | |||
} | |||
} | |||
void matrix_init(void) | |||
{ | |||
debug_enable = true; | |||
//debug_matrix =true; | |||
serial_init(); // arguments all #defined | |||
#if (HANDSPRING == 0) | |||
pins_init(); // set all inputs and outputs. | |||
#endif | |||
print("power up\n"); | |||
digitalWrite(VCC_PIN, PinLevelHigh); | |||
// wait for DCD strobe from keyboard - it will do this | |||
// up to 3 times, then the board needs the RTS toggled to try again | |||
#if ( HANDSPRING == 1) | |||
if ( handspring_handshake() ) { | |||
last_activity = timer_read(); | |||
} else { | |||
print("failed handshake"); | |||
_delay_ms(1000); | |||
//BUG /should/ power cycle or toggle RTS & reset, but this usually works. | |||
} | |||
#else /// Palm / HP device with DCD | |||
while( digitalRead(DCD_PIN) != PinLevelHigh ) {;} | |||
print("dcd\n"); | |||
rts_reset(); // at this point the keyboard should think all is well. | |||
if ( palm_handshake() ) { | |||
last_activity = timer_read(); | |||
} else { | |||
print("failed handshake"); | |||
_delay_ms(1000); | |||
//BUG /should/ power cycle or toggle RTS & reset, but this usually works. | |||
} | |||
#endif | |||
// initialize matrix state: all keys off | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||
matrix_init_quantum(); | |||
return; | |||
} | |||
uint8_t matrix_scan(void) | |||
{ | |||
uint8_t code; | |||
code = serial_recv(); | |||
if (!code) { | |||
/* | |||
disconnect_counter ++; | |||
if (disconnect_counter > MAXDROP) { | |||
// set all keys off | |||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||
} | |||
*/ | |||
// check if the keyboard is asleep. | |||
if (timer_elapsed(last_activity) > SLEEP_TIMEOUT) { | |||
#if(HANDSPRING ==0 ) | |||
palm_reset(); | |||
#else | |||
handspring_reset(); | |||
#endif | |||
return 0; | |||
} | |||
} | |||
last_activity = timer_read(); | |||
disconnect_counter=0; // if we are getting serial data, we're connected. | |||
debug_hex(code); debug(" "); | |||
switch (code) { | |||
case 0xFD: // unexpected reset byte 2 | |||
print("rstD "); | |||
return 0; | |||
case 0xFA: // unexpected reset | |||
print("rstA "); | |||
return 0; | |||
} | |||
if (KEYUP(code)) { | |||
if (code == last_upKey) { | |||
// all keys are not pressed. | |||
// Manual says to disable all modifiers left open now. | |||
// but that could defeat sticky keys. | |||
// BUG? dropping this byte. | |||
last_upKey=0; | |||
return 0; | |||
} | |||
// release | |||
if (matrix_is_on(ROW(code), COL(code))) { | |||
matrix[ROW(code)] &= ~(1<<COL(code)); | |||
last_upKey=code; | |||
} | |||
} else { | |||
// press | |||
if (!matrix_is_on(ROW(code), COL(code))) { | |||
matrix[ROW(code)] |= (1<<COL(code)); | |||
} | |||
} | |||
matrix_scan_quantum(); | |||
return code; | |||
} | |||
bool matrix_is_modified(void) | |||
{ | |||
return is_modified; | |||
} | |||
inline | |||
bool matrix_has_ghost(void) | |||
{ | |||
return false; | |||
} | |||
inline | |||
bool matrix_is_on(uint8_t row, uint8_t col) | |||
{ | |||
return (matrix[row] & (1<<col)); | |||
} | |||
inline | |||
uint8_t matrix_get_row(uint8_t row) | |||
{ | |||
return matrix[row]; | |||
} | |||
void matrix_print(void) | |||
{ | |||
print("\nr/c 01234567\n"); | |||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||
phex(row); print(": "); | |||
pbin_reverse(matrix_get_row(row)); | |||
print("\n"); | |||
} | |||
} | |||
uint8_t matrix_key_count(void) | |||
{ | |||
uint8_t count = 0; | |||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||
count += bitpop(matrix[i]); | |||
} | |||
return count; | |||
} |
@ -0,0 +1,96 @@ | |||
# Stowaway Serial keyboard to USB protocol converter | |||
A converter for Palm Pilot era Stowaway serial keyboards. | |||
Makes extensive use of the code from [cy384](https://github.com/cy384/ppk_usb). Ported to QMK by [milestogo](https://github.com/milestogo). | |||
Hardware Supported: See hardware section below | |||
Hardware Availability: self-built | |||
Make example for this keyboard (after setting up your build environment): | |||
make converter/palm_usb/stowaway:default | |||
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). | |||
## Hardware | |||
Target MCU is ATMega32u4 but other USB capable AVRs should also work. | |||
cy843 has a very specific way of wiring in order to fit all pins in sequence. It breaks | |||
qmk because the Arduino softserial library uses different pins from QMK. | |||
I've wired the pro micro hardware as follows. | |||
Label| TX0,RX1,GND,GND,2 ,3 ,4 ,5 ,6 ,7 | |||
Palm | , , * ,GND,VCC,RX ,NC ,RTS,nc ,DCD | |||
MCU | ,D1 ,D0 , ,C6 , ,E6 | |||
\* The RX line from the keyboard should be conected to a ~10K ohm pull down resistor to ground. | |||
RX --|--3 | |||
10K | |||
| | |||
GND | |||
Power management is not implemented yet, this just reboots the keyboard frequently. | |||
### Keyboards: | |||
Think Outside Stowaway Keyboards | |||
There are at least 5 different versions of these keyboards out there. | |||
Group 1: Palm 3, Palm 5 & HP Journada 540, and Compaq iPaq keyboards. These share | |||
the same RTS protocol, but with different pinouts for each device. | |||
Group 2: Handspring keyboards. These don't do handshaking protocol, and use TTL signal. | |||
Set HANDSPRING to 1 in config.h | |||
Group 3: IRDA models. Untested but theoretically serial. | |||
### Connectors | |||
See https://github.com/cy384/ppk_usb for wiring & sample 3d printable sockets. | |||
Only Palm3 wiring has been tested. | |||
RXD pin is output from keyboard to MCU's RX. | |||
Viewed from left to right with the keyboard in typing position. | |||
Palm3: [NC, VCC, RXD, RTS, NC, NC, DCD, NC, NC, GND] | |||
Palm5: [NC, VCC, RXD, RTS, NC, NC, DCD, NC, NC, GND] (same order, different connector) | |||
Handspring: [VCC/TXD, NC, NC, NC, GND, NC, NC, RXD] | |||
Journada: [NC, NC, NC, GND, NC, RTS, NC, DTR/VCC, RXD, DCD, NC] [GND-IN, VCC-IN] | |||
Ipaq: [NC, NC, DTR/VCC, NC, NC, RTS, NC, RXD, DCD, GND, NC, NC] | |||
### Protocol | |||
Signal: Asynchronous, Negative logic, 9600baud, No Flow control | |||
Frame format: 1-Start bit, 8-Data bits, No-Parity, 1-Stop bit | |||
AVR USART engine expects positive logic while stowaway keyboard signal is negative. | |||
To use AVR UART engine you need external inverter in front of RX and TX pin. | |||
Otherwise you can software serial routine to communicate the keyboard. | |||
This converter uses software method, you doesn't need any inverter part. | |||
Commands From System To Keyboard | |||
none | |||
Commands From Keyboard To System | |||
0xFA Reset/Ready Response(followed by 0xFD) | |||
References | |||
* http://www.splorp.com/pdf/stowawayhwref.pdf | |||
### Todo | |||
- Test on anything but a palm 3 model keyboard. | |||
- Change all of the soft serial to match the new Helix based code so that it is easier | |||
to switch pins. | |||
- The driver should check for a keyboard that pressed the delete key then disconnected. | |||
Check every MAXDROP scans that the keyboard is there, and if not, clear the matrix. | |||
Not implemented yet, since matrix scan is so much faster than serial. |
@ -0,0 +1,46 @@ | |||
MCU = atmega32u4 # Teensy 2.0 | |||
F_CPU = 16000000 | |||
ARCH = AVR8 | |||
F_USB = $(F_CPU) | |||
# Interrupt driven control endpoint task | |||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | |||
BOOTLOADER = caterina | |||
# Build Options | |||
# change to "no" to disable the options, or define them in the Makefile in | |||
# the appropriate keymap folder that will get included automatically | |||
# | |||
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000) | |||
MOUSEKEY_ENABLE = no # Mouse keys(+4700) | |||
EXTRAKEY_ENABLE = no # Audio control and System control(+450) | |||
CONSOLE_ENABLE = yes # Console for debug(+400) | |||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||
NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work | |||
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality | |||
MIDI_ENABLE = no # MIDI controls | |||
AUDIO_ENABLE = no # Audio output on port C6 | |||
UNICODE_ENABLE = no # Unicode | |||
UNICODEMAP_ENABLE = no | |||
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID | |||
RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. | |||
CUSTOM_MATRIX = yes | |||
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE | |||
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend | |||
#HARDWARE_SERIAL = yes | |||
SRC += matrix.c | |||
ifdef HARDWARE_SERIAL | |||
# untested with palm_usb | |||
SRC += protocol/serial_uart.c | |||
OPT_DEFS += -DHARDWARE_SERIAL | |||
else | |||
SRC += protocol/serial_soft.c | |||
endif | |||
DEFAULT_FOLDER = converter/palm_usb/stowaway | |||
@ -0,0 +1,59 @@ | |||
/* | |||
Copyright 2018 milestogo | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include QMK_KEYBOARD_H | |||
enum layers { | |||
_QWERTY=0, | |||
_CDH, | |||
_FN | |||
}; | |||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* | |||
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS, EQL, BACK, APP0, | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC, RBRC, BSLS, APP1, | |||
CAPS, A, S, D, F, G, H, J, K, L, SCLN, QUOT, ENT, APP2, | |||
LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, RSFT, UP, APP3, | |||
LCTL, FN, LALT, CMD, SPACE,SPACE,GRAVE,DONE, DEL, LEFT, DOWN, RIGHT | |||
*/ | |||
[_QWERTY] = LAYOUT( /* Base */ | |||
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_ESC, | |||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, TG(_CDH), | |||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP, | |||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN, | |||
KC_LCTL, MO(_FN), KC_LALT, KC_LGUI, KC_SPACE,KC_SPACE,KC_GRAVE,KC_RGUI, KC_DEL, KC_LEFT,KC_DOWN, KC_RIGHT | |||
), | |||
[_CDH] = LAYOUT( /* Base */ | |||
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_ESC, | |||
KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_LBRC, KC_RBRC, KC_BSLS, _______, | |||
KC_CAPS, KC_A, KC_R, KC_S, KC_T, KC_G, KC_M, KC_N, KC_E, KC_I, KC_O, KC_QUOT, KC_ENT, KC_PGUP, | |||
KC_LSFT, KC_Z, KC_X, KC_C, KC_D, KC_V, KC_K, KC_H, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN, | |||
KC_LCTL, MO(_FN), KC_LALT, KC_LGUI, KC_SPACE,KC_SPACE,KC_GRAVE,KC_RGUI, KC_DEL, KC_LEFT,KC_DOWN, KC_RIGHT | |||
), | |||
[_FN] = LAYOUT( // FN Key | |||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | |||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | |||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | |||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | |||
_______, _______, _______, _______, KC_ENT, _______, _______, _______, _______, _______, _______, _______ | |||
), | |||
}; |
@ -0,0 +1,53 @@ | |||
/* | |||
Copyright 2018 milestogo | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#pragma once | |||
#include "quantum.h" | |||
/* Stowaway Keyboard | |||
based on matrix from http://www.splorp.com/pdf/stowawayhwref.pdf | |||
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS, EQL, BACK APP0, | |||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC, RBRC, BSLS, APP1, | |||
CAPS, A, S, D, F, G, H, J, K, L, SCLN, QUOT, ENT, APP2, | |||
LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, RSFT, UP, APP3, | |||
LCTL, FN, LALT, CMD, SPACE,SPACE,GRAVE,DONE, DEL, LEFT, DOWN, RIGHT | |||
*/ | |||
#define LAYOUT( \ | |||
K000, K001, K002, K004, K005, K006, K007, K064, K065, K066, K060, K061, K062, K063,\ | |||
K031, K011, K012, K013, K014, K015, K016, K074, K075, K076, K077, K070, K071, K072, K073,\ | |||
K030, K021, K022, K023, K024, K025, K026, K084, K085, K086, K087, K080, K081, K082,\ | |||
K110, K003, K020, K054, K055, K056, K057, K094, K095, K096, K090, K111, K091, K092,\ | |||
K032, K042, K043, K010, K027, K067, K017, K097, K100, K101, K102, K103 \ | |||
) { \ | |||
{ K000, K001, K002 , K003, K004, K005, K006, K007 }, \ | |||
{ K010, K011, K012 , K013, K014, K015, K016, K017 }, \ | |||
{ K020, K021, K022 , K023, K024, K025, K026, K027 }, \ | |||
{ K030, K031, K032 , KC_NO,KC_NO, KC_NO,KC_NO, KC_NO }, \ | |||
{ KC_NO, KC_NO, K042 , K043, KC_NO, KC_NO,KC_NO, KC_NO }, \ | |||
{ KC_NO, KC_NO, KC_NO, KC_NO,K054, K055, K056, K057 }, \ | |||
{ K060, K061, K062 , K063, K064, K065, K066, K067 }, \ | |||
{ K070, K071, K072 , K073, K074, K075, K076, K077 }, \ | |||
{ K080, K081, K082 , KC_NO,K084, K085, K086, K087 }, \ | |||
{ K090, K091, K092 , KC_NO,K094, K095, K096, K097 }, \ | |||
{ K100, K101, K102 , K103, KC_NO, KC_NO,KC_NO, KC_NO }, \ | |||
{ K110, K111, KC_NO, KC_NO,KC_NO, KC_NO,KC_NO, KC_NO } \ | |||
} | |||