From 8f8de985c569a5be44f2996cc4696c511a4a3378 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sat, 10 Dec 2011 22:48:53 -0800 Subject: [PATCH] Initial commit of the Epson QX-10 Keyboard module - LEDs are working - Reset command is working - Basic typing is working (USB side drops some characters) - Changing repeat rate is working - Querying modifiers and LEDs is working - Initial layouts are complete - Modifiers are not fully working yet --- CMakeLists.txt | 4 +- Keymap/epsonqx10.h | 331 +++++++++++++++++++++ Keymap/keymap.h | 1 + Macro/buffer/macro.c | 3 + Scan/EpsonQX-10/scan_loop.c | 555 ++++++++++++++++++++++++++++++++++++ Scan/EpsonQX-10/scan_loop.h | 65 +++++ Scan/EpsonQX-10/setup.cmake | 48 ++++ main.c | 2 + setup.cmake | 2 +- 9 files changed, 1008 insertions(+), 3 deletions(-) create mode 100644 Keymap/epsonqx10.h create mode 100644 Scan/EpsonQX-10/scan_loop.c create mode 100644 Scan/EpsonQX-10/scan_loop.h create mode 100644 Scan/EpsonQX-10/setup.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b4e935..44b9141 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,8 +64,8 @@ set( SRCS #| "atmega32u4" # Teensy 2.0 #| "at90usb646" # Teensy++ 1.0 #| "at90usb1286" # Teensy++ 2.0 -set( MCU "atmega32u4" ) -#set( MCU "at90usb1286" ) +#set( MCU "atmega32u4" ) +set( MCU "at90usb1286" ) #| Compiler flag to set the C Standard level. diff --git a/Keymap/epsonqx10.h b/Keymap/epsonqx10.h new file mode 100644 index 0000000..aa15a9e --- /dev/null +++ b/Keymap/epsonqx10.h @@ -0,0 +1,331 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __EPSONQX10_H +#define __EPSONQX10_H + +// This file contains various key layouts for the Epson QX-10 Series of keyboards +// NOTE: Modifiers can't be remapped to non-modifer keys due to how the signals are interpretted +// Remapping between modifier keys is perfectly fine (or even a modifier to a normal key) + + + +// ----- Variables ----- +static uint8_t epsonqx10_ModifierMask[] = { 0x81, 0x83, 0x85, 0x87, 0x89, 0x8B, 0x8D, 0x8F }; + +static uint8_t epsonqx10_DefaultMap[] = { + 0x00, // 0x00 + KEY_F4, // 0x01 + 0, // 0x02 + KEY_F5, // 0x03 + KEY_F6, // 0x04 + KEY_F7, // 0x05 + KEY_F8, // 0x06 + KEY_F9, // 0x07 + 0, // 0x08 + KEY_F10, // 0x09 + KEY_F11, // 0x0A + KEY_F12, // 0x0B + KEY_F13, // 0x0C + 0, // 0x0D + KEY_F14, // 0x0E + KEY_F15, // 0x0F + 0, // 0x10 + 0, // 0x11 + 0, // 0x12 + 0, // 0x13 + 0, // 0x14 + KEYPAD_ENTER, // 0x15 + KEYPAD_PERIOD, // 0x16 + KEYPAD_0, // 0x17 + KEYPAD_EQUAL, // 0x18 + KEYPAD_6, // 0x19 + KEYPAD_5, // 0x1A + KEYPAD_4, // 0x1B + 0, // 0x1C + 0, // 0x1D + KEY_F17, // 0x1E + KEY_F16, // 0x1F + 0, // 0x20 + 0, // 0x21 + 0, // 0x22 + 0, // 0x23 + 0, // 0x24 + KEYPAD_3, // 0x25 + KEYPAD_2, // 0x26 + KEYPAD_1, // 0x27 + KEYPAD_PLUS, // 0x28 + KEYPAD_9, // 0x29 + KEYPAD_8, // 0x2A + KEYPAD_7, // 0x2B + KEYPAD_MINUS, // 0x2C + KEYPAD_ASTERIX, // 0x2D + KEYPAD_SLASH, // 0x2E + KEY_NUM_LOCK, // 0x2F + 0, // 0x30 + 0, // 0x31 + KEY_SPACE, // 0x32 + KEY_Z, // 0x33 + KEY_X, // 0x34 + KEY_C, // 0x35 + KEY_V, // 0x36 + KEY_B, // 0x37 + KEY_N, // 0x38 + KEY_M, // 0x39 + KEY_COMMA, // 0x3A + KEY_PERIOD, // 0x3B + KEY_UP, // 0x3C + KEY_LEFT, // 0x3D + KEY_RIGHT, // 0x3E + KEY_DOWN, // 0x3F + 0, // 0x40 + KEY_F19, // 0x41 + KEY_CAPS_LOCK, // 0x42 + KEY_A, // 0x43 + KEY_S, // 0x44 + KEY_D, // 0x45 + KEY_F, // 0x46 + KEY_G, // 0x47 + KEY_H, // 0x48 + KEY_J, // 0x49 + KEY_K, // 0x4A + KEY_L, // 0x4B + KEY_SEMICOLON, // 0x4C + KEY_QUOTE, // 0x4D + KEY_ENTER, // 0x4E + KEY_SLASH, // 0x4F + 0, // 0x50 + KEY_Q, // 0x51 + KEY_W, // 0x52 + KEY_E, // 0x53 + KEY_R, // 0x54 + KEY_T, // 0x55 + KEY_Y, // 0x56 + KEY_U, // 0x57 + KEY_I, // 0x58 + KEY_O, // 0x59 + KEY_P, // 0x5A + KEY_LEFT_BRACE, // 0x5B + KEY_RIGHT_BRACE, // 0x5C + KEY_BACKSLASH, // 0x5D + KEY_INSERT, // 0x5E + KEY_PAGE_DOWN, // 0x5F + 0, // 0x60 + KEY_2, // 0x61 + KEY_3, // 0x62 + KEY_4, // 0x63 + KEY_5, // 0x64 + KEY_6, // 0x65 + KEY_7, // 0x66 + KEY_8, // 0x67 + KEY_9, // 0x68 + KEY_0, // 0x69 + KEY_MINUS, // 0x6A + KEY_EQUAL, // 0x6B + KEY_TILDE, // 0x6C + KEY_BACKSPACE, // 0x6D + KEY_DELETE, // 0x6E + KEY_PAGE_UP, // 0x6F + 0, // 0x70 + KEY_F3, // 0x71 + KEY_F2, // 0x72 + KEY_F1, // 0x73 + KEY_F18, // 0x74 + KEY_ESC, // 0x75 + KEY_1, // 0x76 + KEY_TAB, // 0x77 + KEY_F19, // 0x78 + 0, // 0x79 + 0, // 0x7A + 0, // 0x7B + 0, // 0x7C + 0, // 0x7D + 0, // 0x7E + 0, // 0x7F + 0, // 0x80 + 0, // 0x81 + 0, // 0x82 + 0, // 0x83 + 0, // 0x84 + KEY_RIGHT_SHIFT, // 0x85 + 0, // 0x86 + KEY_LEFT_SHIFT, // 0x87 + 0, // 0x88 + 0, // 0x89 + 0, // 0x8A + KEY_LEFT_CTRL, // 0x8B + 0, // 0x8C + KEY_GUI, // 0x8D + 0, // 0x8E + KEY_RIGHT_CTRL, // 0x8F +}; + +static uint8_t epsonqx10_ColemakMap[] = { + 0x00, // 0x00 + KEY_F4, // 0x01 + 0, // 0x02 + KEY_F5, // 0x03 + KEY_F6, // 0x04 + KEY_F7, // 0x05 + KEY_F8, // 0x06 + KEY_F9, // 0x07 + 0, // 0x08 + KEY_F10, // 0x09 + KEY_F11, // 0x0A + KEY_F12, // 0x0B + KEY_F13, // 0x0C + 0, // 0x0D + KEY_F14, // 0x0E + KEY_F15, // 0x0F + 0, // 0x10 + 0, // 0x11 + 0, // 0x12 + 0, // 0x13 + 0, // 0x14 + KEYPAD_ENTER, // 0x15 + KEYPAD_PERIOD, // 0x16 + KEYPAD_0, // 0x17 + KEYPAD_EQUAL, // 0x18 + KEYPAD_6, // 0x19 + KEYPAD_5, // 0x1A + KEYPAD_4, // 0x1B + 0, // 0x1C + 0, // 0x1D + KEY_F17, // 0x1E + KEY_F16, // 0x1F + 0, // 0x20 + 0, // 0x21 + 0, // 0x22 + 0, // 0x23 + 0, // 0x24 + KEYPAD_3, // 0x25 + KEYPAD_2, // 0x26 + KEYPAD_1, // 0x27 + KEYPAD_PLUS, // 0x28 + KEYPAD_9, // 0x29 + KEYPAD_8, // 0x2A + KEYPAD_7, // 0x2B + KEYPAD_MINUS, // 0x2C + KEYPAD_ASTERIX, // 0x2D + KEYPAD_SLASH, // 0x2E + KEY_NUM_LOCK, // 0x2F + 0, // 0x30 + 0, // 0x31 + KEY_SPACE, // 0x32 + KEY_Z, // 0x33 + KEY_X, // 0x34 + KEY_C, // 0x35 + KEY_V, // 0x36 + KEY_B, // 0x37 + KEY_K, // 0x38 + KEY_M, // 0x39 + KEY_COMMA, // 0x3A + KEY_PERIOD, // 0x3B + KEY_UP, // 0x3C + KEY_LEFT, // 0x3D + KEY_RIGHT, // 0x3E + KEY_DOWN, // 0x3F + 0, // 0x40 + KEY_F19, // 0x41 + KEY_CAPS_LOCK, // 0x42 + KEY_A, // 0x43 + KEY_R, // 0x44 + KEY_S, // 0x45 + KEY_T, // 0x46 + KEY_D, // 0x47 + KEY_H, // 0x48 + KEY_N, // 0x49 + KEY_E, // 0x4A + KEY_I, // 0x4B + KEY_O, // 0x4C + KEY_QUOTE, // 0x4D + KEY_ENTER, // 0x4E + KEY_SLASH, // 0x4F + 0, // 0x50 + KEY_Q, // 0x51 + KEY_W, // 0x52 + KEY_F, // 0x53 + KEY_P, // 0x54 + KEY_G, // 0x55 + KEY_J, // 0x56 + KEY_L, // 0x57 + KEY_U, // 0x58 + KEY_Y, // 0x59 + KEY_SEMICOLON, // 0x5A + KEY_LEFT_BRACE, // 0x5B + KEY_RIGHT_BRACE, // 0x5C + KEY_BACKSLASH, // 0x5D + KEY_INSERT, // 0x5E + KEY_PAGE_DOWN, // 0x5F + 0, // 0x60 + KEY_2, // 0x61 + KEY_3, // 0x62 + KEY_4, // 0x63 + KEY_5, // 0x64 + KEY_6, // 0x65 + KEY_7, // 0x66 + KEY_8, // 0x67 + KEY_9, // 0x68 + KEY_0, // 0x69 + KEY_MINUS, // 0x6A + KEY_EQUAL, // 0x6B + KEY_TILDE, // 0x6C + KEY_BACKSPACE, // 0x6D + KEY_DELETE, // 0x6E + KEY_PAGE_UP, // 0x6F + 0, // 0x70 + KEY_F3, // 0x71 + KEY_F2, // 0x72 + KEY_F1, // 0x73 + KEY_F18, // 0x74 + KEY_ESC, // 0x75 + KEY_1, // 0x76 + KEY_TAB, // 0x77 + KEY_F19, // 0x78 + 0, // 0x79 + 0, // 0x7A + 0, // 0x7B + 0, // 0x7C + 0, // 0x7D + 0, // 0x7E + 0, // 0x7F + 0, // 0x80 + 0, // 0x81 + 0, // 0x82 + 0, // 0x83 + 0, // 0x84 + KEY_RIGHT_SHIFT, // 0x85 + 0, // 0x86 + KEY_LEFT_SHIFT, // 0x87 + 0, // 0x88 + 0, // 0x89 + 0, // 0x8A + KEY_LEFT_CTRL, // 0x8B + 0, // 0x8C + KEY_GUI, // 0x8D + 0, // 0x8E + KEY_RIGHT_CTRL, // 0x8F +}; + + + +#endif + diff --git a/Keymap/keymap.h b/Keymap/keymap.h index 11d53bc..1137126 100644 --- a/Keymap/keymap.h +++ b/Keymap/keymap.h @@ -42,6 +42,7 @@ // See files for full layout descriptions #include "budkeypad.h" +#include "epsonqx10.h" #include "heathzenith.h" #include "kaypro1.h" #include "microswitch8304.h" diff --git a/Macro/buffer/macro.c b/Macro/buffer/macro.c index 657ab91..c9df96e 100644 --- a/Macro/buffer/macro.c +++ b/Macro/buffer/macro.c @@ -198,6 +198,7 @@ uint8_t sendCode = 0; // USBCode Macro Detection int usbcodeMacro( uint8_t usbCode ) { + /* // Keyboard Input Test Macro switch ( usbCode ) { @@ -226,6 +227,8 @@ int usbcodeMacro( uint8_t usbCode ) } return 1; + */ + return 0; } diff --git a/Scan/EpsonQX-10/scan_loop.c b/Scan/EpsonQX-10/scan_loop.c new file mode 100644 index 0000000..ec74c9c --- /dev/null +++ b/Scan/EpsonQX-10/scan_loop.c @@ -0,0 +1,555 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// ----- Includes ----- + +// AVR Includes +#include +#include +#include + +// Project Includes +#include +#include + +// Local Includes +#include "scan_loop.h" + + + +// ----- Defines ----- + +// Pinout Defines +#define CLOCK_PORT PORTB +#define CLOCK_DDR DDRB +#define CLOCK_PIN 0 + + +// ----- Macros ----- + +// Make sure we haven't overflowed the buffer +#define bufferAdd(byte) \ + if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \ + KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte + +#define setLED(id, status) \ + status = status ? 0 : 1; \ + scan_setLED( id, status ) + + + +// ----- Variables ----- + +// Buffer used to inform the macro processing module which keys have been detected as pressed +volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER]; +volatile uint8_t KeyIndex_BufferUsed; + +volatile uint8_t currentWaveState = 0; + +volatile uint8_t calcLED = 0; +volatile uint8_t insertLED = 0; +volatile uint8_t shiftLockLED = 0; +volatile uint8_t schedLED = 0; +volatile uint8_t drawLED = 0; + + + +// ----- Function Declarations ----- + +void scan_diagnostics( void ); +void processKeyValue( uint8_t keyValue ); +void scan_diagnostics( void ); +void scan_setRepeatStart( uint8_t n ); +void scan_readSwitchStatus( void ); +void scan_repeatControl( uint8_t on ); +void scan_enableKeyboard( uint8_t enable ); +void scan_setRepeatRate( uint8_t n ); +void scan_setLED( uint8_t ledNumber, uint8_t on ); +void scan_readLED( void ); + + + +// ----- Interrupt Functions ----- + +// Generates a constant external clock +ISR( TIMER1_COMPA_vect ) +{ + if ( currentWaveState ) + { + CLOCK_PORT &= ~(1 << CLOCK_PIN); + currentWaveState--; + } + else + { + CLOCK_PORT |= (1 << CLOCK_PIN); + currentWaveState++; + } +} + +// USART Receive Buffer Full Interrupt +ISR(USART1_RX_vect) +{ + cli(); // Disable Interrupts + + uint8_t keyValue = 0x00; + + // Read the raw packet from the USART + keyValue = UDR1; + + // Debug + char tmpStr[6]; + hexToStr( keyValue, tmpStr ); + dPrintStrs( tmpStr, " " ); + + // Process the scancode + if ( keyValue != 0x00 ) + processKeyValue( keyValue ); + + sei(); // Re-enable Interrupts +} + + + +// ----- Functions ----- + +// Setup +inline void scan_setup() +{ + // Setup Timer Pulse (16 bit) + // 16 MHz / (2 * Prescaler * (1 + OCR1A)) = 1204.8 baud (820 us) + // Prescaler is 1 + /* + TCCR1B = 0x09; + OCR1AH = 0x19; + OCR1AL = 0xEF; + TIMSK1 = (1 << OCIE1A); + CLOCK_DDR = (1 << CLOCK_PIN); + */ + // 16 MHz / (2 * Prescaler * (1 + OCR1A)) = 1200.1 baud + // Prescaler is 1 + // Twice every 1200 baud (actually 1200.1, timer isn't accurate enough) + // This is close to 820 us, but a bit slower + TCCR1B = 0x09; + OCR1AH = 0x1A; + OCR1AL = 0x09; + TIMSK1 = (1 << OCIE1A); + CLOCK_DDR = (1 << CLOCK_PIN); + + + // Setup the the USART interface for keyboard data input + + // Setup baud rate + // 16 MHz / ( 16 * Baud ) = UBRR + // Baud <- 1200 as per the spec (see datasheet archives), rounding to 1200.1 (as that's as accurate as the timer can be) + // Thus UBRR = 833.26 -> round to 833 + uint16_t baud = 833; // Max setting of 4095 + UBRR1H = (uint8_t)(baud >> 8); + UBRR1L = (uint8_t)baud; + + // Enable the receiver, transitter, and RX Complete Interrupt + UCSR1B = 0x98; + + // Set frame format: 8 data, no stop bits or parity + // Synchrounous USART mode + // Tx Data on Falling Edge, Rx on Rising + UCSR1C = 0x47; + + // Reset the keyboard before scanning, we might be in a wierd state + _delay_ms( 1 ); + scan_resetKeyboard(); + + scan_setRepeatRate( 0x00 ); // Set the fastest repeat rate +} + + +// Main Detection Loop +inline uint8_t scan_loop() +{ + return 0; +} + +// TODO +void processKeyValue( uint8_t keyValue ) +{ + // Detect LED Status + uint8_t inputType = keyValue & 0xC0; + + // Determine the input type + switch ( inputType ) + { + // LED Status + case 0xC0: + // Binary Representation: 1100 llln + // Hex Range: 0xC0 to 0xCF + // - First 3 bits determine which LED (0 to 7) + // - Last bit is whether the LED is On (1) or Off (0) + // 000 - N/A (A) + // 001 - N/A (B) + // 010 - INSERT + // 011 - SHIFT LOCK + // 100 - N/A (C) + // 101 - DRAW + // 110 - SCHED + // 111 - CALC + break; + + // SW (Switch) Status + case 0x80: + { + // Binary Representation: 1000 dddn + // Hex Range: 0x80 to 0x8F + // - First 3 bits determine which DB (KRTN) (See datasheet) + // - Last bit is whether the key is enabled + // 000 - N/A? + // 001 - N/A? + // 010 - Right SHIFT + // 011 - Left SHIFT + // 100 - N/A? + // 101 - Left CTRL + // 110 - GRPH SHIFT + // 111 - Right CTRL + + // Detect Modifier Press/Release + uint8_t press = keyValue & 0x01; + + // Modifier Press Detected + if ( press ) + { + // Make sure the key isn't already in the buffer + for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ ) + { + // Key isn't in the buffer yet + if ( c == KeyIndex_BufferUsed ) + { + bufferAdd( keyValue ); + break; + } + + // Key already in the buffer + if ( KeyIndex_Buffer[c] == keyValue ) + break; + } + } + // Modifier Release Detected + else + { + // Check for the released key, and shift the other keys lower on the buffer + uint8_t c; + for ( c = 0; c < KeyIndex_BufferUsed; c++ ) + { + // Key to release found + if ( KeyIndex_Buffer[c] == keyValue ) + { + // Shift keys from c position + for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ ) + KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1]; + + // Decrement Buffer + KeyIndex_BufferUsed--; + + break; + } + } + + // Error case (no key to release) + if ( c == KeyIndex_BufferUsed + 1 ) + { + errorLED( 1 ); + char tmpStr[6]; + hexToStr( keyValue, tmpStr ); + erro_dPrint( "Could not find key to release: ", tmpStr ); + } + } + break; + } + + // Key code + default: + // Binary Representation: 0ddd pppp + // Hex Range: 0x00 to 0x7F + // - First 3 bits determine which DB (KRTN) (See datasheet) + // - Last 4 bits corresond to the KSC signals (P13, P12, P11, P10 respectively) + // Or, that can be read as, each key has it's own keycode (with NO release code) + // Modifiers are treated differently + + // Add the key to the buffer, if it isn't already in the current Key Buffer + for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ ) + { + // Key isn't in the buffer yet + if ( c == KeyIndex_BufferUsed ) + { + bufferAdd( keyValue ); + break; + } + + // Key already in the buffer + if ( KeyIndex_Buffer[c] == keyValue ) + break; + } + // Special Internal Key Mapping/Functions + switch ( keyValue ) + { + // LED Test + case 0x0A: // CALC + setLED( 0x07, calcLED ); // 0x4F + break; + case 0x0B: // SCHED + setLED( 0x0E, schedLED ); // 0x5D + break; + case 0x0C: // DRAW + setLED( 0x0D, drawLED ); // 0x5B + break; + case 0x42: // SHIFT LOCK + setLED( 0x0B, shiftLockLED ); // 0x57 + break; + case 0x5E: // INSERT + setLED( 0x02, insertLED ); // 0x45 + break; + + /* + // TEST + case 0x51: + scan_resetKeyboard(); + break; + case 0x52: + scan_diagnostics(); + break; + case 0x53: + scan_setRepeatStart( 0x00 ); + break; + case 0x54: + scan_readSwitchStatus(); + break; + case 0x55: + scan_repeatControl( 0x00 ); + break; + case 0x56: + scan_repeatControl( 0x01 ); + break; + case 0x57: + scan_enableKeyboard( 0x00 ); + break; + case 0x58: + scan_enableKeyboard( 0x01 ); + break; + case 0x59: + scan_setRepeatRate( 0x00 ); + break; + case 0x5A: + scan_readLED(); + break; + */ + } + break; + } +} + +// Send data +// See below functions for the input sequences for the Epson QX-10 Keyboard +uint8_t scan_sendData( uint8_t dataPayload ) +{ + // Debug + char tmpStr[6]; + hexToStr( dataPayload, tmpStr ); + info_dPrint( tmpStr, " " ); + + UDR1 = dataPayload; + return 0; +} + +// Signal KeyIndex_Buffer that it has been properly read +// For the Epson QX-10 only the modifier keys have release signals +// Therefore, only 5 keys could possibly be assigned as a modifiers +// The rest of the keys are single press (like the Kaypro keyboards) +// +// However, this differentiation causes complications on how the key signals are discarded and used +// The single keypresses must be discarded immediately, while the modifiers must be kept +inline void scan_finishedWithBuffer( void ) +{ + uint8_t foundModifiers = 0; + + // Look for all of the modifiers present, there is a max of 8 (but only keys for 5 on the HASCI version) + for ( uint8_t c = 0; c < KeyIndex_BufferUsed; c++ ) + { + // The modifier range is from 0x80 to 0x8F (well, the last bit is the ON/OFF signal, but whatever...) + if ( KeyIndex_Buffer[c] <= 0x8F && KeyIndex_Buffer[c] >= 0x80 ) + { + // Add the modifier back into the the Key Buffer + KeyIndex_Buffer[foundModifiers] = KeyIndex_Buffer[c]; + foundModifiers++; + } + } + + // Adjust the size of the new Key Buffer + KeyIndex_BufferUsed = foundModifiers; + + return; +} + +// Reset/Hold keyboard +// Warning! This will cause the keyboard to not send any data, so you can't disable with a keypress +// The Epson QX-10 Keyboards have a command used to lock the keyboard output +void scan_lockKeyboard( void ) +{ + scan_enableKeyboard( 0x00 ); +} + +void scan_unlockKeyboard( void ) +{ + scan_enableKeyboard( 0x01 ); +} + +// Reset Keyboard +// Does the following +// - Clears the keycode buffer (32 characters) +// - Validates repeat function (what does this do?) +// - Sets repeat start time (500 ms) +// - Sets repeat interval (50 ms) +// - Turns off all LEDs +void scan_resetKeyboard( void ) +{ + // Reset command for the QX-10 Keyboard + scan_sendData( 0xE0 ); + + // Empty buffer, now that keyboard has been reset + KeyIndex_BufferUsed = 0; +} + +// TODO Check +// Runs Diagnostics on the keyboard +// - First does a reset (see scan_resetKeyboard) +// - Blinks all of the LEDs one after another +// - Outputs 0x00 if no keys are pressed +// - Outputs 0xFF if any keys are being pressed +void scan_diagnostics( void ) +{ + // Send reset command with diagnositics + scan_sendData( 0xE7 ); +} + +// TODO Check +// Set Repeat Interval Start +// 300 ms + n * 25 ms +// Interval after which to start the repeated keys +void scan_setRepeatStart( uint8_t n ) +{ + // Send command + // Binary Representation: 000n nnnn + // Hex boundaries 0x00 to 0x1F + // 300 ms to 1075 ms (intervals of 25 ms) + scan_sendData( n ); +} + +// Read Switch Status (preferential to actual keypress outputs) +// 000 - N/A? +// 001 - N/A? +// 010 - Right SHIFT +// 011 - Left SHIFT +// 100 - N/A? +// 101 - Left CTRL +// 110 - GRPH SHIFT +// 111 - Right CTRL +void scan_readSwitchStatus( void ) +{ + scan_sendData( 0x80 ); +} + +// TODO Check +// Repeat Control +// 0x00 Stops repeat function +// 0x01 Enables repeat function +void scan_repeatControl( uint8_t on ) +{ + // Send command + // Binary Representation: 101X XXXn + // Hex options: 0xA0 or 0xA1 + scan_sendData( 0xA0 | on ); +} + +// TODO Check +// Enable Sending Keyboard Data +// 0x00 Stops keycode transmission +// 0x01 Enables keycode transmission +void scan_enableKeyboard( uint8_t enable ) +{ + // Send command + // Binary Representation: 110X XXXn + // Hex options: 0xC0 or 0xC1 + scan_sendData( 0xC0 | enable ); +} + +// Set Repeat Interval +// 30 ms + n * 5 ms +// Period between sending each repeated key after the initial interval +void scan_setRepeatRate( uint8_t n ) +{ + // Send command + // Binary Representation: 001n nnnn + // Hex options: 0x00 to 0x1F + // 30 ms to 185 ms (intervals of 5 ms) + scan_sendData( 0x20 | n ); +} + +// Turn On/Off LED +// 0x00 LED Off +// 0x01 LED On +// +// 8 LEDs max (Note: 5 connected on my board, there is 1 position empty on the PCB for a total of 6) +// 0 to 7 (0x0 to 0x7) +void scan_setLED( uint8_t ledNumber, uint8_t on ) +{ + // Send command + // Binary Representation: 010l llln + // Hex options: 0x40 to 0x4F + // The spec is NOT accurate (especially about the "don't care" bit) + // llll n - Usage + // 0000 X - N/A (1) + // 0001 X - N/A (2) + // 0010 1 - INSERT On + // 0011 0 - SHIFT LOCK Off + // 0100 X - N/A (3) + // 0101 0 - DRAW Off + // 0110 0 - SCHED Off + // 0111 1 - CALC On + // 1000 X - N/A (1) + // 1001 X - N/A (2) + // 1010 0 - INSERT Off + // 1011 1 - SHIFT LOCK On + // 1100 X - N/A (3) + // 1101 1 - DRAW On + // 1110 1 - SCHED On + // 1111 0 - CALC Off + + uint8_t off = 0; + if ( !on ) + { + off = 0x10; + } + scan_sendData( ( 0x40 | (ledNumber << 1) | on ) ^ off ); +} + +// Read LED Status +// High priority data output (may overwrite some keycode data) +void scan_readLED( void ) +{ + scan_sendData( 0x7F ); +} + diff --git a/Scan/EpsonQX-10/scan_loop.h b/Scan/EpsonQX-10/scan_loop.h new file mode 100644 index 0000000..d4da306 --- /dev/null +++ b/Scan/EpsonQX-10/scan_loop.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __SCAN_LOOP_H +#define __SCAN_LOOP_H + +// ----- Includes ----- + +// Compiler Includes +#include + +// Local Includes + + + +// ----- Defines ----- + +#define KEYBOARD_SIZE 0x68 // 104 - Size of the array space for the keyboard(max index) +#define KEYBOARD_BUFFER 24 // Max number of key signals to buffer + + + +// ----- Variables ----- + +extern volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER]; +extern volatile uint8_t KeyIndex_BufferUsed; + + + +// ----- Functions ----- + +// Functions used by main.c +void scan_setup( void ); +uint8_t scan_loop( void ); + + +// Functions available to macro.c +uint8_t scan_sendData( uint8_t dataPayload ); + +void scan_finishedWithBuffer( void ); +void scan_lockKeyboard( void ); +void scan_unlockKeyboard( void ); +void scan_resetKeyboard( void ); + + +#endif // __SCAN_LOOP_H + diff --git a/Scan/EpsonQX-10/setup.cmake b/Scan/EpsonQX-10/setup.cmake new file mode 100644 index 0000000..a393da6 --- /dev/null +++ b/Scan/EpsonQX-10/setup.cmake @@ -0,0 +1,48 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2011 for the Kiibohd Controller +# +# Released into the Public Domain +# +# For the Sony NEWS Topre Keyboard +# +### + + +### +# Module C files +# + +set( SCAN_SRCS + scan_loop.c +) + + +### +# Module H files +# +set( SCAN_HDRS + scan_loop.h +) + + +### +# File Dependency Setup +# +ADD_FILE_DEPENDENCIES( scan_loop.c ${SCAN_HDRS} ) +#add_file_dependencies( scan_loop.c ${SCAN_HDRS} ) +#add_file_dependencies( macro.c keymap.h epsonqx10.h ) + + +### +# Module Specific Options +# +add_definitions( -I${HEAD_DIR}/Keymap ) + +#| Keymap Settings +add_definitions( + -DMODIFIER_MASK=epsonqx10_ModifierMask + -DKEYINDEX_MASK=epsonqx10_ColemakMap + #-DKEYINDEX_MASK=epsonqx10_DefaultMap +) + diff --git a/main.c b/main.c index 1533443..905f7bd 100644 --- a/main.c +++ b/main.c @@ -108,7 +108,9 @@ int main(void) while ( 1 ) { // Setup the scanning module + cli(); scan_setup(); + sei(); while ( 1 ) { diff --git a/setup.cmake b/setup.cmake index 39a50bf..c3c1567 100644 --- a/setup.cmake +++ b/setup.cmake @@ -20,7 +20,7 @@ #| Please the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones ##| Deals with acquiring the keypress information and turning it into a key index -set( ScanModule "SonyNEWS" ) +set( ScanModule "EpsonQX-10" ) ##| Uses the key index and potentially applies special conditions to it, mapping it to a usb key code set( MacroModule "buffer" )