[Jack & Erez] Comments + tiny updates and cleanup
This commit is contained in:
		
							
								
								
									
										114
									
								
								keyboard/ergodox_ez/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								keyboard/ergodox_ez/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| #---------------------------------------------------------------------------- | ||||
| # On command line: | ||||
| # | ||||
| # make = Make software. | ||||
| # | ||||
| # make clean = Clean out built project files. | ||||
| # | ||||
| # That's pretty much all you need. To compile, always go make clean,  | ||||
| # followed by make. | ||||
| # | ||||
| # For advanced users only: | ||||
| # make teensy = Download the hex file to the device, using teensy_loader_cli. | ||||
| #               (must have teensy_loader_cli installed). | ||||
| # | ||||
| #---------------------------------------------------------------------------- | ||||
|  | ||||
| # Target file name (without extension). | ||||
| TARGET = ergodox_ez | ||||
|  | ||||
|  | ||||
| # Directory common source filess exist | ||||
| TOP_DIR = ../.. | ||||
|  | ||||
| # Directory keyboard dependent files exist | ||||
| TARGET_DIR = . | ||||
|  | ||||
| # # project specific files | ||||
| SRC = ergodox_ez.c \ | ||||
| 	  twimaster.c | ||||
|  | ||||
| ifdef KEYMAP | ||||
|     SRC := keymaps/keymap_$(KEYMAP).c $(SRC) | ||||
| else | ||||
|     SRC := keymaps/keymap_default.c $(SRC) | ||||
| endif | ||||
|  | ||||
| CONFIG_H = config.h | ||||
|  | ||||
| # MCU name | ||||
| #MCU = at90usb1287 | ||||
| MCU = atmega32u4 | ||||
|  | ||||
| # Processor frequency. | ||||
| #     This will define a symbol, F_CPU, in all source code files equal to the | ||||
| #     processor frequency in Hz. You can then use this symbol in your source code to | ||||
| #     calculate timings. Do NOT tack on a 'UL' at the end, this will be done | ||||
| #     automatically to create a 32-bit value in your source code. | ||||
| # | ||||
| #     This will be an integer division of F_USB below, as it is sourced by | ||||
| #     F_USB after it has run through any CPU prescalers. Note that this value | ||||
| #     does not *change* the processor frequency - it should merely be updated to | ||||
| #     reflect the processor speed set externally so that the code can use accurate | ||||
| #     software delays. | ||||
| F_CPU = 16000000 | ||||
|  | ||||
|  | ||||
| # | ||||
| # LUFA specific | ||||
| # | ||||
| # Target architecture (see library "Board Types" documentation). | ||||
| ARCH = AVR8 | ||||
|  | ||||
| # Input clock frequency. | ||||
| #     This will define a symbol, F_USB, in all source code files equal to the | ||||
| #     input clock frequency (before any prescaling is performed) in Hz. This value may | ||||
| #     differ from F_CPU if prescaling is used on the latter, and is required as the | ||||
| #     raw input clock is fed directly to the PLL sections of the AVR for high speed | ||||
| #     clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' | ||||
| #     at the end, this will be done automatically to create a 32-bit value in your | ||||
| #     source code. | ||||
| # | ||||
| #     If no clock division is performed on the input clock inside the AVR (via the | ||||
| #     CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. | ||||
| F_USB = $(F_CPU) | ||||
|  | ||||
| # Interrupt driven control endpoint task(+60) | ||||
| OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | ||||
|  | ||||
|  | ||||
| # Boot Section Size in *bytes* | ||||
| #   Teensy halfKay   512 | ||||
| #   Teensy++ halfKay 1024 | ||||
| #   Atmel DFU loader 4096 | ||||
| #   LUFA bootloader  4096 | ||||
| #   USBaspLoader     2048 | ||||
| OPT_DEFS += -DBOOTLOADER_SIZE=4096 | ||||
|  | ||||
|  | ||||
| # Build Options | ||||
| #   comment out to disable the options. | ||||
| # | ||||
| BOOTMAGIC_ENABLE = yes	# Virtual DIP switch configuration(+1000) | ||||
| MOUSEKEY_ENABLE = yes	# Mouse keys(+4700) | ||||
| EXTRAKEY_ENABLE = yes	# Audio control and System control(+450) | ||||
| CONSOLE_ENABLE = yes	# Console for debug(+400) | ||||
| COMMAND_ENABLE = yes    # Commands for debug and configuration | ||||
| # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE | ||||
| # SLEEP_LED_ENABLE = yes  # Breathing sleep LED during USB suspend | ||||
| # NKRO_ENABLE = yes		# USB Nkey Rollover - not yet supported in LUFA | ||||
| # BACKLIGHT_ENABLE = yes  # Enable keyboard backlight functionality | ||||
| # MIDI_ENABLE = YES 		# MIDI controls | ||||
| # UNICODE_ENABLE = YES 		# Unicode | ||||
| # BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID | ||||
|  | ||||
|  | ||||
| # Optimize size but this may cause error "relocation truncated to fit" | ||||
| #EXTRALDFLAGS = -Wl,--relax | ||||
|  | ||||
| # Search Path | ||||
| VPATH += $(TARGET_DIR) | ||||
| VPATH += $(TOP_DIR) | ||||
|  | ||||
| include $(TOP_DIR)/quantum.mk | ||||
|  | ||||
							
								
								
									
										1
									
								
								keyboard/ergodox_ez/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								keyboard/ergodox_ez/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| // TODO: Make up a proper readme for the ErgoDox EZ. | ||||
							
								
								
									
										87
									
								
								keyboard/ergodox_ez/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								keyboard/ergodox_ez/config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /* | ||||
| Copyright 2012 Jun Wako <wakojun@gmail.com> | ||||
| Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com> | ||||
|  | ||||
| This program is free software: you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation, either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License | ||||
| along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
|  | ||||
| #ifndef CONFIG_H | ||||
| #define CONFIG_H | ||||
|  | ||||
| #include "config_common.h" | ||||
|  | ||||
| /* USB Device descriptor parameter */ | ||||
| #define VENDOR_ID       0xFEED | ||||
| #define PRODUCT_ID      0x1307 | ||||
| #define DEVICE_VER      0x0001 | ||||
| #define MANUFACTURER    ErgoDox EZ | ||||
| #define PRODUCT         ErgoDox EZ | ||||
| #define DESCRIPTION     t.m.k. keyboard firmware for Ergodox | ||||
|  | ||||
| /* key matrix size */ | ||||
| #define MATRIX_ROWS 14 | ||||
| #define MATRIX_COLS 6 | ||||
|  | ||||
| #define MOUSEKEY_DELAY          100 | ||||
| #define MOUSEKEY_INTERVAL       20 | ||||
| #define MOUSEKEY_MAX_SPEED      3 | ||||
| #define MOUSEKEY_TIME_TO_MAX    10 | ||||
|  | ||||
| #define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 } | ||||
| #define ROWS (int []){ D0, D5, B5, B6 } | ||||
|  | ||||
| /* COL2ROW or ROW2COL */ | ||||
| #define DIODE_DIRECTION COL2ROW | ||||
|  | ||||
| /* define if matrix has ghost */ | ||||
| //#define MATRIX_HAS_GHOST | ||||
|  | ||||
| /* number of backlight levels */ | ||||
| #define BACKLIGHT_LEVELS 3 | ||||
|  | ||||
| /* Set 0 if debouncing isn't needed */ | ||||
| #define DEBOUNCE    2 | ||||
| #define TAPPING_TERM    100 | ||||
|  | ||||
| /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ | ||||
| #define LOCKING_SUPPORT_ENABLE | ||||
| /* Locking resynchronize hack */ | ||||
| #define LOCKING_RESYNC_ENABLE | ||||
|  | ||||
| /* key combination for command */ | ||||
| #define IS_COMMAND() ( \ | ||||
|     keyboard_report->mods == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \ | ||||
|     keyboard_report->mods == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \ | ||||
| ) | ||||
|  | ||||
| /* | ||||
|  * Feature disable options | ||||
|  *  These options are also useful to firmware size reduction. | ||||
|  */ | ||||
|  | ||||
| /* disable debug print */ | ||||
| // #define NO_DEBUG | ||||
|  | ||||
| /* disable print */ | ||||
| // #define NO_PRINT | ||||
|  | ||||
| /* disable action features */ | ||||
| //#define NO_ACTION_LAYER | ||||
| //#define NO_ACTION_TAPPING | ||||
| //#define NO_ACTION_ONESHOT | ||||
| //#define NO_ACTION_MACRO | ||||
| //#define NO_ACTION_FUNCTION | ||||
| //#define DEBUG_MATRIX_SCAN_RATE | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										123
									
								
								keyboard/ergodox_ez/ergodox_ez.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								keyboard/ergodox_ez/ergodox_ez.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| #include "ergodox_ez.h" | ||||
