├── obj-m162 ├── c=key.eep ├── c=key.bin └── c=key.elf ├── Makefile ├── docs └── Mappings.xls ├── pcb ├── C=Keyv1.0.brd ├── C=Keyv1.0.sch ├── C=Keyv1.1.brd ├── C=Keyv1.1.sch ├── C=Keyv2.0.brd ├── C=Keyv2.0.sch ├── C=Keyv3.0.brd ├── C=Keyv3.0.sch ├── C=Key_v3.1_BOM.xlsx ├── C=Keyv3.1_79x81mm.zip └── C=Key 3.0a Schematic.png ├── reference ├── 251107_l.gif ├── mapper │ ├── a.exe │ ├── convert.c │ └── data ├── pc-keyb_man.pdf ├── 310378-3-left.gif ├── c128dcr-1-left.gif ├── 250469-rev.A-left.gif ├── keyboard_commands.html ├── ps2-to-cbm │ ├── schematic.gif │ ├── source │ │ ├── defs.h │ │ ├── crosspoint.c │ │ ├── keyboard.c │ │ ├── reg-18f4520.h │ │ ├── main.c │ │ ├── pulse-io.c │ │ ├── mouse.c │ │ ├── pinouts.h │ │ ├── config.h │ │ ├── paddles.c │ │ ├── translation.c │ │ ├── ps2.c │ │ └── tables.c │ └── readme.txt └── Commodore keyboard hardware matrix.xls ├── .settings ├── org.eclipse.ltk.core.refactoring.prefs └── org.eclipse.cdt.core.prefs ├── scripts ├── conf2h.awk ├── src2doxy.pl └── crcgen-avr.pl ├── README.md ├── src ├── eeprom.h ├── poll.h ├── scanner.h ├── eeprom.c ├── switches.h ├── led.h ├── main.c ├── kb.h ├── scanner64.h ├── led.c ├── ps2_kb.c ├── config.h ├── switches.c ├── poll64.h ├── kb.c ├── uart.c ├── uart.h ├── ps2.h └── ps2.c ├── .cdtproject ├── config ├── .gitignore ├── .project ├── license.txt └── .cproject /obj-m162/c=key.eep: -------------------------------------------------------------------------------- 1 | :00000001FF 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/Makefile -------------------------------------------------------------------------------- /docs/Mappings.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/docs/Mappings.xls -------------------------------------------------------------------------------- /obj-m162/c=key.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/obj-m162/c=key.bin -------------------------------------------------------------------------------- /obj-m162/c=key.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/obj-m162/c=key.elf -------------------------------------------------------------------------------- /pcb/C=Keyv1.0.brd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv1.0.brd -------------------------------------------------------------------------------- /pcb/C=Keyv1.0.sch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv1.0.sch -------------------------------------------------------------------------------- /pcb/C=Keyv1.1.brd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv1.1.brd -------------------------------------------------------------------------------- /pcb/C=Keyv1.1.sch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv1.1.sch -------------------------------------------------------------------------------- /pcb/C=Keyv2.0.brd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv2.0.brd -------------------------------------------------------------------------------- /pcb/C=Keyv2.0.sch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv2.0.sch -------------------------------------------------------------------------------- /pcb/C=Keyv3.0.brd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv3.0.brd -------------------------------------------------------------------------------- /pcb/C=Keyv3.0.sch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv3.0.sch -------------------------------------------------------------------------------- /pcb/C=Key_v3.1_BOM.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Key_v3.1_BOM.xlsx -------------------------------------------------------------------------------- /reference/251107_l.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/251107_l.gif -------------------------------------------------------------------------------- /reference/mapper/a.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/mapper/a.exe -------------------------------------------------------------------------------- /pcb/C=Keyv3.1_79x81mm.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Keyv3.1_79x81mm.zip -------------------------------------------------------------------------------- /reference/pc-keyb_man.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/pc-keyb_man.pdf -------------------------------------------------------------------------------- /pcb/C=Key 3.0a Schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/pcb/C=Key 3.0a Schematic.png -------------------------------------------------------------------------------- /reference/310378-3-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/310378-3-left.gif -------------------------------------------------------------------------------- /reference/c128dcr-1-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/c128dcr-1-left.gif -------------------------------------------------------------------------------- /reference/250469-rev.A-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/250469-rev.A-left.gif -------------------------------------------------------------------------------- /reference/keyboard_commands.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/keyboard_commands.html -------------------------------------------------------------------------------- /reference/ps2-to-cbm/schematic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/ps2-to-cbm/schematic.gif -------------------------------------------------------------------------------- /reference/Commodore keyboard hardware matrix.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go4retro/c-key/HEAD/reference/Commodore keyboard hardware matrix.xls -------------------------------------------------------------------------------- /.settings/org.eclipse.ltk.core.refactoring.prefs: -------------------------------------------------------------------------------- 1 | #Tue Jul 09 00:20:34 CDT 2013 2 | eclipse.preferences.version=1 3 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false 4 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/defs.h: -------------------------------------------------------------------------------- 1 | typedef int1 BOOL; 2 | typedef int8 U8; 3 | typedef int16 U16; 4 | typedef int32 U32; 5 | typedef signed int8 S8; 6 | typedef signed int16 S16; 7 | typedef signed int32 S32; 8 | 9 | -------------------------------------------------------------------------------- /.settings/org.eclipse.cdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | indexer/filesToParseUpFront= 3 | indexer/indexAllFiles=false 4 | indexer/indexUnusedHeadersWithDefaultLang=false 5 | indexer/indexerId=org.eclipse.cdt.core.fastIndexer 6 | indexer/skipFilesLargerThanMB=8 7 | indexer/skipImplicitReferences=false 8 | indexer/skipMacroReferences=false 9 | indexer/skipReferences=false 10 | indexer/skipTypeReferences=false 11 | indexer/useHeuristicIncludeResolution=true 12 | indexerId=org.eclipse.cdt.core.fastIndexer 13 | -------------------------------------------------------------------------------- /scripts/conf2h.awk: -------------------------------------------------------------------------------- 1 | #! /usr/bin/gawk -f 2 | 3 | # Trivial little script to convert from a makefile-style configuration 4 | # file to a C header. No copyright claimed. 5 | 6 | BEGIN { 7 | print "// autoconf.h generated from " ARGV[1] " at " strftime() "\n" \ 8 | "#ifndef AUTOCONF_H\n" \ 9 | "#define AUTOCONF_H" 10 | } 11 | 12 | /^#/ { sub(/^#/,"//") } 13 | 14 | /^CONFIG_.*=/ { 15 | if (/=n$/) { 16 | sub(/^/,"// "); 17 | } else { 18 | sub(/^/,"#define ") 19 | if (/=y$/) { 20 | sub(/=.*$/,"") 21 | } else { 22 | sub(/=/," ") 23 | } 24 | } 25 | } 26 | 27 | { print } 28 | 29 | END { print "#endif" } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Commodore PS/2 Keyboard Adapter 2 | 3 | ##License 4 | Copyright (C) 2004 Jim Brain and RETRO Innovations 5 | 6 | These files are free designs; you can redistribute them and/or modify 7 | them under the terms of the GNU General Public License, version 2 as 8 | published by the Free Software Foundation. 9 | 10 | These files are distributed in the hope that they will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License along 16 | with these files; if not, write to the Free Software Foundation, Inc., 17 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 | -------------------------------------------------------------------------------- /src/eeprom.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2011 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | 20 | eeprom.h: Definitions for EEPROM config code 21 | 22 | */ 23 | 24 | #ifndef EEPROM_H 25 | #define EEPROM_H 26 | 27 | void update_eeprom(void* address,uint8_t data); 28 | 29 | #endif /*EEPROM_H*/ 30 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/crosspoint.c: -------------------------------------------------------------------------------- 1 | 2 | // 12 rows (AX) and 8 columns (AY) 3 | // three LSb are column (0-7) and four MSb are row (0-11) 4 | 5 | void connect(U8 value, BOOL connect) { 6 | static const U8 rowval[12]={0,1,2,3,4,5,8,9,10,11,12,13}; 7 | U8 row,col,ax,ay; 8 | 9 | if (value>=0x5F) return; 10 | 11 | col=value& 7; // 0 - 7 12 | row=value>>3; // 0 - 11 13 | 14 | ax=rowval[row]; // 0 - 15 15 | ay=col; 16 | 17 | value=ax<<3; 18 | value|=ay; 19 | 20 | 21 | printf("[%d %d %c] ",ay,ax,connect?'+':'-'); 22 | if (bit_test(LATD,7)) bit_set(value,7); else bit_clear(value,7); 23 | output_d(value); 24 | if (connect) output_high(CROSSPOINT_DATA); 25 | else output_low (CROSSPOINT_DATA); 26 | 27 | delay_cycles(1); 28 | output_high(CROSSPOINT_STROBE); 29 | delay_cycles(1); 30 | output_low(CROSSPOINT_STROBE); 31 | } 32 | 33 | 34 | void crosspoint_init(void) { 35 | output_low(CROSSPOINT_DATA); 36 | output_low(CROSSPOINT_STROBE); 37 | output_low(CROSSPOINT_RESET); 38 | delay_cycles(5); 39 | output_high(CROSSPOINT_RESET); 40 | delay_cycles(2); 41 | output_low(CROSSPOINT_RESET); 42 | } 43 | -------------------------------------------------------------------------------- /src/poll.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | poll.h: Definitions for matrix keyboard to CBM computer scanning routine 20 | 21 | */ 22 | #ifndef POLL_H 23 | #define POLL_H 24 | 25 | #ifndef TRUE 26 | #define TRUE 1 27 | #define FALSE 0 28 | #endif 29 | 30 | void poll_init(void); 31 | void poll_irq(void); 32 | void poll(void); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/scanner.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2011 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | scanner.h: Definitions for generic keyboard scanning routine 20 | 21 | */ 22 | #ifndef SCANNER_H 23 | #define SCANNER_H 24 | 25 | #define SCAN_MAP_NONE 0 26 | #define SCAN_MAP_SHIFT 1 27 | #define SCAN_MAP_EXT 2 28 | 29 | void scan_init(void); 30 | void scan_irq(void); 31 | void scan(void); 32 | 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /src/eeprom.c: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | eeprom.c: Persistent configuration storage 20 | 21 | */ 22 | 23 | #include 24 | #include 25 | #include "config.h" 26 | #include "eeprom.h" 27 | 28 | void update_eeprom(void* address,uint8_t data) { 29 | uint8_t tmp; 30 | 31 | while(!eeprom_is_ready()); 32 | tmp=eeprom_read_byte(address); 33 | if(tmp!=data) 34 | while(!eeprom_is_ready()); 35 | eeprom_write_byte(address,data); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/keyboard.c: -------------------------------------------------------------------------------- 1 | S8 kbstate; 2 | 3 | 4 | void keyboard_init() { 5 | kbstate=0; 6 | } 7 | 8 | 9 | void keyboard_handler(void) { 10 | static U16 reinit; 11 | U16 now; 12 | U8 n,c; 13 | 14 | n=ps2_rxavailable1(); 15 | if (!n) { 16 | if (kbstate) return; 17 | now=get_timer0(); 18 | if ((now-reinit)<32000) return; // attempt a reinit once every ~800 ms 19 | reinit=now; 20 | printf("Attempt keyboard reinit (sending FF)\n\r"); 21 | ps2_send1(0xFF); // reset command; reply should be FA (acknowledge) followed by self-test result (AA or FC) 22 | return; 23 | } 24 | c=ps2_getrxbyte1(); 25 | printf("(%d %02X) ",kbstate,c); 26 | switch (kbstate) { 27 | case 0: if (c!=0xAA) {kbstate=-1; break;} 28 | printf("Keyboard self-test passed (AA) sending read ID command (F2)"); 29 | ps2_send1(0xF2); // read ID command; reply should be FA (acknowledge) AB 83 (keyboard ID) 30 | break; 31 | case 1: if (c==0xFA) break; 32 | kbstate=-1; 33 | break; 34 | case 2: if (c==0xAB) break; 35 | printf("Device is not a keyboard. Initialization aborted. "); 36 | kbstate=-1; 37 | break; 38 | case 3: if (c==0x83) {blink_keyboard_led(); break;} 39 | kbstate=-1; 40 | break; 41 | case 4: translate_keyboard(c); 42 | kbstate--; 43 | break; 44 | default:kbstate=-1; 45 | break; 46 | } 47 | printf("\n\r"); 48 | kbstate++; 49 | } 50 | -------------------------------------------------------------------------------- /src/switches.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2011 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | switches.h: Definitions for non-matrixed keyboard switches 20 | 21 | */ 22 | 23 | #ifndef SWITCHES_H 24 | #define SWITCHES_H 25 | 26 | #ifndef SW_RX_BUFFER_SHIFT 27 | # define SW_RX_BUFFER_SHIFT 2 /* log2 of size */ 28 | #endif 29 | 30 | #if !defined PORT_SW_DDR 31 | # error Unknown PORT_SW! 32 | #endif 33 | 34 | #define SW_UP 0x80 35 | 36 | void sw_init(uint8_t mask); 37 | uint8_t sw_data_available(void); 38 | void sw_putc( uint8_t sw); 39 | uint8_t sw_getc( void ); 40 | void sw_scan(void); 41 | 42 | #endif // SWITCHES_H 43 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/reg-18f4520.h: -------------------------------------------------------------------------------- 1 | #BYTE PORTA =0xF80 2 | 3 | #BYTE PORTB =0xF81 4 | 5 | #BYTE PORTC =0xF82 6 | 7 | #BYTE PORTD =0xF83 8 | 9 | #BYTE PORTE =0xF84 10 | 11 | #BYTE LATD =0xF8C 12 | 13 | #BYTE TRISA =0xF92 14 | 15 | #BYTE TRISB =0xF93 16 | 17 | #BYTE TRISC =0xF94 18 | 19 | #BYTE TRISD =0xF95 20 | 21 | #BYTE TRISE =0xF96 22 | 23 | #BYTE OSCTUNE =0xF9B 24 | 25 | #BYTE PIR1 =0xF9E 26 | #BIT RCIF =PIR1.5 27 | #BIT SSPIF =PIR1.3 28 | #BIT CCP1IF =PIR1.2 29 | #BIT TMR2IF =PIR1.1 30 | #BIT TMR1IF =PIR1.0 31 | 32 | #BYTE PIR2 =0xFA1 33 | #BIT CCP2IF =PIR2.0 34 | 35 | #BYTE RCSTA =0xFAB 36 | #BIT OERR =RCSTA.1 37 | #BIT FERR =RCSTA.2 38 | #BIT CREN =RCSTA.4 39 | 40 | #BYTE TXSTA =0xFAC 41 | #BIT BRGH =TXSTA.2 42 | #BIT TXEN =TXSTA.5 43 | 44 | #BYTE RCREG =0xFAE 45 | 46 | #BYTE SPBRG =0xFAF 47 | 48 | #BYTE CVRCON =0xFB5 49 | 50 | #BYTE CCP1CON =0xFBD 51 | #BIT CCP1X =CCP1CON.5 52 | #BIT CCP1Y =CCP1CON.4 53 | 54 | #BYTE CCPR1L =0xFBE 55 | 56 | #BYTE SSPCON1 =0xFC6 57 | #BIT CKP =SSPCON1.4 58 | #BIT SSPEN =SSPCON1.5 59 | 60 | #BYTE SSPSTAT =0xFC7 61 | #BIT BF =SSPSTAT.0 62 | 63 | #BYTE SSPBUF =0xFC9 64 | 65 | #BYTE OSCCON =0xFD3 66 | 67 | #BYTE FSR2H =0xFDA 68 | 69 | #BYTE FSR2L =0xFD9 70 | 71 | #BYTE BSR =0xFE0 72 | 73 | #BYTE INDF0 =0xFEF 74 | 75 | #BYTE FSR0H =0xFEA 76 | 77 | #BYTE FSR0L =0xFE9 78 | 79 | #BYTE INTCON3 =0xFF0 80 | #BIT INT1IF =INTCON3.0 81 | #BIT INT2IF =INTCON3.1 82 | #BIT INT1IE =INTCON3.3 83 | #BIT INT2IE =INTCON3.4 84 | #BIT INT1IP =INTCON3.6 85 | #BIT INT2IP =INTCON3.7 86 | 87 | #BYTE INTCON =0xFF2 88 | #BIT INT0IF =INTCON.1 89 | 90 | -------------------------------------------------------------------------------- /src/led.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | led.h: Definitions for LED indicator routines 20 | 21 | */ 22 | #ifndef LED_H 23 | #define LED_H 24 | 25 | #define LED_DDR DDRD 26 | #define LED_PORT PORTD 27 | #define LED_PIN_0 (PIN0) 28 | #define LED_PIN_1 (PIN1) 29 | #define LED_PIN_2 (PIN2) 30 | #define LED_PIN_3 (PIN3) 31 | #define LED_PIN_4 (PIN4) 32 | #define LED_PIN_5 (PIN5) 33 | #define LED_PIN_6 (PIN6) 34 | #define LED_PIN_7 (PIN7) 35 | 36 | #define LED_FLAG_NONE 0 37 | #define LED_FLAG_END_ON 0x80 38 | #define LED_COUNT_MASK ((uint8_t)~LED_FLAG_END_ON) 39 | 40 | void LED_init(uint8_t led); 41 | void LED_on(uint8_t led); 42 | void LED_off(uint8_t led); 43 | void LED_blink(uint8_t led, uint8_t count, uint8_t flags); 44 | void LED_irq(void); 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | main.c: Main application 20 | 21 | */ 22 | #include 23 | #include 24 | #include "config.h" 25 | #include "poll.h" 26 | #include "ps2.h" 27 | #include "scanner.h" 28 | #include "uart.h" 29 | 30 | ISR(TIMER2_COMP_vect) { 31 | if(MODE_DETECT) { 32 | poll_irq(); 33 | } else { 34 | scan_irq(); 35 | } 36 | } 37 | 38 | void main( void ) { 39 | uart_init(); 40 | 41 | poll_init(); // do it here to reset cross-point switch everytime. 42 | if(MODE_DETECT) { 43 | ps2_init(PS2_MODE_HOST); 44 | uart_putc('H'); 45 | //poll_init(); // do it above to reset cross-point switch everytime 46 | sei(); 47 | poll(); 48 | } else { 49 | ps2_init(PS2_MODE_DEVICE); 50 | uart_putc('D'); 51 | scan_init(); 52 | sei(); 53 | scan(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/kb.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | kb.h: Definitions for generic keyboard routines 20 | 21 | */ 22 | #ifndef KB_H 23 | #define KB_H 24 | 25 | #define KB_ST_PREP 1 26 | #define KB_ST_READ 2 27 | #define KB_ST_READ_PORTS 3 28 | 29 | #define KB_KEY_UP 0x80 30 | 31 | #define KB_NO_REPEAT 0xff 32 | 33 | #define KB_RX_BUFFER_SIZE 16 /* 2,4,8,16,32,64,128 or 256 bytes */ 34 | #define KB_RX_BUFFER_MASK (KB_RX_BUFFER_SIZE - 1) 35 | #if (KB_RX_BUFFER_SIZE & KB_RX_BUFFER_MASK) 36 | # error KB RX buffer size is not a power of 2 37 | #endif 38 | 39 | void kb_init(void); 40 | void kb_set_repeat_delay(uint16_t ms); 41 | void kb_set_repeat_period(uint16_t period); 42 | void kb_set_repeat_code(uint8_t code); 43 | uint8_t kb_get_repeat_code(void); 44 | uint8_t kb_data_available( void ); 45 | uint8_t kb_recv( void ); 46 | void kb_scan(void); 47 | 48 | #endif 49 | 50 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/main.c: -------------------------------------------------------------------------------- 1 | 2 | // This project is compiled with the PCWH compiler v3.249 from CCS. 3 | 4 | 5 | #include "config.h" 6 | #include "defs.h" 7 | #include "pinouts.h" 8 | #include "reg-18f4520.h" 9 | 10 | // Since CCS 3.249 doesn't have a linker, all source files have to be #INCLUDED in the main source file 11 | #include "ps2.c" 12 | #include "paddles.c" 13 | #include "pulse-io.c" 14 | #include "crosspoint.c" 15 | #include "tables.c" 16 | #include "translation.c" 17 | #include "keyboard.c" 18 | #include "mouse.c" 19 | 20 | 21 | void main() { 22 | setup_adc_ports(NO_ANALOGS|VSS_VDD); 23 | setup_adc(ADC_OFF|ADC_TAD_MUL_0); 24 | setup_psp(PSP_DISABLED); 25 | setup_spi(FALSE); 26 | setup_wdt(WDT_OFF); 27 | setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); // 0.1 us X 256 = 25.6 us per tick X 65536 = 1677.721 ms per period 28 | setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); 29 | setup_timer_2(T2_DISABLED,0,1); 30 | setup_timer_3(T3_DISABLED|T3_DIV_BY_1); 31 | setup_comparator(NC_NC_NC_NC); 32 | setup_vref(FALSE); 33 | setup_low_volt_detect(FALSE); 34 | setup_oscillator(FALSE); 35 | 36 | output_a (INITIAL_PORTA_VALUE); 37 | output_b (INITIAL_PORTB_VALUE); 38 | output_c (INITIAL_PORTC_VALUE); 39 | output_d (INITIAL_PORTD_VALUE); 40 | output_e (INITIAL_PORTE_VALUE); 41 | set_tris_a(INITIAL_TRISA_VALUE); 42 | set_tris_b(INITIAL_TRISB_VALUE); 43 | set_tris_c(INITIAL_TRISC_VALUE); 44 | set_tris_d(INITIAL_TRISD_VALUE); 45 | set_tris_e(INITIAL_TRISE_VALUE); 46 | 47 | printf("Startup\n\r"); 48 | crosspoint_init(); 49 | paddle_init(); 50 | ps2_init(); 51 | enable_interrupts(GLOBAL); 52 | keyboard_init(); 53 | mouse_init(); 54 | 55 | while(1) { 56 | keyboard_handler(); 57 | mouse_handler(); 58 | pulse_handler(); 59 | } 60 | sleep(); 61 | } 62 | -------------------------------------------------------------------------------- /reference/mapper/convert.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int getNybble(char x) { 4 | switch (x) { 5 | case 'a': 6 | case 'A': 7 | return 10; 8 | case 'b': 9 | case 'B': 10 | return 11; 11 | case 'c': 12 | case 'C': 13 | return 12; 14 | case 'd': 15 | case 'D': 16 | return 13; 17 | case 'e': 18 | case 'E': 19 | return 14; 20 | case 'f': 21 | case 'F': 22 | return 15; 23 | default: 24 | return x-'0'; 25 | } 26 | } 27 | 28 | int main(int a, char* args[]) { 29 | int i = getNybble(args[3][2])*16 + getNybble(args[3][3]); 30 | int j; 31 | int y=(i&2?4:0)|(i&16?2:0) | (i&32?1:0); 32 | int x=(i&4?8:0) | (i&64?4:0) | (i&128?2:0) | (i&8?1:0); 33 | //printf("X=%d\n",x); 34 | switch(y) { 35 | case 4: y=3; break; 36 | case 5: y=2; break; 37 | case 6: y=1; break; 38 | case 7: y=0; break; 39 | case 0: y=7; break; 40 | case 1: y=6; break; 41 | case 2: y=5; break; 42 | case 3: y=4; break; 43 | } 44 | switch(x) { 45 | case 13:x=8; break; 46 | case 12:x=9; break; 47 | case 11: x=10; break; 48 | case 10: x=11; break; 49 | case 9: x=12; break; 50 | case 8: x=13; break; 51 | case 5: x=4; break; 52 | case 4: x=5; break; 53 | case 3: x=3; break; 54 | case 2: x=2; break; 55 | case 1: x=1; break; 56 | default: 57 | printf("%s %s %2.2X gave an Error\n",args[1],args[2],i); 58 | exit(-1); 59 | } 60 | j=(x&2?128:0) | (x&4?64:0) | (y&1?32:0) | (y&2?16:0) | (x&1?8:0) | (x&8?4:0) | (y&4?2:0); 61 | printf("%s %s 0x%2.2X\n",args[1],args[2],j); 62 | } 63 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/pulse-io.c: -------------------------------------------------------------------------------- 1 | #define RESTORE_PUSH 0 2 | #define MOUSE_ACTIVITY 1 3 | #define RESET_LINE 2 4 | #define SNAPSHOT_PUSH 3 5 | #define KEYBOARD_ACTIVITY 4 6 | 7 | static U8 pulsetime[5]; 8 | 9 | 10 | #PRAGMA use standard_io (C) 11 | #PRAGMA use standard_io (A) 12 | 13 | void pulse_handler(void) { 14 | U8 now,diff,i,n; 15 | BOOL asserted; 16 | 17 | n=sizeof(pulsetime)/sizeof(pulsetime[0]); 18 | now=make8(get_timer0(),1); 19 | for (i=0; i 2 | #PRAGMA device ICD=TRUE 3 | #PRAGMA device adc=8 4 | #PRAGMA device HIGH_INTS=TRUE 5 | 6 | 7 | #PRAGMA FUSES NOWDT //No Watch Dog Timer 8 | #PRAGMA FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale 9 | #PRAGMA FUSES H4 10 | #PRAGMA FUSES NOPROTECT //Code not protected from reading 11 | #PRAGMA FUSES NOBROWNOUT //No brownout reset 12 | #PRAGMA FUSES BORV42 //Brownout reset at 4.2V 13 | #PRAGMA FUSES NOPUT //No Power Up Timer 14 | #PRAGMA FUSES NOCPD //No EE protection 15 | #PRAGMA FUSES NOSTVREN //Stack full/underflow will not cause reset 16 | #PRAGMA FUSES DEBUG //Debug mode for use with ICD 17 | #PRAGMA FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O 18 | #PRAGMA FUSES NOWRT //Program memory not write protected 19 | #PRAGMA FUSES NOWRTD //Data EEPROM not write protected 20 | #PRAGMA FUSES NOIESO //Internal External Switch Over mode disabled 21 | #PRAGMA FUSES NOFCMEN //Fail-safe clock monitor disabled 22 | #PRAGMA FUSES PBADEN //PORTB pins are configured as analog input channels on RESET 23 | #PRAGMA FUSES NOWRTC //configuration not registers write protected 24 | #PRAGMA FUSES NOWRTB //Boot block not write protected 25 | #PRAGMA FUSES NOEBTR //Memory not protected from table reads 26 | #PRAGMA FUSES NOEBTRB //Boot block not protected from table reads 27 | #PRAGMA FUSES NOCPB //No Boot Block code protection 28 | #PRAGMA FUSES LPT1OSC //Timer1 configured for low-power operation 29 | #PRAGMA FUSES MCLR //Master Clear pin enabled 30 | #PRAGMA FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode) 31 | 32 | #PRAGMA use delay(clock=40000000) 33 | #PRAGMA use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) 34 | 35 | -------------------------------------------------------------------------------- /.cdtproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | make 20 | all 21 | false 22 | true 23 | 24 | 25 | make 26 | clean 27 | false 28 | true 29 | 30 | 31 | make 32 | program 33 | false 34 | true 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | # This may not look like it, but it's a -*- makefile -*- 2 | # 3 | # C=Key - PS/2 CBM keyboard adapter 4 | # Copyright (C) 2004-2008 Jim Brain 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; version 2 of the License only. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | # 19 | # config: User-configurable options to simplify hardware changes and/or 20 | # reduce the code/ram requirements of the code. 21 | # 22 | # 23 | # This file is included in the main Makefile and also parsed 24 | # into autoconf.h. 25 | # This system based on sd2iec Makefile by Ingo Korb 26 | 27 | # MCU to compile for 28 | CONFIG_MCU=atmega162 29 | 30 | # Use the -relax parameter when linking? 31 | # Passing -O9 and -relax to the linker saves ~650 bytes of flash, 32 | # but the option is broken in certain binutils versions. 33 | # (known troublemakers: binutils 2.17, 2.18 seems fine) 34 | CONFIG_LINKER_RELAX=n 35 | 36 | # MCU frequency in Hz 37 | CONFIG_MCU_FREQ=14745600 38 | 39 | # Add a bootloader signature 40 | CONFIG_BOOTLOADER=n 41 | 42 | # Value of the signature word 43 | CONFIG_BOOT_DEVID=0x49454321 44 | 45 | 46 | # Enable UART debugging - requires 24 bytes plus buffer size in RAM 47 | CONFIG_UART_DEBUG=y 48 | 49 | # Baud rate of the UART 50 | CONFIG_UART_BAUDRATE=115200 51 | 52 | # this should be removed 53 | # log2 of the UART buffer size, i.e. 6 for 64, 7 for 128, 8 for 256 etc. 54 | CONFIG_UART_BUF_SHIFT=6 55 | 56 | # Select which hardware to compile for 57 | CONFIG_HARDWARE_VARIANT=1 58 | CONFIG_HARDWARE_NAME=C=Key 59 | 60 | # Track the stack size 61 | # Warning: This option increases the code size a lot. 62 | CONFIG_STACK_TRACKING=n 63 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/paddles.c: -------------------------------------------------------------------------------- 1 | 2 | U16 paddle1local,paddle2local,paddle1value,paddle2value; 3 | BOOL paddle1phase,paddle2phase,paddle1sync,paddle2sync,paddleupdate; 4 | static U16 resync1,resync2; 5 | 6 | 7 | #PRAGMA use standard_io (C) 8 | 9 | void paddle_init(void) { 10 | paddle1value=3440; // range is from 2460==>0 4880 ==>246 11 | paddle2value=3440; 12 | paddle1local=paddle1value; 13 | paddle2local=paddle2value; 14 | paddle1sync=FALSE; 15 | paddle2sync=FALSE; 16 | paddleupdate=FALSE; 17 | enable_interrupts(INT_CCP1); 18 | enable_interrupts(INT_CCP2); 19 | enable_interrupts(INT_TIMER1); 20 | } 21 | 22 | #PRAGMA int_timer1 23 | void paddle_sync_check(void) { // runs once every 13 SID cycles and forces a resync if unplugged & replugged 24 | if (paddle1sync) { 25 | paddle1sync=FALSE; 26 | } else { 27 | output_low(PIN_C2); 28 | CCP_1=paddle1local; 29 | setup_ccp1(CCP_COMPARE_SET_ON_MATCH); 30 | paddle1phase=FALSE; 31 | resync1++; 32 | } 33 | if (paddle2sync) { 34 | paddle2sync=FALSE; 35 | } else { 36 | output_low(PIN_C1); 37 | CCP_2=paddle2local; 38 | setup_ccp2(CCP_COMPARE_SET_ON_MATCH); 39 | paddle2phase=FALSE; 40 | resync2++; 41 | } 42 | if (paddleupdate) { 43 | paddle1local=paddle1value; 44 | paddle2local=paddle2value; 45 | } 46 | } 47 | 48 | 49 | #PRAGMA int_ccp1 NOCLEAR 50 | void paddle1_done(void) { 51 | if (paddle1phase) { 52 | output_low(PIN_C2); 53 | CCP_1+=paddle1local; 54 | setup_ccp1(CCP_COMPARE_SET_ON_MATCH); 55 | CCP1IF=0; 56 | paddle1phase=FALSE; 57 | paddle1sync=TRUE; 58 | } else { 59 | CCP1IF=0; 60 | setup_ccp1(CCP_CAPTURE_FE); 61 | delay_cycles(1); 62 | output_float(PIN_C2); 63 | paddle1phase=TRUE; 64 | } 65 | } 66 | 67 | #PRAGMA int_ccp2 NOCLEAR 68 | void paddle2_done(void) { 69 | if (paddle2phase) { 70 | output_low(PIN_C1); 71 | CCP_2+=paddle2local; 72 | setup_ccp2(CCP_COMPARE_SET_ON_MATCH); 73 | CCP2IF=0; 74 | paddle2phase=FALSE; 75 | paddle2sync=TRUE; 76 | } else { 77 | delay_us(5); 78 | CCP2IF=0; 79 | setup_ccp2(CCP_CAPTURE_FE); 80 | delay_cycles(1); 81 | output_float(PIN_C1); 82 | paddle2phase=TRUE; 83 | } 84 | } 85 | 86 | #PRAGMA use fast_io (C) 87 | 88 | -------------------------------------------------------------------------------- /src/scanner64.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2011 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | scanner64.h: Definitions for C64/C128 keyboard scanning routine 20 | 21 | */ 22 | 23 | #ifndef _SCANNER64_H 24 | #define _SCANNER64_H 25 | 26 | #define SCAN_IRQ_DIVIDER (28) 27 | #define SCAN_LED_IRQ_DIVIDER (F_CPU/256/2/SCAN_IRQ_DIVIDER/3) // 3/s 28 | 29 | #define SCAN_ADDR_LAYOUT (void*)8 30 | 31 | #define SCAN_CBM_KEY_NONE 0xff 32 | #define SCAN_CBM_KEY_UNMAPPED 0xfe 33 | #define SCAN_CBM_KEY_SPECIAL 0xc0 34 | 35 | #define POLL_JOY_NONE 0 36 | #define POLL_JOY_UP 1 37 | #define POLL_JOY_DOWN 2 38 | #define POLL_JOY_RIGHT 4 39 | #define POLL_JOY_LEFT 8 40 | #define POLL_JOY_FIRE 16 41 | 42 | #define SCAN_FLAG_NONE 0 43 | #define SCAN_FLAG_LSHIFT 1 44 | #define SCAN_FLAG_RSHIFT 2 45 | #define SCAN_FLAG_SHIFT 3 46 | #define SCAN_FLAG_CTRL 4 47 | #define SCAN_FLAG_CMDR 8 48 | 49 | #define SCAN_LAYOUT_SYMBOLIC_C64 0 50 | #define SCAN_LAYOUT_POSITIONAL_C64 1 51 | #define SCAN_LAYOUT_NUM 2 52 | 53 | #define SCAN_C64_KEY_RSHIFT 0x33 54 | #define SCAN_C64_KEY_LSHIFT 0x0c 55 | #define SCAN_C64_KEY_CMDR 0x02 56 | #define SCAN_C64_KEY_1 0x07 57 | #define SCAN_C64_KEY_2 0x00 58 | #define SCAN_C64_KEY_3 0x0f 59 | #define SCAN_C64_KEY_EQUALS 0x32 60 | #define SCAN_C64_KEY_RETURN 0x3e 61 | #define SCAN_C64_KEY_CTRL 0x05 62 | #define SCAN_C64_KEY_DEL 0x3f 63 | 64 | #endif //_SCANNER64_H_ 65 | -------------------------------------------------------------------------------- /scripts/src2doxy.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w -i~ 2 | 3 | # src2doxy.pl - create doxygen-compatible comments from readable C source 4 | # Copyright (C) 2008 Ingo Korb 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; version 2 of the License only. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | # 19 | # This script parses a subset of kernel-doc style comments and rewrites 20 | # them as something doxygen will understand. 21 | use strict; 22 | 23 | my $incomment = 0; 24 | my $inspecialcomment = 0; 25 | my @postcomment = (); 26 | my @outputstack; 27 | 28 | while (<>) { 29 | my $filename; 30 | ($filename = $ARGV) =~ s!.*/!!; 31 | 32 | chomp; 33 | s/\r$//; 34 | s/\s+$//; 35 | 36 | # doxygen is too stupid to understand after-the-variable comments 37 | # without external help. WARNING: Will substitute within strings! 38 | s!([^ \t]\s+)/// !$1///< !; 39 | 40 | $incomment = 1 if m!^/\*!; 41 | if (m!^/\*\*$!) { 42 | $inspecialcomment = 1; 43 | # Kill output 44 | $_ = ""; 45 | next; 46 | } 47 | 48 | if ($incomment) { 49 | if (m!\*/$!) { 50 | # End of comment 51 | $incomment = 0; 52 | $inspecialcomment = 0; 53 | @outputstack = @postcomment; 54 | @postcomment = (); 55 | } elsif (/$filename:\s+(.*).?\s*$/) { 56 | # Add file description 57 | push @postcomment, "\n/*! \\file $ARGV\n * \\brief $1. */\n"; 58 | } 59 | if ($inspecialcomment == 1) { 60 | # First line of special comment: Brief description 61 | $inspecialcomment = 2; 62 | m/^\s*\*\s*((struct |union )?[^: \t]+):?\s+-?\s*(.*)\s*$/; 63 | $_ = "/*! \\brief $3\n *"; 64 | } elsif ($inspecialcomment == 2) { 65 | # Modify parameters 66 | s/\@([^: \t]+)\s*:\s+(.*)\s*$/\\param $1 $2/; 67 | } 68 | } 69 | } continue { 70 | print "$_\n"; 71 | while (scalar(@outputstack)) { 72 | print shift @outputstack,"\n"; 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/led.c: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | led.h: LED indicator routines 20 | 21 | */ 22 | #include 23 | #include 24 | #include "config.h" 25 | #include "led.h" 26 | 27 | static uint8_t led_mask; 28 | static uint8_t led_status; 29 | static uint8_t led_count[8]; 30 | /* 31 | * 00000000 = Off 32 | * 11111111 = On 33 | * bbbbbbbb = blink b times 34 | * 35 | */ 36 | static uint8_t led_program[8]; 37 | 38 | void LED_init(uint8_t led) { 39 | LED_DDR |=(1< PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | ps2_kb.c: Convenience functions for PS/2 Keyboards 20 | 21 | */ 22 | 23 | #include 24 | #include 25 | #include "config.h" 26 | #include "ps2.h" 27 | 28 | static uint8_t ps2_leds = 0; 29 | static uint8_t ps2_codeset = 2; 30 | 31 | 32 | void ps2_handle_cmds(uint8_t data) { 33 | uint8_t i; 34 | 35 | switch(data) { 36 | case PS2_CMD_ACK: 37 | //ignore. 38 | break; 39 | case PS2_CMD_RESET: 40 | ps2_putc(PS2_CMD_ACK); 41 | ps2_putc(PS2_CMD_BAT); 42 | break; 43 | case PS2_CMD_DISABLE: 44 | // we should disable sending output if we receive this command. 45 | case PS2_CMD_ENABLE: 46 | //clear out KB buffers 47 | ps2_clear_buffers(); 48 | ps2_putc(PS2_CMD_ACK); 49 | break; 50 | default: 51 | ps2_putc(PS2_CMD_ACK); 52 | break; 53 | case PS2_CMD_ECHO: 54 | ps2_putc(PS2_CMD_ECHO); 55 | break; 56 | case PS2_CMD_SET_CODE_SET: 57 | ps2_putc(PS2_CMD_ACK); 58 | i = ps2_getc(); 59 | if(i == 0) { 60 | ps2_putc(ps2_codeset); 61 | } else { 62 | ps2_codeset = i; 63 | } 64 | break; 65 | case PS2_CMD_SET_RATE: 66 | // this should to be caught in another area, ignore if received here. 67 | break; 68 | case PS2_CMD_READ_ID: 69 | ps2_putc(PS2_CMD_ACK); 70 | ps2_putc(0xab); 71 | ps2_putc(0x83); 72 | break; 73 | case PS2_CMD_LEDS: 74 | ps2_putc(PS2_CMD_ACK); 75 | ps2_leds = ps2_getc()&0x07; 76 | ps2_putc(PS2_CMD_ACK); 77 | break; 78 | case PS2_CMD_RESEND: 79 | break; 80 | } 81 | } 82 | 83 | 84 | /* this returns the initial delay in ms */ 85 | uint16_t ps2_get_typematic_delay(uint8_t rate) { 86 | return (((rate & 0x60) >> 5) + 1) * 250; 87 | } 88 | 89 | 90 | /* this returns the rate in CPS */ 91 | uint16_t ps2_get_typematic_period(uint8_t rate) { 92 | return ((8 + (rate & 0x07)) * (1 << ((rate & 0x18) >> 3)) << 2); 93 | } 94 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | 165 | #SVN 166 | .svn 167 | 168 | #Xilinx ISE WebPack 169 | *.xmsgs 170 | *.tim 171 | *.tspec 172 | _xmsgs 173 | /hdl/*.err 174 | /hdl/iseconfig 175 | /hdl/_pace.ucf 176 | 177 | #EAGLE CAD 178 | /pcb/*.lck 179 | 180 | #GCC 181 | .dep 182 | obj-*/src* 183 | obj-*/*.h 184 | 185 | #Project Stuff 186 | archive 187 | -------------------------------------------------------------------------------- /reference/mapper/data: -------------------------------------------------------------------------------- 1 | #define C64_KEY_RUNSTOP 0x40 2 | #define C64_KEY_LSHIFT 0x48 3 | #define C64_KEY_X 0x04 4 | #define C64_KEY_V 0x0C 5 | #define C64_KEY_N 0x84 6 | #define C64_KEY_COMMA 0x8C 7 | #define C64_KEY_SLASH 0x44 8 | #define C64_KEY_CRSR_DOWN 0x4c 9 | #define C64_KEY_CTRL 0x60 10 | #define C64_KEY_A 0x68 11 | #define C64_KEY_D 0x24 12 | #define C64_KEY_G 0x2C 13 | #define C64_KEY_J 0xA4 14 | #define C64_KEY_L 0xAC 15 | #define C64_KEY_SEMICOLON 0x64 16 | #define C64_KEY_CRSR_RIGHT 0x6C 17 | #define C64_KEY_BACKARROW 0x50 18 | #define C64_KEY_W 0x58 19 | #define C64_KEY_R 0x14 20 | #define C64_KEY_Y 0x1C 21 | #define C64_KEY_I 0x94 22 | #define C64_KEY_P 0x9C 23 | #define C64_KEY_ASTERIX 0x54 24 | #define C64_KEY_RETURN 0x5C 25 | #define C64_KEY_1 0x70 26 | #define C64_KEY_3 0x78 27 | #define C64_KEY_5 0x34 28 | #define C64_KEY_7 0x3C 29 | #define C64_KEY_9 0xB4 30 | #define C64_KEY_PLUS 0xBC 31 | #define C64_KEY_POUND 0x74 32 | #define C64_KEY_DELETE 0x7C 33 | #define C64_KEY_2 0x42 34 | #define C64_KEY_4 0x4A 35 | #define C64_KEY_6 0x06 36 | #define C64_KEY_8 0x0E 37 | #define C64_KEY_0 0x86 38 | #define C64_KEY_MINUS 0x8E 39 | #define C64_KEY_HOME 0x46 40 | #define C64_KEY_F7 0x4E 41 | #define C64_KEY_Q 0x62 42 | #define C64_KEY_E 0x6A 43 | #define C64_KEY_T 0x26 44 | #define C64_KEY_U 0x2E 45 | #define C64_KEY_O 0xA6 46 | #define C64_KEY_AT 0xAE 47 | #define C64_KEY_UPARROW 0x66 48 | #define C64_KEY_F5 0x6E 49 | #define C64_KEY_CBM 0x52 50 | #define C64_KEY_S 0x5A 51 | #define C64_KEY_F 0x16 52 | #define C64_KEY_H 0x1E 53 | #define C64_KEY_K 0x96 54 | #define C64_KEY_COLON 0x9E 55 | #define C64_KEY_EQUALS 0x56 56 | #define C64_KEY_F3 0x5E 57 | #define C64_KEY_SPACE 0x72 58 | #define C64_KEY_Z 0x7A 59 | #define C64_KEY_C 0x36 60 | #define C64_KEY_B 0x3E 61 | #define C64_KEY_M 0xB6 62 | #define C64_KEY_PERIOD 0xBE 63 | #define C64_KEY_RSHIFT 0x76 64 | #define C64_KEY_F1 0x7E 65 | #define C128_KEY_NOSCROLL 0x08 66 | #define C128_KEY_NUM_3 0x80 67 | #define C128_KEY_NUM_1 0x88 68 | #define C128_KEY_NUM_PERIOD 0x28 69 | #define C128_KEY_NUM_MINUS 0xA0 70 | #define C128_KEY_NUM_5 0xA8 71 | #define C128_KEY_NUM_0 0x18 72 | #define C128_KEY_NUM_PLUS 0x90 73 | #define C128_KEY_NUM_8 0x98 74 | #define C128_KEY_CRSR_UP 0x0A 75 | #define C128_KEY_LINEFEED 0x82 76 | #define C128_KEY_TAB 0x8A 77 | #define C128_KEY_CRSR_RIGHT 0x2A 78 | #define C128_KEY_NUM_9 0xA2 79 | #define C128_KEY_NUM_7 0xAA 80 | #define C128_KEY_CRSR_LEFT 0x1A 81 | #define C128_KEY_NUM_6 0x92 82 | #define C128_KEY_NUM_4 0x9A 83 | #define C128_KEY_CRSR_DOWN 0x3A 84 | #define C128_KEY_ENTER 0xB2 85 | #define C128_KEY_NUM_2 0xBA 86 | #define C128_KEY_ALT 0x38 87 | #define C128_KEY_ESC 0xB0 88 | #define C128_KEY_HELP 0xB8 89 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2011 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | config.h: User-configurable options to simplify hardware changes and/or 20 | reduce the code/ram requirements of the code. 21 | */ 22 | 23 | #ifndef CONFIG_H 24 | #define CONFIG_H 25 | 26 | #include "autoconf.h" 27 | 28 | #define PS2_ENABLE_HOST 29 | #define PS2_ENABLE_DEVICE 30 | #define KB_SCAN_PORTS // scan the KB ports for joystick activity 31 | 32 | #ifndef TRUE 33 | #define FALSE 0 34 | #define TRUE (!FALSE) 35 | #endif 36 | 37 | // log2 of the PS2 buffer size, i.e. 6 for 64, 7 for 128, 8 for 256 etc. 38 | #define PS2_RX_BUFFER_SHIFT 3 39 | #define PS2_TX_BUFFER_SHIFT 3 40 | 41 | #define ENABLE_UART0 42 | // log2 of the UART buffer size, i.e. 6 for 64, 7 for 128, 8 for 256 etc. 43 | #define UART0_TX_BUFFER_SHIFT 3 44 | //#define UART0_RX_BUFFER_SHIFT 3 45 | #define UART0_BAUDRATE CONFIG_UART_BAUDRATE 46 | 47 | #if CONFIG_HARDWARE_VARIANT == 1 48 | 49 | #define MODE_DETECT (PIND & (1 << PIN4)) 50 | #define RESET_INIT() do {PORTD |= (1 << PIN5); } while(0) 51 | #define RESET_ON() do {DDRD |= (1 << PIN5); PORTD &= (uint8_t)~(1 << PIN5); } while(0) 52 | #define RESET_OFF() do {DDRD &= (uint8_t)~(1 << PIN5); PORTD |= ~(1 << PIN5); } while(0) 53 | 54 | #define KB_ROW_HI_OUT PORTB 55 | #define KB_ROW_HI_IN PINB 56 | #define KB_ROW_HI_DDR DDRB 57 | #define KB_ROW_LO_OUT PORTC 58 | #define KB_ROW_LO_IN PINC 59 | #define KB_ROW_LO_DDR DDRC 60 | #define KB_COL_OUT PORTA 61 | #define KB_COL_IN PINA 62 | #define KB_COL_DDR DDRA 63 | 64 | #define PS2_CLK_DDR DDRD 65 | #define PS2_CLK_OUT PORTD 66 | #define PS2_CLK_IN PIND 67 | #define PS2_CLK_PIN _BV(PD3) 68 | #define PS2_DATA_DDR DDRD 69 | #define PS2_DATA_OUT PORTD 70 | #define PS2_DATA_IN PIND 71 | #define PS2_DATA_PIN _BV(PD2) 72 | 73 | #define PORT_SW_OUT PORTE 74 | #define PORT_SW_IN PINE 75 | #define PORT_SW_DDR DDRE 76 | 77 | #define XPT_PORT_DATA_OUT PORTB 78 | #define XPT_DDR_DATA DDRB 79 | #define XPT_PORT_STROBE_OUT PORTD 80 | #define XPT_DDR_STROBE DDRD 81 | 82 | #define XPT_PIN_STROBE (1< PS/2 backslash (\) 44 | C64 left arrow key ==> PS/2 left quote (`) 45 | C64 restore key ==> PS/2 pause/break 46 | C64 run/stop key ==> PS/2 esc 47 | C64 commodore key ==> PS/2 Windows key 48 | 49 | Also, since three keys (@ ^ and +) require using the shift key, they themselves can't be combined with the shift key. This will only pose a problem if you're doing keyboard graphics (in which case a real C64 keyboard is probably more useful anyway since a PS/2 keyboard doesn't have the symbols on the front of the keys). 50 | 51 | All the remaining keys on the PS/2 keyboard that don't map to a C64 equivalent will have no effect when pressed. 52 | 53 | Caps Lock also has no effect since the typical function of a caps locks key is to only type uppercase letters, whereas the C64 "shift lock" key causes EVERY key to be shifted. 54 | 55 | 2.2 Mouse emulation 56 | 57 | The mouse emulation simulates a 1531 mouse in proportional mode and is compatible with the 1531 driver for Geos. There is no emulation of a 1530 joystick-type mouse or of the 1531 in joystick mode. 58 | 59 | 2.3 Special functions 60 | 61 | A few extra features are available: 62 | If you have a Super Snapshot cartridge, connect the button to pin 2 of the CPU and pressing F12 will push the snapshot button. 63 | 64 | If you have an A/B switch for your joystick, connect the control line to pin 23 of the CPU and pressing num lock will toggle between joystick 1 and joystick 2. 65 | 66 | If you want to be able to reset your C64 from the keyboard, connect pin 24 of the CPU to the input of the 556 chip inside the C64 and pressing ctrl-alt-del will reset the C64. 67 | 68 | 69 | 3.0 Modifications 70 | 71 | To compile the project, you will need the CCS compiler (www.ccsinfo.com) version 3.249. Version 4.xxx should work as well. From the "File" menu select "Open" and choose "main.c". Press F9 to compile. 72 | 73 | Since the code only uses 22% of the ROM on the PIC18F4520, an equivalent CPU with less ROM can be used to save cost. 74 | 75 | To change the key mappings, edit TABLES.C and change the main translation table. Any PS/2 scancode can be mapped to any key, including the extra keys found on multimedia keyboards. 76 | 77 | -------------------------------------------------------------------------------- /src/switches.c: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2011 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | switches.c: Functions for non-matrixed keyboard switches 20 | 21 | */ 22 | 23 | // TODO: if putc has depressed a IO pin, don't record it as a switch closure. 24 | 25 | #include 26 | #include 27 | #include "config.h" 28 | #include "switches.h" 29 | 30 | static unsigned char rx_buf[_BV( SW_RX_BUFFER_SHIFT)]; 31 | static volatile uint8_t rx_head; 32 | static volatile uint8_t rx_tail; 33 | 34 | static uint8_t cache; 35 | static uint8_t in_mask; 36 | 37 | static void sw_store(uint8_t data) { 38 | 39 | rx_head = ( rx_head + 1 ) & (sizeof(rx_buf) - 1); /* Calculate and store new index */ 40 | 41 | if ( rx_head == rx_tail ) { 42 | /* ERROR! Receive buffer overflow */ 43 | } 44 | 45 | rx_buf[rx_head] = data; /* Store received data in buffer */ 46 | } 47 | 48 | uint8_t sw_data_available( void ) { 49 | return ( rx_head != rx_tail ); /* Return 0 (FALSE) if the receive buffer is empty */ 50 | } 51 | 52 | void sw_putc( uint8_t sw) { 53 | // bit 7 indicates key up. 54 | uint8_t state = (sw & SW_UP); 55 | sw = sw & 0x7F; // tuti: cut of the state bit 7! 56 | sw = _BV(sw); // turn into bit mask; 57 | if(sw & in_mask) { 58 | if(state) { 59 | // bring to input and set HI-Z 60 | PORT_SW_DDR &= (uint8_t)~sw; 61 | PORT_SW_OUT |= sw; 62 | } else { 63 | PORT_SW_DDR |= sw; 64 | PORT_SW_OUT &= (uint8_t)~sw; 65 | } 66 | } 67 | } 68 | 69 | uint8_t sw_getc( void ) { 70 | 71 | while ( rx_head == rx_tail ) { 72 | ; 73 | } 74 | rx_tail = ( rx_tail + 1 ) & (sizeof(rx_buf) - 1); /* Calculate and store buffer index */ 75 | 76 | return rx_buf[rx_tail]; /* Return data */ 77 | } 78 | 79 | void sw_scan(void) { 80 | uint8_t mask, up, down, in; 81 | 82 | in=(PORT_SW_IN & in_mask); 83 | if(in != cache) { 84 | // a key has changed. 85 | mask = in ^ cache; 86 | down=cache & mask; 87 | up=in & mask; 88 | if(up) { 89 | // keys released. 90 | if(up & 1) {sw_store(SW_UP | 0);} 91 | if(up & 2) {sw_store(SW_UP | 1);} 92 | if(up & 4) {sw_store(SW_UP | 2);} 93 | if(up & 8) {sw_store(SW_UP | 3);} 94 | if(up & 16) {sw_store(SW_UP | 4);} 95 | if(up & 32) {sw_store(SW_UP | 5);} 96 | if(up & 64) {sw_store(SW_UP | 6);} 97 | if(up & 128) {sw_store(SW_UP | 7);} 98 | } 99 | if(down) { 100 | // keys pressed. 101 | if(down & 1) {sw_store(0);} 102 | if(down & 2) {sw_store(1);} 103 | if(down & 4) {sw_store(2);} 104 | if(down & 8) {sw_store(3);} 105 | if(down & 16) {sw_store(4);} 106 | if(down & 32) {sw_store(5);} 107 | if(down & 64) {sw_store(6);} 108 | if(down & 128) {sw_store(7);} 109 | } 110 | cache = in; 111 | } 112 | } 113 | 114 | void sw_init(uint8_t mask) { 115 | // bring them HI-Z 116 | PORT_SW_OUT |= mask; 117 | // bring them to inputs; 118 | PORT_SW_DDR &= (uint8_t)~mask; 119 | in_mask = mask; 120 | cache=(PORT_SW_IN & mask); 121 | } 122 | -------------------------------------------------------------------------------- /scripts/crcgen-avr.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # Generate bootloader CRC for the LPC176x version of sd2iec 4 | # 5 | # Copyright (C) 2012-2017 Ingo Korb 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions 10 | # are met: 11 | # 1. Redistributions of source code must retain the above copyright 12 | # notice, this list of conditions and the following disclaimer. 13 | # 2. Redistributions in binary form must reproduce the above copyright 14 | # notice, this list of conditions and the following disclaimer in the 15 | # documentation and/or other materials provided with the distribution. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | # SUCH DAMAGE. 28 | 29 | use strict; 30 | use warnings; 31 | use feature ':5.10'; 32 | 33 | my $BOOTINFO_SIZE = 8; 34 | my $CRC_SIZE = 2; 35 | 36 | # translated from avr-libc version because it appears that 37 | # it implements a non-standard variant of this CRC 38 | sub crc_ccitt_update { 39 | my $crc = shift; 40 | my $data = ord(shift); 41 | 42 | $data ^= $crc & 0xff; 43 | $data = ($data ^ ($data << 4)) & 0xff; 44 | 45 | return ((($data << 8) & 0xffff) | (($crc >> 8) & 0xff)) ^ 46 | ((($data >> 4) & 0xff) ^ (($data << 3) & 0xffff)); 47 | } 48 | 49 | # insert new data in a bootinfo block 50 | sub update_bootinfo { 51 | my $bufref = shift; 52 | my $address = shift; 53 | my $devid = shift; 54 | my $version = shift; 55 | 56 | my $bootinfo = pack("Vvv", $devid, $version, 0); 57 | 58 | substr($$bufref, $address, length($bootinfo)) = $bootinfo; 59 | } 60 | 61 | # insert new CRC in a bootinfo block 62 | sub update_crc { 63 | my $bufref = shift; 64 | my $address = shift; 65 | my $crc = shift; 66 | 67 | my $bincrc = pack("v", $crc); 68 | 69 | substr($$bufref, $address, 2) = $bincrc; 70 | } 71 | 72 | # parse command line 73 | if (scalar(@ARGV) != 4) { 74 | say "Usage: $0 "; 75 | exit 1; 76 | } 77 | 78 | my $filename = shift; 79 | my $length = shift; 80 | my $devid = hex shift; 81 | my $version = hex shift; 82 | 83 | if ($length =~ /^0/) { 84 | $length = oct $length; 85 | } else { 86 | $length = 0+$length; 87 | } 88 | 89 | # samity checks 90 | if (! -e $filename) { 91 | say STDERR "ERROR: Input file >$filename< does not exist"; 92 | exit 2; 93 | } 94 | 95 | if (-s $filename > $length) { 96 | say STDERR "ERROR: Input file is longer than specified length"; 97 | exit 2; 98 | } 99 | 100 | # read file into buffer 101 | my $buffer; 102 | 103 | open IN,"<",$filename or die "Can't open $filename: $!"; 104 | binmode IN; 105 | if (-s $filename > 0) { 106 | read IN, $buffer, (-s $filename) or die "Error reading file: $!"; 107 | } else { 108 | # accept empty files for testing 109 | $buffer = ""; 110 | } 111 | close IN; 112 | 113 | # pad up to specified length 114 | if (length($buffer) < $length) { 115 | $buffer .= chr(0xff)x($length - length($buffer)); 116 | } 117 | 118 | # update bootinfo block 119 | update_bootinfo(\$buffer, $length - $BOOTINFO_SIZE, $devid, $version); 120 | 121 | # calculate CRC 122 | my $crc = 0xffff; 123 | 124 | for (my $i = 0; $i < $length - $CRC_SIZE; $i++) { 125 | $crc = crc_ccitt_update($crc, substr($buffer, $i, 1)); 126 | } 127 | 128 | # insert CRC 129 | update_crc(\$buffer, $length - $CRC_SIZE, $crc); 130 | 131 | # write new file 132 | open OUT,">",$filename or die "Can't open $filename for writing: $!"; 133 | binmode OUT; 134 | print OUT $buffer; 135 | close OUT; 136 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | c=keyv2 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.make.core.makeBuilder 10 | clean,full,incremental, 11 | 12 | 13 | org.eclipse.cdt.core.errorOutputParser 14 | org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser; 15 | 16 | 17 | org.eclipse.cdt.make.core.append_environment 18 | true 19 | 20 | 21 | org.eclipse.cdt.make.core.autoBuildTarget 22 | all 23 | 24 | 25 | org.eclipse.cdt.make.core.build.location 26 | 27 | 28 | 29 | org.eclipse.cdt.make.core.build.target.auto 30 | all 31 | 32 | 33 | org.eclipse.cdt.make.core.build.target.clean 34 | clean 35 | 36 | 37 | org.eclipse.cdt.make.core.build.target.inc 38 | all 39 | 40 | 41 | org.eclipse.cdt.make.core.buildCommand 42 | make 43 | 44 | 45 | org.eclipse.cdt.make.core.buildLocation 46 | 47 | 48 | 49 | org.eclipse.cdt.make.core.cleanBuildTarget 50 | clean 51 | 52 | 53 | org.eclipse.cdt.make.core.enableAutoBuild 54 | false 55 | 56 | 57 | org.eclipse.cdt.make.core.enableCleanBuild 58 | true 59 | 60 | 61 | org.eclipse.cdt.make.core.enableFullBuild 62 | true 63 | 64 | 65 | org.eclipse.cdt.make.core.enabledIncrementalBuild 66 | true 67 | 68 | 69 | org.eclipse.cdt.make.core.environment 70 | 71 | 72 | 73 | org.eclipse.cdt.make.core.fullBuildTarget 74 | clean all 75 | 76 | 77 | org.eclipse.cdt.make.core.incrementalBuildTarget 78 | all 79 | 80 | 81 | org.eclipse.cdt.make.core.stopOnError 82 | false 83 | 84 | 85 | org.eclipse.cdt.make.core.useDefaultBuildCmd 86 | true 87 | 88 | 89 | 90 | 91 | org.eclipse.cdt.make.core.ScannerConfigBuilder 92 | 93 | 94 | org.eclipse.cdt.make.core.ScannerConfigDiscoveryEnabled 95 | true 96 | 97 | 98 | org.eclipse.cdt.make.core.esiProviderCommandEnabled 99 | true 100 | 101 | 102 | org.eclipse.cdt.make.core.esiProviderParserId 103 | org.eclipse.cdt.make.core.GCCSpecsConsoleParser 104 | 105 | 106 | org.eclipse.cdt.make.core.makeBuilderParserEnabled 107 | true 108 | 109 | 110 | org.eclipse.cdt.make.core.makeBuilderParserId 111 | org.eclipse.cdt.make.core.GCCScannerInfoConsoleParser 112 | 113 | 114 | org.eclipse.cdt.make.core.siProblemGenerationEnabled 115 | true 116 | 117 | 118 | org.eclipse.cdt.make.core.useDefaultESIProviderCmd 119 | true 120 | 121 | 122 | 123 | 124 | 125 | org.eclipse.cdt.core.cnature 126 | org.eclipse.cdt.make.core.makeNature 127 | org.eclipse.cdt.make.core.ScannerConfigNature 128 | 129 | 130 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/translation.c: -------------------------------------------------------------------------------- 1 | 2 | void translate_keyboard(U8 scancode) { 3 | static BOOL leftshift,rightshift,leftcontrol,rightcontrol,leftalt,rightalt,capslock,numlock,scrolllock; 4 | static BOOL release,extcode,pausekey; 5 | U8 tableindex,action,category,argument; 6 | 7 | action=0; 8 | switch(scancode) { 9 | case 0xE0: 10 | extcode=TRUE; 11 | break; 12 | case 0xE1: 13 | pausekey=TRUE; 14 | break; 15 | case 0xF0: 16 | release=TRUE; 17 | return; 18 | case 0xAB: //keyboard ID is AB 83 19 | case 0x00: //overflow 20 | case 0xAA: //self-test passed 21 | case 0xEE: //echo 22 | case 0xFA: //ack 23 | case 0xFC: //self-test failed 24 | case 0xFE: //resend 25 | case 0xFF: //key detect error or overflow 26 | break; 27 | default: 28 | if (scancode==0x12) leftshift =!release; 29 | if (scancode==0x59) rightshift =!release; 30 | if ((scancode==0x14) && !extcode) leftcontrol =!release; 31 | if ((scancode==0x14) && extcode) rightcontrol=!release; 32 | if ((scancode==0x77) && pausekey) {pausekey =!release; break;} 33 | if ((scancode==0x11) && extcode) rightalt =!release; 34 | if ((scancode==0x11) && !extcode) leftalt =!release; 35 | tableindex=scancode; 36 | if (extcode ) tableindex+=0x80; 37 | if (pausekey) tableindex+=0xC0; 38 | action=translation[tableindex]; 39 | printf("[%02X %02X] ",tableindex,action); 40 | extcode=FALSE; 41 | break; 42 | } 43 | category=action&0xC0; 44 | argument=action&0x3F; 45 | if (!release) blink_keyboard_led(); 46 | switch (category) { 47 | case REMAP: // Standard key - connect or disconnect one crosspoint 48 | connect(argument,!release); 49 | break; 50 | case SPECIAL:// Extended categories 51 | category=(action&0x38); 52 | argument=(action&0x07); 53 | switch(category) { 54 | case RESTORE_KEY: // Restore button 55 | if (release) break; 56 | printf(" RESTORE "); 57 | press_restore_key(); 58 | break; 59 | case PUNCTUATION1: // Translate diffrently if shifted 60 | case PUNCTUATION2: // Translate diffrently if shifted 61 | if (category==PUNCTUATION2) argument+=8; 62 | if (!leftshift && !rightshift) { 63 | argument=punctuation_norm[argument]; 64 | if (bit_test(argument,6)) connect(0x34,!release); 65 | } else { 66 | argument=punctuation_swap[argument]; 67 | if (!bit_test(argument,6)) { 68 | if (!release) { 69 | if (leftshift ) connect(0x0F,FALSE); // release left shift 70 | if (rightshift) connect(0x34,FALSE); // release right shift 71 | } else { 72 | if (leftshift ) connect(0x0F,TRUE); // press left shift 73 | if (rightshift) connect(0x34,TRUE); // press right shift 74 | } 75 | } 76 | } 77 | bit_clear(argument,6); 78 | connect(argument,!release); 79 | break; 80 | case LOCK_KEY: // Caps lock, Num Lock, Scroll Lock 81 | if (release) break; 82 | if (argument==1) capslock^=1; 83 | if (argument==2) {numlock^=1; output_bit(JOYSWITCH_SELECT,~input(JOYSWITCH_SELECT));} 84 | if (argument==3) scrolllock^=1; 85 | set_keyboard_lights(numlock,capslock,scrolllock); 86 | break; 87 | case SNAPSHOT: 88 | if (release) break; 89 | press_snapshot_button(); 90 | break; 91 | case CBM_RESET: 92 | if (release) break; 93 | if ((leftcontrol || rightcontrol) && (leftalt || rightalt)) press_reset_button(); 94 | break; 95 | case RELEASE_ALL: 96 | if (release) break; 97 | crosspoint_init(); 98 | break; 99 | default: 100 | printf("Nothing defined for subcategory %d ",category); 101 | break; 102 | } 103 | break; 104 | case SHIFT_REMAP: // Shifted key - press SHIFT then press the key or release the key and then release SHIFT 105 | if (!release) connect(0x34,TRUE); // press left shift 106 | connect(argument,!release); 107 | if (release) connect(0x34,FALSE); // release left shift 108 | break; 109 | case IGNORE:// Ignored key - do nothing 110 | default: 111 | break; 112 | } 113 | release=FALSE; 114 | } 115 | 116 | #define PADDLEMIN 3250 117 | #define PADDLEMAX 4500 118 | 119 | void translate_mouse(U8 a, U8 b, U8 c, U8 d) { 120 | BOOL left,middle,right; 121 | S16 dx,dy; 122 | 123 | left =bit_test(a,0); 124 | right =bit_test(a,1); 125 | middle=bit_test(a,2); 126 | if (bit_test(a,4)) dx=make16(-1,b); else dx=make16(0,b); 127 | if (bit_test(a,5)) dy=make16(-1,c); else dy=make16(0,c); 128 | 129 | paddle1value+=dx*9; 130 | paddle2value+=dy*9; 131 | if (paddle1value>PADDLEMAX) paddle1value=PADDLEMIN; 132 | if (paddle2value>PADDLEMAX) paddle2value=PADDLEMIN; 133 | if (paddle1value PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2011 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | poll64.h: Definitions for PS/2 Keyboard to CBM computer scanning routine 20 | 21 | */ 22 | 23 | #ifndef _POLL64_H 24 | #define _POLL64_H 25 | 26 | #define POLL_IRQ_DIVIDER (240) 27 | #define POLL_LED_IRQ_DIVIDER (F_CPU/1024/2/POLL_IRQ_DIVIDER/3) // 3/s 28 | 29 | #define POLL_ADDR_LAYOUT (void*)0 30 | #define POLL_ADDR_LED_STATE (void*)1 31 | #define POLL_ADDR_SW_STATE (void*)2 32 | 33 | #define POLL_CBM_KEY_NONE 0xff 34 | #define POLL_CBM_KEY_UNMAPPED 0xfe 35 | #define POLL_CBM_KEY_SPECIAL 0xc0 36 | 37 | #define POLL_MAP_NONE 0 38 | #define POLL_MAP_SHIFT 1 39 | 40 | #define POLL_LAYOUT_POSITIONAL_C64 0 41 | #define POLL_LAYOUT_POSITIONAL_C128 1 42 | #define POLL_LAYOUT_SYMBOLIC_C64 2 43 | #define POLL_LAYOUT_SYMBOLIC_C128 3 44 | #define POLL_LAYOUT_NUM 4 45 | 46 | #define POLL_ST_IDLE 0 47 | #define POLL_ST_GET_X_KEY 1 48 | #define POLL_ST_GET_KEY_UP 2 49 | #define POLL_ST_GET_X_KEY_UP 3 50 | #define POLL_ST_GET_PAUSE_1 4 51 | #define POLL_ST_GET_PAUSE_2 5 52 | #define POLL_ST_GET_PAUSE_3 6 53 | #define POLL_ST_GET_PAUSE_4 7 54 | #define POLL_ST_GET_PAUSE_5 8 55 | #define POLL_ST_GET_PAUSE_6 9 56 | #define POLL_ST_GET_PAUSE_7 10 57 | 58 | #define POLL_C64_KEY_RUNSTOP 0x7A 59 | #define POLL_C64_KEY_LSHIFT 0x72 60 | #define POLL_C64_KEY_X 0x7E 61 | #define POLL_C64_KEY_V 0x76 62 | #define POLL_C64_KEY_N 0xBE 63 | #define POLL_C64_KEY_COMMA 0xB6 64 | #define POLL_C64_KEY_SLASH 0x3E 65 | #define POLL_C64_KEY_CRSR_DOWN 0x36 66 | #define POLL_C64_KEY_CTRL 0x5A 67 | #define POLL_C64_KEY_A 0x52 68 | #define POLL_C64_KEY_D 0x5E 69 | #define POLL_C64_KEY_G 0x56 70 | #define POLL_C64_KEY_J 0x9E 71 | #define POLL_C64_KEY_L 0x96 72 | #define POLL_C64_KEY_SEMICOLON 0x1E 73 | #define POLL_C64_KEY_CRSR_RIGHT 0x16 74 | #define POLL_C64_KEY_BACKARROW 0x6A 75 | #define POLL_C64_KEY_W 0x62 76 | #define POLL_C64_KEY_R 0x6E 77 | #define POLL_C64_KEY_Y 0x66 78 | #define POLL_C64_KEY_I 0xAE 79 | #define POLL_C64_KEY_P 0xA6 80 | #define POLL_C64_KEY_ASTERIX 0x2E 81 | #define POLL_C64_KEY_RETURN 0x26 82 | #define POLL_C64_KEY_1 0x4A 83 | #define POLL_C64_KEY_3 0x42 84 | #define POLL_C64_KEY_5 0x4E 85 | #define POLL_C64_KEY_7 0x46 86 | #define POLL_C64_KEY_9 0x8E 87 | #define POLL_C64_KEY_PLUS 0x86 88 | #define POLL_C64_KEY_POUND 0x0E 89 | #define POLL_C64_KEY_DELETE 0x06 90 | #define POLL_C64_KEY_2 0x78 91 | #define POLL_C64_KEY_4 0x70 92 | #define POLL_C64_KEY_6 0x7C 93 | #define POLL_C64_KEY_8 0x74 94 | #define POLL_C64_KEY_0 0xBC 95 | #define POLL_C64_KEY_MINUS 0xB4 96 | #define POLL_C64_KEY_HOME 0x3C 97 | #define POLL_C64_KEY_F7 0x34 98 | #define POLL_C64_KEY_Q 0x58 99 | #define POLL_C64_KEY_E 0x50 100 | #define POLL_C64_KEY_T 0x5C 101 | #define POLL_C64_KEY_U 0x54 102 | #define POLL_C64_KEY_O 0x9C 103 | #define POLL_C64_KEY_AT 0x94 104 | #define POLL_C64_KEY_UPARROW 0x1C 105 | #define POLL_C64_KEY_F5 0x14 106 | #define POLL_C64_KEY_CBM 0x68 107 | #define POLL_C64_KEY_S 0x60 108 | #define POLL_C64_KEY_F 0x6C 109 | #define POLL_C64_KEY_H 0x64 110 | #define POLL_C64_KEY_K 0xAC 111 | #define POLL_C64_KEY_COLON 0xA4 112 | #define POLL_C64_KEY_EQUALS 0x2C 113 | #define POLL_C64_KEY_F3 0x24 114 | #define POLL_C64_KEY_SPACE 0x48 115 | #define POLL_C64_KEY_Z 0x40 116 | #define POLL_C64_KEY_C 0x4C 117 | #define POLL_C64_KEY_B 0x44 118 | #define POLL_C64_KEY_M 0x8C 119 | #define POLL_C64_KEY_PERIOD 0x84 120 | #define POLL_C64_KEY_RSHIFT 0x0C 121 | #define POLL_C64_KEY_F1 0x04 122 | 123 | #define POLL_C128_KEY_NO_SCROLL 0x3A 124 | #define POLL_C128_KEY_NUM_3 0xB2 125 | #define POLL_C128_KEY_NUM_1 0xBA 126 | #define POLL_C128_KEY_NUM_PERIOD 0x1A 127 | #define POLL_C128_KEY_NUM_MINUS 0x92 128 | #define POLL_C128_KEY_NUM_5 0x9A 129 | #define POLL_C128_KEY_NUM_0 0x2A 130 | #define POLL_C128_KEY_NUM_PLUS 0xA2 131 | #define POLL_C128_KEY_NUM_8 0xAA 132 | #define POLL_C128_KEY_CRSR_UP 0x38 133 | #define POLL_C128_KEY_LINEFEED 0xB0 134 | #define POLL_C128_KEY_TAB 0xB8 135 | #define POLL_C128_KEY_CRSR_RIGHT 0x18 136 | #define POLL_C128_KEY_NUM_9 0x90 137 | #define POLL_C128_KEY_NUM_7 0x98 138 | #define POLL_C128_KEY_CRSR_LEFT 0x28 139 | #define POLL_C128_KEY_NUM_6 0xA0 140 | #define POLL_C128_KEY_NUM_4 0xA8 141 | #define POLL_C128_KEY_CRSR_DOWN 0x08 142 | #define POLL_C128_KEY_ENTER 0x80 143 | #define POLL_C128_KEY_NUM_2 0x88 144 | #define POLL_C128_KEY_ALT 0x0A 145 | #define POLL_C128_KEY_ESC 0x82 146 | #define POLL_C128_KEY_HELP 0x8A 147 | 148 | // pseudo keys: 149 | 150 | #define POLL_C128_PKEY_4080 0x00 151 | #define POLL_C128_PKEY_CAPSENSE 0x10 152 | #define POLL_C64_PKEY_RESTORE 0x20 153 | 154 | #define POLL_FLAG_LSHIFT 1 155 | #define POLL_FLAG_RSHIFT 2 156 | #define POLL_FLAG_SHIFT (POLL_FLAG_LSHIFT | POLL_FLAG_RSHIFT) 157 | #define POLL_FLAG_ALT 4 158 | #define POLL_FLAG_CONTROL 8 159 | #define POLL_FLAG_CTRL_ALT (POLL_FLAG_CONTROL | POLL_FLAG_ALT) 160 | 161 | 162 | #endif //_POLL64_H_ 163 | -------------------------------------------------------------------------------- /src/kb.c: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | kb.c: generic keyboard routines 20 | 21 | */ 22 | 23 | // TODO Allow users to mask off certain lines of the rows and columns as not used. 24 | #include 25 | #include 26 | #include "config.h" 27 | #include "kb.h" 28 | 29 | static uint8_t kb_rxbuf[KB_RX_BUFFER_SIZE]; 30 | static volatile uint8_t kb_rxhead; 31 | static volatile uint8_t kb_rxtail; 32 | 33 | static uint8_t kb_save[16]; 34 | static volatile uint8_t kb_state; 35 | static volatile uint8_t kb_scan_idx; 36 | 37 | #ifdef KB_SCAN_PORTS 38 | static uint8_t kb_port_save[2]; 39 | #endif 40 | 41 | static volatile uint8_t kb_repeat_code; 42 | static volatile uint16_t kb_repeat_count; 43 | static volatile uint16_t kb_repeat_delay; 44 | static volatile uint16_t kb_repeat_period; 45 | static volatile uint8_t kb_curr_value; 46 | 47 | static void kb_store(uint8_t data) { 48 | uint8_t tmphead; 49 | 50 | tmphead = (kb_rxhead + 1) & KB_RX_BUFFER_MASK; 51 | kb_rxhead = tmphead; /* Store new index */ 52 | 53 | //if ( tmphead == kb_rxtail ) { 54 | /* ERROR! Receive buffer overflow */ 55 | //} 56 | 57 | kb_rxbuf[tmphead] = data; /* Store received data in buffer */ 58 | } 59 | 60 | static void kb_decode(uint8_t new, uint8_t *old, uint8_t base) { 61 | uint8_t i, mask, result; 62 | // we have a key change. 63 | /* 64 | If old was: 00001010 65 | and new was: 01001000 66 | we need to xor: 01000010 67 | which will tell us what changed. 68 | 69 | Then, new & xor gives us new keys 70 | and old and xor gives us keys no longer pressed. 71 | */ 72 | mask = new ^ *old; 73 | result = (*old & mask); 74 | i = 0; 75 | while(result) { 76 | // we have keys no longer pressed. 77 | if(result & 1) 78 | kb_store((base + i) | KB_KEY_UP); 79 | result = result >> 1; 80 | i++; 81 | } 82 | result=(new & mask); 83 | i = 0; 84 | while(result) { 85 | // we have keys pressed. 86 | if(result & 1) 87 | kb_store(base + i); 88 | result = result >> 1; 89 | i++; 90 | } 91 | *old = new; 92 | } 93 | 94 | void kb_scan(void) { 95 | // this should be called 120 times/sec 96 | uint8_t j; 97 | uint8_t in; 98 | uint16_t tmp; 99 | // this is where we scan. 100 | // we scan at 120Hz 101 | switch(kb_state) { 102 | default: 103 | case KB_ST_READ: 104 | in = kb_repeat_code; 105 | if(in != KB_NO_REPEAT) { 106 | kb_repeat_count--; 107 | if(!kb_repeat_count) { 108 | kb_repeat_count = kb_repeat_period; 109 | kb_store(in); 110 | } 111 | } 112 | // do housekeeping 113 | in = kb_curr_value; 114 | j = kb_scan_idx; 115 | #ifdef KB_SCAN_PORTS 116 | // we broght lines hi, so check for port action. If we have it, then discard character. 117 | if(KB_ROW_LO_IN == 0xff && KB_COL_IN == 0xff && in != kb_save[j]) { 118 | #else 119 | if(in != kb_save[j]) { 120 | #endif 121 | kb_decode(in, &kb_save[j], j<<3); 122 | } 123 | j = (j + 1) & 0x0f; 124 | kb_scan_idx = j; 125 | // we just read, prep now. 126 | // set pin low: 127 | tmp = (1 << j); 128 | j = (tmp & 0xff); 129 | in = (tmp >> 8); 130 | KB_ROW_LO_DDR = j; 131 | KB_ROW_HI_DDR = in; 132 | KB_ROW_LO_OUT = (uint8_t)~j; 133 | KB_ROW_HI_OUT = (uint8_t)~in; 134 | kb_state = KB_ST_PREP; 135 | break; 136 | case KB_ST_PREP: 137 | // we just prepped, read. 138 | kb_curr_value = (uint8_t) ~KB_COL_IN; 139 | kb_state = KB_ST_READ; 140 | #ifdef KB_SCAN_PORTS 141 | // set rows back to input. 142 | KB_ROW_LO_DDR = 0; 143 | KB_ROW_HI_DDR = 0; 144 | KB_ROW_LO_OUT = 0xff; 145 | KB_ROW_HI_OUT = 0xff; 146 | j = kb_scan_idx; 147 | if(j == 0) { 148 | kb_state = KB_ST_READ_PORTS; 149 | } 150 | break; 151 | case KB_ST_READ_PORTS: 152 | // read the two ports directly 153 | in = (uint8_t)~KB_ROW_LO_IN; 154 | if(in != kb_port_save[1]) { 155 | kb_decode(in, &kb_port_save[1], 0x78); 156 | } 157 | in = (uint8_t)~KB_COL_IN; 158 | if(in != kb_port_save[0]) { 159 | kb_decode(in, &kb_port_save[0], 0x70); 160 | } 161 | kb_state = KB_ST_READ; 162 | #endif 163 | break; 164 | } 165 | } 166 | 167 | void kb_init() { 168 | kb_state = KB_ST_READ; 169 | kb_repeat_code = KB_NO_REPEAT; // set keyboard repeat to 0. 170 | kb_set_repeat_delay(250); // wait 250 ms 171 | kb_set_repeat_period(32); // once every 32 ms 172 | 173 | #ifdef KB_SCAN_PORTS 174 | KB_ROW_LO_OUT = 0xff; 175 | KB_ROW_HI_OUT = 0xff; 176 | #endif 177 | KB_COL_OUT = 0xff; // turn on pullups. 178 | } 179 | 180 | void kb_set_repeat_delay(uint16_t ms) { 181 | // 1800 ticks/sec, .5 ms per tick. 182 | kb_repeat_delay = (ms << 1); 183 | kb_repeat_count = kb_repeat_delay; 184 | } 185 | 186 | void kb_set_repeat_period(uint16_t period) { 187 | kb_repeat_period = (period << 1); 188 | } 189 | 190 | void kb_set_repeat_code(uint8_t code) { 191 | if(code != kb_repeat_code) { 192 | kb_repeat_count = kb_repeat_delay; 193 | kb_repeat_code = code; 194 | } 195 | } 196 | 197 | uint8_t kb_get_repeat_code() { 198 | return kb_repeat_code; 199 | } 200 | 201 | uint8_t kb_data_available(void) { 202 | return ( kb_rxhead != kb_rxtail ); /* Return 0 (FALSE) if the receive buffer is empty */ 203 | } 204 | 205 | uint8_t kb_recv( void ) { 206 | uint8_t tmptail; 207 | 208 | while (kb_rxhead == kb_rxtail); 209 | tmptail = (kb_rxtail + 1) & KB_RX_BUFFER_MASK;/* Calculate buffer index */ 210 | 211 | kb_rxtail = tmptail; /* Store new index */ 212 | 213 | return kb_rxbuf[tmptail]; /* Return data */ 214 | } 215 | 216 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/ps2.c: -------------------------------------------------------------------------------- 1 | 2 | static U8 ps2buf0[20],ps2buf1[20]; 3 | static U8 *ps2wp0,*ps2rp0,*ps2wp1,*ps2rp1; 4 | 5 | 6 | #PRAGMA INT_EXT HIGH 7 | void ps2clk0_fallingedge_interrupt(void) { 8 | static U16 prevedge,now; 9 | static U8 bit,rxshift; 10 | static BOOL indata; 11 | 12 | // sample as close to the falling edge as possible (will be about 40 cycles (4us) for non-fast interrupts) 13 | indata=input(PS2_DATA0); 14 | // typical time between falling edges is 83us (12 kHz clock) 15 | // this will add some degree of noise immunity by clearing out the shift register if 16 | // it's been a long time (more than 0.1 us X 256 X 20 = 512 us) since the last edge 17 | // wraparound is not handled so any noise that occured during the 512 us window around X*1677.7216 ms ago is not filtered 18 | now=get_timer0(); 19 | if ((now-prevedge)>20) bit=0; 20 | prevedge=now; 21 | if (!bit) rxshift=0; 22 | rxshift>>=1; 23 | if (indata) bit_set(rxshift,7); 24 | bit++; 25 | if (bit==9) { 26 | ps2buf0[ps2wp0]=rxshift; 27 | ps2wp0++; 28 | if (ps2wp0==sizeof(ps2buf0)) ps2wp0=0; 29 | } 30 | if (bit==11) bit=0; 31 | } 32 | 33 | #PRAGMA INT_EXT1 HIGH 34 | void ps2clk1_fallingedge_interrupt(void) { 35 | static U16 prevedge,now; 36 | static U8 bit,rxshift; 37 | static BOOL indata; 38 | 39 | // sample as close to the falling edge as possible (will be about 40 cycles (4us) for non-fast interrupts) 40 | indata=input(PS2_DATA1); 41 | // typical time between falling edges is 83us (12 kHz clock) 42 | // this will add some degree of noise immunity by clearing out the shift register if 43 | // it's been a long time (more than 0.1 us X 256 X 20 = 512 us) since the last edge 44 | // wraparound is not handled so any noise that occured during the 512 us window around X*1677.7216 ms ago is not filtered 45 | now=get_timer0(); 46 | if ((now-prevedge)>20) bit=0; 47 | prevedge=now; 48 | if (!bit) rxshift=0; 49 | rxshift>>=1; 50 | if (indata) bit_set(rxshift,7); 51 | bit++; 52 | if (bit==9) { 53 | ps2buf1[ps2wp1]=rxshift; 54 | ps2wp1++; 55 | if (ps2wp1==sizeof(ps2buf1)) ps2wp1=0; 56 | } 57 | if (bit==11) bit=0; 58 | } 59 | 60 | 61 | #define CLKHI 0 62 | #define CLKLO 1 63 | #define DATAHI 2 64 | #define DATALO 3 65 | 66 | BOOL waitfor_ps2_0(U8 state) { 67 | U16 start,now; 68 | start=get_timer0(); 69 | do { 70 | switch (state) { 71 | case CLKHI: if ( input(PS2_CLK0 )) return(TRUE); break; 72 | case CLKLO: if (!input(PS2_CLK0 )) return(TRUE); break; 73 | case DATAHI: if ( input(PS2_DATA0)) return(TRUE); break; 74 | case DATALO: if (!input(PS2_DATA0)) return(TRUE); break; 75 | } 76 | now=get_timer0(); 77 | } while (now-start<196); // waiting more than 5ms means the keypad is probably unplugged 78 | return(FALSE); 79 | } 80 | 81 | BOOL waitfor_ps2_1(U8 state) { 82 | U16 start,now; 83 | start=get_timer0(); 84 | do { 85 | switch (state) { 86 | case CLKHI: if ( input(PS2_CLK1 )) return(TRUE); break; 87 | case CLKLO: if (!input(PS2_CLK1 )) return(TRUE); break; 88 | case DATAHI: if ( input(PS2_DATA1)) return(TRUE); break; 89 | case DATALO: if (!input(PS2_DATA1)) return(TRUE); break; 90 | } 91 | now=get_timer0(); 92 | } while (now-start<196); // waiting more than 5ms means the keypad is probably unplugged 93 | return(FALSE); 94 | } 95 | 96 | #PRAGMA use standard_io (PS2_CLK_PORT) 97 | #PRAGMA use standard_io (PS2_DATA_PORT) 98 | 99 | // normally will take about 3ms but can take 120ms if the keypad is unplugged 100 | BOOL ps2_send0(U8 txchar) { 101 | U16 txshift; 102 | BOOL parity,status; 103 | U8 i; 104 | 105 | txshift=txchar; 106 | parity=1; 107 | for (i=0; i<8; i++) { 108 | if (bit_test(txchar,0)) parity^=1; 109 | txchar>>=1; 110 | } 111 | if (parity) bit_set(txshift,8); // parity bit 112 | bit_set(txshift,9); // stop bit 113 | status=TRUE; 114 | disable_interrupts(INT_EXT); 115 | output_low(PS2_CLK0); 116 | delay_us(110); 117 | output_float(PS2_CLK0); 118 | output_low(PS2_DATA0); 119 | for (i=0; i<10; i++) { 120 | status&=waitfor_ps2_0(CLKLO); 121 | if (bit_test(txshift,0)) output_float(PS2_DATA0); 122 | else output_low (PS2_DATA0); 123 | txshift>>=1; 124 | status&=waitfor_ps2_0(CLKHI); 125 | } 126 | status&=waitfor_ps2_0(DATALO); 127 | status&=waitfor_ps2_0(CLKLO); 128 | status&=waitfor_ps2_0(CLKHI); 129 | status&=waitfor_ps2_0(DATAHI); 130 | INT0IF=0; 131 | enable_interrupts(INT_EXT); 132 | return(status); 133 | } 134 | 135 | BOOL ps2_send1(U8 txchar) { 136 | U16 txshift; 137 | BOOL parity,status; 138 | U8 i; 139 | 140 | txshift=txchar; 141 | parity=1; 142 | for (i=0; i<8; i++) { 143 | if (bit_test(txchar,0)) parity^=1; 144 | txchar>>=1; 145 | } 146 | if (parity) bit_set(txshift,8); // parity bit 147 | bit_set(txshift,9); // stop bit 148 | status=TRUE; 149 | disable_interrupts(INT_EXT1); 150 | output_low(PS2_CLK1); 151 | delay_us(110); 152 | output_float(PS2_CLK1); 153 | output_low(PS2_DATA1); 154 | for (i=0; i<10; i++) { 155 | status&=waitfor_ps2_1(CLKLO); 156 | if (bit_test(txshift,0)) output_float(PS2_DATA1); 157 | else output_low (PS2_DATA1); 158 | txshift>>=1; 159 | status&=waitfor_ps2_1(CLKHI); 160 | } 161 | status&=waitfor_ps2_1(DATALO); 162 | status&=waitfor_ps2_1(CLKLO); 163 | status&=waitfor_ps2_1(CLKHI); 164 | status&=waitfor_ps2_1(DATAHI); 165 | INT1IF=0; 166 | enable_interrupts(INT_EXT1); 167 | return(status); 168 | } 169 | 170 | void ps2_suspend0(void) { 171 | disable_interrupts(INT_EXT); 172 | output_low(PS2_CLK0); 173 | INT0IF=0; 174 | } 175 | 176 | void ps2_suspend1(void) { 177 | disable_interrupts(INT_EXT1); 178 | output_low(PS2_CLK1); 179 | INT1IF=0; 180 | } 181 | 182 | void ps2_resume0(void) { 183 | output_float(PS2_CLK0); // data will start flowing in about 800 us 184 | INT0IF=0; 185 | enable_interrupts(INT_EXT); 186 | } 187 | 188 | void ps2_resume1(void) { 189 | output_float(PS2_CLK1); // data will start flowing in about 800 us 190 | INT1IF=0; 191 | enable_interrupts(INT_EXT1); 192 | } 193 | 194 | #PRAGMA use fast_io (PS2_CLK_PORT) 195 | #PRAGMA use fast_io (PS2_DATA_PORT) 196 | 197 | 198 | void ps2_init(void) { 199 | ps2wp0=0; 200 | ps2rp0=0; 201 | ps2wp1=0; 202 | ps2rp1=0; 203 | ext_int_edge(0,H_TO_L); 204 | ext_int_edge(1,H_TO_L); 205 | enable_interrupts(INT_EXT); 206 | enable_interrupts(INT_EXT1); 207 | } 208 | 209 | 210 | U8 ps2_rxavailable1(void) { 211 | U8 w,r; 212 | disable_interrupts(GLOBAL); 213 | w=ps2wp1; // create a local copy since the ISR owns the global one 214 | enable_interrupts(GLOBAL); 215 | r=ps2rp1; 216 | if (w>=r) return(w-r); 217 | else return(w+sizeof(ps2buf1)-r); 218 | } 219 | 220 | U8 ps2_rxavailable0(void) { 221 | U8 w,r; 222 | disable_interrupts(GLOBAL); 223 | w=ps2wp0; // create a local copy since the ISR owns the global one 224 | enable_interrupts(GLOBAL); 225 | r=ps2rp0; 226 | if (w>=r) return(w-r); 227 | else return(w+sizeof(ps2buf0)-r); 228 | } 229 | 230 | U8 ps2_getrxbyte1(void) { 231 | U8 x; 232 | x=ps2buf1[ps2rp1]; 233 | ps2rp1++; 234 | if (ps2rp1==sizeof(ps2buf1)) ps2rp1=0; 235 | return(x); 236 | } 237 | 238 | U8 ps2_getrxbyte0(void) { 239 | U8 x; 240 | x=ps2buf0[ps2rp0]; 241 | ps2rp0++; 242 | if (ps2rp0==sizeof(ps2buf0)) ps2rp0=0; 243 | return(x); 244 | } 245 | 246 | 247 | BOOL set_keyboard_lights(BOOL numlock, BOOL capslock, BOOL scrollock) { 248 | BOOL status; 249 | U8 cmd; 250 | cmd=0; 251 | if (numlock ) bit_set(cmd,1); 252 | if (capslock ) bit_set(cmd,2); 253 | if (scrollock) bit_set(cmd,0); 254 | status=ps2_send1(0xED); 255 | delay_ms(2); 256 | status&=ps2_send1(cmd); 257 | delay_ms(2); 258 | return(status); 259 | } 260 | -------------------------------------------------------------------------------- /src/uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2011 4 | 5 | This code is a modification of uart functions in sd2iec: 6 | Copyright (C) 2007,2008 Ingo Korb 7 | 8 | This program is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; version 2 of the License only. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | uart.c: UART access routines 22 | 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "config.h" 30 | #include "uart.h" 31 | 32 | #ifdef ENABLE_UART0 33 | # if defined UART0_TX_BUFFER_SHIFT && UART0_TX_BUFFER_SHIFT > 0 34 | static uint8_t tx0_buf[1 << UART0_TX_BUFFER_SHIFT]; 35 | static volatile uint8_t tx0_tail; 36 | static volatile uint8_t tx0_head; 37 | # endif 38 | # if defined UART0_RX_BUFFER_SHIFT && UART0_RX_BUFFER_SHIFT > 0 39 | static uint8_t rx0_buf[1 << UART0_RX_BUFFER_SHIFT]; 40 | static volatile uint8_t rx0_tail; 41 | static volatile uint8_t rx0_head; 42 | # endif 43 | #endif 44 | 45 | #ifdef ENABLE_UART1 46 | # if defined UART1_TX_BUFFER_SHIFT && UART1_TX_BUFFER_SHIFT > 0 47 | static uint8_t tx1_buf[1 << UART1_TX_BUFFER_SHIFT]; 48 | static volatile uint8_t tx1_tail; 49 | static volatile uint8_t tx1_head; 50 | # endif 51 | # if defined UART1_RX_BUFFER_SHIFT && UART1_RX_BUFFER_SHIFT > 0 52 | static uint8_t rx1_buf[1 << UART1_RX_BUFFER_SHIFT]; 53 | static volatile uint8_t rx1_head; 54 | static volatile uint8_t rx1_tail; 55 | # endif 56 | #endif 57 | 58 | /* UART0 Interrupt handlers */ 59 | #if defined ENABLE_UART0 60 | # if defined UART0_TX_BUFFER_SHIFT && UART0_TX_BUFFER_SHIFT > 0 61 | ISR(USARTA_UDRE_vect) { 62 | if ( tx0_head != tx0_tail ) { 63 | UDRA = tx0_buf[tx0_tail]; /* Start transmition */ 64 | /* Calculate and store buffer index */ 65 | tx0_tail = (tx0_tail + 1) & (sizeof(tx0_buf) - 1); 66 | } else { 67 | UCSRAB &= ~ _BV(UDRIEA); /* Disable interrupt */ 68 | } 69 | } 70 | # endif 71 | 72 | # if defined UART0_RX_BUFFER_SHIFT && UART0_RX_BUFFER_SHIFT > 0 73 | ISR(USARTA_RXC_vect) { 74 | /* Calculate and store buffer index */ 75 | rx0_head = (rx0_head + 1) & (sizeof(rx0_buf) - 1); 76 | if ( rx0_head == rx0_tail ) { 77 | /* ERROR! Receive buffer overflow */ 78 | } 79 | rx0_buf[rx0_head] = UDRA; /* Read and store received data */ 80 | } 81 | # endif 82 | 83 | uint8_t uart0_data_available(void) { 84 | #if defined UART0_RX_BUFFER_SHIFT && UART0_RX_BUFFER_SHIFT > 0 85 | /* Return 0 (FALSE) if the receive buffer is empty */ 86 | return ( rx0_head != rx0_tail ); 87 | #else 88 | return ((UCSRAA & (1 << RXCA)) != 0); 89 | #endif 90 | } 91 | uint8_t uart_data_available(void) __attribute__ ((weak, alias("uart0_data_available"))); 92 | 93 | void uart0_putc(uint8_t data) { 94 | #if defined UART0_TX_BUFFER_SHIFT && UART0_TX_BUFFER_SHIFT > 0 95 | /* Calculate buffer index */ 96 | uint8_t t = (tx0_head + 1) & (sizeof(tx0_buf) - 1); 97 | while(t == tx0_tail); /* Wait for free space in buffer */ 98 | 99 | tx0_buf[tx0_head] = data; /* Store data in buffer */ 100 | tx0_head = t; /* Store new index */ 101 | UCSRAB |= _BV(UDRIEA); /* Enable UDR0E interrupt */ 102 | #else 103 | loop_until_bit_is_set(UCSRAA,UDREA); 104 | UDRA = data; 105 | #endif 106 | } 107 | void uart_putc(uint8_t data) __attribute__ ((weak, alias("uart0_putc"))); 108 | 109 | uint8_t uart0_getc(void) { 110 | # if defined UART0_RX_BUFFER_SHIFT && UART0_RX_BUFFER_SHIFT > 0 111 | while (rx0_head == rx0_tail) {;} 112 | /* Calculate and store buffer index */ 113 | rx0_tail = ( rx0_tail + 1 ) & (sizeof(rx0_buf)-1); 114 | return rx0_buf[rx0_tail]; /* Return data */ 115 | # else 116 | loop_until_bit_is_set(UCSRAA,RXCA); 117 | return UDRA; 118 | # endif 119 | } 120 | uint8_t uart_getc(void) __attribute__ ((weak, alias("uart0_getc"))); 121 | 122 | void uart0_flush(void) { 123 | # if defined UART0_TX_BUFFER_SHIFT && UART0_TX_BUFFER_SHIFT > 0 124 | while (tx0_head != tx0_tail) ; 125 | # endif 126 | } 127 | void uart_flush(void) __attribute__ ((weak, alias("uart0_flush"))); 128 | 129 | void uart0_puts_P(const char *text) { 130 | uint8_t ch; 131 | 132 | while ((ch = pgm_read_byte(text++))) { 133 | uart0_putc(ch); 134 | } 135 | } 136 | 137 | void uart_puts_P(const char *text) __attribute__ ((weak, alias("uart0_puts_P"))); 138 | 139 | void uart0_putcrlf(void) { 140 | uart0_putc(13); 141 | uart0_putc(10); 142 | } 143 | void uart_putcrlf(void) __attribute__ ((weak, alias("uart0_putcrlf"))); 144 | 145 | # ifdef DYNAMIC_UART 146 | void uart0_config(uint16_t rate, uartlen_t length, uartpar_t parity, uartstop_t stopbits) { 147 | UBRRAH = rate >> 8; 148 | UBRRAL = rate & 0xff; 149 | 150 | UART0_CONFIG(length, parity, stopbits); 151 | } 152 | void uart_config(uint16_t rate, uartlen_t length, uartpar_t parity, uartstop_t stopbits) __attribute__ ((weak, alias("uart0_config"))); 153 | # endif 154 | 155 | void uart0_puthex(uint8_t hex) { 156 | uint8_t tmp = hex >> 4; 157 | 158 | uart_putc(tmp>9?tmp - 10 + 'a':tmp + '0'); 159 | tmp = hex & 0x0f; 160 | uart_putc(tmp>9?tmp - 10 + 'a':tmp + '0'); 161 | } 162 | void uart_puthex(uint8_t hex) __attribute__ ((weak, alias("uart0_puthex"))); 163 | 164 | void uart0_trace(void *ptr, uint16_t start, uint16_t len) { 165 | uint16_t i; 166 | uint8_t j; 167 | uint8_t ch; 168 | uint8_t *data = ptr; 169 | 170 | data+=start; 171 | for(i=0;i> 8); 174 | uart0_puthex(start & 0xff); 175 | uart0_putc('|'); 176 | uart0_putc(' '); 177 | for(j = 0;j < 16;j++) { 178 | if(i + j < len) { 179 | ch=*(data + j); 180 | uart0_puthex(ch); 181 | } else { 182 | uart0_putc(' '); 183 | uart0_putc(' '); 184 | } 185 | uart0_putc(' '); 186 | } 187 | uart0_putc('|'); 188 | for(j = 0;j < 16;j++) { 189 | if(i + j < len) { 190 | ch=*(data++); 191 | if(ch < 32 || ch > 0x7e) 192 | ch='.'; 193 | uart0_putc(ch); 194 | } else { 195 | uart0_putc(' '); 196 | } 197 | } 198 | uart0_putc('|'); 199 | uart0_putcrlf(); 200 | start += 16; 201 | } 202 | } 203 | void uart_trace(void *ptr, uint16_t start, uint16_t len) __attribute__ ((weak, alias("uart0_trace"))); 204 | 205 | 206 | static int ioputc(char c, FILE *stream) { 207 | (void) stream; 208 | if (c == '\n') 209 | uart0_putc('\r'); 210 | uart0_putc(c); 211 | return 0; 212 | } 213 | 214 | static FILE mystdout = FDEV_SETUP_STREAM(ioputc, NULL, _FDEV_SETUP_WRITE); 215 | #endif 216 | 217 | #ifdef ENABLE_UART1 218 | # if defined UART1_TX_BUFFER_SHIFT && UART1_TX_BUFFER_SHIFT > 0 219 | ISR(USARTB_UDRE_vect) { 220 | if ( tx1_head != tx1_tail ) { 221 | UDRB = tx1_buf[tx1_tail]; /* Start transmition */ 222 | /* Calculate and store buffer index */ 223 | tx1_tail = (tx1_tail + 1) & (sizeof(tx1_buf) - 1); 224 | } else { 225 | UCSRBB &= ~ _BV(UDRIEB); /* Disable interrupt */ 226 | } 227 | } 228 | # endif 229 | 230 | # if defined UART1_RX_BUFFER_SHIFT && UART1_RX_BUFFER_SHIFT > 0 231 | ISR(USARTB_RXC_vect) { 232 | /* Calculate and store buffer index */ 233 | rx1_head = ( rx1_head + 1 ) & (sizeof(rx1_buf) - 1); 234 | if ( rx1_head == rx1_tail ) { 235 | /* ERROR! Receive buffer overflow */ 236 | } 237 | rx1_buf[rx1_head] = UDRB; /* Read and store received data */ 238 | } 239 | # endif 240 | 241 | void uart1_putc(char data) { 242 | # if defined UART1_TX_BUFFER_SHIFT && UART1_TX_BUFFER_SHIFT > 0 243 | uint8_t t = (tx1_head + 1) & (sizeof(tx1_buf) - 1); 244 | UCSRBB &= ~ _BV(UDRIEB); // turn off RS232 irq 245 | tx1_buf[tx1_head] = data; 246 | tx1_head = t; 247 | UCSRBB |= _BV(UDRIEB); 248 | # else 249 | loop_until_bit_is_set(UCSRBA,UDREB); 250 | UDRB = data; 251 | # endif 252 | } 253 | 254 | uint8_t uart1_getc(void) { 255 | #if !defined UART1_RX_BUFFER_SHIFT || UART1_RX_BUFFER_SHIFT == 0 256 | loop_until_bit_is_set(UCSRBA,RXCB); 257 | return UDRB; 258 | #else 259 | uint8_t tmptail; 260 | 261 | while ( rx1_head == rx1_tail ) { ; } 262 | tmptail = ( rx1_tail + 1 ) & (sizeof(rx1_buf)-1);/* Calculate buffer index */ 263 | 264 | rx1_tail = tmptail; /* Store new index */ 265 | 266 | return rx1_buf[tmptail]; /* Return data */ 267 | #endif 268 | } 269 | 270 | void uart1_puts(char* str) { 271 | while(*str) 272 | uart1_putc(*str++); 273 | } 274 | 275 | # ifdef DYNAMIC_UART 276 | void uart1_config(uint16_t rate, uartlen_t length, uartpar_t parity, uartstop_t stopbits) { 277 | UBRRBH = rate >> 8; 278 | UBRRBL = rate & 0xff; 279 | 280 | UART1_CONFIG(length, parity, stopbits); 281 | } 282 | # endif 283 | #endif 284 | 285 | #if defined ENABLE_UART0 || defined ENABLE_UART1 286 | /* Initialize UART */ 287 | void uart_init(void) { 288 | /* Set the baud rate */ 289 | # if defined ENABLE_UART0 290 | UART0_MODE_SETUP(); 291 | 292 | UBRRAH = CALC_BPS(UART0_BAUDRATE) >> 8; 293 | UBRRAL = CALC_BPS(UART0_BAUDRATE) & 0xff; 294 | 295 | # ifdef UART_DOUBLE_SPEED 296 | /* double the speed of the serial port. */ 297 | UCSRAA = (1< 0 303 | | _BV(RXCIEA) 304 | # endif 305 | | _BV(RXENA) 306 | | _BV(TXENA) 307 | ); 308 | 309 | 310 | 311 | /* Flush buffers */ 312 | # if defined UART0_TX_BUFFER_SHIFT && UART0_TX_BUFFER_SHIFT > 0 313 | tx0_tail = 0; 314 | tx0_head = 0; 315 | # endif 316 | # if defined UART0_RX_BUFFER_SHIFT && UART0_RX_BUFFER_SHIFT > 0 317 | rx0_tail = 0; 318 | rx0_head = 0; 319 | # endif 320 | 321 | stdout = &mystdout; 322 | # endif 323 | 324 | # ifdef ENABLE_UART1 325 | UART1_MODE_SETUP(); 326 | 327 | UBRRBH = CALC_BPS(UART1_BAUDRATE) >> 8; 328 | UBRRBL = CALC_BPS(UART1_BAUDRATE) & 0xff; 329 | 330 | /* Enable UART receiver and transmitter */ 331 | UCSRBB = (0 332 | # if defined UART1_RX_BUFFER_SHIFT && UART1_RX_BUFFER_SHIFT > 0 333 | | _BV(RXCIEB) 334 | # endif 335 | | _BV(RXENB) 336 | | _BV(TXENB) 337 | ); 338 | 339 | /* Flush buffers */ 340 | # if defined UART1_TX_BUFFER_SHIFT && UART1_TX_BUFFER_SHIFT > 0 341 | tx1_tail = 0; 342 | tx1_head = 0; 343 | # endif 344 | # if defined UART1_RX_BUFFER_SHIFT && UART1_RX_BUFFER_SHIFT > 0 345 | rx1_tail = 0; 346 | rx1_head = 0; 347 | # endif 348 | # endif 349 | } 350 | #endif 351 | -------------------------------------------------------------------------------- /src/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This code is a modification of uart functions in sd2iec: 6 | Copyright (C) 2007,2008 Ingo Korb 7 | 8 | This program is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; version 2 of the License only. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | uart.h: Definitions for the UART access routines 22 | 23 | */ 24 | 25 | #ifndef UART_H 26 | #define UART_H 27 | 28 | #ifdef UART_DOUBLE_SPEED 29 | #define CALC_BPS(x) (int)((double)F_CPU/(8.0*x)-1) 30 | #else 31 | #define CALC_BPS(x) (int)((double)F_CPU/(16.0*x)-1) 32 | #endif 33 | 34 | #define B0300 CALC_BPS(300) 35 | #define B0600 CALC_BPS(600) 36 | #define B1200 CALC_BPS(1200) 37 | #define B2400 CALC_BPS(2400) 38 | #define B4800 CALC_BPS(4800) 39 | #define B9600 CALC_BPS(9600) 40 | #define B19200 CALC_BPS(19200) 41 | #define B38400 CALC_BPS(38400) 42 | #define B57600 CALC_BPS(57600) 43 | #define B76800 CALC_BPS(76800) 44 | #define B115200 CALC_BPS(115200) 45 | #define B230400 CALC_BPS(230400) 46 | #define B460800 CALC_BPS(460800) 47 | #define B921600 CALC_BPS(921600) 48 | 49 | #if defined __AVR_ATmega162__ || defined __AVR_ATmega644__ || defined __AVR_ATmega644P__ || defined __AVR_ATmega1281__ || defined __AVR_ATmega2561__ || defined __AVR_ATmega128__ 50 | 51 | # ifdef SWAP_UART 52 | # define UDREA UDRE1 53 | # define RXCIEA RXCIE1 54 | # define TXCIEA TXCIE1 55 | # define RXENA RXEN1 56 | # define TXENA TXEN1 57 | # define UCSZA0 UCSZ10 58 | # define UCSZA1 UCSZ11 59 | # define UPMA0 UPM10 60 | # define UPMA1 UPM11 61 | # define USBSA USBS1 62 | # define URSELA URSEL1 63 | # define RXCA RXC1 64 | # define RXENA RXEN1 65 | # define TXCA TXC1 66 | # define TXENA TXEN1 67 | # define UBRRAH UBRR1H 68 | # define UBRRAL UBRR1L 69 | # define UCSRAA UCSR1A 70 | # define UCSRAB UCSR1B 71 | # define UCSRAC UCSR1C 72 | # define UDRA UDR1 73 | # define UDRIEA UDRIE1 74 | # define U2XA U2X1 75 | # define USARTA_UDRE_vect USART1_UDRE_vect 76 | # define USARTA_RXC_vect USART1_RXC_vect 77 | # define UDREB UDRE0 78 | # define RXCIEB RXCIE0 79 | # define TXCIEB TXCIE0 80 | # define RXENB RXEN0 81 | # define TXENB TXEN0 82 | # define UCSZB0 UCSZ00 83 | # define UCSZB1 UCSZ01 84 | # define UPMB0 UPM00 85 | # define UPMB1 UPM01 86 | # define USBSB USBS0 87 | # define URSELB URSEL0 88 | # define RXCB RXC0 89 | # define TXCB TXC0 90 | # define UBRRBH UBRR0H 91 | # define UBRRBL UBRR0L 92 | # define UCSRBA UCSR0A 93 | # define UCSRBB UCSR0B 94 | # define UCSRBAC UCSR0C 95 | # define UDRB UDR0 96 | # define UDRIEB UDRIE0 97 | # define U2XB U2X0 98 | # define USARTB_UDRE_vect USART0_UDRE_vect 99 | # define USARTB_RXC_vect USART0_RXC_vect 100 | 101 | # else 102 | /* Default is USART0 */ 103 | # define UDREA UDRE0 104 | # define RXCIEA RXCIE0 105 | # define TXCIEA TXCIE0 106 | # define RXENA RXEN0 107 | # define TXENA TXEN0 108 | # define UCSZA0 UCSZ00 109 | # define UCSZA1 UCSZ01 110 | # define UPMA0 UPM00 111 | # define UPMA1 UPM01 112 | # define USBSA USBS0 113 | # define URSELA URSEL0 114 | # define RXCA RXC0 115 | # define RXENA RXEN0 116 | # define TXCA TXC0 117 | # define TXENA TXEN0 118 | # define UBRRAH UBRR0H 119 | # define UBRRAL UBRR0L 120 | # define UCSRAA UCSR0A 121 | # define UCSRAB UCSR0B 122 | # define UCSRAC UCSR0C 123 | # define UDRA UDR0 124 | # define UDRIEA UDRIE0 125 | # define U2XA U2X0 126 | # define USARTA_UDRE_vect USART0_UDRE_vect 127 | # define USARTA_RXC_vect USART0_RXC_vect 128 | # define UDREB UDRE1 129 | # define RXCIEB RXCIE1 130 | # define TXCIEB TXCIE1 131 | # define RXENB RXEN1 132 | # define TXENB TXEN1 133 | # define UCSZB0 UCSZ10 134 | # define UCSZB1 UCSZ11 135 | # define UPMB0 UPM10 136 | # define UPMB1 UPM11 137 | # define USBSB USBS1 138 | # define URSELB URSEL1 139 | # define RXCB RXC1 140 | # define TXCB TXC1 141 | # define UBRRBH UBRR1H 142 | # define UBRRBL UBRR1L 143 | # define UCSRBA UCSR1A 144 | # define UCSRBB UCSR1B 145 | # define UCSRBC UCSR1C 146 | # define UDRB UDR1 147 | # define UDRIEB UDRIE1 148 | # define U2XB U2X1 149 | # define USARTB_UDRE_vect USART1_UDRE_vect 150 | # define USARTB_RXC_vect USART1_RXC_vect 151 | # endif 152 | 153 | #elif defined __AVR_ATmega28__ || defined __AVR_ATmega48__ || defined __AVR_ATmega88__ || defined __AVR_ATmega168__ 154 | # define UDREA UDRE0 155 | # define UCSZA0 UCSZ00 156 | # define UCSZA1 UCSZ01 157 | # define UPMA0 UPM00 158 | # define UPMA1 UPM01 159 | # define USBSA USBS0 160 | # define UCSZB0 UCSZ10 161 | # define UCSZB1 UCSZ11 162 | # define UPMB0 UPM10 163 | # define UPMB1 UPM11 164 | # define USBSB USBS1 165 | 166 | # define UDRA UDR0 167 | # define RXCA RXC0 168 | # define RXENA RXEN0 169 | # define TXCA TXC0 170 | # define TXENA TXEN0 171 | # define UBRRAH UBRR0H 172 | # define UBRRAL UBRR0L 173 | # define UCSRAA UCSR0A 174 | # define UCSRAB UCSR0B 175 | # define UCSRAC UCSR0C 176 | # define UDRIEA UDRIE0 177 | # define U2XA U2X0 178 | # define USARTA_UDRE_vect USART_UDRE_vect 179 | # define USARTA_RXC_vect USART_RXC_vect 180 | 181 | #elif defined __AVR_ATtiny2313__ || defined __AVR_ATtiny4313__ || defined __AVR_ATmega165__ || defined __AVR_ATmega165A__ || defined __AVR_ATmega165P__ || defined __AVR_ATmega165PA__ || defined __AVR_ATmega32__ || defined __AVR_ATmega16__ || defined __AVR_ATmega8__ 182 | // only 1 uart 183 | # define UDREA UDRE 184 | # define UDRA UDR 185 | # define RXCA RXC 186 | # define RXENA RXEN 187 | # define TXCA TXC 188 | # define TXENA TXEN 189 | # define UBRRAH UBRRH 190 | # define UBRRAL UBRRL 191 | # define UCSRAA UCSRA 192 | # define UCSRAB UCSRB 193 | # define UCSRAC UCSRC 194 | # define UDRIEA UDRIE 195 | # define URSELA URSEL 196 | # define U2XA U2X 197 | # if defined __AVR_ATmega165__ 198 | # define USARTA_UDRE_vect USART0_UDRE_vect 199 | # define USARTA_RXC_vect USART0_RXC_vect 200 | # else 201 | # define USARTA_UDRE_vect USART_UDRE_vect 202 | # define USARTA_RXC_vect USART_RXC_vect 203 | # endif 204 | # define USBSA USBS 205 | # define UCSZA0 UCSZ0 206 | # define UCSZA1 UCSZ1 207 | # define UPMA0 UPM0 208 | # define UPMA1 UPM1 209 | 210 | #else 211 | # error Unknown chip! 212 | #endif 213 | 214 | #if defined __AVR_ATmega8__ || defined __AVR_ATmega16__ || defined __AVR_ATmega32__ || defined __AVR_ATmega162__ 215 | # define UART0_CONFIG(l,p,s) do{\ 216 | uint8_t __tmp; \ 217 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { \ 218 | __tmp = UCSRAC; \ 219 | __tmp = UCSRAC & (uint8_t)~(UART_LENGTH_MASK | UART_PARITY_MASK | UART_STOP_MASK); \ 220 | UCSRAC = __tmp | _BV(URSELA) | (l & UART_LENGTH_MASK) | (p & UART_PARITY_MASK) | (s & UART_STOP_MASK); \ 221 | } \ 222 | } while(0) 223 | # if defined __AVR_ATmega16__ || defined __AVR_ATmega32__ 224 | # define UART0_MODE_SETUP() do { UCSRAC = _BV(URSELA) | _BV(UCSZA1) | _BV(UCSZA0); } while(0) 225 | # else 226 | # define UART0_MODE_SETUP() do { UCSRAC = _BV(UCSZA1) | _BV(UCSZA0); } while(0) 227 | # endif 228 | # if defined __AVR_ATmega162__ 229 | # define UART1_CONFIG(l,p,s) do{\ 230 | uint8_t __tmp; \ 231 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { \ 232 | __tmp = UCSRBC; \ 233 | __tmp = UCSRBC & (uint8_t)~(UART_LENGTH_MASK | UART_PARITY_MASK | UART_STOP_MASK); \ 234 | UCSRBC = __tmp | _BV(URSELB) | (l & UART_LENGTH_MASK) | (p & UART_PARITY_MASK) | (s & UART_STOP_MASK); \ 235 | } \ 236 | } while(0) 237 | # define UART1_MODE_SETUP() do { UCSRBC = _BV(URSELB) | _BV(UCSZB1) | _BV(UCSZB0); } while(0) 238 | # endif 239 | #else 240 | # define UART0_CONFIG(l,p,s) do{\ 241 | UCSRAC = (UCSRAC & (uint8_t)~(UART_LENGTH_MASK | UART_PARITY_MASK | UART_STOP_MASK)) |\ 242 | (l & UART_LENGTH_MASK) | (p & UART_PARITY_MASK) | (s & UART_STOP_MASK); \ 243 | } while(0) 244 | # define UART1_CONFIG(l,p,s) do{\ 245 | UCSRBC = (UCSRBC & (uint8_t)~(UART_LENGTH_MASK | UART_PARITY_MASK | UART_STOP_MASK)) |\ 246 | (l & UART_LENGTH_MASK) | (p & UART_PARITY_MASK) | (s & UART_STOP_MASK); \ 247 | } while(0) 248 | # define UART0_MODE_SETUP() do { UCSRAC = _BV(UCSZA1) | _BV(UCSZA0); } while(0) 249 | # define UART1_MODE_SETUP() do { UCSRBC = _BV(UCSZB1) | _BV(UCSZB0); } while(0) 250 | #endif 251 | 252 | #if defined ENABLE_UART0 || defined ENABLE_UART1 253 | #include 254 | void uart_init(void); 255 | uint8_t uart_getc(void); 256 | void uart_putc(uint8_t c); 257 | void uart_puthex(uint8_t hex); 258 | void uart_trace(void *ptr, uint16_t start, uint16_t len); 259 | void uart_flush(void); 260 | //void uart_puts_P(prog_char *text); 261 | void uart_puts_P(const char *text); 262 | uint8_t uart_data_available(void); 263 | void uart_putcrlf(void); 264 | 265 | #else 266 | # define uart_init() do {} while(0) 267 | #define uart_getc() 0 268 | #define uart_putc(x) do {} while(0) 269 | #define uart_puthex(x) do {} while(0) 270 | #define uart_trace(x,y,z) do {} while(0) 271 | #define uart_flush() do {} while(0) 272 | #define uart_puts_P(x) do {} while(0) 273 | #define uart_putcrlf() do {} while(0) 274 | 275 | #endif 276 | 277 | #if defined ENABLE_UART0 278 | uint8_t uart0_getc(void); 279 | void uart0_putc(uint8_t data); 280 | void uart_puthex(uint8_t hex); 281 | void uart_trace(void *ptr, uint16_t start, uint16_t len); 282 | void uart0_flush(void); 283 | //void uart0_puts_P(prog_char *text); 284 | void uart0_puts_P(const char *text); 285 | uint8_t uart0_data_available(void); 286 | void uart0_putcrlf(void); 287 | # include 288 | # define dprintf(str,...) printf_P(PSTR(str), ##__VA_ARGS__) 289 | #else 290 | # define uart0_getc() 0 291 | # define uart0_putc(x) do {} while(0) 292 | # define uart0_puthex(x) do {} while(0) 293 | # define uart_trace(x,y,z) do {} while(0) 294 | # define uart0_puts_P(x) do {} while(0) 295 | # define uart0_data_available() do {} while(0) 296 | # define uart0_putcrlf() do {} while(0) 297 | #endif 298 | 299 | #ifdef ENABLE_UART1 300 | uint8_t uart1_getc(void); 301 | void uart1_putc(char c); 302 | void uart1_puts(char* str); 303 | #else 304 | # define uart1_getc() 0 305 | # define uart1_putc(x) do {} while(0) 306 | # define uart1_puts(x) do {} while(0) 307 | #endif 308 | 309 | #define UART_LENGTH_MASK (_BV(UCSZA1) | _BV(UCSZA0)) 310 | #define UART_LENGTH_5 0 311 | #define UART_LENGTH_6 _BV(UCSZA0) 312 | #define UART_LENGTH_7 _BV(UCSZA1) 313 | #define UART_LENGTH_8 UART_LENGTH_MASK 314 | 315 | #define UART_PARITY_MASK (_BV(UPMA1) | _BV(UPMA0)) 316 | #define UART_PARITY_NONE 0 317 | #define UART_PARITY_EVEN _BV(UPMA1) 318 | #define UART_PARITY_ODD UART_PARITY_MASK 319 | 320 | #define UART_STOP_MASK _BV(USBSA) 321 | #define UART_STOP_1 0 322 | #define UART_STOP_2 UART_STOP_MASK 323 | 324 | typedef enum {STOP_0 = UART_STOP_1, 325 | STOP_1 = UART_STOP_2, 326 | } uartstop_t; 327 | 328 | typedef enum {LENGTH_5 = UART_LENGTH_5, 329 | LENGTH_6 = UART_LENGTH_6, 330 | LENGTH_7 = UART_LENGTH_7, 331 | LENGTH_8 = UART_LENGTH_8 332 | } uartlen_t; 333 | 334 | typedef enum {PARITY_NONE = UART_PARITY_NONE, 335 | PARITY_EVEN = UART_PARITY_EVEN, 336 | PARITY_ODD = UART_PARITY_ODD 337 | } uartpar_t; 338 | 339 | #if defined ENABLE_UART0 && defined DYNAMIC_UART 340 | void uart_config(uint16_t rate, uartlen_t length, uartpar_t parity, uartstop_t stopbits); 341 | #else 342 | #define uart_config(bps, length, parity, stopbits) do {} while(0) 343 | #endif 344 | 345 | #if defined ENABLE_UART1 && defined DYNAMIC_UART 346 | void uart1_config(uint16_t rate, uartlen_t length, uartpar_t parity, uartstop_t stopbits); 347 | #else 348 | #define uart1_config(bps, length, parity, stopbits) do {} while(0) 349 | #endif 350 | 351 | #endif 352 | -------------------------------------------------------------------------------- /src/ps2.h: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | ps2.h: public functions and KEY definitions 20 | 21 | */ 22 | 23 | #ifndef PS2_H 24 | #define PS2_H 25 | 26 | typedef enum { PS2_MODE_DEVICE = 1, PS2_MODE_HOST = 2 } ps2mode_t; 27 | 28 | #define PS2_KEY_UP 0xf0 29 | #define PS2_KEY_EXT 0xe0 30 | #define PS2_KEY_EXT_2 0xe1 31 | 32 | 33 | // normal keys 34 | #define PS2_KEY_F9 0x01 35 | #define PS2_KEY_F5 0x03 36 | #define PS2_KEY_F3 0x04 37 | #define PS2_KEY_F1 0x05 38 | #define PS2_KEY_F2 0x06 39 | #define PS2_KEY_F12 0x07 40 | #define PS2_KEY_F10 0x09 41 | #define PS2_KEY_F8 0x0a 42 | #define PS2_KEY_F6 0x0b 43 | #define PS2_KEY_F4 0x0c 44 | #define PS2_KEY_TAB 0x0d 45 | #define PS2_KEY_BACKQUOTE 0x0e 46 | #define PS2_KEY_ALT 0x11 47 | #define PS2_KEY_LSHIFT 0x12 48 | #define PS2_KEY_LCTRL 0x14 49 | #define PS2_KEY_Q 0x15 50 | #define PS2_KEY_1 0x16 51 | #define PS2_KEY_Z 0x1a 52 | #define PS2_KEY_S 0x1b 53 | #define PS2_KEY_A 0x1c 54 | #define PS2_KEY_W 0x1d 55 | #define PS2_KEY_2 0x1e 56 | #define PS2_KEY_C 0x21 57 | #define PS2_KEY_X 0x22 58 | #define PS2_KEY_D 0x23 59 | #define PS2_KEY_E 0x24 60 | #define PS2_KEY_4 0x25 61 | #define PS2_KEY_3 0x26 62 | #define PS2_KEY_SPACE 0x29 63 | #define PS2_KEY_V 0x2a 64 | #define PS2_KEY_F 0x2b 65 | #define PS2_KEY_T 0x2c 66 | #define PS2_KEY_R 0x2d 67 | #define PS2_KEY_5 0x2e 68 | #define PS2_KEY_N 0x31 69 | #define PS2_KEY_B 0x32 70 | #define PS2_KEY_H 0x33 71 | #define PS2_KEY_G 0x34 72 | #define PS2_KEY_Y 0x35 73 | #define PS2_KEY_6 0x36 74 | #define PS2_KEY_M 0x3a 75 | #define PS2_KEY_J 0x3b 76 | #define PS2_KEY_U 0x3c 77 | #define PS2_KEY_7 0x3d 78 | #define PS2_KEY_8 0x3e 79 | #define PS2_KEY_COMMA 0x41 80 | #define PS2_KEY_K 0x42 81 | #define PS2_KEY_I 0x43 82 | #define PS2_KEY_O 0x44 83 | #define PS2_KEY_0 0x45 84 | #define PS2_KEY_9 0x46 85 | #define PS2_KEY_PERIOD 0x49 86 | #define PS2_KEY_SLASH 0x4a 87 | #define PS2_KEY_L 0x4b 88 | #define PS2_KEY_SEMICOLON 0x4c 89 | #define PS2_KEY_P 0x4d 90 | #define PS2_KEY_MINUS 0x4e 91 | #define PS2_KEY_APOSTROPHE 0x52 92 | #define PS2_KEY_INT2 0x53 93 | #define PS2_KEY_LBRACKET 0x54 94 | #define PS2_KEY_EQUALS 0x55 95 | #define PS2_KEY_CAPS_LOCK 0x58 96 | #define PS2_KEY_RSHIFT 0x59 97 | #define PS2_KEY_ENTER 0x5a 98 | #define PS2_KEY_RBRACKET 0x5b 99 | #define PS2_KEY_BACKSLASH 0x5d 100 | #define PS2_KEY_INT1 0x61 101 | #define PS2_KEY_BS 0x66 102 | #define PS2_KEY_NUM_1 0x69 103 | #define PS2_KEY_NUM_4 0x6b 104 | #define PS2_KEY_NUM_7 0x6c 105 | #define PS2_KEY_NUM_0 0x70 106 | #define PS2_KEY_NUM_PERIOD 0x71 107 | #define PS2_KEY_NUM_2 0x72 108 | #define PS2_KEY_NUM_5 0x73 109 | #define PS2_KEY_NUM_6 0x74 110 | #define PS2_KEY_NUM_8 0x75 111 | #define PS2_KEY_ESC 0x76 112 | #define PS2_KEY_NUM_LOCK 0x77 113 | #define PS2_KEY_F11 0x78 114 | #define PS2_KEY_NUM_PLUS 0x79 115 | #define PS2_KEY_NUM_3 0x7a 116 | #define PS2_KEY_NUM_MINUS 0x7b 117 | #define PS2_KEY_NUM_STAR 0x7c 118 | #define PS2_KEY_NUM_9 0x7d 119 | #define PS2_KEY_SCROLL_LOCK 0x7e 120 | #define PS2_KEY_F7 0x83 121 | 122 | 123 | // extended keys 124 | #define PS2_KEY_RALT 0x11 125 | #define PS2_KEY_ECTRL 0x12 126 | #define PS2_KEY_RCTRL 0x14 127 | #define PS2_KEY_NUM_SLASH 0x4a 128 | #define PS2_KEY_NUM_ENTER 0x5a 129 | #define PS2_KEY_END 0x69 130 | #define PS2_KEY_CRSR_LEFT 0x6b 131 | #define PS2_KEY_HOME 0x6c 132 | #define PS2_KEY_INSERT 0x70 133 | #define PS2_KEY_DELETE 0x71 134 | #define PS2_KEY_CRSR_DOWN 0x72 135 | #define PS2_KEY_CRSR_RIGHT 0x74 136 | #define PS2_KEY_CRSR_UP 0x75 137 | #define PS2_KEY_PAGE_DOWN 0x7a 138 | #define PS2_KEY_PAGE_UP 0x7d 139 | 140 | // significantly extended keys 141 | // E012E07C 142 | #define PS2_KEY_PRINT_SCREEN 0x7c 143 | // E11477E1F014F077 144 | #define PS2_KEY_PCTRL 0x14 145 | #define PS2_KEY_PAUSE 0x77 146 | 147 | 148 | #define PS2_CMD_LEDS 0xed 149 | #define PS2_CMD_ECHO 0xee 150 | #define PS2_CMD_SET_CODE_SET 0xf0 151 | #define PS2_CMD_READ_ID 0xf2 152 | #define PS2_CMD_SET_RATE 0xf3 153 | #define PS2_CMD_ENABLE 0xf4 154 | #define PS2_CMD_DISABLE 0xf5 155 | #define PS2_CMD_DEFAULT 0xf6 156 | #define PS2_CMD_RESEND 0xfe 157 | #define PS2_CMD_RESET 0xff 158 | 159 | #define PS2_CMD_ERROR 0x00 160 | #define PS2_CMD_BAT 0xaa 161 | #define PS2_CMD_ECHO_RESP 0xee 162 | #define PS2_CMD_ACK 0xfa 163 | #define PS2_CMD_BAT_FAILURE 0xfc 164 | #define PS2_CMD_OVERFLOW 0xff 165 | 166 | #define PS2_LED_SCROLL_LOCK (1 << 0) 167 | #define PS2_LED_NUM_LOCK (1 << 1) 168 | #define PS2_LED_CAPS_LOCK (1 << 2) 169 | 170 | #define PS2_MS_CMD_RESET PS2_CMD_RESET 171 | #define PS2_MS_CMD_RESEND PS2_CMD_RESEND 172 | #define PS2_MS_CMD_ACK PS2_CMD_ACK 173 | #define PS2_MS_CMD_REPORT 0xf4 174 | #define PS2_MS_CMD_REPORTOFF 0xf5 175 | #define PS2_MS_CMD_SET_SAMPLE 0xf3 176 | #define PS2_MS_CMD_READ_ID PS2_CMD_READ_ID 177 | #define PS2_MS_CMD_READ_DATA 0xeb 178 | 179 | #define PS2_RX_BUFFER_MASK (_BV(PS2_RX_BUFFER_SHIFT) - 1) 180 | #define PS2_TX_BUFFER_MASK (_BV(PS2_TX_BUFFER_SHIFT) - 1) 181 | /* 182 | * After a device sends a byte to host, it has to holdoff for a while 183 | * before doing anything else. One KB I tested this is 2.14mS. 184 | */ 185 | 186 | /* PS2 Clock INT */ 187 | #if defined __AVR_ATmega8__ || defined __AVR_ATmega16__ || defined __AVR_ATmega32__ || defined __AVR_ATmega162__ 188 | # define CLK_INTDR MCUCR // INT Direction Register 189 | # define CLK_INTCR GICR // INT Control Register 190 | # define CLK_INTFR GIFR // INT Flag Register 191 | # if PS2_CLK_PIN == _BV(PD3) 192 | # define CLK_ISC0 ISC10 193 | # define CLK_ISC1 ISC11 194 | # define CLK_INT INT1 195 | # define CLK_INTF INTF1 196 | # define CLK_INT_vect INT1_vect 197 | # elif PS2_CLK_PIN == _BV(PD2) 198 | # define CLK_ISC0 ISC00 199 | # define CLK_ISC1 ISC01 200 | # define CLK_INT INT0 201 | # define CLK_INTF INTF0 202 | # define CLK_INT_vect INT0_vect 203 | # else 204 | # error "Please define CLK INT Settings" 205 | # endif 206 | #else 207 | # define CLK_INTDR EICRA // INT Direction Register 208 | # define CLK_INTCR EIMSK // INT Control Register 209 | # define CLK_INTFR EIFR // INT Flag Register 210 | # if PS2_CLK_PIN == _BV(PD3) 211 | # define CLK_ISC0 ISC10 212 | # define CLK_ISC1 ISC11 213 | # define CLK_INT INT1 214 | # define CLK_INTF INTF1 215 | # define CLK_INT_vect INT1_vect 216 | # else 217 | # define CLK_ISC0 ISC00 218 | # define CLK_ISC1 ISC01 219 | # define CLK_INT INT0 220 | # define CLK_INTF INTF0 221 | # define CLK_INT_vect INT0_vect 222 | # endif 223 | #endif 224 | 225 | /* PS2 Timer */ 226 | #if defined __AVR_ATmega8__ 227 | 228 | # define PS2_TIMER_COMP_vect TIMER2_COMP_vect 229 | # define PS2_OCR OCR2 230 | # define PS2_TCNT TCNT2 231 | # define PS2_TCCR1 TCCR2 232 | # define PS2_TCCR1_DATA _BV(CS21) 233 | # define PS2_TCCR2 TCCR2 234 | # define PS2_TCCR2_DATA _BV(WGM21) 235 | # define PS2_TIFR TIFR 236 | # define PS2_TIFR_DATA _BV(OCF2) 237 | # define PS2_TIMSK TIMSK 238 | # define PS2_TIMSK_DATA _BV(OCIE2) 239 | 240 | #elif defined __AVR_ATmega28__ || defined __AVR_ATmega48__ || defined __AVR_ATmega88__ || defined __AVR_ATmega168__ 241 | 242 | # define PS2_TIMER_COMP_vect TIMER2_COMPA_vect 243 | # define PS2_OCR OCR2A 244 | # define PS2_TCNT TCNT2 245 | # define PS2_TCCR1 TCCR2B 246 | # define PS2_TCCR1_DATA _BV(CS21) 247 | # define PS2_TCCR2 TCCR2A 248 | # define PS2_TCCR2_DATA _BV(WGM21) 249 | # define PS2_TIFR TIFR2 250 | # define PS2_TIFR_DATA _BV(OCF2A) 251 | # define PS2_TIMSK TIMSK2 252 | # define PS2_TIMSK_DATA _BV(OCIE2A) 253 | 254 | #elif defined __AVR_ATmega16__ || defined __AVR_ATmega32__ || defined __AVR_ATmega162__ 255 | 256 | # define PS2_TIMER_COMP_vect TIMER0_COMP_vect 257 | # define PS2_OCR OCR0 258 | # define PS2_TCNT TCNT0 259 | # define PS2_TCCR1 TCCR0 260 | # define PS2_TCCR1_DATA _BV(CS01) 261 | # define PS2_TCCR2 TCCR0 262 | # define PS2_TCCR2_DATA _BV(WGM01) 263 | # define PS2_TIFR TIFR 264 | # define PS2_TIFR_DATA _BV(OCF0) 265 | # define PS2_TIMSK TIMSK 266 | # define PS2_TIMSK_DATA _BV(OCIE0) 267 | 268 | #else 269 | # error Unknown chip! 270 | #endif 271 | 272 | 273 | 274 | #define PS2_HALF_CYCLE 36 275 | #define PS2_SEND_HOLDOFF_COUNT ((uint8_t)(2140/PS2_HALF_CYCLE)) 276 | 277 | typedef enum {PS2_ST_IDLE 278 | ,PS2_ST_PREP_START 279 | ,PS2_ST_SEND_START 280 | ,PS2_ST_PREP_BIT 281 | ,PS2_ST_SEND_BIT 282 | ,PS2_ST_PREP_PARITY 283 | ,PS2_ST_SEND_PARITY 284 | ,PS2_ST_PREP_STOP 285 | ,PS2_ST_SEND_STOP 286 | ,PS2_ST_HOLDOFF 287 | ,PS2_ST_WAIT_START 288 | ,PS2_ST_GET_START 289 | ,PS2_ST_WAIT_BIT 290 | ,PS2_ST_GET_BIT 291 | ,PS2_ST_WAIT_PARITY 292 | ,PS2_ST_GET_PARITY 293 | ,PS2_ST_WAIT_STOP 294 | ,PS2_ST_GET_STOP 295 | ,PS2_ST_GET_ACK 296 | ,PS2_ST_WAIT_ACK 297 | ,PS2_ST_WAIT_ACK2 298 | ,PS2_ST_HOST_INHIBIT 299 | ,PS2_ST_WAIT_RESPONSE 300 | } ps2state_t; 301 | 302 | static inline __attribute__((always_inline)) void ps2_init_timer(void) { 303 | // set prescaler to System Clock/8 304 | PS2_TCCR1 |= PS2_TCCR1_DATA; 305 | // CTC mode 306 | PS2_TCCR2 |= PS2_TCCR2_DATA; 307 | } 308 | 309 | static inline __attribute__((always_inline)) void ps2_set_clk(void) { 310 | PS2_CLK_OUT |= PS2_CLK_PIN; 311 | PS2_CLK_DDR &= (uint8_t)~PS2_CLK_PIN; 312 | } 313 | 314 | static inline __attribute__((always_inline)) void ps2_clear_clk(void) { 315 | PS2_CLK_DDR |= PS2_CLK_PIN; 316 | PS2_CLK_OUT &= (uint8_t)~PS2_CLK_PIN; 317 | } 318 | 319 | static inline __attribute__((always_inline)) uint8_t ps2_read_clk(void) { 320 | return PS2_CLK_IN & PS2_CLK_PIN; 321 | } 322 | 323 | static inline __attribute__((always_inline)) void ps2_set_data(void) { 324 | PS2_DATA_OUT |= PS2_DATA_PIN; 325 | PS2_DATA_DDR &= (uint8_t)~PS2_DATA_PIN; 326 | } 327 | 328 | static inline __attribute__((always_inline)) void ps2_clear_data(void) { 329 | PS2_DATA_DDR |= PS2_DATA_PIN; 330 | PS2_DATA_OUT &= (uint8_t)~PS2_DATA_PIN; 331 | } 332 | 333 | static inline __attribute__((always_inline)) uint8_t ps2_read_data(void) { 334 | return PS2_DATA_IN & PS2_DATA_PIN; 335 | } 336 | 337 | #if defined PS2_ENABLE_HOST && defined PS2_ENABLE_DEVICE 338 | #define PS2_CALL(dev,host) \ 339 | switch(ps2_mode) {\ 340 | case PS2_MODE_DEVICE: \ 341 | dev; \ 342 | break; \ 343 | case PS2_MODE_HOST: \ 344 | host; \ 345 | break; \ 346 | } 347 | #else 348 | # if defined PS2_ENABLE_DEVICE 349 | # define PS2_CALL(dev,host) dev 350 | # else 351 | # define PS2_CALL(dev,host) host 352 | # endif 353 | #endif 354 | 355 | void ps2_init(ps2mode_t mode); 356 | uint8_t ps2_getc(void); 357 | void ps2_putc(uint8_t data); 358 | uint8_t ps2_data_available(void); 359 | void ps2_handle_cmds(uint8_t data); 360 | uint16_t ps2_get_typematic_delay(uint8_t rate); 361 | uint16_t ps2_get_typematic_period(uint8_t rate); 362 | void ps2_clear_buffers(void); 363 | 364 | // Add 1 and multiply by 250ms to get time 365 | #define PS2_GET_DELAY(rate) ((rate & 0x60) >> 5) 366 | // Multiply by 4.17 to get CPS (or << 2) 367 | #define PS2_GET_RATE(rate) ((8 + (rate & 0x07)) * (1 << ((rate & 0x18) >> 3))) 368 | #define CALC_RATE(delay,rate) ((rate & 0x1f) + ((delay & 0x03) << 5)) 369 | 370 | #endif 371 | 372 | -------------------------------------------------------------------------------- /reference/ps2-to-cbm/source/tables.c: -------------------------------------------------------------------------------- 1 | /* 0 1 2 3 4 5 6 7 2 | ================================================================================== 3 | 0 DEL 3 5 7 9 + pound 1 4 | 1 ENTER W R Y I P * leftarrow 5 | 2 CRSRrt A D G J L ; CTRL 6 | 3 F7 4 6 8 0 - HOME 2 7 | 4 F1 Z C B M . RSHIFT space 8 | 5 F3 S F H K : = commodore 9 | 6 F5 E T U O @ uparrow Q 10 | 7 CRSRdn LSHIFT X V N , / STOP 11 | 12 | 13 | The following key combinations are not emulated: 14 | SHIFT @ 15 | SHIFT ^ 16 | SHIFT = 17 | SHIFT * (can be done from the keypad) 18 | SHIFT + (can be done from the keypad) 19 | 20 | The following keys have bizarre equivalents: 21 | RESTORE Pause 22 | RUN/STOP Escape 23 | COMMODORE Windows 24 | 25 | The following keys have different symbols: 26 | pound \ 27 | left arrow ` 28 | 29 | Table 1 uses 256 bytes 30 | Table 2 uses 9 bytes 31 | Table 3 uses 9 bytes 32 | 33 | */ 34 | 35 | // Each scancode results in one of four possible operations: ignore it, remap it to a key, remap it to a shifted key, or do something special 36 | #define IGNORE (0<<6) 37 | #define REMAP (1<<6) 38 | #define SHIFT_REMAP (2<<6) 39 | #define SPECIAL (3<<6) 40 | 41 | // Operation 0: ignore ==> No definitions are required for ignored keys 42 | 43 | // Operations 1 & 2: remap ==> This requires definitions for CBM keys 44 | #define COL0 (0<<3) 45 | #define COL1 (1<<3) 46 | #define COL2 (2<<3) 47 | #define COL3 (3<<3) 48 | #define COL4 (4<<3) 49 | #define COL5 (5<<3) 50 | #define COL6 (6<<3) 51 | #define COL7 (7<<3) 52 | 53 | #define ROW0 (0<<0) 54 | #define ROW1 (1<<0) 55 | #define ROW2 (2<<0) 56 | #define ROW3 (3<<0) 57 | #define ROW4 (4<<0) 58 | #define ROW5 (5<<0) 59 | #define ROW6 (6<<0) 60 | #define ROW7 (7<<0) 61 | 62 | #define CBM_DEL (ROW0 + COL0) 63 | #define CBM_3 (ROW0 + COL1) 64 | #define CBM_5 (ROW0 + COL2) 65 | #define CBM_7 (ROW0 + COL3) 66 | #define CBM_9 (ROW0 + COL4) 67 | #define CBM_PLUS (ROW0 + COL5) 68 | #define CBM_POUND (ROW0 + COL6) 69 | #define CBM_1 (ROW0 + COL7) 70 | 71 | #define CBM_ENTER (ROW1 + COL0) 72 | #define CBM_W (ROW1 + COL1) 73 | #define CBM_R (ROW1 + COL2) 74 | #define CBM_Y (ROW1 + COL3) 75 | #define CBM_I (ROW1 + COL4) 76 | #define CBM_P (ROW1 + COL5) 77 | #define CBM_STAR (ROW1 + COL6) 78 | #define CBM_LEFTARR (ROW1 + COL7) 79 | 80 | #define CBM_CRSR_RT (ROW2 + COL0) 81 | #define CBM_A (ROW2 + COL1) 82 | #define CBM_D (ROW2 + COL2) 83 | #define CBM_G (ROW2 + COL3) 84 | #define CBM_J (ROW2 + COL4) 85 | #define CBM_L (ROW2 + COL5) 86 | #define CBM_SEMICOL (ROW2 + COL6) 87 | #define CBM_CTRL (ROW2 + COL7) 88 | 89 | #define CBM_F7 (ROW3 + COL0) 90 | #define CBM_4 (ROW3 + COL1) 91 | #define CBM_6 (ROW3 + COL2) 92 | #define CBM_8 (ROW3 + COL3) 93 | #define CBM_0 (ROW3 + COL4) 94 | #define CBM_MINUS (ROW3 + COL5) 95 | #define CBM_HOME (ROW3 + COL6) 96 | #define CBM_2 (ROW3 + COL7) 97 | 98 | #define CBM_F1 (ROW4 + COL0) 99 | #define CBM_Z (ROW4 + COL1) 100 | #define CBM_C (ROW4 + COL2) 101 | #define CBM_B (ROW4 + COL3) 102 | #define CBM_M (ROW4 + COL4) 103 | #define CBM_PERIOD (ROW4 + COL5) 104 | #define CBM_RSHIFT (ROW4 + COL6) 105 | #define CBM_SPACE (ROW4 + COL7) 106 | 107 | #define CBM_F3 (ROW5 + COL0) 108 | #define CBM_S (ROW5 + COL1) 109 | #define CBM_F (ROW5 + COL2) 110 | #define CBM_H (ROW5 + COL3) 111 | #define CBM_K (ROW5 + COL4) 112 | #define CBM_COLON (ROW5 + COL5) 113 | #define CBM_EQUALS (ROW5 + COL6) 114 | #define CBM_LOGO (ROW5 + COL7) 115 | 116 | #define CBM_F5 (ROW6 + COL0) 117 | #define CBM_E (ROW6 + COL1) 118 | #define CBM_T (ROW6 + COL2) 119 | #define CBM_U (ROW6 + COL3) 120 | #define CBM_O (ROW6 + COL4) 121 | #define CBM_ALPHA (ROW6 + COL5) 122 | #define CBM_UPARR (ROW6 + COL6) 123 | #define CBM_Q (ROW6 + COL7) 124 | 125 | #define CBM_CRSR_DN (ROW7 + COL0) 126 | #define CBM_LSHIFT (ROW7 + COL1) 127 | #define CBM_X (ROW7 + COL2) 128 | #define CBM_V (ROW7 + COL3) 129 | #define CBM_N (ROW7 + COL4) 130 | #define CBM_COMMA (ROW7 + COL5) 131 | #define CBM_SLASH (ROW7 + COL6) 132 | #define CBM_STOP (ROW7 + COL7) 133 | 134 | // Operation 3: special ==> Definitions for special actions 135 | #define PUNCTUATION1 (1<<3) 136 | #define PUNCTUATION2 (2<<3) 137 | #define RESTORE_KEY (3<<3) 138 | #define LOCK_KEY (4<<3) 139 | #define SNAPSHOT (5<<3) 140 | #define CBM_RESET (6<<3) 141 | #define RELEASE_ALL (7<<3) 142 | 143 | // ============== Main translation table ============== 144 | 145 | static const U8 translation[256]={ 146 | IGNORE , // 00 147 | IGNORE , // 01 F9 148 | IGNORE , // 02 149 | REMAP + CBM_F5 , // 03 F5 150 | REMAP + CBM_F3 , // 04 F3 151 | REMAP + CBM_F1 , // 05 F1 152 | SHIFT_REMAP+ CBM_F1 , // 06 F2 153 | SPECIAL + SNAPSHOT , // 07 F12 154 | IGNORE , // 08 155 | IGNORE , // 09 F10 156 | SHIFT_REMAP+ CBM_F7 , // 0A F8 157 | SHIFT_REMAP+ CBM_F5 , // 0B F6 158 | SHIFT_REMAP+ CBM_F3 , // 0C F4 159 | IGNORE , // 0D Tab Untab 160 | REMAP + CBM_LEFTARR, // 0E ` ~ {Translates to leftarrow} 161 | IGNORE , // 0F 162 | IGNORE , // 10 163 | IGNORE , // 11 Alt (left) 164 | REMAP + CBM_LSHIFT , // 12 Shift (left) 165 | IGNORE , // 13 166 | REMAP + CBM_CTRL , // 14 Control (left) 167 | REMAP + CBM_Q , // 15 q Q 168 | REMAP + CBM_1 , // 16 1 ! 169 | IGNORE , // 17 170 | IGNORE , // 18 171 | IGNORE , // 19 172 | REMAP + CBM_Z , // 1A z Z 173 | REMAP + CBM_S , // 1B s S 174 | REMAP + CBM_A , // 1C a A 175 | REMAP + CBM_W , // 1D w W 176 | SPECIAL+PUNCTUATION1 + 2, // 1E 2 @ 177 | IGNORE , // 1F 178 | IGNORE , // 20 179 | REMAP + CBM_C , // 21 c C 180 | REMAP + CBM_X , // 22 x X 181 | REMAP + CBM_D , // 23 d D 182 | REMAP + CBM_E , // 24 e E 183 | REMAP + CBM_4 , // 25 4 $ 184 | REMAP + CBM_3 , // 26 3 # 185 | IGNORE , // 27 186 | IGNORE , // 28 187 | REMAP + CBM_SPACE , // 29 space 188 | REMAP + CBM_V , // 2A v V 189 | REMAP + CBM_F , // 2B f F 190 | REMAP + CBM_T , // 2C t T 191 | REMAP + CBM_R , // 2D r R 192 | REMAP + CBM_5 , // 2E 5 % 193 | IGNORE , // 2F 194 | IGNORE , // 30 195 | REMAP + CBM_N , // 31 n N 196 | REMAP + CBM_B , // 32 b B 197 | REMAP + CBM_H , // 33 h H 198 | REMAP + CBM_G , // 34 g G 199 | REMAP + CBM_Y , // 35 y Y 200 | SPECIAL+PUNCTUATION1 + 3, // 36 6 ^ 201 | IGNORE , // 37 202 | IGNORE , // 38 203 | IGNORE , // 39 204 | REMAP + CBM_M , // 3A m M 205 | REMAP + CBM_J , // 3B j J 206 | REMAP + CBM_U , // 3C u U 207 | SPECIAL+PUNCTUATION1 + 4, // 3D 7 & 208 | SPECIAL+PUNCTUATION1 + 5, // 3E 8 * 209 | IGNORE , // 3F 210 | IGNORE , // 40 211 | REMAP + CBM_COMMA , // 41 , < 212 | REMAP + CBM_K , // 42 k K 213 | REMAP + CBM_I , // 43 i I 214 | REMAP + CBM_O , // 44 o O 215 | SPECIAL+PUNCTUATION1 + 7, // 45 0 ) 216 | SPECIAL+PUNCTUATION1 + 6, // 46 9 ( 217 | IGNORE , // 47 218 | IGNORE , // 48 219 | REMAP + CBM_PERIOD , // 49 . > 220 | REMAP + CBM_SLASH , // 4A / ? 221 | REMAP + CBM_L , // 4B l L 222 | SPECIAL+PUNCTUATION1 + 1, // 4C ; : 223 | REMAP + CBM_P , // 4D p P 224 | REMAP + CBM_MINUS , // 4E - _ 225 | IGNORE , // 4F 226 | IGNORE , // 50 227 | IGNORE , // 51 228 | SPECIAL+PUNCTUATION2 + 0, // 52 ' " 229 | IGNORE , // 53 230 | SHIFT_REMAP+ CBM_COLON , // 54 [ { 231 | SPECIAL+PUNCTUATION1 + 0, // 55 = + 232 | IGNORE , // 56 233 | IGNORE , // 57 234 | SPECIAL + LOCK_KEY+ 1, // 58 Caps Lock 235 | REMAP + CBM_RSHIFT , // 59 Shift (right) 236 | REMAP + CBM_ENTER , // 5A Enter 237 | SHIFT_REMAP+ CBM_SEMICOL, // 5B ] } 238 | IGNORE , // 5C 239 | REMAP + CBM_POUND , // 5D \ | {Translates to the pound symbol} 240 | IGNORE , // 5E 241 | IGNORE , // 5F 242 | IGNORE , // 60 243 | IGNORE , // 61 244 | IGNORE , // 62 245 | IGNORE , // 63 246 | IGNORE , // 64 247 | IGNORE , // 65 248 | REMAP + CBM_DEL , // 66 Backspace 249 | IGNORE , // 67 250 | IGNORE , // 68 251 | IGNORE , // 69 [Keypad] 1 End 252 | IGNORE , // 6A 253 | IGNORE , // 6B [Keypad] 4 Left arrow 254 | IGNORE , // 6C [Keypad] 7 Home 255 | IGNORE , // 6D 256 | IGNORE , // 6E 257 | IGNORE , // 6F 258 | IGNORE , // 70 [Keypad] 0 Insert 259 | IGNORE , // 71 [Keypad] . Delete 260 | IGNORE , // 72 [Keypad] 2 Down arrow 261 | IGNORE , // 73 [Keypad] 5 262 | IGNORE , // 74 [Keypad] 6 Right arrow 263 | IGNORE , // 75 [Keypad] 8 Up arrow 264 | REMAP + CBM_STOP , // 76 Escape 265 | SPECIAL + LOCK_KEY+ 2, // 77 Num lock 266 | SPECIAL + RELEASE_ALL, // 78 F11 267 | REMAP + CBM_PLUS , // 79 [Keypad] + 268 | IGNORE , // 7A [Keypad] 3 Page Down 269 | REMAP + CBM_MINUS , // 7B [Keypad] - 270 | REMAP + CBM_STAR , // 7C [Keypad] * 271 | IGNORE , // 7D [Keypad] 9 Page Up 272 | SPECIAL + LOCK_KEY+ 3, // 7E Scroll Lock 273 | IGNORE , // 7F 274 | // ====== Scancodes that are prefixed with with E0 ===== 275 | IGNORE , // 00 276 | IGNORE , // 01 277 | IGNORE , // 02 278 | REMAP + CBM_F7 , // 83 F7 !!! Kludge 1 of 2 ==> The actual scan code for F7 is [83] but we are treating it as [E0 03] 279 | IGNORE , // 04 280 | IGNORE , // 05 281 | IGNORE , // 06 282 | IGNORE , // 07 283 | IGNORE , // 08 284 | IGNORE , // 09 285 | IGNORE , // 0A 286 | IGNORE , // 0B 287 | IGNORE , // 0C 288 | IGNORE , // 0D 289 | IGNORE , // 0E 290 | IGNORE , // 0F 291 | IGNORE , // 10 [Multimedia] WWW Search 292 | IGNORE , // 11 Alt (right) 293 | IGNORE , // 12 Print screen (first scancode) 294 | IGNORE , // 13 295 | REMAP + CBM_CTRL , // 14 Control (right) 296 | IGNORE , // 15 [Multimedia] Previous track 297 | IGNORE , // 16 298 | IGNORE , // 17 299 | IGNORE , // 18 [Multimedia] WWW Favorites 300 | IGNORE , // 19 301 | IGNORE , // 1A 302 | IGNORE , // 1B 303 | IGNORE , // 1C 304 | IGNORE , // 1D 305 | IGNORE , // 1E 306 | REMAP + CBM_LOGO , // 1F Windows (left) 307 | IGNORE , // 20 [Multimedia] WWW Refresh 308 | IGNORE , // 21 [Multimedia] Volume Down 309 | IGNORE , // 22 310 | IGNORE , // 23 [Multimedia] Mute 311 | IGNORE , // 24 312 | IGNORE , // 25 313 | IGNORE , // 26 314 | REMAP + CBM_LOGO , // 27 Windows (right) 315 | IGNORE , // 28 [Multimedia] WWW Stop 316 | IGNORE , // 29 317 | IGNORE , // 2A 318 | IGNORE , // 2B [Multimedia] Calculator 319 | IGNORE , // 2C 320 | IGNORE , // 2D 321 | IGNORE , // 2E 322 | IGNORE , // 2F Context menu 323 | IGNORE , // 30 [Multimedia] WWW Forward 324 | IGNORE , // 31 325 | IGNORE , // 32 [Multimedia] Volume Up 326 | IGNORE , // 33 327 | IGNORE , // 34 [Multimedia] Play / Pause 328 | IGNORE , // 35 329 | IGNORE , // 36 330 | IGNORE , // 37 [ACPI] Power 331 | IGNORE , // 38 [Multimedia] WWW Back 332 | IGNORE , // 39 333 | IGNORE , // 3A [Multimedia] WWW Home 334 | IGNORE , // 3B [Multimedia] Stop 335 | IGNORE , // 3C 336 | IGNORE , // 3D 337 | IGNORE , // 3E 338 | IGNORE , // 3F [ACPI] Sleep 339 | IGNORE , // 40 [Multimedia] My Computer 340 | IGNORE , // 41 341 | IGNORE , // 42 342 | IGNORE , // 43 343 | IGNORE , // 44 344 | IGNORE , // 45 345 | IGNORE , // 46 346 | IGNORE , // 47 347 | IGNORE , // 48 [Multimedia] Email 348 | IGNORE , // 49 349 | REMAP + CBM_SLASH , // 4A [Keypad] / 350 | IGNORE , // 4B 351 | IGNORE , // 4C 352 | IGNORE , // 4D [Multimedia] Next track 353 | IGNORE , // 4E 354 | IGNORE , // 4F 355 | IGNORE , // 50 [Multimedia] Media Select 356 | IGNORE , // 51 357 | IGNORE , // 52 358 | IGNORE , // 53 359 | SPECIAL + RESTORE_KEY, // 54 Pause / Break !!! Kludge 2 of 2 ==> The actual scancode is [E1 14] but we are treating it as [E0 14] 360 | IGNORE , // 55 361 | IGNORE , // 56 362 | IGNORE , // 57 363 | IGNORE , // 58 364 | IGNORE , // 59 365 | REMAP + CBM_ENTER , // 5A [Keypad] Enter 366 | IGNORE , // 5B 367 | IGNORE , // 5C 368 | IGNORE , // 5D 369 | IGNORE , // 5E [ACPI] Wake 370 | IGNORE , // 5F 371 | IGNORE , // 60 372 | IGNORE , // 61 373 | IGNORE , // 62 374 | IGNORE , // 63 375 | IGNORE , // 64 376 | IGNORE , // 65 377 | IGNORE , // 66 378 | IGNORE , // 67 379 | IGNORE , // 68 380 | IGNORE , // 69 End 381 | IGNORE , // 6A 382 | SHIFT_REMAP+ CBM_CRSR_RT, // 6B Left arrow 383 | REMAP + CBM_HOME , // 6C Home 384 | IGNORE , // 6D 385 | IGNORE , // 6E 386 | IGNORE , // 6F 387 | SHIFT_REMAP+ CBM_DEL , // 70 Insert 388 | SPECIAL + CBM_RESET , // 71 Delete 389 | REMAP + CBM_CRSR_DN, // 72 Down arrow 390 | IGNORE , // 73 391 | REMAP + CBM_CRSR_RT, // 74 Right arrow 392 | SHIFT_REMAP+ CBM_CRSR_DN, // 75 Up arrow 393 | IGNORE , // 76 394 | IGNORE , // 77 395 | IGNORE , // 78 396 | IGNORE , // 79 397 | IGNORE , // 7A Page Down 398 | IGNORE , // 7B 399 | IGNORE , // 7C Print screen (second scancode) 400 | IGNORE , // 7D Page Up 401 | IGNORE , // 7E 402 | IGNORE // 7F 403 | }; 404 | 405 | 406 | static const U8 punctuation_norm[9] ={ 407 | (6<<3) + (5<<0), // SPECIAL PUNCTUATION1 0 KEY = ==> = 408 | (6<<3) + (2<<0), // SPECIAL PUNCTUATION1 1 KEY ; ==> ; 409 | (7<<3) + (3<<0), // SPECIAL PUNCTUATION1 2 KEY 2 ==> 2 410 | (2<<3) + (3<<0), // SPECIAL PUNCTUATION1 3 KEY 6 ==> 6 411 | (3<<3) + (0<<0), // SPECIAL PUNCTUATION1 4 KEY 7 ==> 7 412 | (3<<3) + (3<<0), // SPECIAL PUNCTUATION1 5 KEY 8 ==> 8 413 | (4<<3) + (0<<0), // SPECIAL PUNCTUATION1 6 KEY 9 ==> 9 414 | (4<<3) + (3<<0), // SPECIAL PUNCTUATION1 7 KEY 0 ==> 0 415 | (1<<6)+ (3<<3) + (0<<0) // SPECIAL PUNCTUATION2 0 KEY ' ==> SHIFT 7 416 | }; 417 | 418 | 419 | static const U8 punctuation_swap[9] ={ 420 | (5<<3) + (0<<0), // SPECIAL PUNCTUATION1 0 SHIFTED = ==> + 421 | (5<<3) + (5<<0), // SPECIAL PUNCTUATION1 1 SHIFTED ; ==> : 422 | (5<<3) + (6<<0), // SPECIAL PUNCTUATION1 2 SHIFTED 2 ==> @ 423 | (6<<3) + (6<<0), // SPECIAL PUNCTUATION1 3 SHIFTED 6 ==> ^ 424 | (1<<6) +(2<<3) + (3<<0), // SPECIAL PUNCTUATION1 4 SHIFTED 7 ==> SHIFT 6 425 | (6<<3) + (1<<0), // SPECIAL PUNCTUATION1 5 SHIFTED 8 ==> * 426 | (1<<6) +(3<<3) + (3<<0), // SPECIAL PUNCTUATION1 6 SHIFTED 9 ==> SHIFT 8 427 | (1<<6) +(4<<3) + (0<<0), // SPECIAL PUNCTUATION1 7 SHIFTED 0 ==> SHIFT 9 428 | (1<<6) +(7<<3) + (3<<0) // SPECIAL PUNCTUATION2 0 SHIFTED ' ==> SHIFT 2 429 | }; 430 | 431 | -------------------------------------------------------------------------------- /src/ps2.c: -------------------------------------------------------------------------------- 1 | /* 2 | C=Key - Commodore <-> PS/2 Interface 3 | Copyright Jim Brain and RETRO Innovations, 2004-2012 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | ps2.c: Internal functions for host/device PS/2 modes 20 | 21 | timing information derived from http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/PS2/ps2.htm 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "config.h" 30 | #include "ps2.h" 31 | #include "uart.h" 32 | 33 | static uint8_t rxbuf[1 << PS2_RX_BUFFER_SHIFT]; 34 | static volatile uint8_t rx_head; 35 | static volatile uint8_t rx_tail; 36 | static uint8_t txbuf[1 << PS2_TX_BUFFER_SHIFT]; 37 | static volatile uint8_t tx_head; 38 | static volatile uint8_t tx_tail; 39 | 40 | static volatile ps2state_t ps2_state; 41 | static volatile uint8_t ps2_byte; 42 | static volatile uint8_t ps2_bit_count; 43 | static volatile uint8_t ps2_parity; 44 | 45 | static ps2mode_t ps2_mode; 46 | 47 | static volatile uint8_t ps2_holdoff_count; 48 | 49 | static void ps2_enable_clk_rise(void) { 50 | // turn off IRQ 51 | CLK_INTCR &= (uint8_t)~_BV(CLK_INT); 52 | // reset flag 53 | CLK_INTFR |= _BV(CLK_INTF); 54 | // rising edge 55 | CLK_INTDR |= _BV(CLK_ISC1) | _BV(CLK_ISC0); 56 | // turn on 57 | CLK_INTCR |= _BV(CLK_INT); 58 | } 59 | 60 | static void ps2_enable_clk_fall(void) { 61 | // turn off IRQ 62 | CLK_INTCR &= (uint8_t)~_BV(CLK_INT); 63 | // reset flag 64 | CLK_INTFR |= _BV(CLK_INTF); 65 | // falling edge 66 | CLK_INTDR = (CLK_INTDR & (uint8_t)~(_BV(CLK_ISC1) | _BV(CLK_ISC0))) | _BV(CLK_ISC1); 67 | // turn on 68 | CLK_INTCR |= _BV(CLK_INT); 69 | } 70 | 71 | static void ps2_disable_clk(void) { 72 | CLK_INTCR &= (uint8_t)~_BV(CLK_INT); 73 | } 74 | 75 | static void ps2_enable_timer(uint8_t us) { 76 | // clear flag. 77 | PS2_TIFR |= PS2_TIFR_DATA; 78 | // clear TCNT; 79 | PS2_TCNT = 0; 80 | // set the count... 81 | #if F_CPU > 14000000 82 | // us is uS.... Need to * 14 to get ticks, then divide by 8... 83 | // cheat... * 14 / 8 = *2 = <<1 84 | PS2_OCR = (uint8_t)(us << 1); 85 | #elif F_CPU > 7000000 86 | PS2_OCR = us; 87 | #else 88 | PS2_OCR = (us >> 1); 89 | #endif 90 | // enable output compare IRQ 91 | PS2_TIMSK |= PS2_TIMSK_DATA; 92 | } 93 | 94 | static void ps2_disable_timer(void) { 95 | // disable output compare IRQ 96 | PS2_TIMSK &= (uint8_t)~PS2_TIMSK_DATA; 97 | } 98 | 99 | static void ps2_write_byte(void) { 100 | uint8_t tmp; 101 | /* Calculate buffer index */ 102 | tmp = ( rx_head + 1 ) & PS2_RX_BUFFER_MASK; 103 | rx_head = tmp; /* Store new index */ 104 | 105 | if ( tmp == rx_tail ) { 106 | /* ERROR! Receive buffer overflow */ 107 | } 108 | rxbuf[tmp] = ps2_byte; /* Store received data in buffer */ 109 | } 110 | 111 | static void ps2_read_byte(void) { 112 | ps2_bit_count = 0; 113 | ps2_parity = 0; 114 | ps2_byte = txbuf[( tx_tail + 1 ) & PS2_TX_BUFFER_MASK]; /* Start transmition */ 115 | } 116 | 117 | static void ps2_commit_read_byte(void) { 118 | tx_tail = ( tx_tail + 1 ) & PS2_TX_BUFFER_MASK; /* Store new index */ 119 | } 120 | 121 | static void ps2_write_bit(void) { 122 | ps2_state=PS2_ST_PREP_BIT; 123 | // set DATA.. 124 | switch (ps2_byte & 1) { 125 | case 0: 126 | ps2_clear_data(); 127 | break; 128 | case 1: 129 | ps2_parity++; 130 | ps2_set_data(); 131 | break; 132 | } 133 | // shift right. 134 | ps2_byte= ps2_byte >> 1; 135 | ps2_bit_count++; 136 | // valid data now. 137 | } 138 | 139 | static void ps2_read_bit(void) { 140 | ps2_byte = ps2_byte >> 1; 141 | ps2_bit_count++; 142 | if(ps2_read_data()) { 143 | ps2_byte |= 0x80; 144 | ps2_parity++; 145 | } 146 | } 147 | 148 | static void ps2_write_parity(void) { 149 | if((ps2_parity & 1) == 1) { 150 | ps2_clear_data(); 151 | } else { 152 | ps2_set_data(); 153 | } 154 | } 155 | 156 | static void ps2_clear_counters(void) { 157 | ps2_byte = 0; 158 | ps2_bit_count = 0; 159 | ps2_parity = 0; 160 | } 161 | 162 | void ps2_clear_buffers(void) { 163 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 164 | tx_head = 0; 165 | tx_tail = 0; 166 | rx_head = 0; 167 | rx_tail = 0; 168 | } 169 | } 170 | 171 | #ifdef PS2_ENABLE_DEVICE 172 | static void ps2_device_trigger_send(void) { 173 | // start clocking. 174 | // wait a half cycle 175 | ps2_enable_timer(PS2_HALF_CYCLE); 176 | // bring DATA line low to ensure everyone knows our intentions 177 | ps2_clear_data(); 178 | } 179 | #endif 180 | 181 | #ifdef PS2_ENABLE_HOST 182 | static void ps2_host_trigger_send(void) { 183 | // need to get devices attention... 184 | ps2_disable_clk(); 185 | ps2_clear_clk(); 186 | // yes, bring CLK lo for 100uS 187 | ps2_enable_timer(100); 188 | } 189 | #endif 190 | 191 | static void ps2_trigger_send(void) { 192 | // set state 193 | ps2_state = PS2_ST_PREP_START; 194 | PS2_CALL(ps2_device_trigger_send(),ps2_host_trigger_send()); 195 | } 196 | 197 | 198 | static void ps2_check_for_data(void) { 199 | // do we have data to send? 200 | if( tx_head != tx_tail) { 201 | ps2_trigger_send(); 202 | } else { 203 | ps2_state = PS2_ST_IDLE; 204 | ps2_disable_timer(); // TODO check if this is needed for host mode as well. 205 | ps2_enable_clk_fall(); 206 | } 207 | } 208 | 209 | #ifdef PS2_ENABLE_HOST 210 | static inline __attribute__((always_inline)) void ps2_host_timer_irq(void) { 211 | ps2_disable_timer(); 212 | switch (ps2_state) { 213 | case PS2_ST_GET_BIT: 214 | case PS2_ST_GET_PARITY: 215 | case PS2_ST_GET_STOP: 216 | // do we have data to send to keyboard? 217 | ps2_check_for_data(); 218 | break; 219 | case PS2_ST_PREP_START: 220 | // we waited 100uS for device to notice us, bring DATA low and CLK hi 221 | ps2_clear_data(); 222 | ps2_set_clk(); 223 | if(!ps2_read_clk()) { 224 | // kb wants to talk to us. 225 | ps2_set_data(); 226 | ps2_enable_clk_fall(); 227 | ps2_state = PS2_ST_GET_BIT; 228 | } else { 229 | // really start bit... 230 | // now, wait for falling CLK 231 | ps2_enable_clk_fall(); 232 | ps2_state = PS2_ST_PREP_BIT; 233 | ps2_read_byte(); 234 | } 235 | break; 236 | default: 237 | break; 238 | } 239 | } 240 | 241 | 242 | static inline __attribute__((always_inline)) void ps2_host_clk_irq(void) { 243 | switch(ps2_state) { 244 | case PS2_ST_WAIT_RESPONSE: 245 | case PS2_ST_IDLE: 246 | // keyboard sent start bit 247 | // should read it, but will assume it is good. 248 | ps2_state = PS2_ST_GET_BIT; 249 | // if we don't get another CLK in 100uS, timeout. 250 | ps2_enable_timer(100); 251 | ps2_clear_counters(); 252 | break; 253 | case PS2_ST_GET_BIT: 254 | // if we don't get another CLK in 100uS, timeout. 255 | ps2_enable_timer(100); 256 | // read bit; 257 | ps2_read_bit(); 258 | if(ps2_bit_count == 8) { 259 | // done, do Parity bit 260 | ps2_state = PS2_ST_GET_PARITY; 261 | } 262 | break; 263 | case PS2_ST_GET_PARITY: 264 | // if we don't get another CLK in 100uS, timeout. 265 | ps2_enable_timer(100); 266 | // grab parity 267 | // for now, assume it is OK. 268 | ps2_state = PS2_ST_GET_STOP; 269 | break; 270 | case PS2_ST_GET_STOP: 271 | ps2_disable_timer(); 272 | // stop bit 273 | // for now, assume it is OK. 274 | ps2_write_byte(); 275 | // wait for CLK to rise before doing anything else. 276 | ps2_state = PS2_ST_HOLDOFF; 277 | ps2_enable_clk_rise(); 278 | break; 279 | case PS2_ST_HOLDOFF: 280 | // CLK rose, so now, check for more data. 281 | // do we have data to send to keyboard? 282 | ps2_check_for_data(); 283 | break; 284 | // case PS2_ST_SEND_START: 285 | // ps2_state = PS2_ST_PREP_BIT; 286 | // break; 287 | case PS2_ST_PREP_BIT: 288 | // time to send bits... 289 | if(ps2_bit_count == 8) { 290 | // we are done..., do parity 291 | ps2_write_parity(); 292 | ps2_state = PS2_ST_SEND_PARITY; 293 | } else { 294 | ps2_write_bit(); 295 | } 296 | break; 297 | case PS2_ST_SEND_PARITY: 298 | // send stop bit. 299 | ps2_set_data(); 300 | ps2_state = PS2_ST_SEND_STOP; 301 | break; 302 | case PS2_ST_SEND_STOP: 303 | if(!ps2_read_data()) { 304 | // commit the send 305 | ps2_commit_read_byte(); 306 | /* 307 | * We could wait for the CLK hi, then check to see if we have more 308 | * data to send. However, all cmds out have a required ack or response 309 | * so we'll just set to a non-IDLE state and wait for the CLK 310 | */ 311 | ps2_state = PS2_ST_WAIT_RESPONSE; 312 | ps2_enable_clk_fall(); 313 | } else { 314 | // wait for another cycle. We should timeout here, I think 315 | } 316 | break; 317 | default: 318 | break; 319 | } 320 | } 321 | 322 | static void ps2_host_init(void) { 323 | } 324 | #endif 325 | 326 | #ifdef PS2_ENABLE_DEVICE 327 | static void ps2_device_host_inhibit(void) { 328 | // CLK is low. Host wants to talk to us. 329 | // turn off timer 330 | ps2_disable_timer(); 331 | // look for rising clock 332 | ps2_enable_clk_rise(); 333 | ps2_state = PS2_ST_HOST_INHIBIT; 334 | // release DATA line, if we happen to have it. 335 | ps2_set_data(); 336 | } 337 | 338 | 339 | static inline __attribute__((always_inline)) void ps2_device_timer_irq(void) { 340 | switch (ps2_state) { 341 | case PS2_ST_PREP_START: 342 | // clk the start bit, which is already been cleared. 343 | ps2_clear_clk(); 344 | ps2_state = PS2_ST_SEND_START; 345 | break; 346 | case PS2_ST_SEND_START: 347 | ps2_read_byte(); 348 | ps2_set_clk(); // bring CLK hi 349 | if(ps2_read_clk()) { 350 | ps2_write_bit(); 351 | } else { 352 | ps2_device_host_inhibit(); 353 | } 354 | break; 355 | case PS2_ST_PREP_BIT: 356 | ps2_clear_clk(); 357 | ps2_state = PS2_ST_SEND_BIT; 358 | break; 359 | case PS2_ST_SEND_BIT: 360 | ps2_set_clk(); // bring CLK hi 361 | if(ps2_read_clk()) { 362 | if(ps2_bit_count == 8) { 363 | // we are done..., do parity 364 | ps2_write_parity(); 365 | ps2_state = PS2_ST_PREP_PARITY; 366 | } else { 367 | // state is set in function. 368 | ps2_write_bit(); 369 | } 370 | } else { 371 | ps2_device_host_inhibit(); 372 | } 373 | break; 374 | case PS2_ST_PREP_PARITY: 375 | // clock parity 376 | ps2_clear_clk(); 377 | ps2_state = PS2_ST_SEND_PARITY; 378 | break; 379 | case PS2_ST_SEND_PARITY: 380 | ps2_set_clk(); // bring CLK hi 381 | if(ps2_read_clk()) { 382 | ps2_set_data(); 383 | ps2_state = PS2_ST_PREP_STOP; 384 | } else { 385 | ps2_device_host_inhibit(); 386 | } 387 | break; 388 | case PS2_ST_PREP_STOP: 389 | ps2_clear_clk(); 390 | ps2_state = PS2_ST_SEND_STOP; 391 | break; 392 | case PS2_ST_SEND_STOP: 393 | // If host wanted to abort, they had to do it before now. 394 | ps2_commit_read_byte(); 395 | ps2_set_clk(); // bring CLK hi 396 | if(ps2_read_clk()) { 397 | if(ps2_read_data()) { 398 | // for some reason, you have to wait a while before sending again. 399 | ps2_holdoff_count=PS2_SEND_HOLDOFF_COUNT; 400 | ps2_state = PS2_ST_HOLDOFF; 401 | } else { 402 | // Host wants to talk to us. 403 | ps2_state = PS2_ST_WAIT_START; 404 | } 405 | } else { 406 | ps2_device_host_inhibit(); 407 | } 408 | break; 409 | case PS2_ST_WAIT_START: 410 | // set CLK lo 411 | ps2_clear_clk(); 412 | ps2_clear_counters(); 413 | // read start bit 414 | if(ps2_read_data()) { 415 | // not sure what you do if start bit is high... 416 | ps2_set_clk(); 417 | ps2_state = PS2_ST_IDLE; 418 | ps2_disable_timer(); 419 | ps2_enable_clk_fall(); 420 | } else { 421 | ps2_state = PS2_ST_GET_START; 422 | } 423 | break; 424 | case PS2_ST_GET_START: 425 | ps2_set_clk(); // bring CLK hi 426 | if(ps2_read_clk()) { 427 | ps2_state = PS2_ST_WAIT_BIT; 428 | } else { 429 | ps2_device_host_inhibit(); 430 | } 431 | break; 432 | case PS2_ST_WAIT_BIT: 433 | ps2_clear_clk(); 434 | // you read incoming bits on falling clock. 435 | ps2_read_bit(); 436 | ps2_state = PS2_ST_GET_BIT; 437 | break; 438 | case PS2_ST_GET_BIT: 439 | ps2_set_clk(); // bring CLK hi 440 | if(ps2_read_clk()) { 441 | if(ps2_bit_count == 8) { 442 | // done, do Parity bit 443 | ps2_state = PS2_ST_GET_PARITY; 444 | } else { 445 | ps2_state = PS2_ST_WAIT_BIT; 446 | } 447 | } else { 448 | // host aborted send. 449 | ps2_device_host_inhibit(); 450 | } 451 | break; 452 | case PS2_ST_GET_PARITY: 453 | ps2_clear_clk(); 454 | // ignore parity for now. 455 | ps2_state = PS2_ST_WAIT_STOP; 456 | break; 457 | case PS2_ST_WAIT_STOP: 458 | ps2_set_clk(); // bring CLK hi 459 | if(ps2_read_clk()) { 460 | if(ps2_read_data()) { 461 | ps2_state = PS2_ST_WAIT_ACK; 462 | // bing DATA low to ack 463 | ps2_clear_data(); 464 | // commit data 465 | //ps2_write_byte(); jlb, moved. 466 | } else { 467 | ps2_state = PS2_ST_GET_PARITY; 468 | } 469 | } else { 470 | // host aborted send. 471 | ps2_device_host_inhibit(); 472 | } 473 | break; 474 | case PS2_ST_WAIT_ACK: 475 | ps2_clear_clk(); 476 | ps2_state = PS2_ST_GET_ACK; 477 | break; 478 | case PS2_ST_GET_ACK: 479 | ps2_set_clk(); 480 | ps2_set_data(); 481 | // we just need to wait a 50uS or so, to ensure the host saw the CLK go high 482 | ps2_holdoff_count = 1; 483 | ps2_state = PS2_ST_HOLDOFF; 484 | ps2_write_byte(); //jlb moved 485 | break; 486 | case PS2_ST_HOLDOFF: 487 | ps2_holdoff_count--; 488 | if(!ps2_holdoff_count) { 489 | if(ps2_read_clk()) { 490 | if(ps2_read_data()) { 491 | ps2_check_for_data(); 492 | } else { 493 | ps2_state = PS2_ST_WAIT_START; 494 | } 495 | } else { 496 | ps2_device_host_inhibit(); 497 | } 498 | } 499 | break; 500 | default: 501 | ps2_disable_timer(); 502 | break; 503 | } 504 | } 505 | 506 | 507 | static inline __attribute__((always_inline)) void ps2_device_clk_irq(void) { 508 | ps2_disable_clk(); 509 | 510 | switch(ps2_state) { 511 | case PS2_ST_IDLE: 512 | case PS2_ST_PREP_START: 513 | // host is holding us off. Wait for CLK hi... 514 | ps2_device_host_inhibit(); 515 | break; 516 | case PS2_ST_HOST_INHIBIT: 517 | // CLK went hi 518 | if(ps2_read_data()) { 519 | // we can send if we need to. 520 | ps2_check_for_data(); 521 | } else { 522 | // host wants to send data, CLK is high. 523 | // wait half cycle to let things settle. 524 | // clock in data from host. 525 | ps2_enable_timer(PS2_HALF_CYCLE); 526 | ps2_state = PS2_ST_WAIT_START; 527 | } 528 | break; 529 | default: 530 | break; 531 | } 532 | } 533 | 534 | static void ps2_device_init(void) { 535 | } 536 | #endif 537 | 538 | ISR(PS2_TIMER_COMP_vect) { 539 | PS2_CALL(ps2_device_timer_irq(),ps2_host_timer_irq()); 540 | } 541 | 542 | ISR(CLK_INT_vect) { 543 | PS2_CALL(ps2_device_clk_irq(),ps2_host_clk_irq()); 544 | } 545 | 546 | uint8_t ps2_getc( void ) { 547 | uint8_t tmptail; 548 | 549 | while ( rx_head == rx_tail ) { 550 | // wait for char to arrive, if none in Q 551 | ; 552 | } 553 | // Calculate buffer index 554 | tmptail = ( rx_tail + 1 ) & PS2_RX_BUFFER_MASK; 555 | // Store new index 556 | rx_tail = tmptail; 557 | return rxbuf[tmptail]; 558 | } 559 | 560 | void ps2_putc( uint8_t data ) { 561 | uint8_t tmphead; 562 | // Calculate buffer index 563 | tmphead = ( tx_head + 1 ) & PS2_TX_BUFFER_MASK; 564 | while ( tmphead == tx_tail ) { 565 | // Wait for free space in buffer 566 | ; 567 | } 568 | // Store data in buffer 569 | txbuf[tmphead] = data; 570 | // Store new index 571 | tx_head = tmphead; 572 | 573 | // turn off IRQs 574 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 575 | if(ps2_state == PS2_ST_IDLE) { 576 | // start transmission; 577 | ps2_trigger_send(); 578 | } 579 | } 580 | } 581 | 582 | uint8_t ps2_data_available( void ) { 583 | return ( rx_head != rx_tail ); /* Return 0 (FALSE) if the receive buffer is empty */ 584 | } 585 | 586 | void ps2_init(ps2mode_t mode) { 587 | ps2_init_timer(); 588 | 589 | ps2_mode = mode; 590 | ps2_clear_buffers(); 591 | 592 | ps2_set_clk(); 593 | ps2_set_data(); 594 | 595 | ps2_state = PS2_ST_IDLE; 596 | ps2_enable_clk_fall(); 597 | PS2_CALL(ps2_device_init(),ps2_host_init()); 598 | } 599 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | 342 | -------------------------------------------------------------------------------- /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | make 18 | all 19 | false 20 | true 21 | 22 | 23 | make 24 | clean 25 | false 26 | true 27 | 28 | 29 | make 30 | program 31 | false 32 | true 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | --------------------------------------------------------------------------------