From 317bdcb59a14ba7ede4504f00f595949178b9389 Mon Sep 17 00:00:00 2001 From: Matt Harlum Date: Sat, 31 Jan 2015 14:59:31 +1100 Subject: [PATCH] Initial Commit --- .gitignore | 8 ++ README.md | 9 ++ license.txt | 16 +++ makefile | 383 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ps2kbd.c | 328 ++++++++++++++++++++++++++++++++++++++++++++ ps2kbd.d | 1 + ps2kbd.h | 58 ++++++++ 7 files changed, 803 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 license.txt create mode 100644 makefile create mode 100644 ps2kbd.c create mode 100644 ps2kbd.d create mode 100644 ps2kbd.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..19ad033 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.sym +*.lss +*.hex +*.elf +*.o +*.lst +*.eep +*.map diff --git a/README.md b/README.md new file mode 100644 index 0000000..99c7048 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +PS2KBD for Atmel ATTINY861 +============== + +This is a simple PS/2 to Ascii converter I wrote for my 6502 based homebrew computer. + +Pin 4 goes high to signal the host that a new character is ready to be read. +Pin 9 is PS/2 CLK +Pin 8 is PS/2 DATA +ASCII Character is written to Port A diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..2b44cb5 --- /dev/null +++ b/license.txt @@ -0,0 +1,16 @@ +PS2KBC, a PS2 Controler implemented on the Atmel ATTINY861. +Copyright (C) 2015 Matt Harlum + +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..ed1010d --- /dev/null +++ b/makefile @@ -0,0 +1,383 @@ +# WinAVR Sample makefile written by Eric B. Weddington, J�rg Wunsch, et al. +# Modified (bringing often-changed options to the top) by Elliot Williams +# Modified (cleaned the code a bit) by Aleksandar (Aleks) Lazarov + +# make all = Make software (hex, elf) +# make clean = Clean out built project files. +# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB). +# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio +# 4.07 or greater). +# make install = Download the hex file to the device, using avrdude. Please +# customize the information regarding the programmer and +# avrdude settings below first! +# make filename.s = Just compile filename.c into the assembler code only +# To rebuild project do "make clean" then "make all". + +# Microcontroller Type +MCU=attiny861 + +# Target file name (without extension). +TARGET = ps2kbd + +# Programming hardware: type `avrdude -c ?` to get a full listing. +AVRDUDE_PROGRAMMER = usbasp + +# Port to which the programmer is connected +#AVRDUDE_PORT = /dev/tty.usbmodem1411 + +############# Don't need to change below here for most purposes (Elliot) + +# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPT = s + +# Output format. (can be srec, ihex, binary) +FORMAT = ihex + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c + +# If there is more than one source file, append them above, or modify and +# uncomment the following: +#SRC += foo.c bar.c + +# You can also wrap lines by appending a backslash to the end of the line: +#SRC += baz.c \ +#xyzzy.c + + + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. +ASRC = + + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +EXTRAINCDIRS = + + +# Optional compiler flags. +# -g: generate debugging information (for GDB, or for COFF conversion) +# -O*: optimization level +# -f...: tuning, see gcc manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -ahlms: create assembler listing +CFLAGS = -g -O$(OPT) \ +-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \ +-Wall -Wstrict-prototypes \ +-Wa,-adhlns=$(<:.c=.lst) \ +$(patsubst %,-I%,$(EXTRAINCDIRS)) + + +# Set a "language standard" compiler flag. +# Unremark just one line below to set the language standard to use. +# gnu99 = C99 + GNU extensions. See GCC manual for more information. +#CFLAGS += -std=c89 +#CFLAGS += -std=gnu89 +#CFLAGS += -std=c99 +CFLAGS += -std=gnu99 + + + +# Optional assembler flags. +# -Wa,...: tell GCC to pass this to the assembler. +# -ahlms: create listing +# -gstabs: have the assembler create line number information; note that +# for use in COFF files, additional information about filenames +# and function names needs to be present in the assembler source +# files -- see avr-libc docs [FIXME: not yet described there] +ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs + + + +# Optional linker flags. +# -Wl,...: tell GCC to pass this to linker. +# -Map: create map file +# --cref: add cross reference to map file +LDFLAGS = -Wl,-Map=$(TARGET).map,--cref + + + +# Additional libraries + +# Minimalistic printf version +#LDFLAGS += -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires -lm below) +#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt + +# -lm = math library +LDFLAGS += -lm + + +# Programming support using avrdude. Settings and variables. + + +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + +#AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER) +# Uncomment the following if you are using arduino (or any other programmer +# that needs custom baud rate) as a programmer. +#AVRDUDE_FLAGS += -b 19200 + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE += -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_FLAGS += -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See +# to submit bug reports. +AVRDUDE_FLAGS += -v -v + +#Run while cable attached or don't +#AVRDUDE_FLAGS += -E reset #keep chip disabled while cable attached +#AVRDUDE_FLAGS += -E noreset + +#AVRDUDE_WRITE_FLASH = -U lfuse:w:0x04:m #run with 8 Mhz clock + +#AVRDUDE_WRITE_FLASH = -U lfuse:w:0x21:m #run with 1 Mhz clock #default clock mode + +#AVRDUDE_WRITE_FLASH = -U lfuse:w:0x01:m #run with 1 Mhz clock no start up time + +# --------------------------------------------------------------------------- + + +# Define programs and commands. +SHELL = bash +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size + + +# Programming support using avrdude. +AVRDUDE = avrdude + + +REMOVE = rm -f +COPY = cp + +HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex +ELFSIZE = $(SIZE) -A $(TARGET).elf + + + +# Define Messages +# English +MSG_ERRORS_NONE = Errors: none +MSG_BEGIN = -------- begin -------- +MSG_END = -------- end -------- +MSG_SIZE_BEFORE = Size before: +MSG_SIZE_AFTER = Size after: +MSG_COFF = Converting to AVR COFF: +MSG_EXTENDED_COFF = Converting to AVR Extended COFF: +MSG_FLASH = Creating load file for Flash: +MSG_EEPROM = Creating load file for EEPROM: +MSG_EXTENDED_LISTING = Creating Extended Listing: +MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling: +MSG_ASSEMBLING = Assembling: +MSG_CLEANING = Cleaning project: + + + + +# Define all object files. +OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) + +# Define all listing files. +LST = $(ASRC:.S=.lst) $(SRC:.c=.lst) + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + + +# Default target: make program! +all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \ + $(TARGET).lss $(TARGET).sym sizeafter finished end + + +# writeflash: $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + +# Eye candy. +# AVR Studio 3.x does not check make's exit code but relies on +# the following magic strings to be generated by the compile job. +begin: + @echo + @echo $(MSG_BEGIN) + +finished: + @echo $(MSG_ERRORS_NONE) + +end: + @echo $(MSG_END) + @echo + + +# Display size of file. +sizebefore: + @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi + +sizeafter: + @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi + + + +# Display compiler version information. +gccversion : + @$(CC) --version + + + + +# Convert ELF to COFF for use in debugging / simulating in +# AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ + --change-section-address .data-0x800000 \ + --change-section-address .bss-0x800000 \ + --change-section-address .noinit-0x800000 \ + --change-section-address .eeprom-0x810000 + + +coff: $(TARGET).elf + @echo + @echo $(MSG_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-avr $< $(TARGET).cof + + +extcoff: $(TARGET).elf + @echo + @echo $(MSG_EXTENDED_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof + + + + +# Program the device. +install: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + + + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +%.eep: %.elf + @echo + @echo $(MSG_EEPROM) $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +%.lss: %.elf + @echo + @echo $(MSG_EXTENDED_LISTING) $@ + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +%.sym: %.elf + @echo + @echo $(MSG_SYMBOL_TABLE) $@ + avr-nm -n $< > $@ + + + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo + @echo $(MSG_LINKING) $@ + $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +%.o : %.c + @echo + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +%.s : %.c + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +%.o : %.S + @echo + @echo $(MSG_ASSEMBLING) $< + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + + + + + + +# Target: clean project. +clean: begin clean_list finished end + +clean_list : + @echo + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).hex + $(REMOVE) $(TARGET).eep + $(REMOVE) $(TARGET).obj + $(REMOVE) $(TARGET).cof + $(REMOVE) $(TARGET).elf + $(REMOVE) $(TARGET).map + $(REMOVE) $(TARGET).obj + $(REMOVE) $(TARGET).a90 + $(REMOVE) $(TARGET).sym + $(REMOVE) $(TARGET).lnk + $(REMOVE) $(TARGET).lss + $(REMOVE) $(OBJ) + $(REMOVE) $(LST) + $(REMOVE) $(SRC:.c=.s) + $(REMOVE) $(SRC:.c=.d) + $(REMOVE) *~ + +# Automatically generate C source code dependencies. +# (Code originally taken from the GNU make user manual and modified +# (See README.txt Credits).) +# +# Note that this will work with sh (bash) and sed that is shipped with WinAVR +# (see the SHELL variable defined above). +# This may not work with other shells or other seds. +# +%.d: %.c + set -e; $(CC) -MM $(ALL_CFLAGS) $< \ + | sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \ + [ -s $@ ] || rm -f $@ + + +# Remove the '-' if you want to see the dependency files generated. +-include $(SRC:.c=.d) + + + +# Listing of phony targets. +.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \ + clean clean_list program diff --git a/ps2kbd.c b/ps2kbd.c new file mode 100644 index 0000000..238d4b6 --- /dev/null +++ b/ps2kbd.c @@ -0,0 +1,328 @@ +/* +PS2KBC, a PS2 Controler implemented on the Atmel ATTINY861. +Copyright (C) 2015 Matt Harlum + +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include +#include +#include "ps2kbd.h" +#include + + +// Volatile, declared here because they're used in and out of the ISR +volatile uint8_t rcv_byte = 0; +volatile uint8_t rcv_bitcount = 0; +volatile uint8_t send_bitcount = 0; +volatile uint8_t scancode = 0; +volatile uint8_t strobe = 0 ; +volatile uint8_t ssp = 0; // 0 = Start/ 1 = stop/ 2 = parity +volatile uint8_t sr = 0; // 0 = 0 - Receive, 0 = 1 = Send +volatile uint8_t send_parity = 0; +volatile uint8_t send_byte = 0; +volatile uint8_t parity_errors = 0; // Currently unused but will provide error info to host computer +volatile uint8_t framing_errors = 0; + + +int calc_parity(unsigned parity_x) +{ + // Calculate Odd-Parity of byte needed to send PS/2 Packet + unsigned parity_y; + parity_y = parity_x ^ (parity_x >> 1); + parity_y = parity_y ^ (parity_y >> 2); + parity_y = parity_y ^ (parity_y >> 4); + return parity_y & 1; +} + +void framing_error(uint8_t num) +{ + // Deal with PS/2 Protocol Framing errors. delay for the rest of the packet and clear interrupts generated during the delay. + framing_errors++; + GIMSK &= ~(1 << INT0); + _delay_ms(8); + GIFR |= (1 << INTF0); // Clear Interrupt flag + GIMSK |= (1 << INT0); +} + +void sendps2(uint8_t data, uint8_t responseneeded) +{ +/* Complicated shit to send a PS/2 Packet. + Begin the request by making both inputs outputs, drag clock low for at least 100us then take data low and release clock. + the device will soon after start clocking in the data so make clk an input again and pay attention to the interrupt. + The device will clock in 1 start bit, 8 data bits, 1 parity bit then 1 stop bit. It will then ack by taking data low on the 12th clk (though this is currently ignored) and then it will respond with an 0xFA ACK */ + uint8_t send_tries = 3; + scancode = 0; + do + { + send_byte = data; + send_parity = calc_parity(send_byte); + GIMSK &= ~(1 << INT0); // Disable interrupt for CLK + DDRB |= (1 << DDB6 | 1 << DDB5); // CLK/Data are now Outputs + PORTB &= ~(1 << PB6); // Bring Clock low + _delay_us(150); + PORTB &= ~(1 << PB5); // Bring data Low + PORTB |= (1 << PB6); // Release clock and set it as an input again, clear interrupt flags and re-enable the intterupts + DDRB &= ~(1 << DDB6); + GIFR |= (1 << INTF0); + GIMSK |= (1 << INT0); + sr = 1; + while (sr == 1) {} // All the work for sending the data is handled inside the interrupt + DDRB &= ~(1 << DDB6 | 1 << DDB5); // Clock and Data set back to input + while (strobe == 0) {} // Wait for ACK packet before proceeding + strobe = 0; + send_tries--; + } while ((send_tries) && (scancode != 0xFA)); // If the response is not an ack, resend up to 3 times. + + if (responseneeded) // Are we expecting a response besides ACK? + { + while (strobe == 0) {} + strobe = 0; + } +} + +void parity_error(void) +{ + parity_errors++; + sendps2(0xFE,0); // Inform the KBD of the Parity error and request a resend. +} + +ISR (INT0_vect) +{ + if (sr == 1) { //Send bytes to device. + if (send_bitcount >=0 && send_bitcount <=7) // Data Byte + { + if ((send_byte >> send_bitcount) & 1) { + PORTB |= (1 << PB5); + } + else + { + PORTB &= ~(1 << PB5); + } + } + else if (send_bitcount == 8) // Parity Bit + { + if (send_parity) + { + PORTB &= ~(1 << PB5); + } + else + { + PORTB |= (1 << PB5); + } + } + else if (send_bitcount == 9) // Stop Bit + { + PORTB |= (1 << PB5); + } + if (send_bitcount < 10) + { + send_bitcount++; + } + else + { + send_bitcount = 0; + sr = 0; + } + } + + else { // Receive from device + uint8_t result = 0; + + if (PINB & (1 << PB5)) + { + result = 1; + } + else { + result = 0; + } + + if (rcv_bitcount <=9) + { + if (rcv_bitcount >=1 && rcv_bitcount <= 8) + { + rcv_byte |= (result << (rcv_bitcount - 1)); //Scancode Byte + } + else if (rcv_bitcount == 0) + { + ssp = result; // Start Bit + } + else if (rcv_bitcount == 9) + { + ssp |= (result << 2); // Parity Bit + } + rcv_bitcount++; + } + else if (rcv_bitcount >= 10) + { + ssp |= (result << 1); // Stop Bit + if ((ssp & 0x2) != 0x02) // Check start and stop bits. + { + framing_error(ssp); + } + else if (calc_parity(rcv_byte) == (ssp >> 2)) + { + parity_error(); + strobe = 0; + } + else + { + scancode = rcv_byte; + strobe = 1; + } + rcv_bitcount = 0; + rcv_byte = 0; + result = 0; + } + + } + +} + + +int main (void) { + volatile uint8_t kb_register = 0; // 0 = keyup | 1 = shift | 2 = ctrl | 3 = alt | 4 = capslock | 5 = numlock | 6 = scroll lock + volatile char ret_char = 0; + DDRB &= ~(1 << DDB6 | 1 << DDB5); // PINB6 = PS/2 Clock, PINB5 = PS/2 Data both set as input + DDRB |= (1 << DDB3); + DDRA |= (0xFF); + MCUCR |= (1 << ISC01 | 1 << PUD); // Interrupt on Falling Edge, force disable pullups + GIMSK |= (1 << INT0); // Enable Interrupt on PINB2 aka INT0 + + sei(); + sendps2(0xff,1); // reset kbd + sendps2(0xf0,0); // Set Codeset + sendps2(0x02,0); // Codeset 2 + + + while (1) { + if (strobe) + { + GIMSK &= ~(1 << INT0); // Disable interrupt for CLK + DDRB |= (1 << DDB6); // CLK now an outout + PORTB &= ~(1 << PB6); // Bring Clock low, inhibit keyboard until done processing event + if (kb_register & (1 << KB_KUP)) //This is a keyup event + { + switch(scancode) + { + case 0x12: + case 0x59: + kb_register &= ~(1 << KB_SHIFT); + break; + case 0x14: + kb_register &= ~(1 << KB_CTRL); + break; + case 0x11: + kb_register &= ~(1 << KB_ALT); + break; + default: + break; + } + kb_register &= ~(1 << KB_KUP); + + } + else + { + switch(scancode) + { + case 0xF0: //Key up + kb_register |= (1 << KB_KUP); + break; + case 0xE0: //Extended key sequence + kb_register |= (1 << KB_EXT); + break; + case 0x12: + case 0x59: // Shift + kb_register |= (1 << KB_SHIFT); + break; + case 0x66: //backspace + ret_char = 0x7F; + break; + case 0x5A: //enter + ret_char = 0x0D; + break; + case 0x0D: //tab + ret_char = 0x09; + break; + case 0x14: //ctrl + kb_register |= (1 << KB_CTRL); + break; + case 0x11: //alt + kb_register |= (1 << KB_ALT); + break; + case 0x76: //esc + ret_char = 0x1B; + break; + case 0x58: //capslock + kb_register ^= (1 << KB_CAPSLK); + sendps2(0xed,0); + sendps2((kb_register >> 4),0); // Set KBD Lights + break; + case 0x77: //numlock + kb_register ^= (1 << KB_NUMLK); + sendps2(0xed,0); + sendps2((kb_register >> 4),0); // Set KBD Lights + break; + case 0x7E: //scrllock + kb_register ^= (1 << KB_SCRLK); + sendps2(0xed,0); + sendps2((kb_register >> 4),0); // Set KBD Lights + break; + default: // Fall through for Alphanumeric Characters + if (kb_register & (1 << KB_CTRL)) // ASCII Control Code + { + ret_char = ps2_to_ascii_shifted[scancode]; + if ((ret_char >=0x41) && (ret_char <= 0x5A)) //Make sure we don't read outside the valid range of codes + { + ret_char ^= 0x40; + } + else + { + ret_char = 0; + } + } + else if (kb_register & (1<< KB_SHIFT)) { + ret_char = ps2_to_ascii_shifted[scancode]; + } + else if (kb_register & (1 <= 0x61) && (ret_char <= 0x7A)) + { + ret_char ^= 0x20; + } + } + else + { + ret_char = ps2_to_ascii[scancode]; + } + break; + } + if (ret_char) + { + PORTA = ret_char; + PORTB |= 1 << PB3; + _delay_us(10); + PORTB &= ~(1 << PB3); + ret_char = 0; + PORTA = 0; + } + } + strobe = 0; + PORTB |= (1 << PB6); // Release clock and set it as an input again, clear interrupt flags and re-enable the interupts + DDRB &= ~(1 << DDB6); + GIFR |= (1 << INTF0); + GIMSK |= (1 << INT0); + } + } +} diff --git a/ps2kbd.d b/ps2kbd.d new file mode 100644 index 0000000..b1e1316 --- /dev/null +++ b/ps2kbd.d @@ -0,0 +1 @@ +ps2kbd.o ps2kbd.d : ps2kbd.c ps2kbd.h diff --git a/ps2kbd.h b/ps2kbd.h new file mode 100644 index 0000000..3b8b452 --- /dev/null +++ b/ps2kbd.h @@ -0,0 +1,58 @@ +/* +PS2KBC, a PS2 Controler implemented on the Atmel ATTINY861. +Copyright (C) 2015 Matt Harlum + +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#define KB_KUP 0 +#define KB_SHIFT 1 +#define KB_CTRL 2 +#define KB_ALT 3 +#define KB_CAPSLK 4 +#define KB_NUMLK 5 +#define KB_SCRLK 6 +#define KB_EXT 7 + + +#ifndef F_CPU +#define F_CPU 8000000UL +#endif + +const uint8_t ps2_to_ascii[] = // Scancode > Ascii table. +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', 0, // 00-0F + 0, 0, 0, 0, 0, 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2', 0, //10-1F + 0, 'c', 'x', 'd', 'e', '4', '3', 0, 0, ' ', 'v', 'f', 't', 'r', '5', 0, //20-2F + 0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j', 'u', '7', '8', 0, //30-3F + 0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', 'l', ';', 'p', '-', 0, //40-4F + 0, 0, '\'', 0, '[', '=', 0, 0, 0, 0, 0, ']', 0, '\\', 0, 0, //50-5F + 0, 0, 0, 0, 0, 0, 0, 0, 0, '1', 0, '4', '7', 0, 0, 0, //60-6F + '0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0, //70-7F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //80-8F +}; + +const uint8_t ps2_to_ascii_shifted[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', 0, // 00-0F + 0, 0, 0, 0, 0, 'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@', 0, //10-1F + 0, 'C', 'X', 'D', 'E', '$', '#', 0, 0, ' ', 'V', 'F', 'T', 'R', '%', 0, //20-2F + 0, 'N', 'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J', 'U', '&', '*', 0, //30-3F + 0, '<', 'K', 'I', 'O', ')', '(', 0, 0, '>', '?', 'L', ':', 'P', '_', 0, //40-4F + 0, 0, '"', 0, '{', '+', 0, 0, 0, 0, 0, '}', 0, '|', 0, 0, //50-5F + 0, 0, 0, 0, 0, 0, 0, 0, 0, '1', 0, '4', '7', 0, 0, 0, //60-6F + '0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0, //70-7F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //80-8F +}; + \ No newline at end of file