| #include "i2cmaster.h" | ||||
|  | ||||
| bool i2c_initialized = 0; | ||||
| uint8_t mcp23018_status = 0x20; | ||||
|  | ||||
| bool ergodox_left_led_1 = 0;  // left top | ||||
| bool ergodox_left_led_2 = 0;  // left middle | ||||
| bool ergodox_left_led_3 = 0;  // left bottom | ||||
|  | ||||
| __attribute__ ((weak)) | ||||
| void * matrix_init_user(void) { | ||||
|  | ||||
| }; | ||||
|  | ||||
| __attribute__ ((weak)) | ||||
| void * matrix_scan_user(void) { | ||||
|  | ||||
| }; | ||||
|  | ||||
| void * matrix_init_kb(void) { | ||||
|    // keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md") | ||||
|     TCCR1A = 0b10101001;  // set and configure fast PWM | ||||
|     TCCR1B = 0b00001001;  // set and configure fast PWM | ||||
|  | ||||
|     // (tied to Vcc for hardware convenience) | ||||
|     DDRB  &= ~(1<<4);  // set B(4) as input | ||||
|     PORTB &= ~(1<<4);  // set B(4) internal pull-up disabled | ||||
|  | ||||
|     // unused pins - C7, D4, D5, D7, E6 | ||||
|     // set as input with internal pull-ip enabled | ||||
|     DDRC  &= ~(1<<7); | ||||
|     DDRD  &= ~(1<<7 | 1<<5 | 1<<4); | ||||
|     DDRE  &= ~(1<<6); | ||||
|     PORTC |=  (1<<7); | ||||
|     PORTD |=  (1<<7 | 1<<5 | 1<<4); | ||||
|     PORTE |=  (1<<6); | ||||
|  | ||||
|     ergodox_blink_all_leds(); | ||||
|  | ||||
| 	if (matrix_init_user) { | ||||
| 		(*matrix_init_user)(); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| void * matrix_scan_kb(void) { | ||||
|  | ||||
| 	if (matrix_scan_user) { | ||||
| 		(*matrix_scan_user)(); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
|  | ||||
| void ergodox_blink_all_leds(void) | ||||
| { | ||||
|     ergodox_led_all_off(); | ||||
|     ergodox_led_all_set(LED_BRIGHTNESS_HI); | ||||
|     ergodox_led_all_on(); | ||||
|     _delay_ms(333); | ||||
|     ergodox_led_all_off(); | ||||
| } | ||||
|  | ||||
| uint8_t init_mcp23018(void) { | ||||
|     mcp23018_status = 0x20; | ||||
|  | ||||
|     // I2C subsystem | ||||
|     if (i2c_initialized == 0) { | ||||
|         i2c_init();  // on pins D(1,0) | ||||
|         i2c_initialized++; | ||||
|         _delay_ms(1000); | ||||
|     } | ||||
|  | ||||
|     // set pin direction | ||||
|     // - unused  : input  : 1 | ||||
|     // - input   : input  : 1 | ||||
|     // - driving : output : 0 | ||||
|     mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(IODIRA);            if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(0b00000000);        if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(0b00111111);        if (mcp23018_status) goto out; | ||||
|     i2c_stop(); | ||||
|  | ||||
|     // set pull-up | ||||
|     // - unused  : on  : 1 | ||||
|     // - input   : on  : 1 | ||||
|     // - driving : off : 0 | ||||
|     mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(GPPUA);             if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(0b00000000);        if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(0b00111111);        if (mcp23018_status) goto out; | ||||
|  | ||||
| out: | ||||
|     i2c_stop(); | ||||
|  | ||||
|     if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update(); | ||||
|  | ||||
|     return mcp23018_status; | ||||
| } | ||||
|  | ||||
| uint8_t ergodox_left_leds_update(void) { | ||||
|     if (mcp23018_status) { // if there was an error | ||||
|         return mcp23018_status; | ||||
|     } | ||||
|  | ||||
|     // set logical value (doesn't matter on inputs) | ||||
|     // - unused  : hi-Z : 1 | ||||
|     // - input   : hi-Z : 1 | ||||
|     // - driving : hi-Z : 1 | ||||
|     mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(OLATA);             if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(0b11111111 | ||||
|             & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT) | ||||
|           );                                        if (mcp23018_status) goto out; | ||||
|     mcp23018_status = i2c_write(0b11111111 | ||||
|             & ~(ergodox_left_led_2<<LEFT_LED_2_SHIFT) | ||||
|             & ~(ergodox_left_led_1<<LEFT_LED_1_SHIFT) | ||||
|           );                                        if (mcp23018_status) goto out; | ||||
|  | ||||
| out: | ||||
|     i2c_stop(); | ||||
|     return mcp23018_status; | ||||
| } | ||||
|  | ||||
							
								
								
									
										145
									
								
								keyboard/ergodox_ez/ergodox_ez.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								keyboard/ergodox_ez/ergodox_ez.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| #ifndef PLANCK_H | ||||
| #define PLANCK_H | ||||
|  | ||||
| #include "matrix.h" | ||||
| #include "keymap_common.h" | ||||
| #include "backlight.h" | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include <avr/io.h> | ||||
| #include "i2cmaster.h" | ||||
| #include <util/delay.h> | ||||
|  | ||||
| #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) | ||||
| #define CPU_16MHz       0x00 | ||||
|  | ||||
| // I2C aliases and register addresses (see "mcp23018.md") | ||||
| #define I2C_ADDR        0b0100000 | ||||
| #define I2C_ADDR_WRITE  ( (I2C_ADDR<<1) | I2C_WRITE ) | ||||
| #define I2C_ADDR_READ   ( (I2C_ADDR<<1) | I2C_READ  ) | ||||
| #define IODIRA          0x00            // i/o direction register | ||||
| #define IODIRB          0x01 | ||||
| #define GPPUA           0x0C            // GPIO pull-up resistor register | ||||
| #define GPPUB           0x0D | ||||
| #define GPIOA           0x12            // general purpose i/o port register (write modifies OLAT) | ||||
| #define GPIOB           0x13 | ||||
| #define OLATA           0x14            // output latch register | ||||
| #define OLATB           0x15 | ||||
|  | ||||
| extern uint8_t mcp23018_status; | ||||
|  | ||||
| void init_ergodox(void); | ||||
| void ergodox_blink_all_leds(void); | ||||
| uint8_t init_mcp23018(void); | ||||
| uint8_t ergodox_left_leds_update(void); | ||||
|  | ||||
| #define LED_BRIGHTNESS_LO       31 | ||||
| #define LED_BRIGHTNESS_HI       255 | ||||
|  | ||||
| #define LEFT_LED_1_SHIFT        7       // in MCP23018 port B | ||||
| #define LEFT_LED_2_SHIFT        6       // in MCP23018 port B | ||||
| #define LEFT_LED_3_SHIFT        7       // in MCP23018 port A | ||||
|  | ||||
| extern bool ergodox_left_led_1;         // left top | ||||
| extern bool ergodox_left_led_2;         // left middle | ||||
| extern bool ergodox_left_led_3;         // left bottom | ||||
|  | ||||
| inline void ergodox_board_led_on(void)      { DDRD |=  (1<<6); PORTD |=  (1<<6); } | ||||
| inline void ergodox_right_led_1_on(void)    { DDRB |=  (1<<5); PORTB |=  (1<<5); } | ||||
| inline void ergodox_right_led_2_on(void)    { DDRB |=  (1<<6); PORTB |=  (1<<6); } | ||||
| inline void ergodox_right_led_3_on(void)    { DDRB |=  (1<<7); PORTB |=  (1<<7); } | ||||
| inline void ergodox_left_led_1_on(void)     { ergodox_left_led_1 = 1; } | ||||
| inline void ergodox_left_led_2_on(void)     { ergodox_left_led_2 = 1; } | ||||
| inline void ergodox_left_led_3_on(void)     { ergodox_left_led_3 = 1; } | ||||
|  | ||||
| inline void ergodox_board_led_off(void)     { DDRD &= ~(1<<6); PORTD &= ~(1<<6); } | ||||
| inline void ergodox_right_led_1_off(void)   { DDRB &= ~(1<<5); PORTB &= ~(1<<5); } | ||||
| inline void ergodox_right_led_2_off(void)   { DDRB &= ~(1<<6); PORTB &= ~(1<<6); } | ||||
| inline void ergodox_right_led_3_off(void)   { DDRB &= ~(1<<7); PORTB &= ~(1<<7); } | ||||
| inline void ergodox_left_led_1_off(void)    { ergodox_left_led_1 = 0; } | ||||
| inline void ergodox_left_led_2_off(void)    { ergodox_left_led_2 = 0; } | ||||
| inline void ergodox_left_led_3_off(void)    { ergodox_left_led_3 = 0; } | ||||
|  | ||||
| inline void ergodox_led_all_on(void) | ||||
| { | ||||
|     ergodox_board_led_on(); | ||||
|     ergodox_right_led_1_on(); | ||||
|     ergodox_right_led_2_on(); | ||||
|     ergodox_right_led_3_on(); | ||||
|     ergodox_left_led_1_on(); | ||||
|     ergodox_left_led_2_on(); | ||||
|     ergodox_left_led_3_on(); | ||||
|     ergodox_left_leds_update(); | ||||
| } | ||||
|  | ||||
| inline void ergodox_led_all_off(void) | ||||
| { | ||||
|     ergodox_board_led_off(); | ||||
|     ergodox_right_led_1_off(); | ||||
|     ergodox_right_led_2_off(); | ||||
|     ergodox_right_led_3_off(); | ||||
|     ergodox_left_led_1_off(); | ||||
|     ergodox_left_led_2_off(); | ||||
|     ergodox_left_led_3_off(); | ||||
|     ergodox_left_leds_update(); | ||||
| } | ||||
|  | ||||
| inline void ergodox_right_led_1_set(uint8_t n)    { OCR1A = n; } | ||||
| inline void ergodox_right_led_2_set(uint8_t n)    { OCR1B = n; } | ||||
| inline void ergodox_right_led_3_set(uint8_t n)    { OCR1C = n; } | ||||
|  | ||||
| inline void ergodox_led_all_set(uint8_t n) | ||||
| { | ||||
|     ergodox_right_led_1_set(n); | ||||
|     ergodox_right_led_2_set(n); | ||||
|     ergodox_right_led_3_set(n); | ||||
| } | ||||
|  | ||||
| #define KEYMAP(                                                 \ | ||||
|                                                                 \ | ||||
|     /* left hand, spatial positions */                          \ | ||||
|     k00,k01,k02,k03,k04,k05,k06,                                \ | ||||
|     k10,k11,k12,k13,k14,k15,k16,                                \ | ||||
|     k20,k21,k22,k23,k24,k25,                                    \ | ||||
|     k30,k31,k32,k33,k34,k35,k36,                                \ | ||||
|     k40,k41,k42,k43,k44,                                        \ | ||||
|                             k55,k56,                            \ | ||||
|                                 k54,                            \ | ||||
|                         k53,k52,k51,                            \ | ||||
|                                                                 \ | ||||
|     /* right hand, spatial positions */                         \ | ||||
|         k07,k08,k09,k0A,k0B,k0C,k0D,                            \ | ||||
|         k17,k18,k19,k1A,k1B,k1C,k1D,                            \ | ||||
|             k28,k29,k2A,k2B,k2C,k2D,                            \ | ||||
|         k37,k38,k39,k3A,k3B,k3C,k3D,                            \ | ||||
|                 k49,k4A,k4B,k4C,k4D,                            \ | ||||
|     k57,k58,                                                    \ | ||||
|     k59,                                                        \ | ||||
|     k5C,k5B,k5A )                                               \ | ||||
|                                                                 \ | ||||
|    /* matrix positions */                                       \ | ||||
|    {                                                            \ | ||||
|     { k00, k10, k20, k30, k40, KC_NO },   \ | ||||
|     { k01, k11, k21, k31, k41, k51 },   \ | ||||
|     { k02, k12, k22, k32, k42, k52 },   \ | ||||
|     { k03, k13, k23, k33, k43, k53 },   \ | ||||
|     { k04, k14, k24, k34, k44, k54 },   \ | ||||
|     { k05, k15, k25, k35, KC_NO, k55 },   \ | ||||
|     { k06, k16, KC_NO, k36, KC_NO, k56 },   \ | ||||
|                                                                  \ | ||||
|     { k07, k17, KC_NO, k37,KC_NO, k57 },   \ | ||||
|     { k08, k18, k28, k38,KC_NO, k58 },   \ | ||||
|     { k09, k19, k29, k39, k49, k59 },   \ | ||||
|     { k0A, k1A, k2A, k3A, k4A, k5A },   \ | ||||
|     { k0B, k1B, k2B, k3B, k4B, k5B },   \ | ||||
|     { k0C, k1C, k2C, k3C, k4C, k5C },   \ | ||||
|     { k0D, k1D, k2D, k3D, k4D, KC_NO }    \ | ||||
|    } | ||||
|  | ||||
| void * matrix_init_user(void); | ||||
| void * matrix_scan_user(void); | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										178
									
								
								keyboard/ergodox_ez/i2cmaster.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								keyboard/ergodox_ez/i2cmaster.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| #ifndef _I2CMASTER_H | ||||
| #define _I2CMASTER_H   1 | ||||
| /*************************************************************************  | ||||
| * Title:    C include file for the I2C master interface  | ||||
| *           (i2cmaster.S or twimaster.c) | ||||
| * Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury | ||||
| * File:     $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $ | ||||
| * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 | ||||
| * Target:   any AVR device | ||||
| * Usage:    see Doxygen manual | ||||
| **************************************************************************/ | ||||
|  | ||||
| #ifdef DOXYGEN | ||||
| /** | ||||
|  @defgroup pfleury_ic2master I2C Master library | ||||
|  @code #include <i2cmaster.h> @endcode | ||||
|    | ||||
|  @brief I2C (TWI) Master Software Library | ||||
|  | ||||
|  Basic routines for communicating with I2C slave devices. This single master  | ||||
|  implementation is limited to one bus master on the I2C bus.  | ||||
|  | ||||
|  This I2c library is implemented as a compact assembler software implementation of the I2C protocol  | ||||
|  which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c). | ||||
|  Since the API for these two implementations is exactly the same, an application can be linked either against the | ||||
|  software I2C implementation or the hardware I2C implementation. | ||||
|  | ||||
|  Use 4.7k pull-up resistor on the SDA and SCL pin. | ||||
|   | ||||
|  Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module  | ||||
|  i2cmaster.S to your target when using the software I2C implementation !  | ||||
|   | ||||
|  Adjust the  CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion. | ||||
|  | ||||
|  @note  | ||||
|     The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted  | ||||
|     to GNU assembler and AVR-GCC C call interface. | ||||
|     Replaced the incorrect quarter period delays found in AVR300 with  | ||||
|     half period delays.  | ||||
|      | ||||
|  @author Peter Fleury pfleury@gmx.ch  http://jump.to/fleury | ||||
|  | ||||
|  @par API Usage Example | ||||
|   The following code shows typical usage of this library, see example test_i2cmaster.c | ||||
|  | ||||
|  @code | ||||
|  | ||||
|  #include <i2cmaster.h> | ||||
|  | ||||
|  | ||||
|  #define Dev24C02  0xA2      // device address of EEPROM 24C02, see datasheet | ||||
|  | ||||
|  int main(void) | ||||
|  { | ||||
|      unsigned char ret; | ||||
|  | ||||
|      i2c_init();                             // initialize I2C library | ||||
|  | ||||
|      // write 0x75 to EEPROM address 5 (Byte Write)  | ||||
|      i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode | ||||
|      i2c_write(0x05);                        // write address = 5 | ||||
|      i2c_write(0x75);                        // write value 0x75 to EEPROM | ||||
|      i2c_stop();                             // set stop conditon = release bus | ||||
|  | ||||
|  | ||||
|      // read previously written value back from EEPROM address 5  | ||||
|      i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode | ||||
|  | ||||
|      i2c_write(0x05);                        // write address = 5 | ||||
|      i2c_rep_start(Dev24C02+I2C_READ);       // set device address and read mode | ||||
|  | ||||
|      ret = i2c_readNak();                    // read one byte from EEPROM | ||||
|      i2c_stop(); | ||||
|  | ||||
|      for(;;); | ||||
|  } | ||||
|  @endcode | ||||
|  | ||||
| */ | ||||
| #endif /* DOXYGEN */ | ||||
|  | ||||
| /**@{*/ | ||||
|  | ||||
| #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 | ||||
| #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" | ||||
| #endif | ||||
|  | ||||
| #include <avr/io.h> | ||||
|  | ||||
| /** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */ | ||||
| #define I2C_READ    1 | ||||
|  | ||||
| /** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */ | ||||
| #define I2C_WRITE   0 | ||||
|  | ||||
|  | ||||
| /** | ||||
|  @brief initialize the I2C master interace. Need to be called only once  | ||||
|  @param  void | ||||
|  @return none | ||||
|  */ | ||||
| extern void i2c_init(void); | ||||
|  | ||||
|  | ||||
| /**  | ||||
|  @brief Terminates the data transfer and releases the I2C bus  | ||||
|  @param void | ||||
|  @return none | ||||
|  */ | ||||
| extern void i2c_stop(void); | ||||
|  | ||||
|  | ||||
| /**  | ||||
|  @brief Issues a start condition and sends address and transfer direction  | ||||
|    | ||||
|  @param    addr address and transfer direction of I2C device | ||||
|  @retval   0   device accessible  | ||||
|  @retval   1   failed to access device  | ||||
|  */ | ||||
| extern unsigned char i2c_start(unsigned char addr); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  @brief Issues a repeated start condition and sends address and transfer direction  | ||||
|  | ||||
|  @param   addr address and transfer direction of I2C device | ||||
|  @retval  0 device accessible | ||||
|  @retval  1 failed to access device | ||||
|  */ | ||||
| extern unsigned char i2c_rep_start(unsigned char addr); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  @brief Issues a start condition and sends address and transfer direction  | ||||
|     | ||||
|  If device is busy, use ack polling to wait until device ready  | ||||
|  @param    addr address and transfer direction of I2C device | ||||
|  @return   none | ||||
|  */ | ||||
| extern void i2c_start_wait(unsigned char addr); | ||||
|  | ||||
|   | ||||
| /** | ||||
|  @brief Send one byte to I2C device | ||||
|  @param    data  byte to be transfered | ||||
|  @retval   0 write successful | ||||
|  @retval   1 write failed | ||||
|  */ | ||||
| extern unsigned char i2c_write(unsigned char data); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  @brief    read one byte from the I2C device, request more data from device  | ||||
|  @return   byte read from I2C device | ||||
|  */ | ||||
| extern unsigned char i2c_readAck(void); | ||||
|  | ||||
| /** | ||||
|  @brief    read one byte from the I2C device, read is followed by a stop condition  | ||||
|  @return   byte read from I2C device | ||||
|  */ | ||||
| extern unsigned char i2c_readNak(void); | ||||
|  | ||||
| /**  | ||||
|  @brief    read one byte from the I2C device | ||||
|   | ||||
|  Implemented as a macro, which calls either i2c_readAck or i2c_readNak | ||||
|   | ||||
|  @param    ack 1 send ack, request more data from device<br> | ||||
|                0 send nak, read is followed by a stop condition  | ||||
|  @return   byte read from I2C device | ||||
|  */ | ||||
| extern unsigned char i2c_read(unsigned char ack); | ||||
| #define i2c_read(ack)  (ack) ? i2c_readAck() : i2c_readNak();  | ||||
|  | ||||
|  | ||||
| /**@}*/ | ||||
| #endif | ||||
							
								
								
									
										133
									
								
								keyboard/ergodox_ez/keymaps/keymap_default.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								keyboard/ergodox_ez/keymaps/keymap_default.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| #include "ergodox_ez.h" | ||||
| #include "debug.h" | ||||
| #include "action_layer.h" | ||||
|  | ||||
| // TODO: Define layer names that make sense for the ErgoDox EZ. | ||||
| #define DEFAULT_LAYER 0 | ||||
| #define COLEMAK_LAYER 1 | ||||
| #define DVORAK_LAYER 2 | ||||
| #define LOWER_LAYER 1 | ||||
| #define RAISE_LAYER 4 | ||||
|  | ||||
| const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||
| [DEFAULT_LAYER] = KEYMAP(  // layer 0 : default | ||||
|         // left hand | ||||
|         KC_EQL, KC_1,   KC_2,   KC_3,   KC_4,   KC_5,   KC_ESC, | ||||
|         KC_BSLS,KC_Q,   KC_W,   KC_E,   KC_R,   KC_T,   KC_FN2, | ||||
|         KC_TAB, KC_A,   KC_S,   KC_D,   KC_F,   KC_G, | ||||
|         KC_LSFT,KC_Z,   KC_X,   KC_C,   KC_V,   KC_B,   KC_FN1, | ||||
|         KC_LGUI,KC_GRV, KC_BSLS,KC_LEFT,KC_RGHT, | ||||
|                                       KC_LCTL,KC_LALT, | ||||
|                                            KC_HOME, | ||||
|                                  KC_BSPC,KC_DEL, KC_END, | ||||
|         // right hand | ||||
|              KC_FN3, KC_6,   KC_7,   KC_8,   KC_9,   KC_0,   KC_MINS, | ||||
|              KC_LBRC,KC_Y,   KC_U,   KC_I,   KC_O,   KC_P,   KC_RBRC, | ||||
|                   KC_H,   KC_J,   KC_K,   KC_L,   KC_SCLN,KC_QUOT, | ||||
|              KC_FN1, KC_N,   KC_M,   KC_COMM,KC_DOT, KC_SLSH,KC_RSFT, | ||||
|                        KC_LEFT,KC_DOWN,KC_UP,  KC_RGHT,KC_RGUI, | ||||
|         KC_RALT,KC_RCTL, | ||||
|         KC_PGUP, | ||||
|         KC_PGDN,KC_ENT, KC_SPC | ||||
|     ), | ||||
| [LOWER_LAYER] = KEYMAP(  // layer 0 : default | ||||
|         // left hand | ||||
|         KC_EQL, KC_1,   KC_2,   KC_3,   LALT(KC_TAB),   KC_5,   KC_ESC, | ||||
|         KC_BSLS,KC_Q,   S(KC_W),   KC_E,   KC_R,   KC_T,   KC_FN2, | ||||
|         KC_TAB, KC_A,   KC_S,   KC_D,   KC_F,   KC_G, | ||||
|         KC_LSFT,KC_Z,   KC_X,   KC_C,   KC_V,   KC_B,   KC_FN1, | ||||
|         KC_LGUI,KC_GRV, KC_BSLS,KC_LEFT,KC_RGHT, | ||||
|                                       KC_LCTL,KC_LALT, | ||||
|                                            KC_HOME, | ||||
|                                  KC_BSPC,KC_DEL, KC_END, | ||||
|         // right hand | ||||
|              KC_FN3, KC_6,   KC_7,   KC_8,   KC_9,   KC_0,   KC_MINS, | ||||
|              KC_LBRC,KC_Y,   KC_U,   KC_I,   KC_O,   KC_P,   KC_RBRC, | ||||
|              KC_H,   KC_J,   KC_K,   KC_L,   KC_SCLN,KC_QUOT, | ||||
|              KC_FN1, KC_N,   KC_M,   KC_COMM,KC_DOT, KC_SLSH,KC_RSFT, | ||||
|                        KC_LEFT,KC_DOWN,KC_UP,  KC_RGHT,KC_RGUI, | ||||
|         KC_RALT,KC_RCTL, | ||||
|         KC_PGUP, | ||||
|         KC_PGDN,KC_ENT, KC_SPC | ||||
|     ) | ||||
| }; | ||||
|  | ||||
| const uint16_t PROGMEM fn_actions[] = { | ||||
|  | ||||
|     [1] = ACTION_LAYER_MOMENTARY(LOWER_LAYER),  // to RAISE | ||||
|     [2] = ACTION_LAYER_MOMENTARY(LOWER_LAYER),  // to LOWER | ||||
|  | ||||
|     [3] = ACTION_DEFAULT_LAYER_SET(DEFAULT_LAYER), | ||||
|     [4] = ACTION_DEFAULT_LAYER_SET(COLEMAK_LAYER), | ||||
|     [5] = ACTION_DEFAULT_LAYER_SET(DVORAK_LAYER), | ||||
| }; | ||||
|  | ||||
| const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | ||||
| { | ||||
|   // MACRODOWN only works in this function | ||||
|       switch(id) { | ||||
|         case 0: | ||||
|         if (record->event.pressed) { | ||||
|           register_code(KC_RSFT); | ||||
|         } else { | ||||
|           unregister_code(KC_RSFT); | ||||
|         } | ||||
|         break; | ||||
|       } | ||||
|     return MACRO_NONE; | ||||
| }; | ||||
|  | ||||
| // Runs just one time when the keyboard initializes. | ||||
| void * matrix_init_user(void) { | ||||
|  | ||||
| }; | ||||
|  | ||||
| // Runs constantly in the background, in a loop. | ||||
| void * matrix_scan_user(void) { | ||||
|     uint8_t layer = biton32(layer_state); | ||||
|  | ||||
|     ergodox_board_led_off(); | ||||
|     ergodox_left_led_1_off(); | ||||
|     ergodox_left_led_2_off(); | ||||
|     ergodox_left_led_3_off(); | ||||
|     switch (layer) { | ||||
|       // TODO: Make this relevant to the ErgoDox EZ. | ||||
|         case 1: | ||||
|             // all | ||||
|             ergodox_left_led_1_on(); | ||||
|             ergodox_left_led_2_on(); | ||||
|             ergodox_left_led_3_on(); | ||||
|             break; | ||||
|         case 2: | ||||
|             // blue | ||||
|             ergodox_left_led_2_on(); | ||||
|             break; | ||||
|         case 8: | ||||
|             // blue and green | ||||
|             ergodox_left_led_2_on(); | ||||
|             // break missed intentionally | ||||
|         case 3: | ||||
|             // green | ||||
|             ergodox_left_led_3_on(); | ||||
|             break; | ||||
|         case 6: | ||||
|             ergodox_board_led_on(); | ||||
|             // break missed intentionally | ||||
|         case 4: | ||||
|         case 5: | ||||
|         case 7: | ||||
|             // white | ||||
|             ergodox_left_led_1_on(); | ||||
|             break; | ||||
|         case 9: | ||||
|             // white+green | ||||
|             ergodox_left_led_1_on(); | ||||
|             ergodox_left_led_3_on(); | ||||
|             break; | ||||
|         default: | ||||
|             // none | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     mcp23018_status = ergodox_left_leds_update(); | ||||
| }; | ||||
							
								
								
									
										211
									
								
								keyboard/ergodox_ez/keymaps/keymap_ergodox_ez.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								keyboard/ergodox_ez/keymaps/keymap_ergodox_ez.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,211 @@ | ||||
| // TODO: Move all of this stuff into the default keymap, and then get rid of this file. | ||||
| #include "action_util.h" | ||||
| #include "action_layer.h" | ||||
| #define KC_SW0 KC_FN0 | ||||
| #define DEBUG_ACTION | ||||
|  | ||||
| static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||
|  | ||||
|     /* Keymap 0: Basic layer | ||||
|      * | ||||
|      * ,--------------------------------------------------.           ,--------------------------------------------------. | ||||
|      * |   =    |   1  |   2  |   3  |   4  |   5  | LEFT |           | RIGHT|   6  |   7  |   8  |   9  |   0  |   -    | | ||||
|      * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------| | ||||
|      * | Del    |   Q  |   W  |   E  |   R  |   T  |  Up  |           |  Up  |   Y  |   U  |   I  |   O  |   P  |   \    | | ||||
|      * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------| | ||||
|      * | BkSp   |   A  |   S  |   D  |   F  |   G  |------|           |------|   H  |   J  |   K  |   L  |; / L2|   '    | | ||||
|      * |--------+------+------+------+------+------|  L1  |           |  L1  |------+------+------+------+------+--------| | ||||
|      * | LShift |Z/Ctrl|   X  |   C  |   V  |   B  |      |           |      |   N  |   M  |   ,  |   .  |//Ctrl| RShift | | ||||
|      * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------' | ||||
|      *   |Grv/L1| ~L1  | TAB  | Left | Right|                                       | Up   | Down |   [  |   ]  | ~L1  | | ||||
|      *   `----------------------------------'                                       `----------------------------------' | ||||
|      *                                        ,-------------.       ,-------------. | ||||
|      *                                        | Rclk | LGui |       | Alt  |Ctrl/Esc| | ||||
|      *                                 ,------|------|------|       |------+--------+------. | ||||
|      *                                 |      |      | Home |       | PgUp |        |      | | ||||
|      *                                 | Space| Enter|------|       |------|  Tab   |Enter | | ||||
|      *                                 |      |      | End  |       | PgDn |        |      | | ||||
|      *                                 `--------------------'       `----------------------' | ||||
|      */ | ||||
|  | ||||
|  | ||||
|     // Basic layer | ||||
|  | ||||
|     KEYMAP( | ||||
|            EQL,  1,    2,    3,    4,    5, LEFT, | ||||
|            DEL,  Q,    W,    E,    R,    T, UP, | ||||
|            BSPC, A,    S,    D,    F,    G, | ||||
|            LSFT, FN29, X,    C,    V,    B, FN1, | ||||
|            FN30,  FN4, TAB,  LEFT, RIGHT, | ||||
|  | ||||
|                                            BTN2,LGUI, | ||||
|                                                 HOME, | ||||
|                                       SPC, ENT, END, | ||||
|            //RIGHT | ||||
|            RIGHT,6,    7,    8,    9,    0,    MINS, | ||||
|            UP,   Y,    U,    I,    O,    P,    BSLS, | ||||
|                  H,    J,    K,    L,    FN31, QUOT, | ||||
|            FN1,  N,    M,    COMM, DOT,  FN28, RSFT, | ||||
|                        UP,   DOWN, LBRC, RBRC, FN4, | ||||
|            LALT, FN27, | ||||
|            PGUP, | ||||
|            PGDN, TAB, ENT | ||||
|            ), | ||||
|  | ||||
|     /* Keymap 1: Symbol Layer | ||||
|      * | ||||
|      * ,--------------------------------------------------.           ,--------------------------------------------------. | ||||
|      * |  Flash |  F1  |  F2  |  F3  |  F4  |  F5  |      |           |      |  F6  |  F7  |  F8  |  F9  |  F10 |   F11  | | ||||
|      * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------| | ||||
|      * |        |   !  |   @  |   {  |   }  |   |  |      |           |      |   Up |   7  |   8  |   9  |   *  |   F12  | | ||||
|      * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------| | ||||
|      * | :      |   #  |   $  |   (  |   )  |   `  |------|           |------| Down |   4  |   5  |   6  |   +  |        | | ||||
|      * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------| | ||||
|      * |        |   %  |   ^  |   [  |   ]  |   ~  |      |           |      |   &  |   1  |   2  |   3  |   \  |        | | ||||
|      * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------' | ||||
|      *   |      |      |      |      |      |                                       |      |    . |   0  |   =  |      | | ||||
|      *   `----------------------------------'                                       `----------------------------------' | ||||
|      *                                        ,-------------.       ,-------------. | ||||
|      *                                        |      |      |       |      |      | | ||||
|      *                                 ,------|------|------|       |------+------+------. | ||||
|      *                                 |      |      |      |       |      |      |      | | ||||
|      *                                 |      |      |------|       |------|      |      | | ||||
|      *                                 |      |      |      |       |      |      |      | | ||||
|      *                                 `--------------------'       `--------------------' | ||||
|      */ | ||||
|     // SYMBOLS | ||||
|     KEYMAP( | ||||
|            FN0,  F1,   F2,   F3,   F4,   F5,   TRNS, | ||||
|            TRNS, FN7,  FN8,  FN23, FN24, FN18, TRNS, | ||||
|            FN22, FN9,  FN10, FN15, FN16, GRV, | ||||
|            TRNS, FN11, FN12, LBRC, RBRC, FN17, TRNS, | ||||
|            TRNS, TRNS, TRNS, TRNS, TRNS, | ||||
|  | ||||
|                                                TRNS, TRNS, | ||||
|                                                      TRNS, | ||||
|                                          TRNS, TRNS, TRNS, | ||||
|         // right hand | ||||
|            TRNS, F6,   F7,   F8,   F9,   F10,   F11, | ||||
|            TRNS, UP,       7,   8,    9,    FN14, F12, | ||||
|                  DOWN,     4,   5,    6,    FN26, TRNS, | ||||
|            TRNS, FN13,     1,   2,    3,    BSLS, TRNS, | ||||
|                            TRNS,DOT,  0,    EQL,  TRNS, | ||||
|            TRNS, TRNS, | ||||
|            TRNS, | ||||
|            TRNS, TRNS, TRNS | ||||
|     ), | ||||
|     /* Keymap 2: Media and mouse keys | ||||
|      * | ||||
|      * ,--------------------------------------------------.           ,--------------------------------------------------. | ||||
|      * |        |      |      |      |      |      |      |           |      |      |      |      |      |      |        | | ||||
|      * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------| | ||||
|      * |        |      | MsUp |      |      |      |      |           |      |      |      |      |      |      |        | | ||||
|      * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------| | ||||
|      * |        |MsLeft|MsDown|MsRght|      |      |------|           |------|      |      |      | Play |      |        | | ||||
|      * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------| | ||||
|      * |        |      |      |      |      |      |      |           |      |      |      | Prev | Next |      |        | | ||||
|      * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------' | ||||
|      *   |      |      |      | Lclk | Rclk |                                       |VolUp |VolDn |      |      |      | | ||||
|      *   `----------------------------------'                                       `----------------------------------' | ||||
|      *                                        ,-------------.       ,-------------. | ||||
|      *                                        |      |      |       |      |      | | ||||
|      *                                 ,------|------|------|       |------+------+------. | ||||
|      *                                 |      |      |      |       |      |      |      | | ||||
|      *                                 |      |      |------|       |------|      |      | | ||||
|      *                                 |      |      |      |       |      |      |      | | ||||
|      *                                 `--------------------'       `--------------------' | ||||
|      */ | ||||
|     // MEDIA AND MOUSE | ||||
|     KEYMAP( | ||||
|            TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, | ||||
|            TRNS, TRNS, MS_U, TRNS, TRNS, TRNS, TRNS, | ||||
|            TRNS, MS_L, MS_D, MS_R, TRNS, TRNS, | ||||
|            TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, | ||||
|            TRNS, TRNS, TRNS, BTN3, BTN2, | ||||
|  | ||||
|                                                TRNS, TRNS, | ||||
|                                                      TRNS, | ||||
|                                          TRNS, TRNS, TRNS, | ||||
|         // right hand | ||||
|            TRNS,  TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, | ||||
|            TRNS,  TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, | ||||
|                   TRNS, TRNS, TRNS, MPLY, TRNS, TRNS, | ||||
|            TRNS,  TRNS, TRNS, MPRV, MNXT, TRNS, TRNS, | ||||
|                         VOLU, VOLD, TRNS, TRNS, TRNS, | ||||
|            TRNS, TRNS, | ||||
|            TRNS, | ||||
|            TRNS, TRNS, WBAK | ||||
|     ), | ||||
| }; | ||||
|  | ||||
| /* id for user defined functions */ | ||||
| enum function_id { | ||||
|     TEENSY_KEY, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Fn action definition | ||||
|  */ | ||||
| static const uint16_t PROGMEM fn_actions[] = { | ||||
|     [0] = ACTION_FUNCTION(TEENSY_KEY),              // FN0  - Teensy key | ||||
|     [1] = ACTION_LAYER_INVERT(1, ON_RELEASE),       // FN1 - Toggle 1 | ||||
|     [2] = ACTION_LAYER_TOGGLE(2),                   // FN2 - Toggle 2 | ||||
|     [3] = ACTION_LAYER_TOGGLE(3),                   // FN3 - Toggle 3 | ||||
|     [4] = ACTION_LAYER_TAP_TOGGLE(1),               // FN4 - Momentary Layer 1 | ||||
|     [5] = ACTION_LAYER_MOMENTARY(2),                // FN5 - Momentary L2 | ||||
|  | ||||
|     // SYMBOLS | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_QUOT),             // FN6 - " | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_1),                // FN7 - ! | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_2),                // FN8 - @ | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_3),                // FN9 - # | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_4),                // FN10 - $ | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_5),                // FN11 - % | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_6),                // FN12 - ^ | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_7),                // FN13 - & | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_8),                // FN14 - * | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_9),                // FN15 - ( | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_0),                // FN16 - ) | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_GRV),              // FN17 - ~ | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),             // FN18 - | | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_MINS),             // FN19 - _ | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_COMM),             // FN20 - < | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_DOT),              // FN21 - > | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_SCLN),             // FN22 - : | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),             // FN23 - { | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),             // FN24 - } | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_SLSH),             // FN25 - ? | ||||
|     ACTION_MODS_KEY(MOD_LSFT, KC_EQL),              // FN26 - + | ||||
|  | ||||
|     ACTION_MODS_TAP_KEY(MOD_LCTL, KC_ESC),          // FN27 - Control/esc on tap | ||||
|     ACTION_MODS_TAP_KEY(MOD_LCTL, KC_SLSH),         // FN28 - slash becomes Ctrl when held (right pinky) | ||||
|     ACTION_MODS_TAP_KEY(MOD_LCTL, KC_Z),            // FN29 - z becomes Ctrl when held (left pinky) | ||||
|  | ||||
|     // Fancy tapping/toggling | ||||
|     ACTION_LAYER_TAP_KEY(1, KC_GRV),                // FN30 - Layer 1 when holding backtick key | ||||
|     ACTION_LAYER_TAP_KEY(2, KC_SCLN),               // FN31 - Layer 2 when holding semicolon key | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| void action_function(keyrecord_t *event, uint8_t id, uint8_t opt) | ||||
| { | ||||
|     print("action_function called\n"); | ||||
|     print("id  = "); phex(id); print("\n"); | ||||
|     print("opt = "); phex(opt); print("\n"); | ||||
|     if (id == TEENSY_KEY) { | ||||
|         clear_keyboard(); | ||||
|         print("\n\nJump to bootloader... "); | ||||
|         _delay_ms(250); | ||||
|         bootloader_jump(); // should not return | ||||
|         print("not supported.\n"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void * matrix_init_user(void) { | ||||
|  | ||||
| }; | ||||
|  | ||||
| void * matrix_scan_user(void) { | ||||
|  | ||||
| }; | ||||
							
								
								
									
										348
									
								
								keyboard/ergodox_ez/matrix.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								keyboard/ergodox_ez/matrix.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,348 @@ | ||||
| /* | ||||
|  | ||||
| Note for ErgoDox EZ customizers: Here be dragons! | ||||
| This is not a file you want to be messing with. | ||||
| All of the interesting stuff for you is under keymaps/ :) | ||||
| Love, Erez | ||||
|  | ||||
| Copyright 2013 Oleg Kostyuk <cub.uanic@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 "action_layer.h" | ||||
| #include "print.h" | ||||
| #include "debug.h" | ||||
| #include "util.h" | ||||
| #include "matrix.h" | ||||
| #include "ergodox_ez.h" | ||||
| #include "i2cmaster.h" | ||||
| #ifdef DEBUG_MATRIX_SCAN_RATE | ||||
| #include  "timer.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef DEBOUNCE | ||||
| #   define DEBOUNCE	5 | ||||
| #endif | ||||
| static uint8_t debouncing = DEBOUNCE; | ||||
|  | ||||
| /* matrix state(1:on, 0:off) */ | ||||
| static matrix_row_t matrix[MATRIX_ROWS]; | ||||
| static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | ||||
|  | ||||
| static matrix_row_t read_cols(uint8_t row); | ||||
| static void init_cols(void); | ||||
| static void unselect_rows(); | ||||
| static void select_row(uint8_t row); | ||||
|  | ||||
| static uint8_t mcp23018_reset_loop; | ||||
|  | ||||
| #ifdef DEBUG_MATRIX_SCAN_RATE | ||||
| uint32_t matrix_timer; | ||||
| uint32_t matrix_scan_count; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| __attribute__ ((weak)) | ||||
| void * matrix_init_kb(void) { | ||||
| }; | ||||
|  | ||||
| __attribute__ ((weak)) | ||||
| void * matrix_scan_kb(void) { | ||||
| }; | ||||
|  | ||||
| inline | ||||
| uint8_t matrix_rows(void) | ||||
| { | ||||
|     return MATRIX_ROWS; | ||||
| } | ||||
|  | ||||
| inline | ||||
| uint8_t matrix_cols(void) | ||||
| { | ||||
|     return MATRIX_COLS; | ||||
| } | ||||
|  | ||||
| void matrix_init(void) | ||||
| { | ||||
|     // initialize row and col | ||||
|  | ||||
|     mcp23018_status = init_mcp23018(); | ||||
|  | ||||
|  | ||||
|     unselect_rows(); | ||||
|     init_cols(); | ||||
|  | ||||
|     // initialize matrix state: all keys off | ||||
|     for (uint8_t i=0; i < MATRIX_ROWS; i++) { | ||||
|         matrix[i] = 0; | ||||
|         matrix_debouncing[i] = 0; | ||||
|     } | ||||
|  | ||||
| #ifdef DEBUG_MATRIX_SCAN_RATE | ||||
|     matrix_timer = timer_read32(); | ||||
|     matrix_scan_count = 0; | ||||
| #endif | ||||
|  | ||||
|     if (matrix_init_kb) { | ||||
|         (*matrix_init_kb)(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| uint8_t matrix_scan(void) | ||||
| { | ||||
|     if (mcp23018_status) { // if there was an error | ||||
|         if (++mcp23018_reset_loop == 0) { | ||||
|             // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans | ||||
|             // this will be approx bit more frequent than once per second | ||||
|             print("trying to reset mcp23018\n"); | ||||
|             mcp23018_status = init_mcp23018(); | ||||
|             if (mcp23018_status) { | ||||
|                 print("left side not responding\n"); | ||||
|             } else { | ||||
|                 print("left side attached\n"); | ||||
|                 ergodox_blink_all_leds(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| #ifdef DEBUG_MATRIX_SCAN_RATE | ||||
|     matrix_scan_count++; | ||||
|  | ||||
|     uint32_t timer_now = timer_read32(); | ||||
|     if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) { | ||||
|         print("matrix scan frequency: "); | ||||
|         pdec(matrix_scan_count); | ||||
|         print("\n"); | ||||
|  | ||||
|         matrix_timer = timer_now; | ||||
|         matrix_scan_count = 0; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||||
|         select_row(i); | ||||
|         matrix_row_t cols = read_cols(i); | ||||
|         if (matrix_debouncing[i] != cols) { | ||||
|             matrix_debouncing[i] = cols; | ||||
|             if (debouncing) { | ||||
|                 debug("bounce!: "); debug_hex(debouncing); debug("\n"); | ||||
|             } | ||||
|             debouncing = DEBOUNCE; | ||||
|         } | ||||
|         unselect_rows(); | ||||
|     } | ||||
|  | ||||
|     if (debouncing) { | ||||
|         if (--debouncing) { | ||||
|             _delay_ms(1); | ||||
|         } else { | ||||
|             for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||||
|                 matrix[i] = matrix_debouncing[i]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     if (matrix_scan_kb) { | ||||
|         (*matrix_scan_kb)(); | ||||
|     } | ||||
|  | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| bool matrix_is_modified(void) | ||||
| { | ||||
|     if (debouncing) return false; | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| inline | ||||
| bool matrix_is_on(uint8_t row, uint8_t col) | ||||
| { | ||||
|     return (matrix[row] & ((matrix_row_t)1<<col)); | ||||
| } | ||||
|  | ||||
| inline | ||||
| matrix_row_t matrix_get_row(uint8_t row) | ||||
| { | ||||
|     return matrix[row]; | ||||
| } | ||||
|  | ||||
| void matrix_print(void) | ||||
| { | ||||
|     print("\nr/c 0123456789ABCDEF\n"); | ||||
|     for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | ||||
|         phex(row); print(": "); | ||||
|         pbin_reverse16(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 += bitpop16(matrix[i]); | ||||
|     } | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| /* Column pin configuration | ||||
|  * | ||||
|  * Teensy | ||||
|  * col: 0   1   2   3   4   5 | ||||
|  * pin: F0  F1  F4  F5  F6  F7 | ||||
|  * | ||||
|  * MCP23018 | ||||
|  * col: 0   1   2   3   4   5 | ||||
|  * pin: B5  B4  B3  B2  B1  B0 | ||||
|  */ | ||||
| static void  init_cols(void) | ||||
| { | ||||
|     // init on mcp23018 | ||||
|     // not needed, already done as part of init_mcp23018() | ||||
|  | ||||
|     // init on teensy | ||||
|     // Input with pull-up(DDR:0, PORT:1) | ||||
|     DDRF  &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); | ||||
|     PORTF |=  (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); | ||||
| } | ||||
|  | ||||
| static matrix_row_t read_cols(uint8_t row) | ||||
| { | ||||
|     if (row < 7) { | ||||
|         if (mcp23018_status) { // if there was an error | ||||
|             return 0; | ||||
|         } else { | ||||
|             uint8_t data = 0; | ||||
|             mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out; | ||||
|             mcp23018_status = i2c_write(GPIOB);             if (mcp23018_status) goto out; | ||||
|             mcp23018_status = i2c_start(I2C_ADDR_READ);     if (mcp23018_status) goto out; | ||||
|             data = i2c_readNak(); | ||||
|             data = ~data; | ||||
|         out: | ||||
|             i2c_stop(); | ||||
|             return data; | ||||
|         } | ||||
|     } else { | ||||
|         _delay_us(30);  // without this wait read unstable value. | ||||
|         // read from teensy | ||||
|         return | ||||
|             (PINF&(1<<0) ? 0 : (1<<0)) | | ||||
|             (PINF&(1<<1) ? 0 : (1<<1)) | | ||||
|             (PINF&(1<<4) ? 0 : (1<<2)) | | ||||
|             (PINF&(1<<5) ? 0 : (1<<3)) | | ||||
|             (PINF&(1<<6) ? 0 : (1<<4)) | | ||||
|             (PINF&(1<<7) ? 0 : (1<<5)) ; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Row pin configuration | ||||
|  * | ||||
|  * Teensy | ||||
|  * row: 7   8   9   10  11  12  13 | ||||
|  * pin: B0  B1  B2  B3  D2  D3  C6 | ||||
|  * | ||||
|  * MCP23018 | ||||
|  * row: 0   1   2   3   4   5   6 | ||||
|  * pin: A0  A1  A2  A3  A4  A5  A6 | ||||
|  */ | ||||
| static void unselect_rows(void) | ||||
| { | ||||
|     // unselect on mcp23018 | ||||
|     if (mcp23018_status) { // if there was an error | ||||
|         // do nothing | ||||
|     } else { | ||||
|         // set all rows hi-Z : 1 | ||||
|         mcp23018_status = i2c_start(I2C_ADDR_WRITE);    if (mcp23018_status) goto out; | ||||
|         mcp23018_status = i2c_write(GPIOA);             if (mcp23018_status) goto out; | ||||
|         mcp23018_status = i2c_write( 0xFF | ||||
|                               & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT) | ||||
|                           );                            if (mcp23018_status) goto out; | ||||
|     out: | ||||
|         i2c_stop(); | ||||
|     } | ||||
|  | ||||
|     // unselect on teensy | ||||
|     // Hi-Z(DDR:0, PORT:0) to unselect | ||||
|     DDRB  &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); | ||||
|     PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); | ||||
|     DDRD  &= ~(1<<2 | 1<<3); | ||||
|     PORTD &= ~(1<<2 | 1<<3); | ||||
|     DDRC  &= ~(1<<6); | ||||
|     PORTC &= ~(1<<6); | ||||
| } | ||||
|  | ||||
| static void select_row(uint8_t row) | ||||
| { | ||||
|     if (row < 7) { | ||||
|         // select on mcp23018 | ||||
|         if (mcp23018_status) { // if there was an error | ||||
|             // do nothing | ||||
|         } else { | ||||
|             // set active row low  : 0 | ||||
|             // set other rows hi-Z : 1 | ||||
|             mcp23018_status = i2c_start(I2C_ADDR_WRITE);        if (mcp23018_status) goto out; | ||||
|             mcp23018_status = i2c_write(GPIOA);                 if (mcp23018_status) goto out; | ||||
|             mcp23018_status = i2c_write( 0xFF & ~(1<<row) | ||||
|                                   & ~(ergodox_left_led_3<<LEFT_LED_3_SHIFT) | ||||
|                               );                                if (mcp23018_status) goto out; | ||||
|         out: | ||||
|             i2c_stop(); | ||||
|         } | ||||
|     } else { | ||||
|         // select on teensy | ||||
|         // Output low(DDR:1, PORT:0) to select | ||||
|         switch (row) { | ||||
|             case 7: | ||||
|                 DDRB  |= (1<<0); | ||||
|                 PORTB &= ~(1<<0); | ||||
|                 break; | ||||
|             case 8: | ||||
|                 DDRB  |= (1<<1); | ||||
|                 PORTB &= ~(1<<1); | ||||
|                 break; | ||||
|             case 9: | ||||
|                 DDRB  |= (1<<2); | ||||
|                 PORTB &= ~(1<<2); | ||||
|                 break; | ||||
|             case 10: | ||||
|                 DDRB  |= (1<<3); | ||||
|                 PORTB &= ~(1<<3); | ||||
|                 break; | ||||
|             case 11: | ||||
|                 DDRD  |= (1<<2); | ||||
|                 PORTD &= ~(1<<3); | ||||
|                 break; | ||||
|             case 12: | ||||
|                 DDRD  |= (1<<3); | ||||
|                 PORTD &= ~(1<<3); | ||||
|                 break; | ||||
|             case 13: | ||||
|                 DDRC  |= (1<<6); | ||||
|                 PORTC &= ~(1<<6); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										208
									
								
								keyboard/ergodox_ez/twimaster.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								keyboard/ergodox_ez/twimaster.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| /************************************************************************* | ||||
| * Title:    I2C master library using hardware TWI interface | ||||
| * Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury | ||||
| * File:     $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $ | ||||
| * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 | ||||
| * Target:   any AVR device with hardware TWI  | ||||
| * Usage:    API compatible with I2C Software Library i2cmaster.h | ||||
| **************************************************************************/ | ||||
| #include <inttypes.h> | ||||
| #include <compat/twi.h> | ||||
|  | ||||
| #include <i2cmaster.h> | ||||
|  | ||||
|  | ||||
| /* define CPU frequency in Mhz here if not defined in Makefile */ | ||||
| #ifndef F_CPU | ||||
| #define F_CPU 16000000UL | ||||
| #endif | ||||
|  | ||||
| /* I2C clock in Hz */ | ||||
| #define SCL_CLOCK  400000L | ||||
|  | ||||
|  | ||||
| /************************************************************************* | ||||
|  Initialization of the I2C bus interface. Need to be called only once | ||||
| *************************************************************************/ | ||||
| void i2c_init(void) | ||||
| { | ||||
|   /* initialize TWI clock | ||||
|    * minimal values in Bit Rate Register (TWBR) and minimal Prescaler | ||||
|    * bits in the TWI Status Register should give us maximal possible | ||||
|    * I2C bus speed - about 444 kHz | ||||
|    * | ||||
|    * for more details, see 20.5.2 in ATmega16/32 secification | ||||
|    */ | ||||
|    | ||||
|   TWSR = 0;     /* no prescaler */ | ||||
|   TWBR = 10;    /* must be >= 10 for stable operation */ | ||||
|  | ||||
| }/* i2c_init */ | ||||
|  | ||||
|  | ||||
| /*************************************************************************	 | ||||
|   Issues a start condition and sends address and transfer direction. | ||||
|   return 0 = device accessible, 1= failed to access device | ||||
| *************************************************************************/ | ||||
| unsigned char i2c_start(unsigned char address) | ||||
| { | ||||
|     uint8_t   twst; | ||||
|  | ||||
| 	// send START condition | ||||
| 	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); | ||||
|  | ||||
| 	// wait until transmission completed | ||||
| 	while(!(TWCR & (1<<TWINT))); | ||||
|  | ||||
| 	// check value of TWI Status Register. Mask prescaler bits. | ||||
| 	twst = TW_STATUS & 0xF8; | ||||
| 	if ( (twst != TW_START) && (twst != TW_REP_START)) return 1; | ||||
|  | ||||
| 	// send device address | ||||
| 	TWDR = address; | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN); | ||||
|  | ||||
| 	// wail until transmission completed and ACK/NACK has been received | ||||
| 	while(!(TWCR & (1<<TWINT))); | ||||
|  | ||||
| 	// check value of TWI Status Register. Mask prescaler bits. | ||||
| 	twst = TW_STATUS & 0xF8; | ||||
| 	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1; | ||||
|  | ||||
| 	return 0; | ||||
|  | ||||
| }/* i2c_start */ | ||||
|  | ||||
|  | ||||
| /************************************************************************* | ||||
|  Issues a start condition and sends address and transfer direction. | ||||
|  If device is busy, use ack polling to wait until device is ready | ||||
|   | ||||
|  Input:   address and transfer direction of I2C device | ||||
| *************************************************************************/ | ||||
| void i2c_start_wait(unsigned char address) | ||||
| { | ||||
|     uint8_t   twst; | ||||
|  | ||||
|  | ||||
|     while ( 1 ) | ||||
|     { | ||||
| 	    // send START condition | ||||
| 	    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); | ||||
|      | ||||
|     	// wait until transmission completed | ||||
|     	while(!(TWCR & (1<<TWINT))); | ||||
|      | ||||
|     	// check value of TWI Status Register. Mask prescaler bits. | ||||
|     	twst = TW_STATUS & 0xF8; | ||||
|     	if ( (twst != TW_START) && (twst != TW_REP_START)) continue; | ||||
|      | ||||
|     	// send device address | ||||
|     	TWDR = address; | ||||
|     	TWCR = (1<<TWINT) | (1<<TWEN); | ||||
|      | ||||
|     	// wail until transmission completed | ||||
|     	while(!(TWCR & (1<<TWINT))); | ||||
|      | ||||
|     	// check value of TWI Status Register. Mask prescaler bits. | ||||
|     	twst = TW_STATUS & 0xF8; | ||||
|     	if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )  | ||||
|     	{    	     | ||||
|     	    /* device busy, send stop condition to terminate write operation */ | ||||
| 	        TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | ||||
| 	         | ||||
| 	        // wait until stop condition is executed and bus released | ||||
| 	        while(TWCR & (1<<TWSTO)); | ||||
| 	         | ||||
|     	    continue; | ||||
|     	} | ||||
|     	//if( twst != TW_MT_SLA_ACK) return 1; | ||||
|     	break; | ||||
|      } | ||||
|  | ||||
| }/* i2c_start_wait */ | ||||
|  | ||||
|  | ||||
| /************************************************************************* | ||||
|  Issues a repeated start condition and sends address and transfer direction  | ||||
|  | ||||
|  Input:   address and transfer direction of I2C device | ||||
|   | ||||
|  Return:  0 device accessible | ||||
|           1 failed to access device | ||||
| *************************************************************************/ | ||||
| unsigned char i2c_rep_start(unsigned char address) | ||||
| { | ||||
|     return i2c_start( address ); | ||||
|  | ||||
| }/* i2c_rep_start */ | ||||
|  | ||||
|  | ||||
| /************************************************************************* | ||||
|  Terminates the data transfer and releases the I2C bus | ||||
| *************************************************************************/ | ||||
| void i2c_stop(void) | ||||
| { | ||||
|     /* send stop condition */ | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | ||||
| 	 | ||||
| 	// wait until stop condition is executed and bus released | ||||
| 	while(TWCR & (1<<TWSTO)); | ||||
|  | ||||
| }/* i2c_stop */ | ||||
|  | ||||
|  | ||||
| /************************************************************************* | ||||
|   Send one byte to I2C device | ||||
|    | ||||
|   Input:    byte to be transfered | ||||
|   Return:   0 write successful  | ||||
|             1 write failed | ||||
| *************************************************************************/ | ||||
| unsigned char i2c_write( unsigned char data ) | ||||
| {	 | ||||
|     uint8_t   twst; | ||||
|      | ||||
| 	// send data to the previously addressed device | ||||
| 	TWDR = data; | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN); | ||||
|  | ||||
| 	// wait until transmission completed | ||||
| 	while(!(TWCR & (1<<TWINT))); | ||||
|  | ||||
| 	// check value of TWI Status Register. Mask prescaler bits | ||||
| 	twst = TW_STATUS & 0xF8; | ||||
| 	if( twst != TW_MT_DATA_ACK) return 1; | ||||
| 	return 0; | ||||
|  | ||||
| }/* i2c_write */ | ||||
|  | ||||
|  | ||||
| /************************************************************************* | ||||
|  Read one byte from the I2C device, request more data from device  | ||||
|   | ||||
|  Return:  byte read from I2C device | ||||
| *************************************************************************/ | ||||
| unsigned char i2c_readAck(void) | ||||
| { | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); | ||||
| 	while(!(TWCR & (1<<TWINT)));     | ||||
|  | ||||
|     return TWDR; | ||||
|  | ||||
| }/* i2c_readAck */ | ||||
|  | ||||
|  | ||||
| /************************************************************************* | ||||
|  Read one byte from the I2C device, read is followed by a stop condition  | ||||
|   | ||||
|  Return:  byte read from I2C device | ||||
| *************************************************************************/ | ||||
| unsigned char i2c_readNak(void) | ||||
| { | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN); | ||||
| 	while(!(TWCR & (1<<TWINT))); | ||||
| 	 | ||||
|     return TWDR; | ||||
|  | ||||
| }/* i2c_readNak */ | ||||
		Reference in New Issue
	
	Block a user