123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- /*
- NeXT non-ADB Keyboard USB Converter
-
- Copyright 2013, Benjamin Gould ([email protected])
-
- Based on:
- TMK firmware code Copyright 2011,2012 Jun WAKO <[email protected]>
- Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
-
- Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
- Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
- Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
-
- 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 <stdint.h>
- #include <stdbool.h>
- #include <avr/io.h>
- #include <util/delay.h>
- #include "print.h"
- #include "util.h"
- #include "serial.h"
- #include "matrix.h"
- #include "debug.h"
- #include "matrix.h"
- #include "next_kbd.h"
-
- static void matrix_make(uint8_t code);
- static void matrix_break(uint8_t code);
-
- static uint8_t matrix[MATRIX_ROWS];
- #define ROW(code) ((code>>3)&0xF)
- #define COL(code) (code&0x07)
-
- static bool is_modified = false;
-
- /* number of matrix rows */
- inline
- uint8_t matrix_rows(void)
- {
- return MATRIX_ROWS;
- }
-
- /* number of matrix columns */
- inline
- uint8_t matrix_cols(void)
- {
- return MATRIX_COLS;
- }
-
- #ifndef NEXT_KBD_LED1_ON
- #define NEXT_KBD_LED1_ON
- #endif
-
- #ifndef NEXT_KBD_LED1_OFF
- #define NEXT_KBD_LED1_OFF
- #endif
-
- #define NEXT_KBD_PWR_READ (NEXT_KBD_PWR_PIN&(1<<NEXT_KBD_PWR_BIT))
-
- static bool power_state = false;
-
- /* intialize matrix for scanning. should be called once. */
- void matrix_init(void)
- {
- #ifdef DEBUG_ON_INIT
- debug_enable = true;
- #endif
-
- // I've found that the matrix likes a little while for things to
- // settle down before it gets started. Not sure why :)
- _delay_ms(250);
-
- dprintf("[ Intializing NeXT keyboard ]\n");
- NEXT_KBD_LED1_DDR |= (1<<NEXT_KBD_LED1_BIT); // LED pin to output
- NEXT_KBD_LED1_ON;
-
- NEXT_KBD_PWR_DDR &= ~(1<<NEXT_KBD_PWR_BIT); // Power Button pin to input
- NEXT_KBD_PWR_PIN |= (1<<NEXT_KBD_PWR_BIT); // KBD_PWR pull up
-
- power_state = NEXT_KBD_PWR_READ ? false : true;
- dprintf("Initial power button state: %b\n", power_state);
-
- next_kbd_init();
-
- // initialize matrix state: all keys off
- for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
-
- #ifdef NEXT_KBD_INIT_FLASH_LEDS
- dprintf("flashing LEDs:");
- // flash the LEDs after initialization
- bool leds_on = true;
- for (uint8_t i = 0; i <= 6; i++)
- {
- leds_on = leds_on ? false : true;
- dprintf(" %b", leds_on);
- next_kbd_set_leds(leds_on, leds_on);
- _delay_ms(250);
- }
- dprintf("\n");
- #endif
-
- dprintf("[ NeXT keyboard initialized ]\n");
-
- return;
- }
-
- #define NEXT_KBD_KEYCODE(response) (uint8_t)((response&0xFF)>>1)
- #define NEXT_KBD_PRESSED_KEYCODE(response) (uint8_t)(((response)&0xF00)==0x400)
- #define NEXT_KBD_PRESSED(response, mask) (uint8_t)(((response)&mask)>0)
- #define NEXT_KBD_PRESSED_CONTROL(response) NEXT_KBD_PRESSED(response,0x01000)
- #define NEXT_KBD_PRESSED_SHIFT_LEFT(response) NEXT_KBD_PRESSED(response,0x02000)
- #define NEXT_KBD_PRESSED_SHIFT_RGHT(response) NEXT_KBD_PRESSED(response,0x04000)
- #define NEXT_KBD_PRESSED_CMD_LEFT(response) NEXT_KBD_PRESSED(response,0x08000)
- #define NEXT_KBD_PRESSED_CMD_RGHT(response) NEXT_KBD_PRESSED(response,0x10000)
- #define NEXT_KBD_PRESSED_ALT_LEFT(response) NEXT_KBD_PRESSED(response,0x20000)
- #define NEXT_KBD_PRESSED_ALT_RGHT(response) NEXT_KBD_PRESSED(response,0x40000)
- #define NEXT_KBD_MAKE_OR_BREAK(key, code) \
- do { \
- if (NEXT_KBD_PRESSED_##key(resp) > 0) \
- matrix_make(code); \
- else \
- matrix_break(code); \
- } while (0);
-
- #define NEXT_KBD_PWR_KEYCODE 0x58
-
- /* scan all key states on matrix */
- uint8_t matrix_scan(void)
- {
- _delay_ms(20);
-
- //next_kbd_set_leds(false, false);
- NEXT_KBD_LED1_OFF;
-
- is_modified = false;
-
- if (!NEXT_KBD_PWR_READ) {
- matrix_make(NEXT_KBD_PWR_KEYCODE);
- power_state = 1;
- if (is_modified)
- {
- dprintf("Power state 1\n");
-
- }
- } else {
- matrix_break(NEXT_KBD_PWR_KEYCODE);
- power_state = 0;
- if (is_modified)
- {
- dprintf("Power state 0\n");
-
- }
- }
-
- uint32_t resp = (next_kbd_recv());
-
- if (resp == NEXT_KBD_KMBUS_IDLE)
- {
- return 0;
- }
-
- NEXT_KBD_LED1_ON;
-
- next_kbd_set_leds(
- NEXT_KBD_PRESSED_SHIFT_LEFT(resp) ? true : false,
- NEXT_KBD_PRESSED_SHIFT_RGHT(resp) ? true : false
- );
-
- dprintf("[ r=%04lX keycode=%02X pressed=%X CTRL=%X SHIFT_LEFT=%X SHIFT_RGHT=%X CMD_LEFT=%X CMD_RGHT=%X ALT_LEFT=%X ALT_RGHT=%X ]\n", \
- resp, \
- NEXT_KBD_KEYCODE(resp), \
- NEXT_KBD_PRESSED_KEYCODE(resp), \
- NEXT_KBD_PRESSED_CONTROL(resp), \
- NEXT_KBD_PRESSED_SHIFT_LEFT(resp), \
- NEXT_KBD_PRESSED_SHIFT_RGHT(resp), \
- NEXT_KBD_PRESSED_CMD_LEFT(resp), \
- NEXT_KBD_PRESSED_CMD_RGHT(resp), \
- NEXT_KBD_PRESSED_ALT_LEFT(resp), \
- NEXT_KBD_PRESSED_ALT_RGHT(resp) \
- );
-
- // Modifier keys don't return keycode; have to check the upper bits
- NEXT_KBD_MAKE_OR_BREAK(ALT_RGHT, 0x51);
- NEXT_KBD_MAKE_OR_BREAK(ALT_LEFT, 0x52);
- NEXT_KBD_MAKE_OR_BREAK(CMD_RGHT, 0x53);
- NEXT_KBD_MAKE_OR_BREAK(CMD_LEFT, 0x54);
- NEXT_KBD_MAKE_OR_BREAK(SHIFT_RGHT, 0x55);
- NEXT_KBD_MAKE_OR_BREAK(SHIFT_LEFT, 0x56);
- NEXT_KBD_MAKE_OR_BREAK(CONTROL, 0x57);
- NEXT_KBD_MAKE_OR_BREAK(KEYCODE, NEXT_KBD_KEYCODE(resp));
-
- return 1;
- }
-
- /* whether modified from previous scan. used after matrix_scan. */
- bool matrix_is_modified()
- {
- return is_modified;
- }
-
- /* whether a switch is on */
- inline
- bool matrix_is_on(uint8_t row, uint8_t col)
- {
- return (matrix[row] & (1<<col));
- }
-
- /* matrix state on row */
- inline
- uint8_t matrix_get_row(uint8_t row)
- {
- return matrix[row];
- }
-
- /* print matrix for debug */
- void matrix_print(void)
- {
- }
-
- inline
- static void matrix_make(uint8_t code)
- {
- if (!matrix_is_on(ROW(code), COL(code))) {
- matrix[ROW(code)] |= 1<<COL(code);
- is_modified = true;
- }
- }
-
- inline
- static void matrix_break(uint8_t code)
- {
- if (matrix_is_on(ROW(code), COL(code))) {
- matrix[ROW(code)] &= ~(1<<COL(code));
- is_modified = true;
- }
- }
|