aboutsummaryrefslogtreecommitdiff
path: root/keyboard/IIgs
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2013-03-05 15:41:21 +0900
committertmk <nobody@nowhere>2013-03-05 15:41:21 +0900
commit5808317b694004c43a6e0f76e9715415cce19a25 (patch)
tree9814dbe96eecbb940a710505feb82125a483dc2d /keyboard/IIgs
parent633d9aa53e3fc2b9fa9f01475cba9c151ab31d9a (diff)
downloadqmk_firmware-5808317b694004c43a6e0f76e9715415cce19a25.tar.gz
qmk_firmware-5808317b694004c43a6e0f76e9715415cce19a25.zip
Fix keymap for new framework
Diffstat (limited to 'keyboard/IIgs')
-rw-r--r--keyboard/IIgs/Makefile95
-rw-r--r--keyboard/IIgs/README45
-rw-r--r--keyboard/IIgs/config.h68
-rw-r--r--keyboard/IIgs/doc/PIN_BYPASS.jpgbin0 -> 329437 bytes
-rw-r--r--keyboard/IIgs/doc/Teensy++_Mod.jpgbin0 -> 74137 bytes
-rwxr-xr-xkeyboard/IIgs/hid_listen.macbin0 -> 13524 bytes
-rw-r--r--keyboard/IIgs/keymap.c142
-rw-r--r--keyboard/IIgs/led.c24
-rw-r--r--keyboard/IIgs/matrix.c363
9 files changed, 737 insertions, 0 deletions
diff --git a/keyboard/IIgs/Makefile b/keyboard/IIgs/Makefile
new file mode 100644
index 000000000..c18e9720c
--- /dev/null
+++ b/keyboard/IIgs/Makefile
@@ -0,0 +1,95 @@
1#----------------------------------------------------------------------------
2# On command line:
3#
4# make all = Make software.
5#
6# make clean = Clean out built project files.
7#
8# make coff = Convert ELF to AVR COFF.
9#
10# make extcoff = Convert ELF to AVR Extended COFF.
11#
12# make program = Download the hex file to the device.
13# Please customize your programmer settings(PROGRAM_CMD)
14#
15# make teensy = Download the hex file to the device, using teensy_loader_cli.
16# (must have teensy_loader_cli installed).
17#
18# make dfu = Download the hex file to the device, using dfu-programmer (must
19# have dfu-programmer installed).
20#
21# make flip = Download the hex file to the device, using Atmel FLIP (must
22# have Atmel FLIP installed).
23#
24# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
25# (must have dfu-programmer installed).
26#
27# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
28# (must have Atmel FLIP installed).
29#
30# make debug = Start either simulavr or avarice as specified for debugging,
31# with avr-gdb or avr-insight as the front end for debugging.
32#
33# make filename.s = Just compile filename.c into the assembler code only.
34#
35# make filename.i = Create a preprocessed source file for use in submitting
36# bug reports to the GCC project.
37#
38# To rebuild project do "make clean" then "make all".
39#----------------------------------------------------------------------------
40
41# Target file name (without extension).
42TARGET = IIgs_Standard
43
44# Directory common source filess exist
45TOP_DIR = ../..
46
47# Directory keyboard dependent files exist
48TARGET_DIR = .
49
50# keyboard dependent files
51SRC = keymap.c \
52 matrix.c \
53 led.c
54
55CONFIG_H = config.h
56
57
58# MCU name, you MUST set this to match the board you are using
59# type "make clean" after changing this, so all files will be rebuilt
60#MCU = at90usb162 # Teensy 1.0
61#MCU = atmega32u4 # Teensy 2.0
62#MCU = at90usb646 # Teensy++ 1.0
63MCU = at90usb1286 # Teensy++ 2.0
64
65
66# Processor frequency.
67# Normally the first thing your program should do is set the clock prescaler,
68# so your program will run at the correct speed. You should also set this
69# variable to same clock speed. The _delay_ms() macro uses this, and many
70# examples use this variable to calculate timings. Do not add a "UL" here.
71F_CPU = 16000000
72
73
74# Build Options
75# comment out to disable the options.
76#
77MOUSEKEY_ENABLE = no # Mouse keys
78#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
79EXTRAKEY_ENABLE = yes # Audio control and System control
80#NKRO_ENABLE = yes # USB Nkey Rollover
81
82
83
84#---------------- Programming Options --------------------------
85PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
86
87
88
89# Search Path
90VPATH += $(TARGET_DIR)
91VPATH += $(TOP_DIR)
92
93include $(TOP_DIR)/protocol/pjrc.mk
94include $(TOP_DIR)/common.mk
95include $(TOP_DIR)/rules.mk
diff --git a/keyboard/IIgs/README b/keyboard/IIgs/README
new file mode 100644
index 000000000..4f9cad1ca
--- /dev/null
+++ b/keyboard/IIgs/README
@@ -0,0 +1,45 @@
1Replacable USB Controller for Apple IIgs/Standard(M0116)
2JeffreySung(nattyman@gmail.com)
3
4===============================
5
6Feature
7-------
8- Replaceable keyboard controller for Apple IIgs(A9M0330)/Standard(M0116)
9- Teensy++ 2.0 required
10- Some signal bypass required
11- ADB keyboard doesn't use matrix for modifier keys. With virtual row for modifier keys,
12 these keys are merged into key matrix using virtual row.
13
14History
15=======
16- 2012.09.17 First Release
17- 2012.09.17 CapsLock support
18- 2012.09.19 Power button added
19Build
20=====
210. Just Type "Make" and return.
22
23Hardware
24========
25PJRC Teensy
26-----------
270. The following ports should not be connected to board.
28 From top view of Teensy++, from GND and counter clock wise.
29 -7,26(in keyboard PCB, these pins are VDD,GND)
30 -30,31(in Teensy++, these pins are Ref,GND respectively)
31 -5,6(D2,D3 for bluetooth in future)
321. Bypass #31 pin(from board) to E4(Teensy)
332. Bypass #30 pin(from board) to F2(Teensy)
343. Bypass #6 pin(from board) to A0(Teensy)
354. Refer doc directory
36
37To Do
38=====
390. When DEBOUNCE defined, there is a errors.
401. Layer Change by toggling Clear Key
412. Eject Key add. (following files should be modified.)
42 common/keycode.h
43 common/keyboard.c
443. Use bluetooth
45EOF
diff --git a/keyboard/IIgs/config.h b/keyboard/IIgs/config.h
new file mode 100644
index 000000000..11acf87c0
--- /dev/null
+++ b/keyboard/IIgs/config.h
@@ -0,0 +1,68 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef CONFIG_H
19#define CONFIG_H
20
21/* controller configuration */
22#include "controller_teensy.h"
23
24
25/* USB Device descriptor parameter */
26/* for Apple
27#define VENDOR_ID 0x05AC
28#define PRODUCT_ID 0xBEE0
29*/
30#define VENDOR_ID 0xFEED
31#define PRODUCT_ID 0xBEE0
32#define DEVICE_VER 0x0202
33#define MANUFACTURER t.m.k.
34#define PRODUCT Apple Desktop Bus Keyboard
35
36
37/* message strings */
38#define DESCRIPTION Apple M0116/A9M0660 keyboard firmware
39
40
41/* matrix size */
42#define MATRIX_ROWS 11 // last row is virtual for modifier
43#define MATRIX_COLS 8
44/* define if matrix has ghost */
45#define MATRIX_HAS_GHOST
46/* Set 0 if need no debouncing */
47#define DEBOUNCE 5
48
49
50/* key combination for command */
51#define IS_COMMAND() ( \
52 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_LCTRL) | MOD_BIT(KC_LALT) | MOD_BIT(KC_LGUI)) || \
53 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
54)
55
56
57/* layer switching */
58#define LAYER_SWITCH_DELAY 100
59#define LAYER_SEND_FN_TERM 300
60
61
62/* mouse keys */
63#ifdef MOUSEKEY_ENABLE
64# define MOUSEKEY_DELAY_TIME 192
65#endif
66
67
68#endif
diff --git a/keyboard/IIgs/doc/PIN_BYPASS.jpg b/keyboard/IIgs/doc/PIN_BYPASS.jpg
new file mode 100644
index 000000000..2998f0c3f
--- /dev/null
+++ b/keyboard/IIgs/doc/PIN_BYPASS.jpg
Binary files differ
diff --git a/keyboard/IIgs/doc/Teensy++_Mod.jpg b/keyboard/IIgs/doc/Teensy++_Mod.jpg
new file mode 100644
index 000000000..146c1ab93
--- /dev/null
+++ b/keyboard/IIgs/doc/Teensy++_Mod.jpg
Binary files differ
diff --git a/keyboard/IIgs/hid_listen.mac b/keyboard/IIgs/hid_listen.mac
new file mode 100755
index 000000000..8758fdf88
--- /dev/null
+++ b/keyboard/IIgs/hid_listen.mac
Binary files differ
diff --git a/keyboard/IIgs/keymap.c b/keyboard/IIgs/keymap.c
new file mode 100644
index 000000000..cd33e223a
--- /dev/null
+++ b/keyboard/IIgs/keymap.c
@@ -0,0 +1,142 @@
1/*
2Copyright 2012 Jeffrey Sung <nattyman@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 * Keymap for Apple IIgs/Standard Keyboard
20 */
21#include <stdint.h>
22#include <stdbool.h>
23#include <avr/pgmspace.h>
24#include "keycode.h"
25#include "print.h"
26#include "debug.h"
27#include "util.h"
28#include "keymap.h"
29
30
31// Convert physical keyboard layout to matrix array.
32// This is a macro to define keymap easily in keyboard layout form.
33#define KEYMAP( R10C5, \
34 R3C7, R3C6, R3C5, R3C4, R3C3, R3C2, R3C1, R8C1, R8C0, R3C0, R0C0, R0C1, R0C2, R0C3, R4C4, R4C5, R4C6, R4C7, \
35 R9C7, R9C6, R9C5, R9C4, R9C3, R9C2, R9C1, R9C0, R1C0, R1C1, R1C2, R1C3, R1C4, R2C4, R2C5, R2C6, R2C3, \
36 R10C0,R7C7, R7C6, R7C5, R7C4, R7C3, R7C2, R7C1, R7C0, R0C4, R1C6, R1C7, R1C5, R2C0, R2C1, R2C2, R2C7, \
37 R10C1,R6C7, R6C6, R6C5, R6C4, R6C3, R6C2, R6C1, R6C0, R0C5, R0C6, R4C0, R4C1, R4C2, \
38 R10C4,R10C2,R10C3,R5C4, R5C7, R5C5, R5C6, R5C0, R5C2, R0C7, R5C1, R5C3, R4C3 \
39) { \
40 { R0C0, R0C1, R0C2, R0C3, R0C4, R0C5, R0C6, R0C7 }, \
41 { R1C0, R1C1, R1C2, R1C3, R1C4, R1C5, R1C6, R1C7 }, \
42 { R2C0, R2C1, R2C2, R2C3, R2C4, R2C5, R2C6, R2C7 }, \
43 { R3C0, R3C1, R3C2, R3C3, R3C4, R3C5, R3C6, R3C7 }, \
44 { R4C0, R4C1, R4C2, R4C3, R4C4, R4C5, R4C6, R4C7 }, \
45 { R5C0, R5C1, R5C2, R5C3, R5C4, R5C5, R5C6, R5C7 }, \
46 { R6C0, R6C1, R6C2, R6C3, R6C4, R6C5, R6C6, R6C7 }, \
47 { R7C0, R7C1, R7C2, R7C3, R7C4, R7C5, R7C6, R7C7 }, \
48 { R8C0, R8C1, KC_NO, KC_NO, KC_NO,KC_NO, KC_NO, KC_NO }, \
49 { R9C0, R9C1, R9C2, R9C3, R9C4, R9C5, R9C6, R9C7 }, \
50 { R10C0,R10C1, R10C2, R10C3, R10C4,R10C5, KC_NO, KC_NO} \
51}
52
53#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
54
55
56// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
57static const uint8_t PROGMEM fn_layer[] = {
58 0, // Fn0
59 1, // Fn1
60 2, // Fn2
61 3, // Fn3
62 4, // Fn4
63 0, // Fn5
64 3, // Fn6
65 3 // Fn7
66};
67
68// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer.
69// See layer.c for details.
70static const uint8_t PROGMEM fn_keycode[] = {
71 KC_NO, // Fn0
72 KC_NO, // Fn1
73 KC_SLSH, // Fn2
74 KC_SCLN, // Fn3
75 KC_SPC, // Fn4
76 KC_NO, // Fn5
77 KC_NO, // Fn6
78 KC_NO // Fn7
79};
80
81static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
82 /* Layer 0: Default Layer
83 * ,-----------------------------------------------------------. ,---------------,
84 * | POWER | | |
85 * |-----------------------------------------------------------| |---------------|
86 * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | |FN0| = | / | * |
87 * |-----------------------------------------------------------| |---------------|
88 * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7 | 8 | 9 | + |
89 * |-----------------------------------------------------' | |---------------|
90 * |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | | 4 | 5 | 6 | - |
91 * |-----------------------------------------------------------| |---------------|
92 * |Shift | Z| X| C| V| B| N| M| ,| .| / |Shift | | 1 | 2 | 3 | E |
93 * |-----------------------------------------------------------| |-----------| N |
94 * |CAPS|Alt |Gui |` |SPC |BSLS |LFT|RGT|DN|UP| | 0 | . | T |
95 * `-----------------------------------------------------------' |---------------'
96 */
97 KEYMAP( KC_PWR,
98 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, \
99 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, \
100 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, \
101 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, \
102 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),
103
104
105 /* Layer 1: Tenkey use Layer
106 * ,-----------------------------------------------------------. ,---------------,
107 * | POWER | | |
108 * |-----------------------------------------------------------| |---------------|
109 * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | |NLK| = | / | * |
110 * |-----------------------------------------------------------| |---------------|
111 * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | |INS| 8 |PGU|V+ |
112 * |-----------------------------------------------------' | |---------------|
113 * |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | |DEL|UP |PGD|V- |
114 * |-----------------------------------------------------------| |---------------|
115 * |Shift | Z| X| C| V| B| N| M| ,| .| / |Shift | |LFT|DN |RGT| E |
116 * |-----------------------------------------------------------| |-----------| N |
117 * |CAPS|Alt |Gui |` |SPC |BSLS |LFT|RGT|DN|UP| | 0 | . | T |
118 * `-----------------------------------------------------------' `---------------'
119 */
120 KEYMAP( KC_PWR, \
121 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, \
122 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, \
123 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, \
124 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, \
125 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),
126};
127
128
129uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
130{
131 return KEYCODE(layer, row, col);
132}
133
134uint8_t keymap_fn_layer(uint8_t index)
135{
136 return pgm_read_byte(&fn_layer[index]);
137}
138
139uint8_t keymap_fn_keycode(uint8_t index)
140{
141 return pgm_read_byte(&fn_keycode[index]);
142}
diff --git a/keyboard/IIgs/led.c b/keyboard/IIgs/led.c
new file mode 100644
index 000000000..f76545f0b
--- /dev/null
+++ b/keyboard/IIgs/led.c
@@ -0,0 +1,24 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "stdint.h"
19#include "led.h"
20
21
22void led_set(uint8_t usb_led)
23{
24}
diff --git a/keyboard/IIgs/matrix.c b/keyboard/IIgs/matrix.c
new file mode 100644
index 000000000..6ca55b7ea
--- /dev/null
+++ b/keyboard/IIgs/matrix.c
@@ -0,0 +1,363 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 * scan matrix
20 */
21#include <stdint.h>
22#include <stdbool.h>
23#include <avr/io.h>
24#include <util/delay.h>
25#include "print.h"
26#include "debug.h"
27#include "util.h"
28#include "matrix.h"
29#include "led.h"
30
31
32#if (MATRIX_COLS > 16)
33# error "MATRIX_COLS must not exceed 16"
34#endif
35#if (MATRIX_ROWS > 255)
36# error "MATRIX_ROWS must not exceed 255"
37#endif
38
39
40#ifndef DEBOUNCE
41# define DEBOUNCE 0
42#endif
43static uint8_t debouncing = DEBOUNCE;
44
45// matrix state buffer(1:on, 0:off)
46#if (MATRIX_COLS <= 8)
47static uint8_t *matrix;
48static uint8_t *matrix_prev;
49static uint8_t _matrix0[MATRIX_ROWS];
50static uint8_t _matrix1[MATRIX_ROWS];
51#else
52static uint16_t *matrix;
53static uint16_t *matrix_prev;
54static uint16_t _matrix0[MATRIX_ROWS];
55static uint16_t _matrix1[MATRIX_ROWS];
56#endif
57
58#ifdef MATRIX_HAS_GHOST
59static bool matrix_has_ghost_in_row(uint8_t row);
60#endif
61static uint8_t read_col(uint8_t row);
62static void unselect_rows(void);
63static void select_row(uint8_t row);
64
65
66inline
67uint8_t matrix_rows(void)
68{
69 return MATRIX_ROWS;
70}
71
72inline
73uint8_t matrix_cols(void)
74{
75 return MATRIX_COLS;
76}
77
78void matrix_init(void)
79{
80 // initialize row and col
81 unselect_rows();
82 // Input with pull-up(DDR:0, PORT:1)
83 // Column C1 ~ C7 (PortC0-6)
84 // Column C0(Port E1)
85 DDRC &= ~0b01111111;
86 PORTC |= 0b01111111;
87 DDRE &= ~0b00000010;
88 PORTE |= 0b00000010;
89 //DDRB &= ~0b00000100;
90 //PORTB |= 0b00000100;
91 // modifier B3/4,F4/5,E4 always input
92 // A0
93 //DDRA |= 0b00000001;
94 //PORTA &= 0b00000001;
95 //DDRB |= 0b00011000;
96 //PORTB &= 0b00011000;
97 //DDRF |= ~0b00110000;
98 //PORTF &= 0b00110000;
99 //DDRB &= ~0b00011000;
100 //PORTB |= 0b00011000;
101 //DDRF &= ~0b00110000;
102 //PORTF |= 0b00110000;
103 //DDRE &= ~0b00010000;
104 //PORTE |= 0b00010000;
105
106 // initialize matrix state: all keys off
107 for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
108 for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
109 matrix = _matrix0;
110 matrix_prev = _matrix1;
111}
112
113uint8_t matrix_scan(void)
114{
115 if (!debouncing) {
116 uint8_t *tmp = matrix_prev;
117 matrix_prev = matrix;
118 matrix = tmp;
119 }
120
121 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
122 unselect_rows();
123 select_row(i);
124 _delay_us(30); // without this wait read unstable value.
125 if ( i == ( MATRIX_ROWS - 1 ) ) { // CHECK CAPS LOCK
126 if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { // CAPS LOCK is ON on HOST
127 if ( ~read_col(i) & (1<< 4) ) { // CAPS LOCK is still DOWN ( 0bXXX1_XXXX)
128 matrix[i] = ~read_col(i) & 0b11101111; // change CAPS LOCK as released
129 } else { // CAPS LOCK in UP
130 matrix[i] = ~read_col(i) | 0b00010000; // send fake caps lock down
131 }
132 } else { // CAPS LOCK is OFF on HOST
133 if (matrix[i] != (uint8_t)~read_col(i)) {
134 matrix[i] = (uint8_t)~read_col(i);
135 if (debouncing) {
136 debug("bounce!: "); debug_hex(debouncing); print("\n");
137 }
138 debouncing = DEBOUNCE;
139 }
140 }
141 } else {
142 if (matrix[i] != (uint8_t)~read_col(i)) {
143 matrix[i] = (uint8_t)~read_col(i);
144 if (debouncing) {
145 debug("bounce!: "); debug_hex(debouncing); print("\n");
146 }
147 debouncing = DEBOUNCE;
148 }
149 }
150 }
151 unselect_rows();
152
153 if (debouncing) {
154 debouncing--;
155 }
156
157 return 1;
158}
159
160bool matrix_is_modified(void)
161{
162 if (debouncing) return false;
163 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
164 if (matrix[i] != matrix_prev[i]) {
165 return true;
166 }
167 }
168 return false;
169}
170
171inline
172bool matrix_has_ghost(void)
173{
174#ifdef MATRIX_HAS_GHOST
175 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
176 if (matrix_has_ghost_in_row(i))
177 return true;
178 }
179#endif
180 return false;
181}
182
183inline
184bool matrix_is_on(uint8_t row, uint8_t col)
185{
186// if ( row == ( MATRIX_ROWS - 1 ) && col == 4) { // CHECK CAPS LOCK
187// if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { // CAPS LOCK is ON on HOST
188// if ((matrix_prev[row] & 0b00010000) && (~matrix[row] & 0b00010000)) {
189// debug("CapsLock Reverse:");debug_hex(matrix[row]);
190// matrix[row] |= 0b00010000;
191// matrix_prev[row] &= ~0b00010000;
192// debug("->");debug_hex(matrix[row]);debug("\n");
193// }
194// }
195// }
196 return (matrix[row] & (1<<col));
197}
198
199inline
200#if (MATRIX_COLS <= 8)
201uint8_t matrix_get_row(uint8_t row)
202#else
203uint16_t matrix_get_row(uint8_t row)
204#endif
205{
206 return matrix[row];
207}
208
209void matrix_print(void)
210{
211 print("\nr/c 01234567\n");
212 for (uint8_t row = 0; row < matrix_rows(); row++) {
213 phex(row); print(": ");
214#if (MATRIX_COLS <= 8)
215 pbin_reverse(matrix_get_row(row));
216#else
217 pbin_reverse16(matrix_get_row(row));
218#endif
219#ifdef MATRIX_HAS_GHOST
220 if (matrix_has_ghost_in_row(row)) {
221 print(" <ghost");
222 }
223#endif
224 print("\n");
225 }
226}
227
228uint8_t matrix_key_count(void)
229{
230 uint8_t count = 0;
231 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
232#if (MATRIX_COLS <= 8)
233 count += bitpop(matrix[i]);
234#else
235 count += bitpop16(matrix[i]);
236#endif
237 }
238 return count;
239}
240
241#ifdef MATRIX_HAS_GHOST
242inline
243static bool matrix_has_ghost_in_row(uint8_t row)
244{
245 // no ghost exists in case less than 2 keys on
246 if (((matrix[row] - 1) & matrix[row]) == 0)
247 return false;
248
249 // ghost exists in case same state as other row
250 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
251 if (i != row && (matrix[i] & matrix[row]) == matrix[row])
252 return true;
253 }
254 return false;
255}
256#endif
257
258inline
259static uint8_t read_col(uint8_t row)
260{
261 // For normal : Column C1 ~ C7 (PortC0-6), C0(Port E1)
262 // For modifier : B3(CNTRL)/4(SHIFT),F4(CMD/GUI)/5(OPTION,ALT)
263 // Modifier would be copied to report->mods except E4(CAPSLOCK)
264 uint8_t tmp;
265 if ( row == 10 ) {
266 tmp = 0xC0;
267 tmp |= (PINB >> 3 ) & 0b00000011; // LEFT CTRL is 0bit in modifier (HID Spec)
268 // LEFT SHIFT is 1bit in modifier (HID Spec)
269 tmp |= (PINF >> 3 ) & 0b00000100; // LEFT ALT is 2bit in modifier (HID Spec)
270 tmp |= (PINF >> 1 ) & 0b00001000; // LEFT GUI is 3bit in modifier (HID Spec)
271 tmp |= (PINA << 4 ) & 0b00010000; // CAPSLOCK
272 tmp |= (PINB << 3 ) & 0b00100000; // POWER
273 } else {
274 tmp = 0x00;
275 tmp = (PINE >> 1)&0b00000001;
276 tmp |= PINC << 1 ;
277 }
278 return tmp;
279}
280
281inline
282static void unselect_rows(void)
283{
284 // Hi-Z(DDR:0, PORT:0) to unselect
285 // DDR : 1, output 0, input
286 DDRB &= ~0b00000011; // PB: 1,0
287 PORTB &= ~0b00000011;
288 DDRD &= ~0b00010000; // PD: 4
289 PORTD &= ~0b00010000;
290 DDRE &= ~0b11000000; // PE: 7,6
291 PORTE &= ~0b11000000;
292 DDRF &= ~0b11000111; // PF: 7,6,2,1,0
293 PORTF &= ~0b11000111;
294 // to unselect virtual row(modifier), set port to output with low
295 DDRA |= 0b00000001; // PA: 0 for CAPSLOCK
296 PORTA &= ~0b00000001;
297 DDRB |= 0b00011100; // PB: 3,4 for modifier(row10)
298 PORTB &= ~0b00011100; // PB: 2 for power
299 DDRF |= 0b00110000; // PF: 4,5 for modifier
300 PORTF &= ~0b00110000;
301}
302
303inline
304static void select_row(uint8_t row)
305{
306 // Output low(DDR:1, PORT:0) to select
307 // with row enable, column could send low to AVR when pressed
308 // row: 0 1 2 3 4 5 6 7 8 9
309 // pin: PB1, PB0, PE7, PE6, PD4, PF2, PF0, PF1, PF6 PF7
310 switch (row) {
311 case 0:
312 DDRB |= (1<<1);
313 PORTB &= ~(1<<1);
314 break;
315 case 1:
316 DDRB |= (1<<0);
317 PORTB &= ~(1<<0);
318 break;
319 case 2:
320 DDRE |= (1<<7);
321 PORTE &= ~(1<<7);
322 break;
323 case 3:
324 DDRE |= (1<<6);
325 PORTE &= ~(1<<6);
326 break;
327 case 4:
328 DDRD |= (1<<4);
329 PORTD &= ~(1<<4);
330 break;
331 case 5:
332 DDRF |= (1<<2);
333 PORTF &= ~(1<<2);
334 break;
335 case 6:
336 DDRF |= (1<<0);
337 PORTF &= ~(1<<0);
338 break;
339 case 7:
340 DDRF |= (1<<1);
341 PORTF &= ~(1<<1);
342 break;
343 case 8:
344 DDRF |= (1<<6);
345 PORTF &= ~(1<<6);
346 break;
347 case 9:
348 DDRF |= (1<<7);
349 PORTF &= ~(1<<7);
350 break;
351 case 10:
352 // modifier has no row enable
353 // to select virtual row, set port as input
354 DDRA &= ~0b00000001;
355 PORTA |= 0b00000001;
356 DDRB &= ~0b00011100;
357 PORTB |= 0b00011100;
358 DDRF &= ~0b00110000;
359 PORTF |= 0b00110000;
360 break;
361
362 }
363}