Merge branch 'ibm4704'
This commit is contained in:
commit
188ab49dd3
|
@ -41,6 +41,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di
|
|||
* [pc98_usb](converter/pc98_usb/) - [PC98] to USB
|
||||
* [usb_usb](converter/usb_usb/) - USB to USB(experimental)
|
||||
* [ascii_usb](converter/ascii_usb/) - ASCII(Serial console terminal) to USB
|
||||
* [ibm4704_usb](converter/ibm4704_usb) - [IBM 4704 keyboard Converter][GH_ibm4704]
|
||||
|
||||
### keyboard
|
||||
* [hhkb](keyboard/hhkb/) - [Happy Hacking Keyboard pro][GH_hhkb] **my main board**
|
||||
|
@ -62,6 +63,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di
|
|||
[GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272
|
||||
[GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060
|
||||
[GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483
|
||||
[GH_ibm4704]: http://geekhack.org/index.php?topic=54706.0
|
||||
[HID_liber]: http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions
|
||||
[Phantom]: http://geekhack.org/index.php?topic=26742
|
||||
[GH60]: http://geekhack.org/index.php?topic=34959
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
# Target file name (without extension).
|
||||
TARGET = ibm4704_usb
|
||||
|
||||
# Directory common source filess exist
|
||||
TOP_DIR = ../..
|
||||
|
||||
# Directory keyboard dependent files exist
|
||||
TARGET_DIR = .
|
||||
|
||||
# project specific files
|
||||
SRC = keymap_common.c \
|
||||
matrix.c \
|
||||
led.c \
|
||||
protocol/ibm4704.c
|
||||
|
||||
ifdef KEYMAP
|
||||
SRC := keymap_$(KEYMAP).c $(SRC)
|
||||
else
|
||||
SRC := keymap_plain.c $(SRC)
|
||||
endif
|
||||
|
||||
CONFIG_H = config.h
|
||||
|
||||
|
||||
# MCU name
|
||||
#MCU = at90usb1287
|
||||
MCU = atmega32u4
|
||||
|
||||
# Processor frequency.
|
||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||
# processor frequency in Hz. You can then use this symbol in your source code to
|
||||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
|
||||
# automatically to create a 32-bit value in your source code.
|
||||
#
|
||||
# This will be an integer division of F_USB below, as it is sourced by
|
||||
# F_USB after it has run through any CPU prescalers. Note that this value
|
||||
# does not *change* the processor frequency - it should merely be updated to
|
||||
# reflect the processor speed set externally so that the code can use accurate
|
||||
# software delays.
|
||||
F_CPU = 16000000
|
||||
|
||||
|
||||
#
|
||||
# LUFA specific
|
||||
#
|
||||
# Target architecture (see library "Board Types" documentation).
|
||||
ARCH = AVR8
|
||||
|
||||
# Input clock frequency.
|
||||
# This will define a symbol, F_USB, in all source code files equal to the
|
||||
# input clock frequency (before any prescaling is performed) in Hz. This value may
|
||||
# differ from F_CPU if prescaling is used on the latter, and is required as the
|
||||
# raw input clock is fed directly to the PLL sections of the AVR for high speed
|
||||
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
|
||||
# at the end, this will be done automatically to create a 32-bit value in your
|
||||
# source code.
|
||||
#
|
||||
# If no clock division is performed on the input clock inside the AVR (via the
|
||||
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
|
||||
F_USB = $(F_CPU)
|
||||
|
||||
# Interrupt driven control endpoint task(+60)
|
||||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
|
||||
|
||||
|
||||
# Boot Section Size in *bytes*
|
||||
# Teensy halfKay 512
|
||||
# Teensy++ halfKay 1024
|
||||
# Atmel DFU loader 4096
|
||||
# LUFA bootloader 4096
|
||||
# USBaspLoader 2048
|
||||
OPT_DEFS += -DBOOTLOADER_SIZE=4096
|
||||
|
||||
|
||||
# Build Options
|
||||
# comment out to disable the options.
|
||||
#
|
||||
#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
|
||||
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
|
||||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
|
||||
CONSOLE_ENABLE = yes # Console for debug(+400)
|
||||
COMMAND_ENABLE = yes # Commands for debug and configuration
|
||||
#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
|
||||
|
||||
|
||||
# Search Path
|
||||
VPATH += $(TARGET_DIR)
|
||||
VPATH += $(TOP_DIR)
|
||||
|
||||
include $(TOP_DIR)/protocol.mk
|
||||
include $(TOP_DIR)/protocol/lufa.mk
|
||||
include $(TOP_DIR)/common.mk
|
||||
include $(TOP_DIR)/rules.mk
|
|
@ -0,0 +1,46 @@
|
|||
IBM 4704 to USB keyboard converter
|
||||
==================================
|
||||
This firmware converts IBM 4704 keyboard protocol to USB HID.
|
||||
|
||||
Keyboard initialization process takes a few seconds at start up. During that you will hear buzzer from the keyboard. **You need to plug USB cable after hooking up your keyboard to the converter.**
|
||||
|
||||
|
||||
4704 Connector
|
||||
--------------
|
||||
Keyboard Plug from front:
|
||||
|
||||
DSUB-9
|
||||
-------------
|
||||
\ N 2 3 4 5 /
|
||||
\ N N N N /
|
||||
---------
|
||||
2 GND
|
||||
3 VCC 5V
|
||||
4 DATA
|
||||
5 CLOCK
|
||||
N No connection/No pin.
|
||||
|
||||
|
||||
Connection
|
||||
----------
|
||||
In case of using ATMega32U4(Teensy2.0):
|
||||
|
||||
1. Supply power with VCC and GND.
|
||||
2. Connect CLOCK to PD1 and DATA to PD0. You can change pin with config.h.
|
||||
3. Optionally you may need pull-up register. 1KOhm probably work.
|
||||
|
||||
|
||||
Build Firmware
|
||||
--------------
|
||||
Just run `make`:
|
||||
|
||||
$ make
|
||||
|
||||
To select keymap:
|
||||
|
||||
$ make KEYMAP=[plain|...]
|
||||
|
||||
|
||||
Keymap
|
||||
------
|
||||
Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `keymap_<name>.c` and see keymap document(you can find in top README.md) and existent keymap files.
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
Copyright 2014 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
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0x4707
|
||||
#define DEVICE_VER 0x0001
|
||||
#define MANUFACTURER t.m.k.
|
||||
#define PRODUCT IBM 4704 keyboard converter
|
||||
#define DESCRIPTION convert IBM 4704 keyboard to USB
|
||||
|
||||
|
||||
/* matrix size */
|
||||
#define MATRIX_ROWS 16 // keycode bit3-6
|
||||
#define MATRIX_COLS 8 // keycode bit0-2
|
||||
|
||||
|
||||
/* key combination for command */
|
||||
#define IS_COMMAND() ( \
|
||||
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
|
||||
)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Busywait
|
||||
*/
|
||||
#define IBM4704_CLOCK_PORT PORTD
|
||||
#define IBM4704_CLOCK_PIN PIND
|
||||
#define IBM4704_CLOCK_DDR DDRD
|
||||
#define IBM4704_CLOCK_BIT 1
|
||||
#define IBM4704_DATA_PORT PORTD
|
||||
#define IBM4704_DATA_PIN PIND
|
||||
#define IBM4704_DATA_DDR DDRD
|
||||
#define IBM4704_DATA_BIT 0
|
||||
|
||||
/*
|
||||
* Pin interrupt
|
||||
*/
|
||||
#ifdef IBM4704_USE_INT
|
||||
#define IBM4704_INT_INIT() do { \
|
||||
EICRA |= ((1<<ISC11) | \
|
||||
(0<<ISC10)); \
|
||||
} while (0)
|
||||
#define IBM4704_INT_ON() do { \
|
||||
EIMSK |= (1<<INT1); \
|
||||
} while (0)
|
||||
#define IBM4704_INT_OFF() do { \
|
||||
EIMSK &= ~(1<<INT1); \
|
||||
} while (0)
|
||||
#define IBM4704_INT_VECT INT1_vect
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,160 @@
|
|||
4704 Keyboard
|
||||
=============
|
||||
Keyboard Models:
|
||||
Model 100 6019273 50-key (grid layout)
|
||||
Model 200 6019284 62-key Alpha(60% layout)
|
||||
Model 300 6019303 77-key Expanded Alpha
|
||||
Model 400 6020218 107-key Full key
|
||||
|
||||
Resourse
|
||||
--------
|
||||
The IBM 4704: lots of pictures and info
|
||||
http://kishy.dyndns.org/?p=648#more-648
|
||||
|
||||
Brochure:
|
||||
http://ed-thelen.org/comp-hist/IBM-ProdAnn/4700.pdf
|
||||
|
||||
|
||||
|
||||
4704 Keyboard Protocol
|
||||
======================
|
||||
On powering up the keyboard sends keyboard id; A3h for 6019284(62-key), for example.
|
||||
After that firmware enters FC command mode and waits for parameter data from host
|
||||
so that it doesn't send any scancode until you send 'FF'(End of FC command).
|
||||
|
||||
|
||||
Connector
|
||||
---------
|
||||
Keyboard Plug from front
|
||||
|
||||
DSUB-9
|
||||
-------------
|
||||
\ N 2 3 4 5 /
|
||||
\ N N N N /
|
||||
---------
|
||||
2 GND
|
||||
3 VCC 5V
|
||||
4 DATA
|
||||
5 CLOCK
|
||||
N No connection/No pin.
|
||||
|
||||
|
||||
Keyboard to Host
|
||||
----------------
|
||||
Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
|
||||
|
||||
____ __ __ __ __ __ __ __ __ __ ________
|
||||
Clock \____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
|
||||
____ ____ ____ ____ ____ ____ ____ ____ ____ ____
|
||||
Data ____/ X____X____X____X____X____X____X____X____X____X________
|
||||
Start 0 1 2 3 4 5 6 7 P Stop
|
||||
|
||||
Start bit: can be long as 300-350us.
|
||||
Inhibit: Pull Data line down to inhibit keyboard to send.
|
||||
Timing: Host reads bit while Clock is hi.
|
||||
Stop bit: Keyboard pulls down Data line to lo after 9th clock.
|
||||
|
||||
|
||||
Host to Keyboard
|
||||
----------------
|
||||
Data bits are LSB first and Pairty is odd. Clock has around 60us high and 30us low part.
|
||||
|
||||
____ __ __ __ __ __ __ __ __ __ ________
|
||||
Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
|
||||
^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
|
||||
Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
|
||||
| Start 0 1 2 3 4 5 6 7 P Stop
|
||||
Request by host
|
||||
|
||||
Start bit: can be long as 300-350us.
|
||||
Request: Host pulls Clock line down to request to send a command.
|
||||
Timing: After Request keyboard pull up Data and down Clock line to low for start bit.
|
||||
After request host release Clock line once Data line becomes hi.
|
||||
Host wirtes a bit while Clock is hi and Keyboard reads while low.
|
||||
Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keybaord pull down the line to lo.
|
||||
|
||||
|
||||
Scancodes
|
||||
---------
|
||||
Keyboard doesn't send Break code for all keys except for Alt by default.
|
||||
|
||||
6019284 62-key:
|
||||
,-----------------------------------------------------------.
|
||||
| `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|???|BS |
|
||||
|-----------------------------------------------------------|
|
||||
|Tab | Q| W| E| R| T| Y| U| I| O| P| ¢| \| PD2|
|
||||
|-----------------------------------------------------------|
|
||||
|Ctrl | A| S| D| F| G| H| J| K| L| ;| '| {}| PD3|
|
||||
|-----------------------------------------------------------|
|
||||
|Shif| <>| Z| X| C| V| B| N| M| ,| ,| /|???|Shift |
|
||||
|-----------------------------------------------------------|
|
||||
|Reset|blk|Alt | Space |Alt |blk|Enter|
|
||||
`-----------------------------------------------------------'
|
||||
+----------+---------------------+----------+----------+
|
||||
|` 00|PD1 04|Caps 20|LShift 30|Reset 31|
|
||||
|1 18|q 05|a 21|<> 3E|Rblank 41|
|
||||
|2 19|w 06|s 22|z 32|Alt 3F|
|
||||
|3 1A|e 13|d 23|x 33|Space 40|
|
||||
|4 10|r 14|f 24|c 34|Alt 3F|
|
||||
|5 11|t 15|g 25|v 35|Lblank 42|
|
||||
|6 12|y 16|h 26|b 36|Enter 2F|
|
||||
|7 08|u 17|j 27|n 37| |
|
||||
|8 09|i 01|k 28|m 38| |
|
||||
|9 0A|o 02|l 29|, 39| |
|
||||
|0 0F|p 03|; 2A|. 3A| |
|
||||
|- 1F|¢ 1B|' 2B|/ 3B| |
|
||||
|= 0D|\ 1C|{} 2C|??? 3C| |
|
||||
|??? 0C|PD2 1D|PD3 2D|RShift 3D| |
|
||||
|BS 0E| | | | |
|
||||
+----------+---------------------+----------+----------+
|
||||
Bit7 is 'press flag' which set 1 on press and 0 on release when break code is enabled.
|
||||
|
||||
NOTE: When break code is enabled the key sends scancode with setting 7th bit on press
|
||||
and without it on release. That is, '`' sends 80h on press and 00h on release.
|
||||
|
||||
|
||||
keyboard command
|
||||
----------------
|
||||
FF Soft Reset(0008h)
|
||||
FE Resend(00e8h)
|
||||
FD Buzzer stop?(00edh)
|
||||
FC Set Key flag(00f6h)
|
||||
FB Soft Reset(0008h)
|
||||
FA Reset(0000h)
|
||||
|
||||
|
||||
Keyboard response
|
||||
-----------------
|
||||
FF Not exist. [Outgoing buffer cannot have FFh(00h in fact)]
|
||||
FE Overflow(key event/receive data) at 00c5h, 0346h
|
||||
FE Memory test error at 0224h
|
||||
FD Command out of bound at 00d8h
|
||||
Key out of bound
|
||||
7E Read/Parity error in receive from host at 00bch
|
||||
|
||||
|
||||
Set Key flag command(FC)
|
||||
------------------------
|
||||
After 'Power on Reset' firmware enters this command mode and waits for data from host,
|
||||
so that you don't need to send 'FC' and it doesn't send any scancode until you send 'FF'.
|
||||
|
||||
Data sent from host:
|
||||
|
||||
bit: 7 6 ... 0
|
||||
en | |
|
||||
| `-----`--- scan code
|
||||
`------------- enable bit(0: enable repeat, 1: enable break)
|
||||
|
||||
00-77 Enable repeat(78-7F: invalid scancode)
|
||||
80-F7 Enable break(F8-FF: invalid scancode)
|
||||
FE Resend(011ah) no need to use
|
||||
FF End(0114h) exits FC command mode.
|
||||
|
||||
Response from keyboard:
|
||||
FD Out of bound - Invalid scancode
|
||||
|
||||
Examples:
|
||||
To enable break code of all keys.
|
||||
|
||||
FC 80 81 ... F7 FF
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
Copyright 2011,2012,2013 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 "keymap_common.h"
|
||||
|
||||
|
||||
/* translates key to keycode */
|
||||
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
|
||||
{
|
||||
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
|
||||
}
|
||||
|
||||
/* translates Fn keycode to action */
|
||||
action_t keymap_fn_to_action(uint8_t keycode)
|
||||
{
|
||||
return (action_t){ .code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]) };
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
Copyright 2011,2012,2013 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 KEYMAP_COMMON_H
|
||||
#define KEYMAP_COMMON_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "keycode.h"
|
||||
#include "action.h"
|
||||
#include "action_macro.h"
|
||||
#include "report.h"
|
||||
#include "print.h"
|
||||
#include "debug.h"
|
||||
#include "keymap.h"
|
||||
|
||||
|
||||
// 32*8(256) byte array which converts PS/2 code into USB code
|
||||
extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
|
||||
extern const uint16_t fn_actions[];
|
||||
|
||||
|
||||
/* Original keys */
|
||||
#define KEYMAP( \
|
||||
K00,K18,K19,K1A,K10,K11,K12,K08,K09,K0A,K0F,K1F,K0D,K0C,K0E, \
|
||||
K04,K05,K06,K13,K14,K15,K16,K17,K01,K02,K03,K1B,K1C,K1D, \
|
||||
K20,K21,K22,K23,K24,K25,K26,K27,K28,K29,K2A,K2B,K2C,K2D, \
|
||||
K30,K3E,K32,K33,K34,K35,K36,K37,K38,K39,K3A,K3B,K3C,K3D, \
|
||||
K31,K41,K3F, K40, K42,K2F \
|
||||
) { \
|
||||
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_NO }, \
|
||||
{ KC_##K08, KC_##K09, KC_##K0A, KC_NO, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F }, \
|
||||
{ KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
|
||||
{ KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_NO, KC_##K1F }, \
|
||||
{ KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \
|
||||
{ KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_NO, KC_##K2F }, \
|
||||
{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \
|
||||
{ KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F }, \
|
||||
{ KC_##K40, KC_##K41, KC_##K42, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
{ K48, K49, K4A, K4B, K4C, K4D, K4E, K4F }, \
|
||||
{ K50, K51, K52, K53, K54, K55, K56, K57 }, \
|
||||
{ K58, K59, K5A, K5B, K5C, K5D, K5E, K5F }, \
|
||||
{ K60, K61, K62, K63, K64, K65, K66, K67 }, \
|
||||
{ K68, K69, K6A, K6B, K6C, K6D, K6E, K6F }, \
|
||||
{ K70, K71, K72, K73, K74, K75, K76, K77 }, \
|
||||
{ K78, K79, K7A, K7B, K7C, K7D, K7E, K7F }, \
|
||||
*/
|
|
@ -0,0 +1,85 @@
|
|||
#include "keymap_common.h"
|
||||
|
||||
|
||||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* 0: default
|
||||
* ,-----------------------------------------------------------.
|
||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|???|BS |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
|
||||
* |-----------------------------------------------------------|
|
||||
* |Ctrl | A| S| D| F| G| H| J| K| L| ;| '|xxx|Ret |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Shif|xxx| Z| X| C| V| B| N| M| ,| ,| /|xxx|Shift |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Ctrl |Gui|Alt | Space |Alt |Gui|Ctrl |
|
||||
* `-----------------------------------------------------------'
|
||||
*/
|
||||
KEYMAP(
|
||||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
|
||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
|
||||
LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT,NO, ENT, \
|
||||
LSFT,NO, Z, X, C, V, B, N, M, COMM,DOT, FN2, NO, FN0, \
|
||||
LCTL,LGUI,LALT, FN3, RGUI,RCTL \
|
||||
),
|
||||
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
|
||||
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS, UP, NO, BSPC, \
|
||||
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,NO, ENT, \
|
||||
LSFT,NO, NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,NO, TRNS, \
|
||||
LCTL,LGUI,LALT, SPC, RGUI,RCTL \
|
||||
),
|
||||
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
|
||||
TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,WSTP,WBAK,WFWD,BSPC, \
|
||||
LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,TRNS,NO, NO, ENT, \
|
||||
LSFT,NO, NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, NO, RSFT,\
|
||||
LCTL,LGUI,LALT, BTN1, RGUI,RCTL \
|
||||
),
|
||||
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
|
||||
TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \
|
||||
LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, NO, ENT, \
|
||||
LSFT,NO, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, TRNS,NO, RSFT, \
|
||||
LCTL,LGUI,LALT, SPC, RGUI,RCTL \
|
||||
),
|
||||
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
|
||||
TAB, NO, NO, NO, NO, NO, WH_L,WH_D,MS_U,WH_U,WH_R,BTN4,BTN5,FN4, \
|
||||
LCTL,VOLD,VOLU,MUTE,NO, NO, BTN2,MS_L,MS_D,MS_R,BTN1,NO, NO, ENT, \
|
||||
LSFT,NO, NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, NO, NO, \
|
||||
LCTL,LGUI,LALT, TRNS, RGUI,RCTL \
|
||||
),
|
||||
};
|
||||
|
||||
enum macro_id {
|
||||
ALT_TAB,
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM fn_actions[] = {
|
||||
[0] = ACTION_LAYER_MOMENTARY(1),
|
||||
[1] = ACTION_LAYER_TAP_KEY(2, KC_SCLN),
|
||||
[2] = ACTION_LAYER_TAP_KEY(3, KC_SLASH),
|
||||
[3] = ACTION_LAYER_TAP_KEY(4, KC_SPC),
|
||||
[4] = ACTION_MACRO(ALT_TAB),
|
||||
};
|
||||
|
||||
/*
|
||||
* Macro definition
|
||||
*/
|
||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
||||
{
|
||||
keyevent_t event = record->event;
|
||||
|
||||
switch (id) {
|
||||
case ALT_TAB:
|
||||
return (event.pressed ?
|
||||
MACRO( D(LALT), D(TAB), END ) :
|
||||
MACRO( U(TAB), END ));
|
||||
}
|
||||
return MACRO_NONE;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#include "keymap_common.h"
|
||||
|
||||
|
||||
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* 0: default
|
||||
* ,-----------------------------------------------------------.
|
||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|???|BS |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
|
||||
* |-----------------------------------------------------------|
|
||||
* |Ctrl | A| S| D| F| G| H| J| K| L| ;| '| #|Ret |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Shif| \| Z| X| C| V| B| N| M| ,| ,| /|???|Shift |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Ctrl |Gui|Alt | Space |Alt* |Gui|Ctrl |
|
||||
* `-----------------------------------------------------------'
|
||||
*/
|
||||
KEYMAP(
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,BSPC, \
|
||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
|
||||
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,NUHS,ENT, \
|
||||
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, FN0, \
|
||||
LCTL,LGUI,LALT, SPC, RGUI,RCTL \
|
||||
),
|
||||
|
||||
/* 1: HHKB */
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
|
||||
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS, UP, NO, INS, \
|
||||
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,NO, ENT, \
|
||||
LSFT,NO, NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,NO, TRNS, \
|
||||
LCTL,LGUI,LALT, SPC, RGUI,RCTL \
|
||||
),
|
||||
};
|
||||
|
||||
const uint16_t PROGMEM fn_actions[] = {
|
||||
[0] = ACTION_LAYER_MOMENTARY(1),
|
||||
};
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
Copyright 2014 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 <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include "action.h"
|
||||
#include "print.h"
|
||||
#include "debug.h"
|
||||
#include "util.h"
|
||||
#include "ibm4704.h"
|
||||
#include "matrix.h"
|
||||
|
||||
|
||||
static void matrix_make(uint8_t code);
|
||||
static void matrix_break(uint8_t code);
|
||||
static void matrix_clear(void);
|
||||
|
||||
|
||||
/*
|
||||
* Matrix Array usage:
|
||||
* IBM 4704 scan codes are assigned into 128(16x8)-cell matrix.
|
||||
*
|
||||
* 8bit wide
|
||||
* +---------+
|
||||
* 0| |
|
||||
* :| XX | 00-7F
|
||||
* f| |
|
||||
* +---------+
|
||||
*
|
||||
* Exceptions:
|
||||
*/
|
||||
static uint8_t matrix[MATRIX_ROWS];
|
||||
|
||||
// scan code bits 7654 3210
|
||||
// R:row/C:column -RRR RCCC
|
||||
#define ROW(code) ((code>>3)&0x0f)
|
||||
#define COL(code) (code&0x07)
|
||||
|
||||
|
||||
inline
|
||||
uint8_t matrix_rows(void)
|
||||
{
|
||||
return MATRIX_ROWS;
|
||||
}
|
||||
|
||||
inline
|
||||
uint8_t matrix_cols(void)
|
||||
{
|
||||
return MATRIX_COLS;
|
||||
}
|
||||
|
||||
static void enable_break(void)
|
||||
{
|
||||
uint8_t ret;
|
||||
print("Enable break: ");
|
||||
// valid scancode: 00-77h
|
||||
for (uint8_t code = 0; code < 0x78; code++) {
|
||||
while (ibm4704_send(0x80|code) != 0) {
|
||||
print("z");
|
||||
_delay_us(500);
|
||||
}
|
||||
_delay_us(2000);
|
||||
ret = ibm4704_recv();
|
||||
if (ret != 0xff) {
|
||||
xprintf("c%02X:r%02X ", code, ret);
|
||||
}
|
||||
_delay_us(1000);
|
||||
}
|
||||
_delay_us(1000);
|
||||
while (ibm4704_send(0xFF) != 0) { _delay_us(500); } // End
|
||||
print("End\n");
|
||||
}
|
||||
|
||||
void matrix_init(void)
|
||||
{
|
||||
uint8_t ret;
|
||||
debug_enable = true;
|
||||
|
||||
ibm4704_init();
|
||||
matrix_clear();
|
||||
|
||||
// read keyboard id
|
||||
while ((ret = ibm4704_recv()) == 0xFF) {
|
||||
ibm4704_send(0xFE);
|
||||
_delay_us(100);
|
||||
}
|
||||
|
||||
_delay_ms(2000); // wait for starting up debug console
|
||||
print("IBM 4704 converter\n");
|
||||
xprintf("Keyboard ID: %02X\n", ret);
|
||||
enable_break();
|
||||
}
|
||||
|
||||
/*
|
||||
* IBM 4704 Scan Code
|
||||
*/
|
||||
uint8_t matrix_scan(void)
|
||||
{
|
||||
uint8_t code = ibm4704_recv();
|
||||
if (code==0xFF) {
|
||||
// Not receivd
|
||||
return 0;
|
||||
} else if ((code&0x78)==0x78) {
|
||||
// 0xFF-F8 and 0x7F-78 is not scancode
|
||||
xprintf("Error: %0X\n", code);
|
||||
matrix_clear();
|
||||
return 0;
|
||||
} else if (code&0x80) {
|
||||
matrix_make(code);
|
||||
} else {
|
||||
matrix_break(code);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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++) {
|
||||
xprintf("%02X: %08b\n", row, bitrev(matrix_get_row(row)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline
|
||||
static void matrix_make(uint8_t code)
|
||||
{
|
||||
matrix[ROW(code)] |= 1<<COL(code);
|
||||
}
|
||||
|
||||
inline
|
||||
static void matrix_break(uint8_t code)
|
||||
{
|
||||
matrix[ROW(code)] &= ~(1<<COL(code));
|
||||
}
|
||||
|
||||
inline
|
||||
static void matrix_clear(void)
|
||||
{
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <util/delay.h>
|
||||
#include "debug.h"
|
||||
#include "ibm4704.h"
|
||||
|
||||
|
||||
#define WAIT(stat, us, err) do { \
|
||||
if (!wait_##stat(us)) { \
|
||||
ibm4704_error = err; \
|
||||
goto ERROR; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
uint8_t ibm4704_error = 0;
|
||||
|
||||
|
||||
void ibm4704_init(void)
|
||||
{
|
||||
inhibit();
|
||||
}
|
||||
|
||||
/*
|
||||
Host to Keyboard
|
||||
----------------
|
||||
Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
|
||||
|
||||
____ __ __ __ __ __ __ __ __ __ ________
|
||||
Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
|
||||
^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
|
||||
Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
|
||||
| Start 0 1 2 3 4 5 6 7 P Stop
|
||||
Request by host
|
||||
|
||||
Start bit: can be long as 300-350us.
|
||||
Request: Host pulls Clock line down to request to send a command.
|
||||
Timing: After Request keyboard pull up Data and down Clock line to low for start bit.
|
||||
After request host release Clock line once Data line becomes hi.
|
||||
Host writes a bit while Clock is hi and Keyboard reads while low.
|
||||
Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo.
|
||||
*/
|
||||
uint8_t ibm4704_send(uint8_t data)
|
||||
{
|
||||
bool parity = true; // odd parity
|
||||
ibm4704_error = 0;
|
||||
|
||||
/* Request to send */
|
||||
idle();
|
||||
clock_lo();
|
||||
|
||||
/* wait for Start bit(Clock:lo/Data:hi) */
|
||||
WAIT(data_hi, 300, 0x30);
|
||||
|
||||
/* Data bit */
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
WAIT(clock_hi, 100, 0x40+i);
|
||||
//_delay_us(5);
|
||||
if (data&(1<<i)) {
|
||||
parity = !parity;
|
||||
data_hi();
|
||||
} else {
|
||||
data_lo();
|
||||
}
|
||||
WAIT(clock_lo, 100, 0x48+i);
|
||||
}
|
||||
|
||||
/* Parity bit */
|
||||
WAIT(clock_hi, 100, 0x34);
|
||||
if (parity) { data_hi(); } else { data_lo(); }
|
||||
WAIT(clock_lo, 100, 0x35);
|
||||
|
||||
/* Stop bit */
|
||||
WAIT(clock_hi, 100, 0x34);
|
||||
data_hi();
|
||||
|
||||
/* End */
|
||||
WAIT(data_lo, 100, 0x36);
|
||||
|
||||
inhibit();
|
||||
_delay_us(200); // wait to recover clock to hi
|
||||
return 0;
|
||||
ERROR:
|
||||
inhibit();
|
||||
if (ibm4704_error >= 0x30) {
|
||||
xprintf("x%02X ", ibm4704_error);
|
||||
}
|
||||
_delay_us(200); // wait to recover clock to hi
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* receive data when host want else inhibit communication */
|
||||
uint8_t ibm4704_recv_response(void)
|
||||
{
|
||||
// 250 * 100us(wait start bit in ibm4704_recv)
|
||||
uint8_t data = 0;
|
||||
uint8_t try = 250;
|
||||
do {
|
||||
data = ibm4704_recv();
|
||||
} while (try-- && ibm4704_error);
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
Keyboard to Host
|
||||
----------------
|
||||
Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
|
||||
|
||||
____ __ __ __ __ __ __ __ __ __ ________
|
||||
Clock \____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
|
||||
____ ____ ____ ____ ____ ____ ____ ____ ____ ____
|
||||
Data ____/ X____X____X____X____X____X____X____X____X____X________
|
||||
Start 0 1 2 3 4 5 6 7 P Stop
|
||||
|
||||
Start bit: can be long as 300-350us.
|
||||
Inhibit: Pull Data line down to inhibit keyboard to send.
|
||||
Timing: Host reads bit while Clock is hi.
|
||||
Stop bit: Keyboard pulls down Data line to lo after 9th clock.
|
||||
*/
|
||||
uint8_t ibm4704_recv(void)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
bool parity = true; // odd parity
|
||||
ibm4704_error = IBM4704_ERR_NONE;
|
||||
|
||||
idle();
|
||||
_delay_us(5); // wait for line settles
|
||||
|
||||
/* start bit */
|
||||
WAIT(clock_lo, 100, 0x11); // wait for keyboard to send
|
||||
WAIT(data_hi, 100, 0x12); // can be delayed that long
|
||||
|
||||
WAIT(clock_hi, 100, 0x13); // first rising edge which can take longer
|
||||
/* data */
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
WAIT(clock_hi, 100, 0x20+i);
|
||||
//_delay_us(5);
|
||||
if (data_in()) {
|
||||
parity = !parity;
|
||||
data |= (1<<i);
|
||||
}
|
||||
WAIT(clock_lo, 150, 0x28+i);
|
||||
}
|
||||
|
||||
/* parity */
|
||||
WAIT(clock_hi, 100, 0x17);
|
||||
if (data_in() != parity) {
|
||||
ibm4704_error = IBM4704_ERR_PARITY;
|
||||
goto ERROR;
|
||||
}
|
||||
WAIT(clock_lo, 150, 0x18);
|
||||
|
||||
/* stop bit */
|
||||
WAIT(clock_hi, 100, 0x19);
|
||||
WAIT(data_lo, 1, 0x19);
|
||||
|
||||
inhibit();
|
||||
_delay_us(200); // wait to recover clock to hi
|
||||
return data;
|
||||
ERROR:
|
||||
if (ibm4704_error > 0x12) {
|
||||
xprintf("x%02X ", ibm4704_error);
|
||||
}
|
||||
inhibit();
|
||||
_delay_us(200); // wait to recover clock to hi
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright 2014 Jun WAKO <wakojun@gmail.com>
|
||||
*/
|
||||
#ifndef IBM4704_H
|
||||
#define IBM4704_H
|
||||
|
||||
#define IBM4704_ERR_NONE 0
|
||||
#define IBM4704_ERR_PARITY 0x70
|
||||
|
||||
|
||||
void ibm4704_init(void);
|
||||
uint8_t ibm4704_send(uint8_t data);
|
||||
uint8_t ibm4704_recv_response(void);
|
||||
uint8_t ibm4704_recv(void);
|
||||
|
||||
|
||||
/* Check pin configuration */
|
||||
#if !(defined(IBM4704_CLOCK_PORT) && \
|
||||
defined(IBM4704_CLOCK_PIN) && \
|
||||
defined(IBM4704_CLOCK_DDR) && \
|
||||
defined(IBM4704_CLOCK_BIT))
|
||||
# error "ibm4704 clock pin configuration is required in config.h"
|
||||
#endif
|
||||
|
||||
#if !(defined(IBM4704_DATA_PORT) && \
|
||||
defined(IBM4704_DATA_PIN) && \
|
||||
defined(IBM4704_DATA_DDR) && \
|
||||
defined(IBM4704_DATA_BIT))
|
||||
# error "ibm4704 data pin configuration is required in config.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* static functions
|
||||
*------------------------------------------------------------------*/
|
||||
static inline void clock_lo(void)
|
||||
{
|
||||
IBM4704_CLOCK_PORT &= ~(1<<IBM4704_CLOCK_BIT);
|
||||
IBM4704_CLOCK_DDR |= (1<<IBM4704_CLOCK_BIT);
|
||||
}
|
||||
static inline void clock_hi(void)
|
||||
{
|
||||
/* input with pull up */
|
||||
IBM4704_CLOCK_DDR &= ~(1<<IBM4704_CLOCK_BIT);
|
||||
IBM4704_CLOCK_PORT |= (1<<IBM4704_CLOCK_BIT);
|
||||
}
|
||||
static inline bool clock_in(void)
|
||||
{
|
||||
IBM4704_CLOCK_DDR &= ~(1<<IBM4704_CLOCK_BIT);
|
||||
IBM4704_CLOCK_PORT |= (1<<IBM4704_CLOCK_BIT);
|
||||
_delay_us(1);
|
||||
return IBM4704_CLOCK_PIN&(1<<IBM4704_CLOCK_BIT);
|
||||
}
|
||||
static inline void data_lo(void)
|
||||
{
|
||||
IBM4704_DATA_PORT &= ~(1<<IBM4704_DATA_BIT);
|
||||
IBM4704_DATA_DDR |= (1<<IBM4704_DATA_BIT);
|
||||
}
|
||||
static inline void data_hi(void)
|
||||
{
|
||||
/* input with pull up */
|
||||
IBM4704_DATA_DDR &= ~(1<<IBM4704_DATA_BIT);
|
||||
IBM4704_DATA_PORT |= (1<<IBM4704_DATA_BIT);
|
||||
}
|
||||
static inline bool data_in(void)
|
||||
{
|
||||
IBM4704_DATA_DDR &= ~(1<<IBM4704_DATA_BIT);
|
||||
IBM4704_DATA_PORT |= (1<<IBM4704_DATA_BIT);
|
||||
_delay_us(1);
|
||||
return IBM4704_DATA_PIN&(1<<IBM4704_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;
|
||||
}
|
||||
|
||||
/* idle state that device can send */
|
||||
static inline void idle(void)
|
||||
{
|
||||
clock_hi();
|
||||
data_hi();
|
||||
}
|
||||
|
||||
/* inhibit device to send
|
||||
* keyboard checks Data line on start bit(Data:hi) and it stops sending if Data line is low.
|
||||
*/
|
||||
static inline void inhibit(void)
|
||||
{
|
||||
clock_hi();
|
||||
data_lo();
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue