mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-10-30 21:02:32 +01:00 
			
		
		
		
	Added protocol support for Macintosh keyboard M0110.
This commit is contained in:
		
							parent
							
								
									e2afc305ed
								
							
						
					
					
						commit
						3f0289e666
					
				
							
								
								
									
										304
									
								
								m0110.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								m0110.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,304 @@ | |||||||
|  | /*
 | ||||||
|  | Copyright 2011 Jun WAKO <wakojun@gmail.com> | ||||||
|  | 
 | ||||||
|  | This software is licensed with a Modified BSD License. | ||||||
|  | All of this is supposed to be Free Software, Open Source, DFSG-free, | ||||||
|  | GPL-compatible, and OK to use in both free and proprietary applications. | ||||||
|  | Additions and corrections to this file are welcome. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Redistribution and use in source and binary forms, with or without | ||||||
|  | modification, are permitted provided that the following conditions are met: | ||||||
|  | 
 | ||||||
|  | * Redistributions of source code must retain the above copyright | ||||||
|  |   notice, this list of conditions and the following disclaimer. | ||||||
|  | 
 | ||||||
|  | * Redistributions in binary form must reproduce the above copyright | ||||||
|  |   notice, this list of conditions and the following disclaimer in | ||||||
|  |   the documentation and/or other materials provided with the | ||||||
|  |   distribution. | ||||||
|  | 
 | ||||||
|  | * Neither the name of the copyright holders nor the names of | ||||||
|  |   contributors may be used to endorse or promote products derived | ||||||
|  |   from this software without specific prior written permission. | ||||||
|  | 
 | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
|  | POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <avr/io.h> | ||||||
|  | #include <avr/interrupt.h> | ||||||
|  | #include <util/delay.h> | ||||||
|  | #include "m0110.h" | ||||||
|  | #include "debug.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static inline void clock_lo(void); | ||||||
|  | static inline void clock_hi(void); | ||||||
|  | static inline bool clock_in(void); | ||||||
|  | static inline void data_lo(void); | ||||||
|  | static inline void data_hi(void); | ||||||
|  | static inline bool data_in(void); | ||||||
|  | static inline uint16_t wait_clock_lo(uint16_t us); | ||||||
|  | static inline uint16_t wait_clock_hi(uint16_t us); | ||||||
|  | static inline uint16_t wait_data_lo(uint16_t us); | ||||||
|  | static inline uint16_t wait_data_hi(uint16_t us); | ||||||
|  | static inline void idle(void); | ||||||
|  | static inline void request(void); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  | Primitive M0110 Library for AVR | ||||||
|  | ============================== | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Signaling | ||||||
|  | --------- | ||||||
|  | CLOCK is always from KEYBOARD. DATA are sent with MSB first. | ||||||
|  | 
 | ||||||
|  | 1) IDLE: both line is high. | ||||||
|  |     CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  |     DATA  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  | 
 | ||||||
|  | 2) KEYBOARD->HOST: HOST reads bit on rising edge. | ||||||
|  |     CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ | ||||||
|  |     DATA  ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ | ||||||
|  |                       <--> 160us(clock low) | ||||||
|  |                          <---> 180us(clock high) | ||||||
|  | 
 | ||||||
|  | 3) HOST->KEYBOARD: HOST asserts bit on falling edge. | ||||||
|  |     CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ | ||||||
|  |     DATA  ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ | ||||||
|  |                 <----> 840us(request to send by host)                     <-> 80us(hold DATA) | ||||||
|  |                       <--> 180us(clock low) | ||||||
|  |                          <---> 220us(clock high) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Protocol | ||||||
|  | -------- | ||||||
|  | COMMAND: | ||||||
|  |     Inquiry     0x10    get key event | ||||||
|  |     Instant     0x12    get key event | ||||||
|  |     Model       0x14    get model number(M0110 responds with 0x09) | ||||||
|  |                         bit 7   1 if another device connected(used when keypad exists?) | ||||||
|  |                         bit4-6  next device model number | ||||||
|  |                         bit1-3  keyboard model number | ||||||
|  |                         bit 0   always 1 | ||||||
|  |     Test        0x16    test(ACK:0x7D/NAK:0x77) | ||||||
|  | 
 | ||||||
|  | KEY EVENT: | ||||||
|  |     bit 7       key state(0:press 1:release) | ||||||
|  |     bit 6-1     scan code | ||||||
|  |     bit 0       always 1 | ||||||
|  |     To get scan code,  use ((bits&(1<<7)) | ((bits&7F))>>1). | ||||||
|  | 
 | ||||||
|  | SCAN CODE: | ||||||
|  |     M0110A | ||||||
|  |     ,---------------------------------------------------------. | ||||||
|  |     |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backs| | ||||||
|  |     |---------------------------------------------------------| | ||||||
|  |     |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \| | ||||||
|  |     |---------------------------------------------------------| | ||||||
|  |     |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| | ||||||
|  |     |---------------------------------------------------------| | ||||||
|  |     |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|        | | ||||||
|  |     `---------------------------------------------------------' | ||||||
|  |          |Opt|Mac |         Space               |Enter|Opt| | ||||||
|  |          `------------------------------------------------' | ||||||
|  |     ,---------------------------------------------------------. | ||||||
|  |     | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33| | ||||||
|  |     |---------------------------------------------------------| | ||||||
|  |     |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| | ||||||
|  |     |---------------------------------------------------------| | ||||||
|  |     |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24| | ||||||
|  |     |---------------------------------------------------------| | ||||||
|  |     |      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|      38| | ||||||
|  |     `---------------------------------------------------------' | ||||||
|  |          | 3A|  37|             31              |   34| 3A| | ||||||
|  |          `------------------------------------------------' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | References | ||||||
|  | ---------- | ||||||
|  | Protocol: | ||||||
|  |     http://www.mac.linux-m68k.org/devel/plushw.php
 | ||||||
|  | Connector: | ||||||
|  |     http://www.kbdbabel.org/conn/kbd_connector_macplus.png
 | ||||||
|  | Signaling: | ||||||
|  |     http://www.kbdbabel.org/signaling/kbd_signaling_mac.png
 | ||||||
|  |     http://typematic.blog.shinobi.jp/Entry/14/
 | ||||||
|  | Scan Codes: | ||||||
|  |     http://m0115.web.fc2.com/m0110.jpg
 | ||||||
|  |     http://m0115.web.fc2.com/m0110a.jpg
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #define WAIT(stat, us, err) do { \ | ||||||
|  |     if (!wait_##stat(us)) { \ | ||||||
|  |         m0110_error = err; \ | ||||||
|  |         goto ERROR; \ | ||||||
|  |     } \ | ||||||
|  | } while (0) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | uint8_t m0110_error = 0; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void m0110_init(void) | ||||||
|  | { | ||||||
|  |     uint8_t data; | ||||||
|  |     idle(); | ||||||
|  |     _delay_ms(255); | ||||||
|  | 
 | ||||||
|  |     m0110_send(M0110_MODLE); | ||||||
|  |     data = m0110_recv(); | ||||||
|  |     print("m0110_init model: "); phex(data); print("\n"); | ||||||
|  | 
 | ||||||
|  |     m0110_send(M0110_TEST); | ||||||
|  |     data = m0110_recv(); | ||||||
|  |     print("m0110_init test: "); phex(data); print("\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t m0110_send(uint8_t data) | ||||||
|  | { | ||||||
|  |     m0110_error = 0; | ||||||
|  | 
 | ||||||
|  |     request(); | ||||||
|  |     WAIT(clock_lo, 1000, 0); | ||||||
|  |     for (uint8_t bit = 0x80; bit; bit >>= 1) { | ||||||
|  |         WAIT(clock_lo, 250, 3); | ||||||
|  |         _delay_us(15); | ||||||
|  |         if (data&bit) { | ||||||
|  |             data_hi(); | ||||||
|  |         } else { | ||||||
|  |             data_lo(); | ||||||
|  |         } | ||||||
|  |         WAIT(clock_hi, 200, 4); | ||||||
|  |     } | ||||||
|  |     _delay_us(100); // hold last bit for 80us
 | ||||||
|  |     idle(); | ||||||
|  |     return 1; | ||||||
|  | ERROR: | ||||||
|  |     if (m0110_error) { | ||||||
|  |         print("m0110_send err: "); phex(m0110_error); print("\n"); | ||||||
|  |     } | ||||||
|  |     idle(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t m0110_recv(void) | ||||||
|  | { | ||||||
|  |     uint8_t data = 0; | ||||||
|  |     m0110_error = 0; | ||||||
|  | 
 | ||||||
|  |     WAIT(clock_lo, -1, 0); // need 250ms? insted 0xffff(16bit max)us
 | ||||||
|  |     for (uint8_t i = 0; i < 8; i++) { | ||||||
|  |         data <<= 1; | ||||||
|  |         WAIT(clock_lo, 200, 2); | ||||||
|  |         WAIT(clock_hi, 200, 3); | ||||||
|  |         if (data_in()) { | ||||||
|  |             data |= 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     idle(); | ||||||
|  |     print("m0110_send recv data: "); phex(data); print("\n"); | ||||||
|  |     return data; | ||||||
|  | ERROR: | ||||||
|  |     if (m0110_error) { | ||||||
|  |         print("m0110_recv err: "); phex(m0110_error); print("\n"); | ||||||
|  |     } | ||||||
|  |     idle(); | ||||||
|  |     return 0xFF; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t m0110_recv_key(void) | ||||||
|  | { | ||||||
|  |     uint8_t key; | ||||||
|  |     m0110_send(M0110_INQUIRY); | ||||||
|  |     key = m0110_recv(); | ||||||
|  |     if (key == 0xFF || key == M0110_NULL) | ||||||
|  |         return M0110_NULL; | ||||||
|  |     else  | ||||||
|  |         return (key&(1<<7) | (key&0x7F)>>1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static inline void clock_lo() | ||||||
|  | { | ||||||
|  |     M0110_CLOCK_PORT &= ~(1<<M0110_CLOCK_BIT); | ||||||
|  |     M0110_CLOCK_DDR  |=  (1<<M0110_CLOCK_BIT); | ||||||
|  | } | ||||||
|  | static inline void clock_hi() | ||||||
|  | { | ||||||
|  |     /* input with pull up */ | ||||||
|  |     M0110_CLOCK_DDR  &= ~(1<<M0110_CLOCK_BIT); | ||||||
|  |     M0110_CLOCK_PORT |=  (1<<M0110_CLOCK_BIT); | ||||||
|  | } | ||||||
|  | static inline bool clock_in() | ||||||
|  | { | ||||||
|  |     M0110_CLOCK_DDR  &= ~(1<<M0110_CLOCK_BIT); | ||||||
|  |     M0110_CLOCK_PORT |=  (1<<M0110_CLOCK_BIT); | ||||||
|  |     _delay_us(1); | ||||||
|  |     return M0110_CLOCK_PIN&(1<<M0110_CLOCK_BIT); | ||||||
|  | } | ||||||
|  | static inline void data_lo() | ||||||
|  | { | ||||||
|  |     M0110_DATA_PORT &= ~(1<<M0110_DATA_BIT); | ||||||
|  |     M0110_DATA_DDR  |=  (1<<M0110_DATA_BIT); | ||||||
|  | } | ||||||
|  | static inline void data_hi() | ||||||
|  | { | ||||||
|  |     /* input with pull up */ | ||||||
|  |     M0110_DATA_DDR  &= ~(1<<M0110_DATA_BIT); | ||||||
|  |     M0110_DATA_PORT |=  (1<<M0110_DATA_BIT); | ||||||
|  | } | ||||||
|  | static inline bool data_in() | ||||||
|  | { | ||||||
|  |     M0110_DATA_DDR  &= ~(1<<M0110_DATA_BIT); | ||||||
|  |     M0110_DATA_PORT |=  (1<<M0110_DATA_BIT); | ||||||
|  |     _delay_us(1); | ||||||
|  |     return M0110_DATA_PIN&(1<<M0110_DATA_BIT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline uint16_t wait_clock_lo(uint16_t us) | ||||||
|  | { | ||||||
|  |     while (clock_in()  && us) { asm(""); _delay_us(1); us--; } | ||||||
|  |     return us; | ||||||
|  | } | ||||||
|  | static inline uint16_t wait_clock_hi(uint16_t us) | ||||||
|  | { | ||||||
|  |     while (!clock_in() && us) { asm(""); _delay_us(1); us--; } | ||||||
|  |     return us; | ||||||
|  | } | ||||||
|  | static inline uint16_t wait_data_lo(uint16_t us) | ||||||
|  | { | ||||||
|  |     while (data_in() && us)  { asm(""); _delay_us(1); us--; } | ||||||
|  |     return us; | ||||||
|  | } | ||||||
|  | static inline uint16_t wait_data_hi(uint16_t us) | ||||||
|  | { | ||||||
|  |     while (!data_in() && us)  { asm(""); _delay_us(1); us--; } | ||||||
|  |     return us; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void idle(void) | ||||||
|  | { | ||||||
|  |     clock_hi(); | ||||||
|  |     data_hi(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void request(void) | ||||||
|  | { | ||||||
|  |     clock_hi(); | ||||||
|  |     data_lo(); | ||||||
|  | } | ||||||
							
								
								
									
										73
									
								
								m0110.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								m0110.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | |||||||
|  | /*
 | ||||||
|  | Copyright 2011 Jun WAKO <wakojun@gmail.com> | ||||||
|  | 
 | ||||||
|  | This software is licensed with a Modified BSD License. | ||||||
|  | All of this is supposed to be Free Software, Open Source, DFSG-free, | ||||||
|  | GPL-compatible, and OK to use in both free and proprietary applications. | ||||||
|  | Additions and corrections to this file are welcome. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Redistribution and use in source and binary forms, with or without | ||||||
|  | modification, are permitted provided that the following conditions are met: | ||||||
|  | 
 | ||||||
|  | * Redistributions of source code must retain the above copyright | ||||||
|  |   notice, this list of conditions and the following disclaimer. | ||||||
|  | 
 | ||||||
|  | * Redistributions in binary form must reproduce the above copyright | ||||||
|  |   notice, this list of conditions and the following disclaimer in | ||||||
|  |   the documentation and/or other materials provided with the | ||||||
|  |   distribution. | ||||||
|  | 
 | ||||||
|  | * Neither the name of the copyright holders nor the names of | ||||||
|  |   contributors may be used to endorse or promote products derived | ||||||
|  |   from this software without specific prior written permission. | ||||||
|  | 
 | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||||||
|  | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
|  | POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef M0110_H | ||||||
|  | #define M0110_H | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* port settings for clock and data line */ | ||||||
|  | #if !(defined(M0110_CLOCK_PORT) && \ | ||||||
|  |       defined(M0110_CLOCK_PIN) && \ | ||||||
|  |       defined(M0110_CLOCK_DDR) && \ | ||||||
|  |       defined(M0110_CLOCK_BIT)) | ||||||
|  | #   error "M0110 clock port setting is required in config.h" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if !(defined(M0110_DATA_PORT) && \ | ||||||
|  |       defined(M0110_DATA_PIN) && \ | ||||||
|  |       defined(M0110_DATA_DDR) && \ | ||||||
|  |       defined(M0110_DATA_BIT)) | ||||||
|  | #   error "M0110 data port setting is required in config.h" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define M0110_INQUIRY     0x10 | ||||||
|  | #define M0110_INSTNAT     0x14 | ||||||
|  | #define M0110_MODLE       0x16 | ||||||
|  | #define M0110_TEST        0x36 | ||||||
|  | 
 | ||||||
|  | #define M0110_NULL        0x7B | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | extern uint8_t m0110_error; | ||||||
|  | 
 | ||||||
|  | /* host role */ | ||||||
|  | void m0110_host_init(void); | ||||||
|  | uint8_t m0110_send(uint8_t data); | ||||||
|  | uint8_t m0110_recv(void); | ||||||
|  | uint8_t m0110_recv_key(void); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										52
									
								
								m0110_usb/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								m0110_usb/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | # Target file name (without extension).
 | ||||||
|  | TARGET = m0110 | ||||||
|  | 
 | ||||||
|  | # Directory common source filess exist
 | ||||||
|  | COMMON_DIR = .. | ||||||
|  | 
 | ||||||
|  | # Directory keyboard dependent files exist
 | ||||||
|  | TARGET_DIR = . | ||||||
|  | 
 | ||||||
|  | # keyboard dependent files
 | ||||||
|  | SRC =	main.c \
 | ||||||
|  | 	keymap.c \
 | ||||||
|  | 	matrix.c \
 | ||||||
|  | 	led.c \
 | ||||||
|  | 	m0110.c | ||||||
|  | 
 | ||||||
|  | CONFIG_H = config.h | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # MCU name, you MUST set this to match the board you are using
 | ||||||
|  | # type "make clean" after changing this, so all files will be rebuilt
 | ||||||
|  | #MCU = at90usb162       # Teensy 1.0
 | ||||||
|  | MCU = atmega32u4       # Teensy 2.0 | ||||||
|  | #MCU = at90usb646       # Teensy++ 1.0
 | ||||||
|  | #MCU = at90usb1286      # Teensy++ 2.0
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Processor frequency.
 | ||||||
|  | #   Normally the first thing your program should do is set the clock prescaler,
 | ||||||
|  | #   so your program will run at the correct speed.  You should also set this
 | ||||||
|  | #   variable to same clock speed.  The _delay_ms() macro uses this, and many
 | ||||||
|  | #   examples use this variable to calculate timings.  Do not add a "UL" here.
 | ||||||
|  | F_CPU = 16000000 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # Build Options
 | ||||||
|  | #   *Comment out* to disable the options.
 | ||||||
|  | #
 | ||||||
|  | #MOUSEKEY_ENABLE = yes	# Mouse keys
 | ||||||
|  | #PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support
 | ||||||
|  | #EXTRAKEY_ENABLE = yes	# Audio control and System control
 | ||||||
|  | #NKRO_ENABLE = yes	# USB Nkey Rollover
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #---------------- Programming Options --------------------------
 | ||||||
|  | PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | include $(COMMON_DIR)/pjrc.mk | ||||||
|  | include $(COMMON_DIR)/common.mk | ||||||
							
								
								
									
										55
									
								
								m0110_usb/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								m0110_usb/README
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | |||||||
|  | M0110 to USB keyboard converter | ||||||
|  | =============================== | ||||||
|  | This firmware converts protocol for Apple Machintosh Keybard M0110. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Connection | ||||||
|  | ---------- | ||||||
|  | You need 4P4C plug and cable to connect Teensy into M0110. | ||||||
|  | Teensy port F0 is assigned for CLOCK line and F1 for DATA by default, you can change pin configuration with editing config.h.. | ||||||
|  | 
 | ||||||
|  | Plug: | ||||||
|  |     http://en.wikipedia.org/wiki/Modular_connector#4P4C | ||||||
|  | 
 | ||||||
|  | Pinout: | ||||||
|  |     http://www.kbdbabel.org/conn/kbd_connector_macplus.png | ||||||
|  |     1(Black):   GND | ||||||
|  |     2(Red):     CLOCK | ||||||
|  |     3(Green):   DATA | ||||||
|  |     4(Yellow):  +5V | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Build Frimware | ||||||
|  | -------------- | ||||||
|  | Optionally edit Makefile and config.h for build options, pin configuration or MCU. | ||||||
|  | 
 | ||||||
|  | $ cd m0110_usb | ||||||
|  | $ make | ||||||
|  | and program your Teensy with loader. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Keymap | ||||||
|  | ------ | ||||||
|  | You can change a keymap by editing code of keymap.c like following. | ||||||
|  | How to define the keymap is probably obvious. You can find  key symbols in usb_keycodes.h. | ||||||
|  | 
 | ||||||
|  | This is a default keymap for M0110. | ||||||
|  | ,---------------------------------------------------------. | ||||||
|  | |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bacpa| | ||||||
|  | |---------------------------------------------------------| | ||||||
|  | |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \| | ||||||
|  | |---------------------------------------------------------| | ||||||
|  | |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| | ||||||
|  | |---------------------------------------------------------| | ||||||
|  | |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shift   | | ||||||
|  | `---------------------------------------------------------' | ||||||
|  |      |Opt|Alt |         Space               |Alt |Opt| | ||||||
|  |      `-----------------------------------------------' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Notes | ||||||
|  | ----- | ||||||
|  | 
 | ||||||
|  | EOF | ||||||
							
								
								
									
										62
									
								
								m0110_usb/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								m0110_usb/config.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | |||||||
|  | /*
 | ||||||
|  | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||||||
|  | 
 | ||||||
|  | This program is free software: you can redistribute it and/or modify | ||||||
|  | it under the terms of the GNU General Public License as published by | ||||||
|  | the Free Software Foundation, either version 2 of the License, or | ||||||
|  | (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | This program is distributed in the hope that it will be useful, | ||||||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  | You should have received a copy of the GNU General Public License | ||||||
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef CONFIG_H | ||||||
|  | #define CONFIG_H | ||||||
|  | 
 | ||||||
|  | /* controller configuration */ | ||||||
|  | #include "controller_teensy.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #define VENDOR_ID       0xFEED | ||||||
|  | #define PRODUCT_ID      0x0110 | ||||||
|  | #define MANUFACTURER    t.m.k. | ||||||
|  | #define PRODUCT         M0110 keyboard converter | ||||||
|  | #define DESCRIPTION     convert M0110 keyboard to USB | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* matrix size */ | ||||||
|  | #define MATRIX_ROWS 8 | ||||||
|  | #define MATRIX_COLS 8 | ||||||
|  | 
 | ||||||
|  | /* Locking Caps Lock support */ | ||||||
|  | //#define MATRIX_HAS_LOCKING_CAPS
 | ||||||
|  | 
 | ||||||
|  | /* key combination for command */ | ||||||
|  | #define IS_COMMAND() ( \ | ||||||
|  |     keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ | ||||||
|  |     keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \ | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* mouse keys */ | ||||||
|  | #ifdef MOUSEKEY_ENABLE | ||||||
|  | #   define MOUSEKEY_DELAY_TIME 192 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* ports */ | ||||||
|  | #define M0110_CLOCK_PORT        PORTF | ||||||
|  | #define M0110_CLOCK_PIN         PINF | ||||||
|  | #define M0110_CLOCK_DDR         DDRF | ||||||
|  | #define M0110_CLOCK_BIT         0 | ||||||
|  | #define M0110_DATA_PORT         PORTF | ||||||
|  | #define M0110_DATA_PIN          PINF | ||||||
|  | #define M0110_DATA_DDR          DDRF | ||||||
|  | #define M0110_DATA_BIT          1 | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										
											BIN
										
									
								
								m0110_usb/doc/m0110.jpg
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								m0110_usb/doc/m0110.jpg
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 48 KiB | 
							
								
								
									
										
											BIN
										
									
								
								m0110_usb/doc/teensy.jpg
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								m0110_usb/doc/teensy.jpg
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 49 KiB | 
							
								
								
									
										118
									
								
								m0110_usb/keymap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								m0110_usb/keymap.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,118 @@ | |||||||
|  | /*
 | ||||||
|  | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||||||
|  | 
 | ||||||
|  | This program is free software: you can redistribute it and/or modify | ||||||
|  | it under the terms of the GNU General Public License as published by | ||||||
|  | the Free Software Foundation, either version 2 of the License, or | ||||||
|  | (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | This program is distributed in the hope that it will be useful, | ||||||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  | You should have received a copy of the GNU General Public License | ||||||
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /* 
 | ||||||
|  |  * Keymap for ADB keyboard | ||||||
|  |  */ | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <avr/pgmspace.h> | ||||||
|  | #include "usb_keyboard.h" | ||||||
|  | #include "usb_keycodes.h" | ||||||
|  | #include "print.h" | ||||||
|  | #include "debug.h" | ||||||
|  | #include "util.h" | ||||||
|  | #include "keymap.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) | ||||||
|  | 
 | ||||||
|  | // Convert physical keyboard layout to matrix array.
 | ||||||
|  | // This is a macro to define keymap easily in keyboard layout form.
 | ||||||
|  | // TODO: layout for M0110A
 | ||||||
|  | /* M0110 */ | ||||||
|  | #define KEYMAP( \ | ||||||
|  |     K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, \ | ||||||
|  |     K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E,K2A, \ | ||||||
|  |     K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27,    K24, \ | ||||||
|  |     K38,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C,             \ | ||||||
|  |         K3A,K37,        K31,                K34              \ | ||||||
|  | ) { \ | ||||||
|  |     { KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ | ||||||
|  |     { KB_##K08, KB_##K09, KB_NO,    KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ | ||||||
|  |     { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | ||||||
|  |     { KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ | ||||||
|  |     { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ | ||||||
|  |     { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ | ||||||
|  |     { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_NO,    KB_NO,    KB_##K37 }, \ | ||||||
|  |     { KB_##K38, KB_##K39, KB_##K3A, KB_NO,    KB_NO,    KB_NO,    KB_NO,    KB_NO    }  \ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
 | ||||||
|  | static const uint8_t PROGMEM fn_layer[] = { | ||||||
|  |     0,              // Fn0
 | ||||||
|  |     0,              // Fn1
 | ||||||
|  |     0,              // Fn2
 | ||||||
|  |     0,              // Fn3
 | ||||||
|  |     0,              // Fn4
 | ||||||
|  |     0,              // Fn5
 | ||||||
|  |     0,              // Fn6
 | ||||||
|  |     0               // Fn7
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer.
 | ||||||
|  | // See layer.c for details.
 | ||||||
|  | static const uint8_t PROGMEM fn_keycode[] = { | ||||||
|  |     KB_NO,          // Fn0
 | ||||||
|  |     KB_NO,          // Fn1
 | ||||||
|  |     KB_NO,          // Fn2
 | ||||||
|  |     KB_NO,          // Fn3
 | ||||||
|  |     KB_NO,          // Fn4
 | ||||||
|  |     KB_NO,          // Fn5
 | ||||||
|  |     KB_NO,          // Fn6
 | ||||||
|  |     KB_NO           // Fn7
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||||
|  |     /* Default Layer: plain keymap
 | ||||||
|  |      * ,---------------------------------------------------------. | ||||||
|  |      * |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bacpa| | ||||||
|  |      * |---------------------------------------------------------| | ||||||
|  |      * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \| | ||||||
|  |      * |---------------------------------------------------------| | ||||||
|  |      * |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| | ||||||
|  |      * |---------------------------------------------------------| | ||||||
|  |      * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shift   | | ||||||
|  |      * `---------------------------------------------------------' | ||||||
|  |      *      |Opt|Alt |         Space               |Alt |Opt| | ||||||
|  |      *      `-----------------------------------------------' | ||||||
|  |      */ | ||||||
|  |     KEYMAP( | ||||||
|  |     GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC, | ||||||
|  |     TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS, | ||||||
|  |     CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,     ENT, | ||||||
|  |     LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH, | ||||||
|  |          LGUI,LALT,          SPC,                     RALT | ||||||
|  |     ), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | ||||||
|  | { | ||||||
|  |     return KEYCODE(layer, row, col); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t keymap_fn_layer(uint8_t fn_bits) | ||||||
|  | { | ||||||
|  |     return pgm_read_byte(&fn_layer[biton(fn_bits)]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t keymap_fn_keycode(uint8_t fn_bits) | ||||||
|  | { | ||||||
|  |     return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								m0110_usb/led.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								m0110_usb/led.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | /*
 | ||||||
|  | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||||||
|  | 
 | ||||||
|  | This program is free software: you can redistribute it and/or modify | ||||||
|  | it under the terms of the GNU General Public License as published by | ||||||
|  | the Free Software Foundation, either version 2 of the License, or | ||||||
|  | (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | This program is distributed in the hope that it will be useful, | ||||||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  | You should have received a copy of the GNU General Public License | ||||||
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "stdint.h" | ||||||
|  | #include "led.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void led_set(uint8_t usb_led) | ||||||
|  | { | ||||||
|  | } | ||||||
							
								
								
									
										193
									
								
								m0110_usb/matrix.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								m0110_usb/matrix.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,193 @@ | |||||||
|  | /*
 | ||||||
|  | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||||||
|  | 
 | ||||||
|  | This program is free software: you can redistribute it and/or modify | ||||||
|  | it under the terms of the GNU General Public License as published by | ||||||
|  | the Free Software Foundation, either version 2 of the License, or | ||||||
|  | (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | This program is distributed in the hope that it will be useful, | ||||||
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  | You should have received a copy of the GNU General Public License | ||||||
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * scan matrix | ||||||
|  |  */ | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <avr/io.h> | ||||||
|  | #include <util/delay.h> | ||||||
|  | #include "print.h" | ||||||
|  | #include "util.h" | ||||||
|  | #include "debug.h" | ||||||
|  | #include "host.h" | ||||||
|  | #include "led.h" | ||||||
|  | #include "m0110.h" | ||||||
|  | #include "matrix.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #define CAPS        0x39 | ||||||
|  | #define CAPS_UP     (CAPS | 0x80) | ||||||
|  | #define ROW(key)    ((key)>>3&0x0F) | ||||||
|  | #define COL(key)    ((key)&0x07) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static bool is_modified = false; | ||||||
|  | 
 | ||||||
|  | // matrix state buffer(1:on, 0:off)
 | ||||||
|  | static uint8_t *matrix; | ||||||
|  | static uint8_t _matrix0[MATRIX_ROWS]; | ||||||
|  | 
 | ||||||
|  | #ifdef MATRIX_HAS_GHOST | ||||||
|  | static bool matrix_has_ghost_in_row(uint8_t row); | ||||||
|  | #endif | ||||||
|  | static void register_key(uint8_t key); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | inline | ||||||
|  | uint8_t matrix_rows(void) | ||||||
|  | { | ||||||
|  |     return MATRIX_ROWS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline | ||||||
|  | uint8_t matrix_cols(void) | ||||||
|  | { | ||||||
|  |     return MATRIX_COLS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void matrix_init(void) | ||||||
|  | { | ||||||
|  |     print_enable = true; | ||||||
|  |     debug_enable = true; | ||||||
|  |     debug_matrix = false; | ||||||
|  |     debug_keyboard = false; | ||||||
|  |     debug_mouse = false; | ||||||
|  |     print("debug enabled.\n"); | ||||||
|  | 
 | ||||||
|  |     m0110_init(); | ||||||
|  |     // initialize matrix state: all keys off
 | ||||||
|  |     for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; | ||||||
|  |     matrix = _matrix0; | ||||||
|  |     return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t matrix_scan(void) | ||||||
|  | { | ||||||
|  |     uint8_t key; | ||||||
|  | 
 | ||||||
|  |     is_modified = false; | ||||||
|  |     key = m0110_recv_key(); | ||||||
|  | 
 | ||||||
|  | #ifdef MATRIX_HAS_LOCKING_CAPS | ||||||
|  |     // Send Caps key up event
 | ||||||
|  |     if (matrix_is_on(ROW(CAPS), COL(CAPS))) { | ||||||
|  |         is_modified = true; | ||||||
|  |         register_key(CAPS_UP); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     if (key == M0110_NULL) { | ||||||
|  |         return 0; | ||||||
|  |     } else { | ||||||
|  | #ifdef MATRIX_HAS_LOCKING_CAPS     | ||||||
|  |         if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { | ||||||
|  |             // CAPS LOCK on:
 | ||||||
|  |             // Ignore LockingCaps key down event
 | ||||||
|  |             if (key == CAPS) return 0; | ||||||
|  |             // Convert LockingCaps key up event into down event
 | ||||||
|  |             if (key == CAPS_UP) key = CAPS; | ||||||
|  |         } else { | ||||||
|  |             // CAPS LOCK off:
 | ||||||
|  |             // Ignore LockingCaps key up event
 | ||||||
|  |             if (key == CAPS_UP) return 0; | ||||||
|  |         } | ||||||
|  | #endif         | ||||||
|  |         is_modified = true; | ||||||
|  |         register_key(key); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (debug_enable) { | ||||||
|  |         print("key: "); phex(key); print("\n"); | ||||||
|  |     } | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool matrix_is_modified(void) | ||||||
|  | { | ||||||
|  |     return is_modified; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline | ||||||
|  | bool matrix_has_ghost(void) | ||||||
|  | { | ||||||
|  | #ifdef MATRIX_HAS_GHOST | ||||||
|  |     for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||||||
|  |         if (matrix_has_ghost_in_row(i)) | ||||||
|  |             return true; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline | ||||||
|  | bool matrix_is_on(uint8_t row, uint8_t col) | ||||||
|  | { | ||||||
|  |     return (matrix[row] & (1<<col)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline | ||||||
|  | uint8_t matrix_get_row(uint8_t row) | ||||||
|  | { | ||||||
|  |     return matrix[row]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void matrix_print(void) | ||||||
|  | { | ||||||
|  |     print("\nr/c 01234567\n"); | ||||||
|  |     for (uint8_t row = 0; row < matrix_rows(); row++) { | ||||||
|  |         phex(row); print(": "); | ||||||
|  |         pbin_reverse(matrix_get_row(row)); | ||||||
|  |         print("\n"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t matrix_key_count(void) | ||||||
|  | { | ||||||
|  |     uint8_t count = 0; | ||||||
|  |     for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||||||
|  |         count += bitpop(matrix[i]); | ||||||
|  |     } | ||||||
|  |     return count; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef MATRIX_HAS_GHOST | ||||||
|  | inline | ||||||
|  | static bool matrix_has_ghost_in_row(uint8_t row) | ||||||
|  | { | ||||||
|  |     // no ghost exists in case less than 2 keys on
 | ||||||
|  |     if (((matrix[row] - 1) & matrix[row]) == 0) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     // ghost exists in case same state as other row
 | ||||||
|  |     for (uint8_t i=0; i < MATRIX_ROWS; i++) { | ||||||
|  |         if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | ||||||
|  |             return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | inline | ||||||
|  | static void register_key(uint8_t key) | ||||||
|  | { | ||||||
|  |     if (key&0x80) { | ||||||
|  |         matrix[ROW(key)] &= ~(1<<COL(key)); | ||||||
|  |     } else { | ||||||
|  |         matrix[ROW(key)] |=  (1<<COL(key)); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 tmk
						tmk