From 3f96ba011359e7e842a5f917c11886c1867ba207 Mon Sep 17 00:00:00 2001 From: milestogo Date: Thu, 6 Dec 2018 17:13:15 -0800 Subject: [PATCH] Keyboard: Palm serial keyboard USB converter (#4485) * Initial palm_usb support * removing left over sun .c file * fixing licenses * actually adding updated files * fixing build error * more include cleanup --- keyboards/converter/palm_usb/config.h | 120 ++++++ keyboards/converter/palm_usb/matrix.c | 398 ++++++++++++++++++ keyboards/converter/palm_usb/readme.md | 96 +++++ keyboards/converter/palm_usb/rules.mk | 46 ++ .../stowaway/keymaps/default/keymap.c | 59 +++ .../converter/palm_usb/stowaway/rules.mk | 0 .../converter/palm_usb/stowaway/stowaway.h | 53 +++ 7 files changed, 772 insertions(+) create mode 100644 keyboards/converter/palm_usb/config.h create mode 100644 keyboards/converter/palm_usb/matrix.c create mode 100644 keyboards/converter/palm_usb/readme.md create mode 100644 keyboards/converter/palm_usb/rules.mk create mode 100644 keyboards/converter/palm_usb/stowaway/keymaps/default/keymap.c create mode 100644 keyboards/converter/palm_usb/stowaway/rules.mk create mode 100644 keyboards/converter/palm_usb/stowaway/stowaway.h diff --git a/keyboards/converter/palm_usb/config.h b/keyboards/converter/palm_usb/config.h new file mode 100644 index 000000000..4520725a1 --- /dev/null +++ b/keyboards/converter/palm_usb/config.h @@ -0,0 +1,120 @@ +/* +Copyright 2012 Jun Wako + +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 . +*/ + +/* 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< + +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 . +*/ + +#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<. +*/ + +#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, _______, _______, _______, _______, _______, _______, _______ + ), + +}; diff --git a/keyboards/converter/palm_usb/stowaway/rules.mk b/keyboards/converter/palm_usb/stowaway/rules.mk new file mode 100644 index 000000000..e69de29bb diff --git a/keyboards/converter/palm_usb/stowaway/stowaway.h b/keyboards/converter/palm_usb/stowaway/stowaway.h new file mode 100644 index 000000000..71af9bf4a --- /dev/null +++ b/keyboards/converter/palm_usb/stowaway/stowaway.h @@ -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 . +*/ + +#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 } \ +} +