diff options
| -rw-r--r-- | m0110.c | 304 | ||||
| -rw-r--r-- | m0110.h | 73 | ||||
| -rw-r--r-- | m0110_usb/Makefile | 52 | ||||
| -rw-r--r-- | m0110_usb/README | 55 | ||||
| -rw-r--r-- | m0110_usb/config.h | 62 | ||||
| -rwxr-xr-x | m0110_usb/doc/m0110.jpg | bin | 0 -> 49360 bytes | |||
| -rwxr-xr-x | m0110_usb/doc/teensy.jpg | bin | 0 -> 50081 bytes | |||
| -rw-r--r-- | m0110_usb/keymap.c | 118 | ||||
| -rw-r--r-- | m0110_usb/led.c | 24 | ||||
| -rw-r--r-- | m0110_usb/matrix.c | 193 | 
10 files changed, 881 insertions, 0 deletions
| diff --git a/m0110.c b/m0110.c new file mode 100644 index 0000000000..725675ed8f --- /dev/null +++ b/m0110.c @@ -0,0 +1,304 @@ +/* +Copyright 2011 Jun WAKO <wakojun@gmail.com> + +This software is licensed with a Modified BSD License. +All of this is supposed to be Free Software, Open Source, DFSG-free, +GPL-compatible, and OK to use in both free and proprietary applications. +Additions and corrections to this file are welcome. + + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright +  notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +  notice, this list of conditions and the following disclaimer in +  the documentation and/or other materials provided with the +  distribution. + +* Neither the name of the copyright holders nor the names of +  contributors may be used to endorse or promote products derived +  from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdbool.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <util/delay.h> +#include "m0110.h" +#include "debug.h" + + +static inline void clock_lo(void); +static inline void clock_hi(void); +static inline bool clock_in(void); +static inline void data_lo(void); +static inline void data_hi(void); +static inline bool data_in(void); +static inline uint16_t wait_clock_lo(uint16_t us); +static inline uint16_t wait_clock_hi(uint16_t us); +static inline uint16_t wait_data_lo(uint16_t us); +static inline uint16_t wait_data_hi(uint16_t us); +static inline void idle(void); +static inline void request(void); + + +/* +Primitive M0110 Library for AVR +============================== + + +Signaling +--------- +CLOCK is always from KEYBOARD. DATA are sent with MSB first. + +1) IDLE: both line is high. +    CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +    DATA  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +2) KEYBOARD->HOST: HOST reads bit on rising edge. +    CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ +    DATA  ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ +                      <--> 160us(clock low) +                         <---> 180us(clock high) + +3) HOST->KEYBOARD: HOST asserts bit on falling edge. +    CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ +    DATA  ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ +                <----> 840us(request to send by host)                     <-> 80us(hold DATA) +                      <--> 180us(clock low) +                         <---> 220us(clock high) + + +Protocol +-------- +COMMAND: +    Inquiry     0x10    get key event +    Instant     0x12    get key event +    Model       0x14    get model number(M0110 responds with 0x09) +                        bit 7   1 if another device connected(used when keypad exists?) +                        bit4-6  next device model number +                        bit1-3  keyboard model number +                        bit 0   always 1 +    Test        0x16    test(ACK:0x7D/NAK:0x77) + +KEY EVENT: +    bit 7       key state(0:press 1:release) +    bit 6-1     scan code +    bit 0       always 1 +    To get scan code,  use ((bits&(1<<7)) | ((bits&7F))>>1). + +SCAN CODE: +    M0110A +    ,---------------------------------------------------------. +    |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backs| +    |---------------------------------------------------------| +    |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \| +    |---------------------------------------------------------| +    |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| +    |---------------------------------------------------------| +    |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|        | +    `---------------------------------------------------------' +         |Opt|Mac |         Space               |Enter|Opt| +         `------------------------------------------------' +    ,---------------------------------------------------------. +    | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33| +    |---------------------------------------------------------| +    |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| +    |---------------------------------------------------------| +    |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24| +    |---------------------------------------------------------| +    |      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|      38| +    `---------------------------------------------------------' +         | 3A|  37|             31              |   34| 3A| +         `------------------------------------------------' + + +References +---------- +Protocol: +    http://www.mac.linux-m68k.org/devel/plushw.php +Connector: +    http://www.kbdbabel.org/conn/kbd_connector_macplus.png +Signaling: +    http://www.kbdbabel.org/signaling/kbd_signaling_mac.png +    http://typematic.blog.shinobi.jp/Entry/14/ +Scan Codes: +    http://m0115.web.fc2.com/m0110.jpg +    http://m0115.web.fc2.com/m0110a.jpg +*/ + + +#define WAIT(stat, us, err) do { \ +    if (!wait_##stat(us)) { \ +        m0110_error = err; \ +        goto ERROR; \ +    } \ +} while (0) + + +uint8_t m0110_error = 0; + + +void m0110_init(void) +{ +    uint8_t data; +    idle(); +    _delay_ms(255); + +    m0110_send(M0110_MODLE); +    data = m0110_recv(); +    print("m0110_init model: "); phex(data); print("\n"); + +    m0110_send(M0110_TEST); +    data = m0110_recv(); +    print("m0110_init test: "); phex(data); print("\n"); +} + +uint8_t m0110_send(uint8_t data) +{ +    m0110_error = 0; + +    request(); +    WAIT(clock_lo, 1000, 0); +    for (uint8_t bit = 0x80; bit; bit >>= 1) { +        WAIT(clock_lo, 250, 3); +        _delay_us(15); +        if (data&bit) { +            data_hi(); +        } else { +            data_lo(); +        } +        WAIT(clock_hi, 200, 4); +    } +    _delay_us(100); // hold last bit for 80us +    idle(); +    return 1; +ERROR: +    if (m0110_error) { +        print("m0110_send err: "); phex(m0110_error); print("\n"); +    } +    idle(); +    return 0; +} + +uint8_t m0110_recv(void) +{ +    uint8_t data = 0; +    m0110_error = 0; + +    WAIT(clock_lo, -1, 0); // need 250ms? insted 0xffff(16bit max)us +    for (uint8_t i = 0; i < 8; i++) { +        data <<= 1; +        WAIT(clock_lo, 200, 2); +        WAIT(clock_hi, 200, 3); +        if (data_in()) { +            data |= 1; +        } +    } +    idle(); +    print("m0110_send recv data: "); phex(data); print("\n"); +    return data; +ERROR: +    if (m0110_error) { +        print("m0110_recv err: "); phex(m0110_error); print("\n"); +    } +    idle(); +    return 0xFF; +} + +uint8_t m0110_recv_key(void) +{ +    uint8_t key; +    m0110_send(M0110_INQUIRY); +    key = m0110_recv(); +    if (key == 0xFF || key == M0110_NULL) +        return M0110_NULL; +    else  +        return (key&(1<<7) | (key&0x7F)>>1); +} + + +static inline void clock_lo() +{ +    M0110_CLOCK_PORT &= ~(1<<M0110_CLOCK_BIT); +    M0110_CLOCK_DDR  |=  (1<<M0110_CLOCK_BIT); +} +static inline void clock_hi() +{ +    /* input with pull up */ +    M0110_CLOCK_DDR  &= ~(1<<M0110_CLOCK_BIT); +    M0110_CLOCK_PORT |=  (1<<M0110_CLOCK_BIT); +} +static inline bool clock_in() +{ +    M0110_CLOCK_DDR  &= ~(1<<M0110_CLOCK_BIT); +    M0110_CLOCK_PORT |=  (1<<M0110_CLOCK_BIT); +    _delay_us(1); +    return M0110_CLOCK_PIN&(1<<M0110_CLOCK_BIT); +} +static inline void data_lo() +{ +    M0110_DATA_PORT &= ~(1<<M0110_DATA_BIT); +    M0110_DATA_DDR  |=  (1<<M0110_DATA_BIT); +} +static inline void data_hi() +{ +    /* input with pull up */ +    M0110_DATA_DDR  &= ~(1<<M0110_DATA_BIT); +    M0110_DATA_PORT |=  (1<<M0110_DATA_BIT); +} +static inline bool data_in() +{ +    M0110_DATA_DDR  &= ~(1<<M0110_DATA_BIT); +    M0110_DATA_PORT |=  (1<<M0110_DATA_BIT); +    _delay_us(1); +    return M0110_DATA_PIN&(1<<M0110_DATA_BIT); +} + +static inline uint16_t wait_clock_lo(uint16_t us) +{ +    while (clock_in()  && us) { asm(""); _delay_us(1); us--; } +    return us; +} +static inline uint16_t wait_clock_hi(uint16_t us) +{ +    while (!clock_in() && us) { asm(""); _delay_us(1); us--; } +    return us; +} +static inline uint16_t wait_data_lo(uint16_t us) +{ +    while (data_in() && us)  { asm(""); _delay_us(1); us--; } +    return us; +} +static inline uint16_t wait_data_hi(uint16_t us) +{ +    while (!data_in() && us)  { asm(""); _delay_us(1); us--; } +    return us; +} + +static inline void idle(void) +{ +    clock_hi(); +    data_hi(); +} + +static inline void request(void) +{ +    clock_hi(); +    data_lo(); +} diff --git a/m0110.h b/m0110.h new file mode 100644 index 0000000000..fe2e91227b --- /dev/null +++ b/m0110.h @@ -0,0 +1,73 @@ +/* +Copyright 2011 Jun WAKO <wakojun@gmail.com> + +This software is licensed with a Modified BSD License. +All of this is supposed to be Free Software, Open Source, DFSG-free, +GPL-compatible, and OK to use in both free and proprietary applications. +Additions and corrections to this file are welcome. + + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright +  notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +  notice, this list of conditions and the following disclaimer in +  the documentation and/or other materials provided with the +  distribution. + +* Neither the name of the copyright holders nor the names of +  contributors may be used to endorse or promote products derived +  from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef M0110_H +#define M0110_H + + +/* port settings for clock and data line */ +#if !(defined(M0110_CLOCK_PORT) && \ +      defined(M0110_CLOCK_PIN) && \ +      defined(M0110_CLOCK_DDR) && \ +      defined(M0110_CLOCK_BIT)) +#   error "M0110 clock port setting is required in config.h" +#endif + +#if !(defined(M0110_DATA_PORT) && \ +      defined(M0110_DATA_PIN) && \ +      defined(M0110_DATA_DDR) && \ +      defined(M0110_DATA_BIT)) +#   error "M0110 data port setting is required in config.h" +#endif + +#define M0110_INQUIRY     0x10 +#define M0110_INSTNAT     0x14 +#define M0110_MODLE       0x16 +#define M0110_TEST        0x36 + +#define M0110_NULL        0x7B + + +extern uint8_t m0110_error; + +/* host role */ +void m0110_host_init(void); +uint8_t m0110_send(uint8_t data); +uint8_t m0110_recv(void); +uint8_t m0110_recv_key(void); + +#endif diff --git a/m0110_usb/Makefile b/m0110_usb/Makefile new file mode 100644 index 0000000000..8c8460c806 --- /dev/null +++ b/m0110_usb/Makefile @@ -0,0 +1,52 @@ +# Target file name (without extension). +TARGET = m0110 + +# Directory common source filess exist +COMMON_DIR = .. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC =	main.c \ +	keymap.c \ +	matrix.c \ +	led.c \ +	m0110.c + +CONFIG_H = config.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162       # Teensy 1.0 +MCU = atmega32u4       # Teensy 2.0 +#MCU = at90usb646       # Teensy++ 1.0 +#MCU = at90usb1286      # Teensy++ 2.0 + + +# Processor frequency. +#   Normally the first thing your program should do is set the clock prescaler, +#   so your program will run at the correct speed.  You should also set this +#   variable to same clock speed.  The _delay_ms() macro uses this, and many +#   examples use this variable to calculate timings.  Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +#   *Comment out* to disable the options. +# +#MOUSEKEY_ENABLE = yes	# Mouse keys +#PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support +#EXTRAKEY_ENABLE = yes	# Audio control and System control +#NKRO_ENABLE = yes	# USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(COMMON_DIR)/pjrc.mk +include $(COMMON_DIR)/common.mk diff --git a/m0110_usb/README b/m0110_usb/README new file mode 100644 index 0000000000..4122edb287 --- /dev/null +++ b/m0110_usb/README @@ -0,0 +1,55 @@ +M0110 to USB keyboard converter +=============================== +This firmware converts protocol for Apple Machintosh Keybard M0110. + + +Connection +---------- +You need 4P4C plug and cable to connect Teensy into M0110. +Teensy port F0 is assigned for CLOCK line and F1 for DATA by default, you can change pin configuration with editing config.h.. + +Plug: +    http://en.wikipedia.org/wiki/Modular_connector#4P4C + +Pinout: +    http://www.kbdbabel.org/conn/kbd_connector_macplus.png +    1(Black):   GND +    2(Red):     CLOCK +    3(Green):   DATA +    4(Yellow):  +5V + + + +Build Frimware +-------------- +Optionally edit Makefile and config.h for build options, pin configuration or MCU. + +$ cd m0110_usb +$ make +and program your Teensy with loader. + + + +Keymap +------ +You can change a keymap by editing code of keymap.c like following. +How to define the keymap is probably obvious. You can find  key symbols in usb_keycodes.h. + +This is a default keymap for M0110. +,---------------------------------------------------------. +|  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bacpa| +|---------------------------------------------------------| +|Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \| +|---------------------------------------------------------| +|CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| +|---------------------------------------------------------| +|Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shift   | +`---------------------------------------------------------' +     |Opt|Alt |         Space               |Alt |Opt| +     `-----------------------------------------------' + + +Notes +----- + +EOF diff --git a/m0110_usb/config.h b/m0110_usb/config.h new file mode 100644 index 0000000000..c12e0738da --- /dev/null +++ b/m0110_usb/config.h @@ -0,0 +1,62 @@ +/* +Copyright 2011 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/>. +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + + +#define VENDOR_ID       0xFEED +#define PRODUCT_ID      0x0110 +#define MANUFACTURER    t.m.k. +#define PRODUCT         M0110 keyboard converter +#define DESCRIPTION     convert M0110 keyboard to USB + + +/* matrix size */ +#define MATRIX_ROWS 8 +#define MATRIX_COLS 8 + +/* Locking Caps Lock support */ +//#define MATRIX_HAS_LOCKING_CAPS + +/* key combination for command */ +#define IS_COMMAND() ( \ +    keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ +    keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +#   define MOUSEKEY_DELAY_TIME 192 +#endif + + +/* ports */ +#define M0110_CLOCK_PORT        PORTF +#define M0110_CLOCK_PIN         PINF +#define M0110_CLOCK_DDR         DDRF +#define M0110_CLOCK_BIT         0 +#define M0110_DATA_PORT         PORTF +#define M0110_DATA_PIN          PINF +#define M0110_DATA_DDR          DDRF +#define M0110_DATA_BIT          1 + +#endif diff --git a/m0110_usb/doc/m0110.jpg b/m0110_usb/doc/m0110.jpgBinary files differ new file mode 100755 index 0000000000..ef9a123abc --- /dev/null +++ b/m0110_usb/doc/m0110.jpg diff --git a/m0110_usb/doc/teensy.jpg b/m0110_usb/doc/teensy.jpgBinary files differ new file mode 100755 index 0000000000..96e93e7e24 --- /dev/null +++ b/m0110_usb/doc/teensy.jpg diff --git a/m0110_usb/keymap.c b/m0110_usb/keymap.c new file mode 100644 index 0000000000..24fe6cd472 --- /dev/null +++ b/m0110_usb/keymap.c @@ -0,0 +1,118 @@ +/* +Copyright 2011 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/>. +*/ + +/*  + * Keymap for ADB keyboard + */ +#include <stdint.h> +#include <stdbool.h> +#include <avr/pgmspace.h> +#include "usb_keyboard.h" +#include "usb_keycodes.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "keymap.h" + + +#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) + +// Convert physical keyboard layout to matrix array. +// This is a macro to define keymap easily in keyboard layout form. +// TODO: layout for M0110A +/* M0110 */ +#define KEYMAP( \ +    K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, \ +    K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E,K2A, \ +    K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27,    K24, \ +    K38,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C,             \ +        K3A,K37,        K31,                K34              \ +) { \ +    { KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ +    { KB_##K08, KB_##K09, KB_NO,    KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ +    { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ +    { KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ +    { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ +    { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ +    { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_NO,    KB_NO,    KB_##K37 }, \ +    { KB_##K38, KB_##K39, KB_##K3A, KB_NO,    KB_NO,    KB_NO,    KB_NO,    KB_NO    }  \ +} + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { +    0,              // Fn0 +    0,              // Fn1 +    0,              // Fn2 +    0,              // Fn3 +    0,              // Fn4 +    0,              // Fn5 +    0,              // Fn6 +    0               // Fn7 +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { +    KB_NO,          // Fn0 +    KB_NO,          // Fn1 +    KB_NO,          // Fn2 +    KB_NO,          // Fn3 +    KB_NO,          // Fn4 +    KB_NO,          // Fn5 +    KB_NO,          // Fn6 +    KB_NO           // Fn7 +}; + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { +    /* Default Layer: plain keymap +     * ,---------------------------------------------------------. +     * |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bacpa| +     * |---------------------------------------------------------| +     * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \| +     * |---------------------------------------------------------| +     * |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| +     * |---------------------------------------------------------| +     * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shift   | +     * `---------------------------------------------------------' +     *      |Opt|Alt |         Space               |Alt |Opt| +     *      `-----------------------------------------------' +     */ +    KEYMAP( +    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC, +    TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS, +    CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,     ENT, +    LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH, +         LGUI,LALT,          SPC,                     RALT +    ), +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ +    return KEYCODE(layer, row, col); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ +    return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ +    return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/m0110_usb/led.c b/m0110_usb/led.c new file mode 100644 index 0000000000..f76545f0ba --- /dev/null +++ b/m0110_usb/led.c @@ -0,0 +1,24 @@ +/* +Copyright 2011 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 "stdint.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ +} diff --git a/m0110_usb/matrix.c b/m0110_usb/matrix.c new file mode 100644 index 0000000000..f045920ccd --- /dev/null +++ b/m0110_usb/matrix.c @@ -0,0 +1,193 @@ +/* +Copyright 2011 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/>. +*/ + +/* + * scan matrix + */ +#include <stdint.h> +#include <stdbool.h> +#include <avr/io.h> +#include <util/delay.h> +#include "print.h" +#include "util.h" +#include "debug.h" +#include "host.h" +#include "led.h" +#include "m0110.h" +#include "matrix.h" + + +#define CAPS        0x39 +#define CAPS_UP     (CAPS | 0x80) +#define ROW(key)    ((key)>>3&0x0F) +#define COL(key)    ((key)&0x07) + + +static bool is_modified = false; + +// matrix state buffer(1:on, 0:off) +static uint8_t *matrix; +static uint8_t _matrix0[MATRIX_ROWS]; + +#ifdef MATRIX_HAS_GHOST +static bool matrix_has_ghost_in_row(uint8_t row); +#endif +static void register_key(uint8_t key); + + +inline +uint8_t matrix_rows(void) +{ +    return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ +    return MATRIX_COLS; +} + +void matrix_init(void) +{ +    print_enable = true; +    debug_enable = true; +    debug_matrix = false; +    debug_keyboard = false; +    debug_mouse = false; +    print("debug enabled.\n"); + +    m0110_init(); +    // initialize matrix state: all keys off +    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; +    matrix = _matrix0; +    return; +} + +uint8_t matrix_scan(void) +{ +    uint8_t key; + +    is_modified = false; +    key = m0110_recv_key(); + +#ifdef MATRIX_HAS_LOCKING_CAPS +    // Send Caps key up event +    if (matrix_is_on(ROW(CAPS), COL(CAPS))) { +        is_modified = true; +        register_key(CAPS_UP); +    } +#endif +    if (key == M0110_NULL) { +        return 0; +    } else { +#ifdef MATRIX_HAS_LOCKING_CAPS     +        if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { +            // CAPS LOCK on: +            // Ignore LockingCaps key down event +            if (key == CAPS) return 0; +            // Convert LockingCaps key up event into down event +            if (key == CAPS_UP) key = CAPS; +        } else { +            // CAPS LOCK off: +            // Ignore LockingCaps key up event +            if (key == CAPS_UP) return 0; +        } +#endif         +        is_modified = true; +        register_key(key); +    } + +    if (debug_enable) { +        print("key: "); phex(key); print("\n"); +    } +    return 1; +} + +bool matrix_is_modified(void) +{ +    return is_modified; +} + +inline +bool matrix_has_ghost(void) +{ +#ifdef MATRIX_HAS_GHOST +    for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +        if (matrix_has_ghost_in_row(i)) +            return true; +    } +#endif +    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; +} + +#ifdef MATRIX_HAS_GHOST +inline +static bool matrix_has_ghost_in_row(uint8_t row) +{ +    // no ghost exists in case less than 2 keys on +    if (((matrix[row] - 1) & matrix[row]) == 0) +        return false; + +    // ghost exists in case same state as other row +    for (uint8_t i=0; i < MATRIX_ROWS; i++) { +        if (i != row && (matrix[i] & matrix[row]) == matrix[row]) +            return true; +    } +    return false; +} +#endif + +inline +static void register_key(uint8_t key) +{ +    if (key&0x80) { +        matrix[ROW(key)] &= ~(1<<COL(key)); +    } else { +        matrix[ROW(key)] |=  (1<<COL(key)); +    } +} | 
