diff options
author | tmk <nobody@nowhere> | 2013-03-05 15:45:15 +0900 |
---|---|---|
committer | tmk <nobody@nowhere> | 2013-03-05 15:45:15 +0900 |
commit | 38bbe976e00a9a7bf6f8157016717e80503bf6a9 (patch) | |
tree | 9113cd57c1bff3deef394ee966e2fdac8731a244 /keyboard/IIgs | |
parent | 1720cf34caa518a2cf85f286d1ca077ebe1a1451 (diff) | |
parent | 5808317b694004c43a6e0f76e9715415cce19a25 (diff) |
Merge branch 'overlays'
Diffstat (limited to 'keyboard/IIgs')
-rw-r--r-- | keyboard/IIgs/Makefile | 95 | ||||
-rw-r--r-- | keyboard/IIgs/README | 45 | ||||
-rw-r--r-- | keyboard/IIgs/config.h | 68 | ||||
-rw-r--r-- | keyboard/IIgs/doc/PIN_BYPASS.jpg | bin | 0 -> 329437 bytes | |||
-rw-r--r-- | keyboard/IIgs/doc/Teensy++_Mod.jpg | bin | 0 -> 74137 bytes | |||
-rwxr-xr-x | keyboard/IIgs/hid_listen.mac | bin | 0 -> 13524 bytes | |||
-rw-r--r-- | keyboard/IIgs/keymap.c | 142 | ||||
-rw-r--r-- | keyboard/IIgs/led.c | 24 | ||||
-rw-r--r-- | keyboard/IIgs/matrix.c | 363 |
9 files changed, 737 insertions, 0 deletions
diff --git a/keyboard/IIgs/Makefile b/keyboard/IIgs/Makefile new file mode 100644 index 0000000000..c18e9720c7 --- /dev/null +++ b/keyboard/IIgs/Makefile @@ -0,0 +1,95 @@ +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF. +# +# make extcoff = Convert ELF to AVR Extended COFF. +# +# make program = Download the hex file to the device. +# Please customize your programmer settings(PROGRAM_CMD) +# +# make teensy = Download the hex file to the device, using teensy_loader_cli. +# (must have teensy_loader_cli installed). +# +# make dfu = Download the hex file to the device, using dfu-programmer (must +# have dfu-programmer installed). +# +# make flip = Download the hex file to the device, using Atmel FLIP (must +# have Atmel FLIP installed). +# +# make dfu-ee = Download the eeprom file to the device, using dfu-programmer +# (must have dfu-programmer installed). +# +# make flip-ee = Download the eeprom file to the device, using Atmel FLIP +# (must have Atmel FLIP installed). +# +# make debug = Start either simulavr or avarice as specified for debugging, +# with avr-gdb or avr-insight as the front end for debugging. +# +# make filename.s = Just compile filename.c into the assembler code only. +# +# make filename.i = Create a preprocessed source file for use in submitting +# bug reports to the GCC project. +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + +# Target file name (without extension). +TARGET = IIgs_Standard + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = keymap.c \ + matrix.c \ + led.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 = no # 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 + + + +# Search Path +VPATH += $(TARGET_DIR) +VPATH += $(TOP_DIR) + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/keyboard/IIgs/README b/keyboard/IIgs/README new file mode 100644 index 0000000000..4f9cad1ca1 --- /dev/null +++ b/keyboard/IIgs/README @@ -0,0 +1,45 @@ +Replacable USB Controller for Apple IIgs/Standard(M0116)
+JeffreySung(nattyman@gmail.com)
+
+===============================
+
+Feature
+-------
+- Replaceable keyboard controller for Apple IIgs(A9M0330)/Standard(M0116)
+- Teensy++ 2.0 required
+- Some signal bypass required
+- ADB keyboard doesn't use matrix for modifier keys. With virtual row for modifier keys,
+ these keys are merged into key matrix using virtual row.
+
+History
+=======
+- 2012.09.17 First Release
+- 2012.09.17 CapsLock support
+- 2012.09.19 Power button added
+Build
+=====
+0. Just Type "Make" and return.
+
+Hardware
+========
+PJRC Teensy
+-----------
+0. The following ports should not be connected to board.
+ From top view of Teensy++, from GND and counter clock wise.
+ -7,26(in keyboard PCB, these pins are VDD,GND)
+ -30,31(in Teensy++, these pins are Ref,GND respectively)
+ -5,6(D2,D3 for bluetooth in future)
+1. Bypass #31 pin(from board) to E4(Teensy)
+2. Bypass #30 pin(from board) to F2(Teensy)
+3. Bypass #6 pin(from board) to A0(Teensy)
+4. Refer doc directory
+
+To Do
+=====
+0. When DEBOUNCE defined, there is a errors.
+1. Layer Change by toggling Clear Key
+2. Eject Key add. (following files should be modified.)
+ common/keycode.h
+ common/keyboard.c
+3. Use bluetooth
+EOF
diff --git a/keyboard/IIgs/config.h b/keyboard/IIgs/config.h new file mode 100644 index 0000000000..11acf87c07 --- /dev/null +++ b/keyboard/IIgs/config.h @@ -0,0 +1,68 @@ +/*
+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"
+
+
+/* USB Device descriptor parameter */
+/* for Apple
+#define VENDOR_ID 0x05AC
+#define PRODUCT_ID 0xBEE0
+*/
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0xBEE0
+#define DEVICE_VER 0x0202
+#define MANUFACTURER t.m.k.
+#define PRODUCT Apple Desktop Bus Keyboard
+
+
+/* message strings */
+#define DESCRIPTION Apple M0116/A9M0660 keyboard firmware
+
+
+/* matrix size */
+#define MATRIX_ROWS 11 // last row is virtual for modifier
+#define MATRIX_COLS 8
+/* define if matrix has ghost */
+#define MATRIX_HAS_GHOST
+/* Set 0 if need no debouncing */
+#define DEBOUNCE 5
+
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_LCTRL) | MOD_BIT(KC_LALT) | MOD_BIT(KC_LGUI)) || \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+
+/* layer switching */
+#define LAYER_SWITCH_DELAY 100
+#define LAYER_SEND_FN_TERM 300
+
+
+/* mouse keys */
+#ifdef MOUSEKEY_ENABLE
+# define MOUSEKEY_DELAY_TIME 192
+#endif
+
+
+#endif
diff --git a/keyboard/IIgs/doc/PIN_BYPASS.jpg b/keyboard/IIgs/doc/PIN_BYPASS.jpg Binary files differnew file mode 100644 index 0000000000..2998f0c3f8 --- /dev/null +++ b/keyboard/IIgs/doc/PIN_BYPASS.jpg diff --git a/keyboard/IIgs/doc/Teensy++_Mod.jpg b/keyboard/IIgs/doc/Teensy++_Mod.jpg Binary files differnew file mode 100644 index 0000000000..146c1ab93c --- /dev/null +++ b/keyboard/IIgs/doc/Teensy++_Mod.jpg diff --git a/keyboard/IIgs/hid_listen.mac b/keyboard/IIgs/hid_listen.mac Binary files differnew file mode 100755 index 0000000000..8758fdf886 --- /dev/null +++ b/keyboard/IIgs/hid_listen.mac diff --git a/keyboard/IIgs/keymap.c b/keyboard/IIgs/keymap.c new file mode 100644 index 0000000000..cd33e223ac --- /dev/null +++ b/keyboard/IIgs/keymap.c @@ -0,0 +1,142 @@ +/*
+Copyright 2012 Jeffrey Sung <nattyman@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 Apple IIgs/Standard Keyboard
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/pgmspace.h>
+#include "keycode.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "keymap.h"
+
+
+// Convert physical keyboard layout to matrix array.
+// This is a macro to define keymap easily in keyboard layout form.
+#define KEYMAP( R10C5, \
+ R3C7, R3C6, R3C5, R3C4, R3C3, R3C2, R3C1, R8C1, R8C0, R3C0, R0C0, R0C1, R0C2, R0C3, R4C4, R4C5, R4C6, R4C7, \
+ R9C7, R9C6, R9C5, R9C4, R9C3, R9C2, R9C1, R9C0, R1C0, R1C1, R1C2, R1C3, R1C4, R2C4, R2C5, R2C6, R2C3, \
+ R10C0,R7C7, R7C6, R7C5, R7C4, R7C3, R7C2, R7C1, R7C0, R0C4, R1C6, R1C7, R1C5, R2C0, R2C1, R2C2, R2C7, \
+ R10C1,R6C7, R6C6, R6C5, R6C4, R6C3, R6C2, R6C1, R6C0, R0C5, R0C6, R4C0, R4C1, R4C2, \
+ R10C4,R10C2,R10C3,R5C4, R5C7, R5C5, R5C6, R5C0, R5C2, R0C7, R5C1, R5C3, R4C3 \
+) { \
+ { R0C0, R0C1, R0C2, R0C3, R0C4, R0C5, R0C6, R0C7 }, \
+ { R1C0, R1C1, R1C2, R1C3, R1C4, R1C5, R1C6, R1C7 }, \
+ { R2C0, R2C1, R2C2, R2C3, R2C4, R2C5, R2C6, R2C7 }, \
+ { R3C0, R3C1, R3C2, R3C3, R3C4, R3C5, R3C6, R3C7 }, \
+ { R4C0, R4C1, R4C2, R4C3, R4C4, R4C5, R4C6, R4C7 }, \
+ { R5C0, R5C1, R5C2, R5C3, R5C4, R5C5, R5C6, R5C7 }, \
+ { R6C0, R6C1, R6C2, R6C3, R6C4, R6C5, R6C6, R6C7 }, \
+ { R7C0, R7C1, R7C2, R7C3, R7C4, R7C5, R7C6, R7C7 }, \
+ { R8C0, R8C1, KC_NO, KC_NO, KC_NO,KC_NO, KC_NO, KC_NO }, \
+ { R9C0, R9C1, R9C2, R9C3, R9C4, R9C5, R9C6, R9C7 }, \
+ { R10C0,R10C1, R10C2, R10C3, R10C4,R10C5, KC_NO, KC_NO} \
+}
+
+#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
+
+
+// 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
+ 1, // Fn1
+ 2, // Fn2
+ 3, // Fn3
+ 4, // Fn4
+ 0, // Fn5
+ 3, // Fn6
+ 3 // 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[] = {
+ KC_NO, // Fn0
+ KC_NO, // Fn1
+ KC_SLSH, // Fn2
+ KC_SCLN, // Fn3
+ KC_SPC, // Fn4
+ KC_NO, // Fn5
+ KC_NO, // Fn6
+ KC_NO // Fn7
+};
+
+static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Layer 0: Default Layer
+ * ,-----------------------------------------------------------. ,---------------,
+ * | POWER | | |
+ * |-----------------------------------------------------------| |---------------|
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | |FN0| = | / | * |
+ * |-----------------------------------------------------------| |---------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7 | 8 | 9 | + |
+ * |-----------------------------------------------------' | |---------------|
+ * |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | | 4 | 5 | 6 | - |
+ * |-----------------------------------------------------------| |---------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| / |Shift | | 1 | 2 | 3 | E |
+ * |-----------------------------------------------------------| |-----------| N |
+ * |CAPS|Alt |Gui |` |SPC |BSLS |LFT|RGT|DN|UP| | 0 | . | T |
+ * `-----------------------------------------------------------' |---------------'
+ */
+ KEYMAP( KC_PWR,
+ KC_ESC, 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_FN1, KC_PEQL, KC_PSLS, KC_PAST, \
+ 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_P7, KC_P8, KC_P9, KC_PPLS, \
+ KC_LCTL,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_P4, KC_P5, KC_P6, KC_PMNS, \
+ KC_LSFT,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_P1, KC_P2, KC_P3, \
+ KC_CAPS,KC_LALT,KC_LGUI,KC_GRV, KC_SPC, KC_BSLS,KC_LEFT,KC_RGHT,KC_DOWN,KC_UP, KC_P0, KC_PDOT, KC_PENT),
+
+
+ /* Layer 1: Tenkey use Layer
+ * ,-----------------------------------------------------------. ,---------------,
+ * | POWER | | |
+ * |-----------------------------------------------------------| |---------------|
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | |NLK| = | / | * |
+ * |-----------------------------------------------------------| |---------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | |INS| 8 |PGU|V+ |
+ * |-----------------------------------------------------' | |---------------|
+ * |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | |DEL|UP |PGD|V- |
+ * |-----------------------------------------------------------| |---------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| / |Shift | |LFT|DN |RGT| E |
+ * |-----------------------------------------------------------| |-----------| N |
+ * |CAPS|Alt |Gui |` |SPC |BSLS |LFT|RGT|DN|UP| | 0 | . | T |
+ * `-----------------------------------------------------------' `---------------'
+ */
+ KEYMAP( KC_PWR, \
+ KC_ESC, 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_FN1, KC_PEQL, KC_PSLS, KC_MUTE, \
+ 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_INS, KC_P8, KC_PGUP, KC_VOLU, \
+ KC_LCTL,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_DEL, KC_UP, KC_PGDN, KC_VOLD, \
+ KC_LSFT,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_LEFT, KC_DOWN, KC_RIGHT, \
+ KC_CAPS,KC_LALT,KC_LGUI,KC_GRV, KC_SPC, KC_BSLS,KC_LEFT,KC_RGHT,KC_DOWN,KC_UP, KC_P0, KC_PDOT, KC_PENT),
+};
+
+
+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 index)
+{
+ return pgm_read_byte(&fn_layer[index]);
+}
+
+uint8_t keymap_fn_keycode(uint8_t index)
+{
+ return pgm_read_byte(&fn_keycode[index]);
+}
diff --git a/keyboard/IIgs/led.c b/keyboard/IIgs/led.c new file mode 100644 index 0000000000..f76545f0ba --- /dev/null +++ b/keyboard/IIgs/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/keyboard/IIgs/matrix.c b/keyboard/IIgs/matrix.c new file mode 100644 index 0000000000..6ca55b7ea2 --- /dev/null +++ b/keyboard/IIgs/matrix.c @@ -0,0 +1,363 @@ +/* +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 "debug.h" +#include "util.h" +#include "matrix.h" +#include "led.h" + + +#if (MATRIX_COLS > 16) +# error "MATRIX_COLS must not exceed 16" +#endif +#if (MATRIX_ROWS > 255) +# error "MATRIX_ROWS must not exceed 255" +#endif + + +#ifndef DEBOUNCE +# define DEBOUNCE 0 +#endif +static uint8_t debouncing = DEBOUNCE; + +// matrix state buffer(1:on, 0:off) +#if (MATRIX_COLS <= 8) +static uint8_t *matrix; +static uint8_t *matrix_prev; +static uint8_t _matrix0[MATRIX_ROWS]; +static uint8_t _matrix1[MATRIX_ROWS]; +#else +static uint16_t *matrix; +static uint16_t *matrix_prev; +static uint16_t _matrix0[MATRIX_ROWS]; +static uint16_t _matrix1[MATRIX_ROWS]; +#endif + +#ifdef MATRIX_HAS_GHOST +static bool matrix_has_ghost_in_row(uint8_t row); +#endif +static uint8_t read_col(uint8_t row); +static void unselect_rows(void); +static void select_row(uint8_t row); + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + // initialize row and col + unselect_rows(); + // Input with pull-up(DDR:0, PORT:1) + // Column C1 ~ C7 (PortC0-6) + // Column C0(Port E1) + DDRC &= ~0b01111111; + PORTC |= 0b01111111; + DDRE &= ~0b00000010; + PORTE |= 0b00000010; + //DDRB &= ~0b00000100; + //PORTB |= 0b00000100; + // modifier B3/4,F4/5,E4 always input + // A0 + //DDRA |= 0b00000001; + //PORTA &= 0b00000001; + //DDRB |= 0b00011000; + //PORTB &= 0b00011000; + //DDRF |= ~0b00110000; + //PORTF &= 0b00110000; + //DDRB &= ~0b00011000; + //PORTB |= 0b00011000; + //DDRF &= ~0b00110000; + //PORTF |= 0b00110000; + //DDRE &= ~0b00010000; + //PORTE |= 0b00010000; + + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; + for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00; + matrix = _matrix0; + matrix_prev = _matrix1; +} + +uint8_t matrix_scan(void) +{ + if (!debouncing) { + uint8_t *tmp = matrix_prev; + matrix_prev = matrix; + matrix = tmp; + } + + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + unselect_rows(); + select_row(i); + _delay_us(30); // without this wait read unstable value. + if ( i == ( MATRIX_ROWS - 1 ) ) { // CHECK CAPS LOCK + if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { // CAPS LOCK is ON on HOST + if ( ~read_col(i) & (1<< 4) ) { // CAPS LOCK is still DOWN ( 0bXXX1_XXXX) + matrix[i] = ~read_col(i) & 0b11101111; // change CAPS LOCK as released + } else { // CAPS LOCK in UP + matrix[i] = ~read_col(i) | 0b00010000; // send fake caps lock down + } + } else { // CAPS LOCK is OFF on HOST + if (matrix[i] != (uint8_t)~read_col(i)) { + matrix[i] = (uint8_t)~read_col(i); + if (debouncing) { + debug("bounce!: "); debug_hex(debouncing); print("\n"); + } + debouncing = DEBOUNCE; + } + } + } else { + if (matrix[i] != (uint8_t)~read_col(i)) { + matrix[i] = (uint8_t)~read_col(i); + if (debouncing) { + debug("bounce!: "); debug_hex(debouncing); print("\n"); + } + debouncing = DEBOUNCE; + } + } + } + unselect_rows(); + + if (debouncing) { + debouncing--; + } + + return 1; +} + +bool matrix_is_modified(void) +{ + if (debouncing) return false; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + if (matrix[i] != matrix_prev[i]) { + return true; + } + } + return false; +} + +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) +{ +// if ( row == ( MATRIX_ROWS - 1 ) && col == 4) { // CHECK CAPS LOCK +// if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { // CAPS LOCK is ON on HOST +// if ((matrix_prev[row] & 0b00010000) && (~matrix[row] & 0b00010000)) { +// debug("CapsLock Reverse:");debug_hex(matrix[row]); +// matrix[row] |= 0b00010000; +// matrix_prev[row] &= ~0b00010000; +// debug("->");debug_hex(matrix[row]);debug("\n"); +// } +// } +// } + return (matrix[row] & (1<<col)); +} + +inline +#if (MATRIX_COLS <= 8) +uint8_t matrix_get_row(uint8_t row) +#else +uint16_t matrix_get_row(uint8_t row) +#endif +{ + return matrix[row]; +} + +void matrix_print(void) +{ + print("\nr/c 01234567\n"); + for (uint8_t row = 0; row < matrix_rows(); row++) { + phex(row); print(": "); +#if (MATRIX_COLS <= 8) + pbin_reverse(matrix_get_row(row)); +#else + pbin_reverse16(matrix_get_row(row)); +#endif +#ifdef MATRIX_HAS_GHOST + if (matrix_has_ghost_in_row(row)) { + print(" <ghost"); + } +#endif + print("\n"); + } +} + +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +#if (MATRIX_COLS <= 8) + count += bitpop(matrix[i]); +#else + count += bitpop16(matrix[i]); +#endif + } + 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 uint8_t read_col(uint8_t row) +{ + // For normal : Column C1 ~ C7 (PortC0-6), C0(Port E1) + // For modifier : B3(CNTRL)/4(SHIFT),F4(CMD/GUI)/5(OPTION,ALT) + // Modifier would be copied to report->mods except E4(CAPSLOCK) + uint8_t tmp; + if ( row == 10 ) { + tmp = 0xC0; + tmp |= (PINB >> 3 ) & 0b00000011; // LEFT CTRL is 0bit in modifier (HID Spec) + // LEFT SHIFT is 1bit in modifier (HID Spec) + tmp |= (PINF >> 3 ) & 0b00000100; // LEFT ALT is 2bit in modifier (HID Spec) + tmp |= (PINF >> 1 ) & 0b00001000; // LEFT GUI is 3bit in modifier (HID Spec) + tmp |= (PINA << 4 ) & 0b00010000; // CAPSLOCK + tmp |= (PINB << 3 ) & 0b00100000; // POWER + } else { + tmp = 0x00; + tmp = (PINE >> 1)&0b00000001; + tmp |= PINC << 1 ; + } + return tmp; +} + +inline +static void unselect_rows(void) +{ + // Hi-Z(DDR:0, PORT:0) to unselect + // DDR : 1, output 0, input + DDRB &= ~0b00000011; // PB: 1,0 + PORTB &= ~0b00000011; + DDRD &= ~0b00010000; // PD: 4 + PORTD &= ~0b00010000; + DDRE &= ~0b11000000; // PE: 7,6 + PORTE &= ~0b11000000; + DDRF &= ~0b11000111; // PF: 7,6,2,1,0 + PORTF &= ~0b11000111; + // to unselect virtual row(modifier), set port to output with low + DDRA |= 0b00000001; // PA: 0 for CAPSLOCK + PORTA &= ~0b00000001; + DDRB |= 0b00011100; // PB: 3,4 for modifier(row10) + PORTB &= ~0b00011100; // PB: 2 for power + DDRF |= 0b00110000; // PF: 4,5 for modifier + PORTF &= ~0b00110000; +} + +inline +static void select_row(uint8_t row) +{ + // Output low(DDR:1, PORT:0) to select + // with row enable, column could send low to AVR when pressed + // row: 0 1 2 3 4 5 6 7 8 9 + // pin: PB1, PB0, PE7, PE6, PD4, PF2, PF0, PF1, PF6 PF7 + switch (row) { + case 0: + DDRB |= (1<<1); + PORTB &= ~(1<<1); + break; + case 1: + DDRB |= (1<<0); + PORTB &= ~(1<<0); + break; + case 2: + DDRE |= (1<<7); + PORTE &= ~(1<<7); + break; + case 3: + DDRE |= (1<<6); + PORTE &= ~(1<<6); + break; + case 4: + DDRD |= (1<<4); + PORTD &= ~(1<<4); + break; + case 5: + DDRF |= (1<<2); + PORTF &= ~(1<<2); + break; + case 6: + DDRF |= (1<<0); + PORTF &= ~(1<<0); + break; + case 7: + DDRF |= (1<<1); + PORTF &= ~(1<<1); + break; + case 8: + DDRF |= (1<<6); + PORTF &= ~(1<<6); + break; + case 9: + DDRF |= (1<<7); + PORTF &= ~(1<<7); + break; + case 10: + // modifier has no row enable + // to select virtual row, set port as input + DDRA &= ~0b00000001; + PORTA |= 0b00000001; + DDRB &= ~0b00011100; + PORTB |= 0b00011100; + DDRF &= ~0b00110000; + PORTF |= 0b00110000; + break; + + } +} |