#include <stdint.h> | #include <stdint.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include "usb_keycodes.h" | |||||
/* keycode in specific layer */ | /* keycode in specific layer */ |
#include "host.h" | #include "host.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "timer.h" | #include "timer.h" | ||||
#include "usb_keycodes.h" | |||||
#include "layer.h" | #include "layer.h" | ||||
static inline uint16_t wait_data_hi(uint16_t us); | static inline uint16_t wait_data_hi(uint16_t us); | ||||
static inline void idle(void); | static inline void idle(void); | ||||
static inline void inhibit(void); | static inline void inhibit(void); | ||||
#if defined PS2_USE_INT || defined PS2_USE_USART | |||||
static inline uint8_t pbuf_dequeue(void); | static inline uint8_t pbuf_dequeue(void); | ||||
static inline void pbuf_enqueue(uint8_t data); | static inline void pbuf_enqueue(uint8_t data); | ||||
#endif | |||||
void ps2_host_init(void) | void ps2_host_init(void) |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = ps2_usb_pjrc_usart | |||||
# Directory common source filess exist | |||||
COMMON_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
ps2_usart.c | |||||
CONFIG_H = config_pjrc_usart.h | |||||
# MCU name, you MUST set this to match the board you are using | |||||
# type "make clean" after changing this, so all files will be rebuilt | |||||
#MCU = at90usb162 # Teensy 1.0 | |||||
MCU = atmega32u4 # Teensy 2.0 | |||||
#MCU = at90usb646 # Teensy++ 1.0 | |||||
#MCU = at90usb1286 # Teensy++ 2.0 | |||||
# Processor frequency. | |||||
# Normally the first thing your program should do is set the clock prescaler, | |||||
# so your program will run at the correct speed. You should also set this | |||||
# variable to same clock speed. The _delay_ms() macro uses this, and many | |||||
# examples use this variable to calculate timings. Do not add a "UL" here. | |||||
F_CPU = 16000000 | |||||
# Build Options | |||||
# *Comment out* to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(COMMON_DIR)/pjrc.mk | |||||
include $(COMMON_DIR)/common.mk |
PS/2 to USB keyboard converter | PS/2 to USB keyboard converter | ||||
============================== | ============================== | ||||
This firmware converts PS/2 keyboard protocol to USB and for now supports only Scan Code Set 2. | This firmware converts PS/2 keyboard protocol to USB and for now supports only Scan Code Set 2. | ||||
This will works on USB AVR(ATMega32U4, AT90USB) or V-USB. | |||||
Features | Features | ||||
-------- | -------- | ||||
Mouse keys | Mouse keys | ||||
You can emulates mouse move and button click using keyboard. | You can emulates mouse move and button click using keyboard. | ||||
System/Media control | System/Media control | ||||
You can sends Power event, Volume down/up and Mute. | You can sends Power event, Volume down/up and Mute. | ||||
USB NKRO(actually 120KRO+8Modifiers) | USB NKRO(actually 120KRO+8Modifiers) | ||||
You can tolggles NKRO feature. | You can tolggles NKRO feature. | ||||
Keymap customization | Keymap customization | ||||
You can customize keymaps easily by editing source code. See keymap.c. | You can customize keymaps easily by editing source code. See keymap.c. | ||||
PS/2 signal handling implementations | |||||
------------------------------------ | |||||
Following three methods are used to implement PS/2 signal handling. | |||||
a. Simple and stupid wait & read loop(intensive use of cycles) | |||||
This is implemented with (expected) portable C code for reference. See ps2.c. | |||||
b. Interrupt driven | |||||
See ps2_intr.c | |||||
c. Using USART hardware module(no cycle needed) | |||||
This uses AVR USART function to recevie PS/2 signal and be used in V-USB converter. | |||||
See ps2_usart.c. | |||||
Build Converter | Build Converter | ||||
--------------- | --------------- | ||||
0. Connect PS/2 keyboard into Teensy with 4 lines(Vcc, GND, Data, Clock). | |||||
By default Clock is on PF0 and Data on PF1. | |||||
You can change this pin configuration by editing config_pjrc.h. | |||||
In this photo Vcc is yellow, GND is green, Data is red and Clock is black. | |||||
http://img17.imageshack.us/img17/7243/201101181933.jpg | |||||
Connect PS/2 keyboard into Teensy with 4 lines(Vcc, GND, Data, Clock). | |||||
For a. Simple and stupid and b. Interrupt implementaion: | |||||
By default Clock is on PF0 and Data on PF1. | |||||
You can change this pin configuration by editing config_pjrc.h. | |||||
In this photo Vcc is yellow, GND is green, Data is red and Clock is black. | |||||
http://img17.imageshack.us/img17/7243/201101181933.jpg | |||||
For c. USART implementation: | |||||
In case of Teensny(ATMega32u4) CLock is on PD2 and Data on PD5. | |||||
Build Frimware | Build Frimware | ||||
-------------- | -------------- | ||||
1. Edit Makefile for build options and MCU setting. | 1. Edit Makefile for build options and MCU setting. | ||||
Use 'atmega32u4' for Teensy 2.0 or 'at90usb1286' for Teensy++ 2.0. | |||||
Use 'atmega32u4' for Teensy 2.0 or 'at90usb1286' for Teensy++ 2.0. | |||||
2. make | 2. make | ||||
Just type 'make' in a terminal. | |||||
Just type 'make' in a terminal. | |||||
Use '-f Makefile.pjrc_intr' option to use b. Interrupt. | |||||
Use '-f Makefile.pjrc_usart' option to use c. USART. | |||||
Use '-f Makefile.vusb' option to build V-USB converter. | |||||
3. program with Teensy Loader. | 3. program with Teensy Loader. | ||||
http://www.pjrc.com/teensy/loader.html | |||||
http://www.pjrc.com/teensy/loader.html | |||||
Demonstration of Features | Demonstration of Features | ||||
), | ), | ||||
Multimedia keys | |||||
--------------- | |||||
Following lists PS/2 special keys supported by Windows. | |||||
http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx | |||||
Key PS/2(Set2) HID | |||||
--------------------------------------------------- | |||||
System Power E0 37 01 0081 | |||||
System Sleep E0 3F 01 0082 | |||||
System Wake E0 5E 01 0083 | |||||
System Mute E0 23 0C 00E2 | |||||
Volume Up E0 32 0C 00E9 | |||||
Volume Down E0 21 0C 00EA | |||||
Scan Next Track E0 4D 0C 00B5 | |||||
Scan Previous Track E0 15 0C 00B6 | |||||
Stop E0 3B 0C 00B7 | |||||
Play/Pause E0 34 0C 00CD | |||||
Media Select E0 50 0C 0183 | |||||
Mail E0 48 0C 018A | |||||
Calculator E0 2B 0C 0192 | |||||
My Computer E0 40 0C 0194 | |||||
WWW Search E0 10 0C 0221 | |||||
WWW Home E0 3A 0C 0223 | |||||
WWW Back E0 38 0C 0224 | |||||
WWW Forward E0 30 0C 0225 | |||||
WWW Stop E0 28 0C 0226 | |||||
WWW Refresh E0 20 0C 0227 | |||||
WWW Favorites E0 18 0C 022A | |||||
EOF | EOF |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x6513 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT PS/2 keyboard converter(USART) | |||||
#define DESCRIPTION convert PS/2 keyboard to USB | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 32 // keycode bit: 3-0 | |||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* PS/2 lines */ | |||||
#define PS2_CLOCK_PORT PORTF | |||||
#define PS2_CLOCK_PIN PINF | |||||
#define PS2_CLOCK_DDR DDRF | |||||
#define PS2_CLOCK_BIT 5 | |||||
#define PS2_DATA_PORT PORTF | |||||
#define PS2_DATA_PIN PINF | |||||
#define PS2_DATA_DDR DDRF | |||||
#define PS2_DATA_BIT 2 | |||||
// synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge | |||||
// set DDR of CLOCK as input to be slave | |||||
#define PS2_USART_INIT() do { \ | |||||
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \ | |||||
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \ | |||||
UCSR1C = ((1 << UMSEL10) | \ | |||||
(3 << UPM10) | \ | |||||
(0 << USBS1) | \ | |||||
(3 << UCSZ10) | \ | |||||
(0 << UCPOL1)); \ | |||||
UCSR1A = 0; \ | |||||
UBRR1H = 0; \ | |||||
UBRR1L = 0; \ | |||||
} while (0) | |||||
#define PS2_USART_RX_INT_ON() do { \ | |||||
UCSR1B = ((1 << RXCIE1) | \ | |||||
(1 << RXEN1)); \ | |||||
} while (0) | |||||
#define PS2_USART_RX_POLL_ON() do { \ | |||||
UCSR1B = (1 << RXEN1); \ | |||||
} while (0) | |||||
#define PS2_USART_OFF() do { \ | |||||
UCSR1C = 0; \ | |||||
UCSR1B &= ~((1 << RXEN1) | \ | |||||
(1 << TXEN1)); \ | |||||
} while (0) | |||||
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1)) | |||||
#define PS2_USART_RX_DATA UDR1 | |||||
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) | |||||
#define PS2_USART_RX_VECT USART1_RX_vect | |||||
#endif |