diff --git a/keyboard/kimera/Makefile b/keyboard/kimera/Makefile new file mode 100644 index 00000000..227af26a --- /dev/null +++ b/keyboard/kimera/Makefile @@ -0,0 +1,165 @@ +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF. +# +# make extcoff = Convert ELF to AVR Extended COFF. +# +# make program = Download the hex file to the device. +# Please customize your programmer settings(PROGRAM_CMD) +# +# make teensy = Download the hex file to the device, using teensy_loader_cli. +# (must have teensy_loader_cli installed). +# +# make dfu = Download the hex file to the device, using dfu-programmer (must +# have dfu-programmer installed). +# +# make flip = Download the hex file to the device, using Atmel FLIP (must +# have Atmel FLIP installed). +# +# make dfu-ee = Download the eeprom file to the device, using dfu-programmer +# (must have dfu-programmer installed). +# +# make flip-ee = Download the eeprom file to the device, using Atmel FLIP +# (must have Atmel FLIP installed). +# +# make debug = Start either simulavr or avarice as specified for debugging, +# with avr-gdb or avr-insight as the front end for debugging. +# +# make filename.s = Just compile filename.c into the assembler code only. +# +# make filename.i = Create a preprocessed source file for use in submitting +# bug reports to the GCC project. +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + +# Target file name (without extension). +TARGET = kimera_lufa + +# Directory common source filess exist +TMK_DIR = ../../tmk_core_custom + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# project specific files +SRC = keymap_common.c \ + matrix.c \ + led.c \ + backlight.c \ + ledmap.c \ + twimaster.c \ + i2c_wrapper.c \ + kimera.c \ + light_ws2812.c \ + rgb.c + +ifdef KEYMAP + SRC := keymap_$(KEYMAP).c $(SRC) +else + SRC := 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 + +# PCB Version +ifdef VER + OPT_DEFS += -DKIMERA_$(REV) +else + OPT_DEFS += -DKIMERA_CORE +endif + +# Additional definitions from command line +ifdef DEFS + OPT_DEFS += $(foreach DEF,$(DEFS),-D$(DEF)) +endif + +# 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 +#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA +USB_6KRO_ENABLE = yes # USB 6key Rollover +#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support +#PS2_USE_BUSYWAIT = yes +BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality +KEYMAP_IN_EEPROM_ENABLE = yes # External keymap in eeprom +#KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor +SOFTPWM_LED_ENABLE = yes # Enable SoftPWM to drive backlight +FADING_LED_ENABLE = yes # Enable fading backlight +BREATHING_LED_ENABLE = yes # Enable breathing backlight +LEDMAP_ENABLE = yes # Enable LED mapping +LEDMAP_IN_EEPROM_ENABLE = yes # Read LED mapping from eeprom + + +# Optimize size but this may cause error "relocation truncated to fit" +#EXTRALDFLAGS = -Wl,--relax + +# Search Path +VPATH += $(TARGET_DIR) +VPATH += $(TMK_DIR) + +include $(TMK_DIR)/protocol/lufa.mk +include $(TMK_DIR)/common.mk +include $(TMK_DIR)/rules.mk diff --git a/keyboard/kimera/Makefile.pjrc b/keyboard/kimera/Makefile.pjrc new file mode 100644 index 00000000..9c49208f --- /dev/null +++ b/keyboard/kimera/Makefile.pjrc @@ -0,0 +1,122 @@ +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF. +# +# make extcoff = Convert ELF to AVR Extended COFF. +# +# make program = Download the hex file to the device. +# Please customize your programmer settings(PROGRAM_CMD) +# +# make teensy = Download the hex file to the device, using teensy_loader_cli. +# (must have teensy_loader_cli installed). +# +# make dfu = Download the hex file to the device, using dfu-programmer (must +# have dfu-programmer installed). +# +# make flip = Download the hex file to the device, using Atmel FLIP (must +# have Atmel FLIP installed). +# +# make dfu-ee = Download the eeprom file to the device, using dfu-programmer +# (must have dfu-programmer installed). +# +# make flip-ee = Download the eeprom file to the device, using Atmel FLIP +# (must have Atmel FLIP installed). +# +# make debug = Start either simulavr or avarice as specified for debugging, +# with avr-gdb or avr-insight as the front end for debugging. +# +# make filename.s = Just compile filename.c into the assembler code only. +# +# make filename.i = Create a preprocessed source file for use in submitting +# bug reports to the GCC project. +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + +# Target file name (without extension). +TARGET = kimera_pjrc + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# project specific files +SRC = keymap_common.c \ + matrix.c \ + led.c \ + backlight.c \ + ledmap.c \ + twimaster.c \ + kimera.c + +ifdef KEYMAP + SRC := keymap_$(KEYMAP).c $(SRC) +else + SRC := keymap_default.c $(SRC) +endif + +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 = atmega32u4 +#MCU = at90usb1286 + + +# 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 + + +# Boot Section Size in *bytes* +# Teensy halfKay 512 +# Atmel DFU loader 4096 +# LUFA bootloader 4096 +OPT_DEFS += -DBOOTLOADER_SIZE=4096 + +# Additional definitions from command line +ifdef DEFS + OPT_DEFS += $(foreach DEF,$(DEFS),-D$(DEF)) +endif + +# 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 +#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA +USB_6KRO_ENABLE = yes # USB 6key Rollover +#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support +#PS2_USE_BUSYWAIT = yes +BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality +KEYMAP_IN_EEPROM_ENABLE = yes # External keymap in eeprom +#KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor +SOFTPWM_LED_ENABLE = yes # Enable SoftPWM to drive backlight +#FADING_LED_ENABLE = yes # Enable fading backlight +BREATHING_LED_ENABLE = yes # Enable breathing backlight +LEDMAP_ENABLE = yes # Enable LED mapping +LEDMAP_IN_EEPROM_ENABLE = yes # Read LED mapping from eeprom + + +# Search Path +VPATH += $(TARGET_DIR) +VPATH += $(TOP_DIR) + +include $(TOP_DIR)/protocol/pjrc.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/keyboard/kimera/Makefile_8M b/keyboard/kimera/Makefile_8M new file mode 100644 index 00000000..a40a3100 --- /dev/null +++ b/keyboard/kimera/Makefile_8M @@ -0,0 +1,156 @@ +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF. +# +# make extcoff = Convert ELF to AVR Extended COFF. +# +# make program = Download the hex file to the device. +# Please customize your programmer settings(PROGRAM_CMD) +# +# make teensy = Download the hex file to the device, using teensy_loader_cli. +# (must have teensy_loader_cli installed). +# +# make dfu = Download the hex file to the device, using dfu-programmer (must +# have dfu-programmer installed). +# +# make flip = Download the hex file to the device, using Atmel FLIP (must +# have Atmel FLIP installed). +# +# make dfu-ee = Download the eeprom file to the device, using dfu-programmer +# (must have dfu-programmer installed). +# +# make flip-ee = Download the eeprom file to the device, using Atmel FLIP +# (must have Atmel FLIP installed). +# +# make debug = Start either simulavr or avarice as specified for debugging, +# with avr-gdb or avr-insight as the front end for debugging. +# +# make filename.s = Just compile filename.c into the assembler code only. +# +# make filename.i = Create a preprocessed source file for use in submitting +# bug reports to the GCC project. +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + +# Target file name (without extension). +TARGET = kimera_8m_lufa + +# Directory common source filess exist +TOP_DIR = ../.. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# project specific files +SRC = keymap_common.c \ + matrix.c \ + led.c \ + backlight.c \ + ledmap.c \ + twimaster.c \ + kimera.c + +ifdef KEYMAP + SRC := keymap_$(KEYMAP).c $(SRC) +else + SRC := 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 +F_CPU = 8000000 + + +# +# 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 + +# Additional definitions from command line +ifdef DEFS + OPT_DEFS += $(foreach DEF,$(DEFS),-D$(DEF)) +endif + +# 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 +#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA +USB_6KRO_ENABLE = yes # USB 6key Rollover +#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support +#PS2_USE_BUSYWAIT = yes +BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality +KEYMAP_IN_EEPROM_ENABLE = yes # External keymap in eeprom +#KEYMAP_SECTION_ENABLE = yes # Fixed address keymap for keymap editor +SOFTPWM_LED_ENABLE = yes # Enable SoftPWM to drive backlight +#FADING_LED_ENABLE = yes # Enable fading backlight +BREATHING_LED_ENABLE = yes # Enable breathing backlight +LEDMAP_ENABLE = yes # Enable LED mapping +LEDMAP_IN_EEPROM_ENABLE = yes # Read LED mapping from eeprom + +# 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)/protocol/lufa.mk +include $(TOP_DIR)/protocol.mk +include $(TOP_DIR)/common.mk +include $(TOP_DIR)/rules.mk diff --git a/keyboard/kimera/backlight.c b/keyboard/kimera/backlight.c new file mode 100644 index 00000000..24777bc0 --- /dev/null +++ b/keyboard/kimera/backlight.c @@ -0,0 +1,236 @@ +/* +Copyright 2014 Kai Ryu + +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 . +*/ + +#include +#include +#include +#include "backlight.h" +#ifdef SOFTPWM_LED_ENABLE +#include "softpwm_led.h" +#else +#include "breathing_led.h" +#endif +#include "action.h" +#include "kimera.h" +#include "rgb.h" + +#ifdef BACKLIGHT_ENABLE + +void backlight_enable(void); +void backlight_disable(void); +inline void backlight_set_raw(uint8_t raw); + +static const uint8_t backlight_table[] PROGMEM = { + 0, 16, 128, 255 +}; + +extern backlight_config_t backlight_config; +uint8_t backlight_brightness; + +/* Backlight pin configuration + * LED4: PB6 (D10) OC1B + */ +#ifndef SOFTPWM_LED_ENABLE +void backlight_enable(void) +{ + // Turn on PWM + LED4_DDR |= (1< 0) { + backlight_enable(); + backlight_set_raw(pgm_read_byte(&backlight_table[level])); + } + else { + backlight_disable(); + } +#endif +} + +#ifndef SOFTPWM_LED_ENABLE +#ifdef BREATHING_LED_ENABLE +void breathing_led_set_raw(uint8_t raw) +{ + backlight_set_raw(raw); +} +#endif +#endif + +inline void backlight_set_raw(uint8_t raw) +{ +#ifdef SOFTPWM_LED_ENABLE + softpwm_led_set_all(raw); +#else + LED4_OCR = raw; +#endif +} + +#ifndef LEDMAP_ENABLE +#ifdef SOFTPWM_LED_ENABLE +void softpwm_led_init(void) +{ + LED4_DDR |= (1< + +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 . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0x16c0 +#define PRODUCT_ID 0x27db +#define DEVICE_VER 0x0005 +#define MANUFACTURER kai1103@gmail.com +#define PRODUCT Kimera +#define DESCRIPTION t.m.k. keyboard firmware for Kimera + +/* key matrix size */ +#define MATRIX_ROWS 32 +#define MATRIX_COLS 32 + +/* keymap in eeprom */ +#define MATRIX_SIZE 16 * 16 +#define FN_ACTIONS_COUNT 32 +#define KEYMAPS_COUNT 3 +#define EECONFIG_KEYMAP_IN_EEPROM 82 + +/* define if matrix has ghost */ +//#define MATRIX_HAS_GHOST + +/* Set 0 if debouncing isn't needed */ +#define DEBOUNCE 5 + +/* number of backlight levels */ +#ifdef BREATHING_LED_ENABLE +#ifdef FADING_LED_ENABLE +#define BACKLIGHT_LEVELS 8 +#else +#define BACKLIGHT_LEVELS 6 +#endif +#else +#define BACKLIGHT_LEVELS 3 +#endif + +/* enable customized backlight logic */ +#define BACKLIGHT_CUSTOM +#define CUSTOM_LED_ENABLE +#define RGB_LED_ENABLE + +/* number of leds */ +#define LED_COUNT 4 + +/* 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_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* + * 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 NO_SUSPEND_POWER_DOWN + +#endif diff --git a/keyboard/kimera/i2c_wrapper.c b/keyboard/kimera/i2c_wrapper.c new file mode 100644 index 00000000..07f87838 --- /dev/null +++ b/keyboard/kimera/i2c_wrapper.c @@ -0,0 +1,95 @@ +/* +Copyright 2016 Kai Ryu + +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 . +*/ + +#include +#include +#include +#include "i2cmaster.h" +#include "i2c_wrapper.h" +#include "debug.h" + +#define wdt_intr_enable(value) \ +__asm__ __volatile__ ( \ + "in __tmp_reg__,__SREG__" "\n\t" \ + "cli" "\n\t" \ + "wdr" "\n\t" \ + "sts %0,%1" "\n\t" \ + "out __SREG__,__tmp_reg__" "\n\t" \ + "sts %0,%2" "\n\t" \ + : /* no outputs */ \ + : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \ + "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \ + "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \ + _BV(WDIE) | (value & 0x07)) ) \ + : "r0" \ +) + +#define SCL_CLOCK 400000L +#define SCL_DURATION (1000000L/SCL_CLOCK)/2 + +static uint8_t i2c_wdt_enabled = 0; + +extern uint8_t i2c_force_stop; + +static void wdt_init(void); + +void i2c_wrapper_init(void) +{ + /* init i2c */ + i2c_init(); + + /* init watch dog */ + wdt_init(); +} + +void i2c_wrapper_task(void) +{ + /* reset watch dog counter */ + wdt_reset(); +} + +void wdt_init(void) +{ + cli(); + wdt_reset(); + wdt_intr_enable(WDTO_2S); + sei(); +} + +ISR(WDT_vect) +{ + xprintf("i2c timeout\n"); + + /* let slave to release SDA */ + TWCR = 0; + DDRD |= (1< + +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 . +*/ + +#ifndef I2C_WRAPPER_H +#define I2C_WRAPPER_H + +void i2c_wrapper_init(void); +void i2c_wrapper_task(void); + +#endif + diff --git a/keyboard/kimera/i2cmaster.h b/keyboard/kimera/i2cmaster.h new file mode 100644 index 00000000..70f51fd3 --- /dev/null +++ b/keyboard/kimera/i2cmaster.h @@ -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 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 @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 + + + #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 + +/** 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
+ 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 diff --git a/keyboard/kimera/keymap_common.c b/keyboard/kimera/keymap_common.c new file mode 100644 index 00000000..cab3f88d --- /dev/null +++ b/keyboard/kimera/keymap_common.c @@ -0,0 +1,50 @@ +/* +Copyright 2014 Kai Ryu + +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 . +*/ +#include "keymap_common.h" +#include "matrix.h" + +/* translates key to keycode */ +uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key) +{ +#ifndef KEYMAP_IN_EEPROM_ENABLE + return pgm_read_byte(&keymaps[(layer)][(key.row) * matrix_cols() + (key.col)]); +#else + return eeconfig_read_keymap_key(layer, key.row, key.col); +#endif +} + +/* translates Fn keycode to action */ +action_t keymap_fn_to_action(uint8_t keycode) +{ + return (action_t) { +#ifndef KEYMAP_IN_EEPROM_ENABLE + .code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]) +#else + .code = eeconfig_read_keymap_fn_action(FN_INDEX(keycode)) +#endif + }; +} + +#ifdef KEYMAP_IN_EEPROM_ENABLE +const uint8_t* keymaps_pointer(void) { + return (const uint8_t*)keymaps; +} + +const uint16_t* fn_actions_pointer(void) { + return fn_actions; +} +#endif diff --git a/keyboard/kimera/keymap_common.h b/keyboard/kimera/keymap_common.h new file mode 100644 index 00000000..9654304d --- /dev/null +++ b/keyboard/kimera/keymap_common.h @@ -0,0 +1,179 @@ +/* +Copyright 2014 Kai Ryu + +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 . +*/ +#ifndef KEYMAP_COMMON_H +#define KEYMAP_COMMON_H + +#include +#include +#include +#include "keycode.h" +#include "action.h" +#include "action_macro.h" +#include "report.h" +#include "host.h" +#include "print.h" +#include "debug.h" +#include "keymap.h" +#include "keymap_in_eeprom.h" + + +extern const uint8_t keymaps[][MATRIX_SIZE]; +extern const uint16_t fn_actions[]; + +/* 16 rows, 16 cols */ +#define KEYMAP_16x16( \ + KAA, KAB, KAC, KAD, KAE, KAF, KAG, KAH, KAJ, KAK, KAL, KAM, KAN, KAP, KAQ, KAR, \ + KBA, KBB, KBC, KBD, KBE, KBF, KBG, KBH, KBJ, KBK, KBL, KBM, KBN, KBP, KBQ, KBR, \ + KCA, KCB, KCC, KCD, KCE, KCF, KCG, KCH, KCJ, KCK, KCL, KCM, KCN, KCP, KCQ, KCR, \ + KDA, KDB, KDC, KDD, KDE, KDF, KDG, KDH, KDJ, KDK, KDL, KDM, KDN, KDP, KDQ, KDR, \ + KEA, KEB, KEC, KED, KEE, KEF, KEG, KEH, KEJ, KEK, KEL, KEM, KEN, KEP, KEQ, KER, \ + KFA, KFB, KFC, KFD, KFE, KFF, KFG, KFH, KFJ, KFK, KFL, KFM, KFN, KFP, KFQ, KFR, \ + KGA, KGB, KGC, KGD, KGE, KGF, KGG, KGH, KGJ, KGK, KGL, KGM, KGN, KGP, KGQ, KGR, \ + KHA, KHB, KHC, KHD, KHE, KHF, KHG, KHH, KHJ, KHK, KHL, KHM, KHN, KHP, KHQ, KHR, \ + KJA, KJB, KJC, KJD, KJE, KJF, KJG, KJH, KJJ, KJK, KJL, KJM, KJN, KJP, KJQ, KJR, \ + KKA, KKB, KKC, KKD, KKE, KKF, KKG, KKH, KKJ, KKK, KKL, KKM, KKN, KKP, KKQ, KKR, \ + KLA, KLB, KLC, KLD, KLE, KLF, KLG, KLH, KLJ, KLK, KLL, KLM, KLN, KLP, KLQ, KLR, \ + KMA, KMB, KMC, KMD, KME, KMF, KMG, KMH, KMJ, KMK, KML, KMM, KMN, KMP, KMQ, KMR, \ + KNA, KNB, KNC, KND, KNE, KNF, KNG, KNH, KNJ, KNK, KNL, KNM, KNN, KNP, KNQ, KNR, \ + KPA, KPB, KPC, KPD, KPE, KPF, KPG, KPH, KPJ, KPK, KPL, KPM, KPN, KPP, KPQ, KPR, \ + KQA, KQB, KQC, KQD, KQE, KQF, KQG, KQH, KQJ, KQK, KQL, KQM, KQN, KQP, KQQ, KQR, \ + KRA, KRB, KRC, KRD, KRE, KRF, KRG, KRH, KRJ, KRK, KRL, KRM, KRN, KRP, KRQ, KRR \ +) { \ + KC_##KAA, KC_##KAB, KC_##KAC, KC_##KAD, KC_##KAE, KC_##KAF, KC_##KAG, KC_##KAH, KC_##KAJ, KC_##KAK, KC_##KAL, KC_##KAM, KC_##KAN, KC_##KAP, KC_##KAQ, KC_##KAR, \ + KC_##KBA, KC_##KBB, KC_##KBC, KC_##KBD, KC_##KBE, KC_##KBF, KC_##KBG, KC_##KBH, KC_##KBJ, KC_##KBK, KC_##KBL, KC_##KBM, KC_##KBN, KC_##KBP, KC_##KBQ, KC_##KBR, \ + KC_##KCA, KC_##KCB, KC_##KCC, KC_##KCD, KC_##KCE, KC_##KCF, KC_##KCG, KC_##KCH, KC_##KCJ, KC_##KCK, KC_##KCL, KC_##KCM, KC_##KCN, KC_##KCP, KC_##KCQ, KC_##KCR, \ + KC_##KDA, KC_##KDB, KC_##KDC, KC_##KDD, KC_##KDE, KC_##KDF, KC_##KDG, KC_##KDH, KC_##KDJ, KC_##KDK, KC_##KDL, KC_##KDM, KC_##KDN, KC_##KDP, KC_##KDQ, KC_##KDR, \ + KC_##KEA, KC_##KEB, KC_##KEC, KC_##KED, KC_##KEE, KC_##KEF, KC_##KEG, KC_##KEH, KC_##KEJ, KC_##KEK, KC_##KEL, KC_##KEM, KC_##KEN, KC_##KEP, KC_##KEQ, KC_##KER, \ + KC_##KFA, KC_##KFB, KC_##KFC, KC_##KFD, KC_##KFE, KC_##KFF, KC_##KFG, KC_##KFH, KC_##KFJ, KC_##KFK, KC_##KFL, KC_##KFM, KC_##KFN, KC_##KFP, KC_##KFQ, KC_##KFR, \ + KC_##KGA, KC_##KGB, KC_##KGC, KC_##KGD, KC_##KGE, KC_##KGF, KC_##KGG, KC_##KGH, KC_##KGJ, KC_##KGK, KC_##KGL, KC_##KGM, KC_##KGN, KC_##KGP, KC_##KGQ, KC_##KGR, \ + KC_##KHA, KC_##KHB, KC_##KHC, KC_##KHD, KC_##KHE, KC_##KHF, KC_##KHG, KC_##KHH, KC_##KHJ, KC_##KHK, KC_##KHL, KC_##KHM, KC_##KHN, KC_##KHP, KC_##KHQ, KC_##KHR, \ + KC_##KJA, KC_##KJB, KC_##KJC, KC_##KJD, KC_##KJE, KC_##KJF, KC_##KJG, KC_##KJH, KC_##KJJ, KC_##KJK, KC_##KJL, KC_##KJM, KC_##KJN, KC_##KJP, KC_##KJQ, KC_##KJR, \ + KC_##KKA, KC_##KKB, KC_##KKC, KC_##KKD, KC_##KKE, KC_##KKF, KC_##KKG, KC_##KKH, KC_##KKJ, KC_##KKK, KC_##KKL, KC_##KKM, KC_##KKN, KC_##KKP, KC_##KKQ, KC_##KKR, \ + KC_##KLA, KC_##KLB, KC_##KLC, KC_##KLD, KC_##KLE, KC_##KLF, KC_##KLG, KC_##KLH, KC_##KLJ, KC_##KLK, KC_##KLL, KC_##KLM, KC_##KLN, KC_##KLP, KC_##KLQ, KC_##KLR, \ + KC_##KMA, KC_##KMB, KC_##KMC, KC_##KMD, KC_##KME, KC_##KMF, KC_##KMG, KC_##KMH, KC_##KMJ, KC_##KMK, KC_##KML, KC_##KMM, KC_##KMN, KC_##KMP, KC_##KMQ, KC_##KMR, \ + KC_##KNA, KC_##KNB, KC_##KNC, KC_##KND, KC_##KNE, KC_##KNF, KC_##KNG, KC_##KNH, KC_##KNJ, KC_##KNK, KC_##KNL, KC_##KNM, KC_##KNN, KC_##KNP, KC_##KNQ, KC_##KNR, \ + KC_##KPA, KC_##KPB, KC_##KPC, KC_##KPD, KC_##KPE, KC_##KPF, KC_##KPG, KC_##KPH, KC_##KPJ, KC_##KPK, KC_##KPL, KC_##KPM, KC_##KPN, KC_##KPP, KC_##KPQ, KC_##KPR, \ + KC_##KQA, KC_##KQB, KC_##KQC, KC_##KQD, KC_##KQE, KC_##KQF, KC_##KQG, KC_##KQH, KC_##KQJ, KC_##KQK, KC_##KQL, KC_##KQM, KC_##KQN, KC_##KQP, KC_##KQQ, KC_##KQR, \ + KC_##KRA, KC_##KRB, KC_##KRC, KC_##KRD, KC_##KRE, KC_##KRF, KC_##KRG, KC_##KRH, KC_##KRJ, KC_##KRK, KC_##KRL, KC_##KRM, KC_##KRN, KC_##KRP, KC_##KRQ, KC_##KRR \ +} + +/* 8 rows, 24 cols */ +#define KEYMAP_8x24( \ + KAA, KAB, KAC, KAD, KAE, KAF, KAG, KAH, KAJ, KAK, KAL, KAM, KAN, KAP, KAQ, KAR, KAS, KAT, KAU, KAV, KAW, KAX, KAY, KAZ, \ + KBA, KBB, KBC, KBD, KBE, KBF, KBG, KBH, KBJ, KBK, KBL, KBM, KBN, KBP, KBQ, KBR, KBS, KBT, KBU, KBV, KBW, KBX, KBY, KBZ, \ + KCA, KCB, KCC, KCD, KCE, KCF, KCG, KCH, KCJ, KCK, KCL, KCM, KCN, KCP, KCQ, KCR, KCS, KCT, KCU, KCV, KCW, KCX, KCY, KCZ, \ + KDA, KDB, KDC, KDD, KDE, KDF, KDG, KDH, KDJ, KDK, KDL, KDM, KDN, KDP, KDQ, KDR, KDS, KDT, KDU, KDV, KDW, KDX, KDY, KDZ, \ + KEA, KEB, KEC, KED, KEE, KEF, KEG, KEH, KEJ, KEK, KEL, KEM, KEN, KEP, KEQ, KER, KES, KET, KEU, KEV, KEW, KEX, KEY, KEZ, \ + KFA, KFB, KFC, KFD, KFE, KFF, KFG, KFH, KFJ, KFK, KFL, KFM, KFN, KFP, KFQ, KFR, KFS, KFT, KFU, KFV, KFW, KFX, KFY, KFZ, \ + KGA, KGB, KGC, KGD, KGE, KGF, KGG, KGH, KGJ, KGK, KGL, KGM, KGN, KGP, KGQ, KGR, KGS, KGT, KGU, KGV, KGW, KGX, KGY, KGZ, \ + KHA, KHB, KHC, KHD, KHE, KHF, KHG, KHH, KHJ, KHK, KHL, KHM, KHN, KHP, KHQ, KHR, KHS, KHT, KHU, KHV, KHW, KHX, KHY, KHZ \ +) KEYMAP_16x16( \ + KAA, KAB, KAC, KAD, KAE, KAF, KAG, KAH, KAJ, KAK, KAL, KAM, KAN, KAP, KAQ, KAR, KAS, KAT, KAU, KAV, KAW, KAX, KAY, KAZ, \ + KBA, KBB, KBC, KBD, KBE, KBF, KBG, KBH, KBJ, KBK, KBL, KBM, KBN, KBP, KBQ, KBR, KBS, KBT, KBU, KBV, KBW, KBX, KBY, KBZ, \ + KCA, KCB, KCC, KCD, KCE, KCF, KCG, KCH, KCJ, KCK, KCL, KCM, KCN, KCP, KCQ, KCR, KCS, KCT, KCU, KCV, KCW, KCX, KCY, KCZ, \ + KDA, KDB, KDC, KDD, KDE, KDF, KDG, KDH, KDJ, KDK, KDL, KDM, KDN, KDP, KDQ, KDR, KDS, KDT, KDU, KDV, KDW, KDX, KDY, KDZ, \ + KEA, KEB, KEC, KED, KEE, KEF, KEG, KEH, KEJ, KEK, KEL, KEM, KEN, KEP, KEQ, KER, KES, KET, KEU, KEV, KEW, KEX, KEY, KEZ, \ + KFA, KFB, KFC, KFD, KFE, KFF, KFG, KFH, KFJ, KFK, KFL, KFM, KFN, KFP, KFQ, KFR, KFS, KFT, KFU, KFV, KFW, KFX, KFY, KFZ, \ + KGA, KGB, KGC, KGD, KGE, KGF, KGG, KGH, KGJ, KGK, KGL, KGM, KGN, KGP, KGQ, KGR, KGS, KGT, KGU, KGV, KGW, KGX, KGY, KGZ, \ + KHA, KHB, KHC, KHD, KHE, KHF, KHG, KHH, KHJ, KHK, KHL, KHM, KHN, KHP, KHQ, KHR, KHS, KHT, KHU, KHV, KHW, KHX, KHY, KHZ, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO \ +) + + +/* 24 rows, 8 cols */ +#define KEYMAP_24x8( \ + KAA, KAB, KAC, KAD, KAE, KAF, KAG, KAH, \ + KBA, KBB, KBC, KBD, KBE, KBF, KBG, KBH, \ + KCA, KCB, KCC, KCD, KCE, KCF, KCG, KCH, \ + KDA, KDB, KDC, KDD, KDE, KDF, KDG, KDH, \ + KEA, KEB, KEC, KED, KEE, KEF, KEG, KEH, \ + KFA, KFB, KFC, KFD, KFE, KFF, KFG, KFH, \ + KGA, KGB, KGC, KGD, KGE, KGF, KGG, KGH, \ + KHA, KHB, KHC, KHD, KHE, KHF, KHG, KHH, \ + KJA, KJB, KJC, KJD, KJE, KJF, KJG, KJH, \ + KKA, KKB, KKC, KKD, KKE, KKF, KKG, KKH, \ + KLA, KLB, KLC, KLD, KLE, KLF, KLG, KLH, \ + KMA, KMB, KMC, KMD, KME, KMF, KMG, KMH, \ + KNA, KNB, KNC, KND, KNE, KNF, KNG, KNH, \ + KPA, KPB, KPC, KPD, KPE, KPF, KPG, KPH, \ + KQA, KQB, KQC, KQD, KQE, KQF, KQG, KQH, \ + KRA, KRB, KRC, KRD, KRE, KRF, KRG, KRH, \ + KSA, KSB, KSC, KSD, KSE, KSF, KSG, KSH, \ + KTA, KTB, KTC, KTD, KTE, KTF, KTG, KTH, \ + KUA, KUB, KUC, KUD, KUE, KUF, KUG, KUH, \ + KVA, KVB, KVC, KVD, KVE, KVF, KVG, KVH, \ + KWA, KWB, KWC, KWD, KWE, KWF, KWG, KWH, \ + KXA, KXB, KXC, KXD, KXE, KXF, KXG, KXH, \ + KYA, KYB, KYC, KYD, KYE, KYF, KYG, KYH, \ + KZA, KZB, KZC, KZD, KZE, KZF, KZG, KZH \ +) KEYMAP_16x16( \ + KAA, KAB, KAC, KAD, KAE, KAF, KAG, KAH, \ + KBA, KBB, KBC, KBD, KBE, KBF, KBG, KBH, \ + KCA, KCB, KCC, KCD, KCE, KCF, KCG, KCH, \ + KDA, KDB, KDC, KDD, KDE, KDF, KDG, KDH, \ + KEA, KEB, KEC, KED, KEE, KEF, KEG, KEH, \ + KFA, KFB, KFC, KFD, KFE, KFF, KFG, KFH, \ + KGA, KGB, KGC, KGD, KGE, KGF, KGG, KGH, \ + KHA, KHB, KHC, KHD, KHE, KHF, KHG, KHH, \ + KJA, KJB, KJC, KJD, KJE, KJF, KJG, KJH, \ + KKA, KKB, KKC, KKD, KKE, KKF, KKG, KKH, \ + KLA, KLB, KLC, KLD, KLE, KLF, KLG, KLH, \ + KMA, KMB, KMC, KMD, KME, KMF, KMG, KMH, \ + KNA, KNB, KNC, KND, KNE, KNF, KNG, KNH, \ + KPA, KPB, KPC, KPD, KPE, KPF, KPG, KPH, \ + KQA, KQB, KQC, KQD, KQE, KQF, KQG, KQH, \ + KRA, KRB, KRC, KRD, KRE, KRF, KRG, KRH, \ + KSA, KSB, KSC, KSD, KSE, KSF, KSG, KSH, \ + KTA, KTB, KTC, KTD, KTE, KTF, KTG, KTH, \ + KUA, KUB, KUC, KUD, KUE, KUF, KUG, KUH, \ + KVA, KVB, KVC, KVD, KVE, KVF, KVG, KVH, \ + KWA, KWB, KWC, KWD, KWE, KWF, KWG, KWH, \ + KXA, KXB, KXC, KXD, KXE, KXF, KXG, KXH, \ + KYA, KYB, KYC, KYD, KYE, KYF, KYG, KYH, \ + KZA, KZB, KZC, KZD, KZE, KZF, KZG, KZH, \ + NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO \ +) + +/* ANSI 104 keymap */ +#define KEYMAP_ANSI_104( \ + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PRS, SCL, PAU, \ + GRV, _1, _2, _3, _4, _5, _6, _7, _8, _9, _0, MNS, EQU, BSP, INS, HOM, PGU, NUM, PSL, PAS, PMN, \ + TAB, Q, W, E, R, T, Y, U, I, O, P, LBR, RBR, BSL, DEL, END, PGD, P7, P8, P9, PPL, \ + CAP, A, S, D, F, G, H, J, K, L, SCN, QUT, ENT, P4, P5, P6, \ + LSF, Z, X, C, V, B, N, M, COM, DOT, SLS, RSF, UP, P1, P2, P3, PEN, \ + LCT, LGU, LAL, SPC, RAL, RGU, APP, RCT, LFT, DOW, RGT, P0, PDT \ +) KEYMAP_8x24( \ + ESC, NO, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PRS, SCL, PAU, NO, NO, NO, NO, NO, NO, NO, \ + GRV, _1, _2, _3, _4, _5, _6, _7, _8, _9, _0, MNS, EQU, BSP, INS, HOM, PGU, NUM, PSL, PAS, PMN, NO, NO, NO, \ + TAB, Q, W, E, R, T, Y, U, I, O, P, LBR, RBR, BSL, DEL, END, PGD, P7, P8, P9, PPL, NO, NO, NO, \ + CAP, A, S, D, F, G, H, J, K, L, SCN, QUT, NO, ENT, NO, NO, NO, P4, P5, P6, NO, NO, NO, NO, \ + LSF, Z, X, C, V, B, N, M, COM, DOT, SLS, NO, NO, RSF, NO, UP, NO, P1, P2, P3, PEN, NO, NO, NO, \ + LCT, LGU, LAL, NO, NO, NO, SPC, NO, NO, NO, RAL, RGU, APP, RCT, LFT, DOW, RGT, P0, NO, PDT, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO \ +) + +#endif diff --git a/keyboard/kimera/keymap_default.c b/keyboard/kimera/keymap_default.c new file mode 100644 index 00000000..7e750b4f --- /dev/null +++ b/keyboard/kimera/keymap_default.c @@ -0,0 +1,81 @@ +#include "keymap_common.h" +#include "rgb.h" + +// Default +#ifdef KEYMAP_SECTION_ENABLE +const uint8_t keymaps[KEYMAPS_COUNT][MATRIX_SIZE] __attribute__ ((section (".keymap.keymaps"))) = { +#else +const uint8_t keymaps[][MATRIX_SIZE] PROGMEM = { +#endif + /* Keymap 0: Default Layer + * ,---------------------------------------------------------------------------------------. + * |Esc| | F1| F2| F3| F4| | F5| F6| F7| F8| | F9|F10|F11|F12|Psc|Slk|Pus| | + * |---------------------------------------------------------------------------------------| + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |Ins|Hom|PgU|Num| /| *| -| + * |---------------------------------------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|Del|End|PgD| 7| 8| 9| | + * |-----------------------------------------------------------------------------------| +| + * |Caps | A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| | + * |-----------------------------------------------------------| ,---. |---------------| + * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift | |Up | | 1| 2| 3| | + * |-----------------------------------------------------------------------------------|Ent| + * |Ctrl|Gui |Alt | Space |Alt |Gui |Fn0 |Ctrl|Lef|Dow|Rig| 0| .| | + * `---------------------------------------------------------------------------------------' + */ + KEYMAP_ANSI_104( + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS, \ + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, \ + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, \ + CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, \ + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, PENT, \ + LCTL,LGUI,LALT, SPC, RALT,RGUI,FN0, RCTL, LEFT,DOWN,RGHT, P0, PDOT ), +}; + +/* + * Fn action definition + */ +#ifdef KEYMAP_SECTION_ENABLE +const uint16_t fn_actions[FN_ACTIONS_COUNT] __attribute__ ((section (".keymap.fn_actions"))) = { +#else +const uint16_t fn_actions[] PROGMEM = { +#endif +}; + +#ifdef KEYMAP_IN_EEPROM_ENABLE +uint16_t keys_count(void) { + return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_SIZE; +} + +uint16_t fn_actions_count(void) { + return sizeof(fn_actions) / sizeof(fn_actions[0]); +} +#endif + +#ifndef NO_ACTION_FUNCTION +enum function_id { + AF_RGB_TOGGLE = 0, + AF_RGB_DECREASE, + AF_RGB_INCREASE, + AF_RGB_STEP +}; + +void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) +{ + if (record->event.pressed) { + switch (id) { + case AF_RGB_TOGGLE: + rgb_toggle(); + break; + case AF_RGB_DECREASE: + rgb_decrease(); + break; + case AF_RGB_INCREASE: + rgb_increase(); + break; + case AF_RGB_STEP: + rgb_step(); + break; + } + } +} +#endif diff --git a/keyboard/kimera/keymap_two_headed.c b/keyboard/kimera/keymap_two_headed.c new file mode 100644 index 00000000..6f09142d --- /dev/null +++ b/keyboard/kimera/keymap_two_headed.c @@ -0,0 +1,62 @@ +#include "keymap_common.h" + +// Two-headed +#ifdef KEYMAP_SECTION_ENABLE +const uint8_t keymaps[KEYMAPS_COUNT][MATRIX_SIZE] __attribute__ ((section (".keymap.keymaps"))) = { +#else +const uint8_t keymaps[][MATRIX_SIZE] PROGMEM = { +#endif + /* Keymap 0: Default Layer + * ,----------------------------------------. ,------------------------------------------------. + * | | | | ||Esc| | F1| F2| F3| F4| | | F5| F6| F7| F8| | F9|F10|F11|F12||Psc|Slk|Pus| + * |---------------||-----------------------| |-----------------------------------||-----------| + * |Num| /| *| -|| `| 1| 2| 3| 4| 5| | 6| 7| 8| 9| 0| -| =|Backsp ||Ins|Hom|PgU| + * |---------------||-------------------------. `-----------------------------------||-----------| + * | 7| 8| 9| ||Tab | Q| W| E| R| T| | Y| U| I| O| P| [| ]| \||Del|End|PgD| + * |-----------| +||--------------------------. `---------------------------------||-----------| + * | 4| 5| 6| ||Caps | A| S| D| F| G| | H| J| K| L| ;| '|Return || | + * |---------------||----------------------------. `-------------------------------|| ,---. | + * | 1| 2| 3| ||Shift | Z| X| C| V| B| | N| M| ,| .| /|Shift || |Up | | + * |-----------|Ent||----------------------------| |------------------------------||-----------| + * | 0| .| ||Ctrl|Gui |Alt | Space | | Space |Alt |Gui |App |Ctrl||Lef|Dow|Rig| + * `---------------------------------------------' `-------------------------------------------' + */ + KEYMAP_16x16( + NO, NO, NO, NO, ESC, NO, F1, F2, F3, F4, NO, NO, NO, NO, NO, NO, \ + NLCK,PSLS,PAST,PMNS,GRV, 1, 2, 3, 4, 5, NO, NO, NO, NO, NO, NO, \ + P7, P8, P9, PPLS,TAB, Q, W, E, R, T, NO, NO, NO, NO, NO, NO, \ + P4, P5, P6, NO, CAPS,A, S, D, F, G, NO, NO, NO, NO, NO, NO, \ + P1, P2, P3, PENT,LSFT,Z, X, C, V, B, NO, NO, NO, NO, NO, NO, \ + P0, NO, PDOT,NO, LCTL,LGUI,LALT,NO, SPC, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, \ + + F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,PAUS,NO, NO, NO, NO, NO, \ + 6, 7, 8, 9, 0, MINS,EQL, BSPC,INS, HOME,PGUP,NO, NO, NO, NO, NO, \ + Y, U, I, O, P, LBRC,RBRC,BSLS,DEL, END, PGDN,NO, NO, NO, NO, NO, \ + H, J, K, L, SCLN,QUOT,NO, ENT, NO, NO, NO, NO, NO, NO, NO, NO, \ + N, M, COMM,DOT, SLSH,NO, NO, RSFT,NO, UP, NO, NO, NO, NO, NO, NO, \ + NO, SPC, NO, RALT,RGUI,APP, RCTL,NO, LEFT,DOWN,RGHT,NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, \ + NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO ), +}; + +/* + * Fn action definition + */ +#ifdef KEYMAP_SECTION_ENABLE +const uint16_t fn_actions[FN_ACTIONS_COUNT] __attribute__ ((section (".keymap.fn_actions"))) = { +#else +const uint16_t fn_actions[] PROGMEM = { +#endif +}; + +#ifdef KEYMAP_IN_EEPROM_ENABLE +uint16_t keys_count(void) { + return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_SIZE; +} + +uint16_t fn_actions_count(void) { + return sizeof(fn_actions) / sizeof(fn_actions[0]); +} +#endif diff --git a/keyboard/kimera/kimera.c b/keyboard/kimera/kimera.c new file mode 100644 index 00000000..500437a8 --- /dev/null +++ b/keyboard/kimera/kimera.c @@ -0,0 +1,386 @@ +/* +Copyright 2014 Kai Ryu + +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 . +*/ + +#define KIMERA_C + +#include +#include +#include "action.h" +#include "i2cmaster.h" +#include "kimera.h" +#include "debug.h" + +static uint8_t row_mapping[PX_COUNT] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 32, 33, 34, 35, 36, 37, 38, 39, + UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, + UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED, UNCONFIGURED +}; +static uint8_t col_mapping[PX_COUNT] = { + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55 +}; +static uint8_t row_count = 16; +static uint8_t col_count = 32; +static uint8_t row_left_count = 8; +static uint8_t col_left_count = 16; +static matrix_row_t col_left_mask; +static uint8_t combining = COMBINING_NONE; +static uint8_t data[EXP_COUNT][EXP_PORT_COUNT]; +static uint8_t exp_in_use = 0; +static uint8_t exp_online = 0; + +static uint8_t read_matrix_mapping(void); +static void write_matrix_mapping(void); +static void expander_init(uint8_t exp); +static uint8_t expander_write(uint8_t exp, uint8_t command, uint8_t *data); +static uint8_t expander_read(uint8_t exp, uint8_t command, uint8_t *data); +static uint8_t expander_write_output(uint8_t exp, uint8_t *data); +static uint8_t expander_write_inversion(uint8_t exp, uint8_t *data); +static uint8_t expander_write_config(uint8_t exp, uint8_t *data); +static uint8_t expander_read_input(uint8_t exp, uint8_t *data); +static void init_data(uint8_t value); + +void kimera_init(void) +{ + /* read config */ + //write_matrix_mapping(); /* debug */ + if (read_matrix_mapping()) { + write_matrix_mapping(); + } + + /* init i/o expanders */ + kimera_scan(); +} + +uint8_t read_matrix_mapping(void) +{ + uint8_t error = 0; + + /* read number of rows and cols */ + uint8_t rows = eeprom_read_byte(EECONFIG_ROW_COUNT); + uint8_t cols = eeprom_read_byte(EECONFIG_COL_COUNT); + if (rows == 0) error++; + else if (rows == UNCONFIGURED) error++; + else if (rows & COMBINING_BIT) { + if (combining != COMBINING_NONE) error++; + combining = COMBINING_ROW; + rows -= COMBINING_BIT; + } + if (cols == 0) error++; + else if (cols == UNCONFIGURED) error++; + else if (cols & COMBINING_BIT) { + if (combining != COMBINING_NONE) error++; + combining = COMBINING_COL; + cols -= COMBINING_BIT; + } + if (rows + cols > PX_COUNT) error++; + if (error) return error; + row_count = rows; + col_count = cols; + if (combining != COMBINING_NONE) { + row_left_count = (rows + 1) / 2; + col_left_count = (cols + 1) / 2; + col_left_mask = (1 << col_left_count) - 1; + } + + /* read row mapping */ + uint8_t *mapping = EECONFIG_ROW_COL_MAPPING; + uint8_t exp; + for (uint8_t i = 0; i < PX_COUNT; i++) { + if (i < row_count) { + row_mapping[i] = eeprom_read_byte(mapping++); + if (row_mapping[i] >= PX_COUNT) { + error++; + } + else { + exp = PX_TO_EXP(row_mapping[i]); + exp_in_use |= (1<= PX_COUNT) { + error++; + } + else { + exp = PX_TO_EXP(col_mapping[i]); + exp_in_use |= (1<= row_left_count) { + col += col_left_count; + } + } + + uint8_t px = col_mapping[col]; + if (px != UNCONFIGURED) { + if (!(data[PX_TO_EXP(px)][PX_TO_PORT(px)] & (1 << PX_TO_PIN(px)))) { + return 1; + } + } + return 0; +} + +matrix_row_t kimera_read_row(uint8_t row) +{ + kimera_read_cols(); + + /* make cols */ + matrix_row_t cols = 0; + for (uint8_t col = 0; col < col_count; col++) { + uint8_t px = col_mapping[col]; + if (px != UNCONFIGURED) { + if (!(data[PX_TO_EXP(px)][PX_TO_PORT(px)] & (1 << PX_TO_PIN(px)))) { + cols |= (1UL << col); + } + } + } + + if (combining == COMBINING_COL) { + if (row < row_left_count) { + cols &= col_left_mask; + } + else { + cols >>= col_left_count; + } + } + + return cols; +} + +void kimera_unselect_rows(void) +{ + /* set all output registers to 0xFF */ + init_data(0xFF); + for (uint8_t exp = 0; exp < EXP_COUNT; exp++) { + expander_write_config(exp, data[exp]); + } +} + +void kimera_select_row(uint8_t row) +{ + /* set selected row to low */ + init_data(0xFF); + uint8_t px = row_mapping[row]; + if (px != UNCONFIGURED) { + uint8_t exp = PX_TO_EXP(px); + data[exp][PX_TO_PORT(px)] &= ~(1 << PX_TO_PIN(px)); + expander_write_config(exp, data[exp]); + } + + if (combining == COMBINING_ROW) { + if (row < row_left_count) { + kimera_select_row(row + row_left_count); + } + } +} + +void expander_init(uint8_t exp) +{ + init_data(0x00); + + /* write inversion register */ + /* + for (uint8_t exp = 0; exp < EXP_COUNT; exp++) { + expander_write_inversion(exp, data[exp]); + } + */ + + /* set output bit */ + /* + for (uint8_t row = 0; row < row_count; row++) { + uint8_t px = row_mapping[row]; + if (px != UNCONFIGURED) { + data[PX_TO_EXP(px)][PX_TO_PORT(px)] &= ~(1 << PX_TO_PIN(px)); + } + } + */ + + /* write config registers */ + //expander_write_config(exp, data[exp]); + + /* write output registers */ + expander_write_output(exp, data[exp]); +} + +uint8_t expander_write(uint8_t exp, uint8_t command, uint8_t *data) +{ + if ((exp_online & (1< + +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 . +*/ + +#ifndef KIMERA_H +#define KIMERA_H + +#include +#include +#include "matrix.h" + +/* + U1 (Pro Micro) + ,----------------. + TX --| TX0(PD3) RAW |-- + RX --| RX1(PD2) GND |-- + --| GND RESET |-- RST + --| GND VCC |-- + SDA --| 2(PD1) (PF4)A3 |-- + SCL --| 3(PD0) (PF5)A2 |-- + (INT) --| 4(PD4) (PF6)A1 |-- + --| 5(PC6) (PF7)A0 |-- + --| 6(PD7) (PB1)15 |-- SCK + LED2 --| 7(PE6) (PB3)14 |-- MISO + LED1 --| 8(PB4) (PB2)16 |-- MOSI + LED3 --| 9(PB5) (PB6)10 |-- LED4 + `----------------' +*/ + +#ifndef KIMERA_CORE + +#define LED1_PORT PORTB +#define LED1_PIN PINB +#define LED1_DDR DDRB +#define LED1_BIT PB4 + +#define LED2_PORT PORTE +#define LED2_PIN PINE +#define LED2_DDR DDRE +#define LED2_BIT PE6 + +#define LED3_PORT PORTB +#define LED3_PIN PINB +#define LED3_DDR DDRB +#define LED3_BIT PB5 + +#define LED4_PORT PORTB +#define LED4_PIN PINB +#define LED4_DDR DDRB +#define LED4_BIT PB6 +#define LED4_OCR OCR1B + +#else + +#define LED1_PORT PORTB +#define LED1_PIN PINB +#define LED1_DDR DDRB +#define LED1_BIT PB5 + +#define LED2_PORT PORTB +#define LED2_PIN PINB +#define LED2_DDR DDRB +#define LED2_BIT PB6 + +#define LED3_PORT PORTC +#define LED3_PIN PINC +#define LED3_DDR DDRC +#define LED3_BIT PC6 + +#define LED4_PORT PORTC +#define LED4_PIN PINC +#define LED4_DDR DDRC +#define LED4_BIT PC7 +#define LED4_OCR OCR4D + +#endif + +/* + IC1 (PCA9555) IC2 (PCA9555) + ,----------. ,----------. + SDA --| SDA P00 |-- P1 SDA --| SDA P00 |-- P9 + SCL --| SCL P01 |-- P2 SCL --| SCL P01 |-- P10 + INT --| INT P02 |-- P3 INT --| INT P02 |-- P11 + | P03 |-- P4 | P03 |-- P12 + GND --| A0 P04 |-- P5 VCC --| A0 P04 |-- P13 + SJ1 --| A1 P05 |-- P6 SJ1 --| A1 P05 |-- P14 + SJ2 --| A2 P06 |-- P7 SJ2 --| A2 P06 |-- P15 + | P07 |-- P8 | P07 |-- P16 + | | | | + | P10 |-- P25 | P10 |-- P17 + | P11 |-- P26 | P11 |-- P18 + | P12 |-- P27 | P12 |-- P19 + | P13 |-- P28 | P13 |-- P20 + | P14 |-- P29 | P14 |-- P21 + | P15 |-- P30 | P15 |-- P22 + | P16 |-- P31 | P16 |-- P23 + | P17 |-- P32 | P17 |-- P24 + `----------' `----------' +*/ + +#define EXP_COUNT 4 +#define EXP_ADDR(n) ((0x20+(n))<<1) +#define EXP_OUTPUT 0 +#define EXP_INPUT 1 +#define EXP_PORT_COUNT 2 +#define EXP_PIN_PER_PORT 8 +enum { + EXP_COMM_INPUT_0 = 0, + EXP_COMM_INPUT_1, + EXP_COMM_OUTPUT_0, + EXP_COMM_OUTPUT_1, + EXP_COMM_INVERSION_0, + EXP_COMM_INVERSION_1, + EXP_COMM_CONFIG_0, + EXP_COMM_CONFIG_1 +}; +#ifndef KIMERA_CORE +#define PX_TO_EXP(x) (((x)>>5<<1)+((((x)>>3)&1)^(((x)>>4)&1))) +#define PX_TO_PORT(x) (((x)>>4)&1) +#else +#define PX_TO_EXP(x) ((x)>>4) +#define PX_TO_PORT(x) (((x)>>3)&1) +#endif +#define PX_TO_PIN(x) ((x)&7) +#define PX_COUNT (EXP_PIN_PER_PORT * EXP_PORT_COUNT * EXP_COUNT) + +#ifdef KIMERA_C +const uint16_t PROGMEM dummy[] = { +}; +#endif + +/* Matrix Mapping in EEPROM */ + +#define EECONFIG_ROW_COUNT (uint8_t *)16 +#define EECONFIG_COL_COUNT (uint8_t *)17 +#define EECONFIG_ROW_COL_MAPPING (uint8_t *)18 +#define UNCONFIGURED 0xFF + +enum { + COMBINING_NONE = 0, + COMBINING_COL, + COMBINING_ROW +}; +#define COMBINING_BIT (0x80) + +/* Functions */ + +void kimera_init(void); +void kimera_scan(void); +uint8_t kimera_matrix_rows(void); +uint8_t kimera_matrix_cols(void); +void kimera_read_cols(void); +uint8_t kimera_get_col(uint8_t row, uint8_t col); +matrix_row_t kimera_read_row(uint8_t row); +void kimera_unselect_rows(void); +void kimera_select_row(uint8_t row); + +#endif diff --git a/keyboard/kimera/led.c b/keyboard/kimera/led.c new file mode 100644 index 00000000..1b6f6a0b --- /dev/null +++ b/keyboard/kimera/led.c @@ -0,0 +1,56 @@ +/* +Copyright 2014 Kai Ryu + +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 . +*/ + +#include +#include "stdint.h" +#include "led.h" +#include "kimera.h" + +#ifndef LEDMAP_ENABLE + +void led_set(uint8_t usb_led) +{ + if (usb_led & (1< + +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 . +*/ + +#include +#include "ledmap.h" +#include "kimera.h" + +#ifdef LEDMAP_ENABLE + +static const uint16_t ledmaps[LED_COUNT] PROGMEM = { + [0] = LEDMAP_NUM_LOCK, // LED1 + [1] = LEDMAP_CAPS_LOCK, // LED2 + [2] = LEDMAP_SCROLL_LOCK, // LED3 + [3] = LEDMAP_BACKLIGHT, // LED4 +}; + +ledmap_t ledmap_get_code(uint8_t index) +{ + return (ledmap_t) { .code = pgm_read_word(&ledmaps[index]) }; +} + +void ledmap_led_init(void) +{ + LED1_DDR |= (1< +#include +#include + +void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds) +{ + ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); +} + +void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask) +{ + ws2812_DDRREG |= pinmask; // Enable DDR + ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask); + _delay_us(50); +} + +void ws2812_sendarray(uint8_t *data,uint16_t datlen) +{ + ws2812_sendarray_mask(data,datlen,_BV(ws2812_pin)); +} + +/* + This routine writes an array of bytes with RGB values to the Dataout pin + using the fast 800kHz clockless WS2811/2812 protocol. +*/ + +// Timing in ns +#define w_zeropulse 350 +#define w_onepulse 900 +#define w_totalperiod 1250 + +// Fixed cycles used by the inner loop +#define w_fixedlow 2 +#define w_fixedhigh 4 +#define w_fixedtotal 8 + +// Insert NOPs to match the timing, if possible +#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000) +#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000) +#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000) + +// w1 - nops between rising edge and falling edge - low +#define w1 (w_zerocycles-w_fixedlow) +// w2 nops between fe low and fe high +#define w2 (w_onecycles-w_fixedhigh-w1) +// w3 nops to complete loop +#define w3 (w_totalcycles-w_fixedtotal-w1-w2) + +#if w1>0 + #define w1_nops w1 +#else + #define w1_nops 0 +#endif + +// The only critical timing parameter is the minimum pulse length of the "0" +// Warn or throw error if this timing can not be met with current F_CPU settings. +#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000) +#if w_lowtime>550 + #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" +#elif w_lowtime>450 + #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." + #warning "Please consider a higher clockspeed, if possible" +#endif + +#if w2>0 +#define w2_nops w2 +#else +#define w2_nops 0 +#endif + +#if w3>0 +#define w3_nops w3 +#else +#define w3_nops 0 +#endif + +#define w_nop1 "nop \n\t" +#define w_nop2 "rjmp .+0 \n\t" +#define w_nop4 w_nop2 w_nop2 +#define w_nop8 w_nop4 w_nop4 +#define w_nop16 w_nop8 w_nop8 + +void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi) +{ + uint8_t curbyte,ctr,masklo; + uint8_t sreg_prev; + + masklo =~maskhi&ws2812_PORTREG; + maskhi |= ws2812_PORTREG; + sreg_prev=SREG; + cli(); + + while (datlen--) { + curbyte=*data++; + + asm volatile( + " ldi %0,8 \n\t" + "loop%=: \n\t" + " out %2,%3 \n\t" // '1' [01] '0' [01] - re +#if (w1_nops&1) +w_nop1 +#endif +#if (w1_nops&2) +w_nop2 +#endif +#if (w1_nops&4) +w_nop4 +#endif +#if (w1_nops&8) +w_nop8 +#endif +#if (w1_nops&16) +w_nop16 +#endif + " sbrs %1,7 \n\t" // '1' [03] '0' [02] + " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low + " lsl %1 \n\t" // '1' [04] '0' [04] +#if (w2_nops&1) + w_nop1 +#endif +#if (w2_nops&2) + w_nop2 +#endif +#if (w2_nops&4) + w_nop4 +#endif +#if (w2_nops&8) + w_nop8 +#endif +#if (w2_nops&16) + w_nop16 +#endif + " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high +#if (w3_nops&1) +w_nop1 +#endif +#if (w3_nops&2) +w_nop2 +#endif +#if (w3_nops&4) +w_nop4 +#endif +#if (w3_nops&8) +w_nop8 +#endif +#if (w3_nops&16) +w_nop16 +#endif + + " dec %0 \n\t" // '1' [+2] '0' [+2] + " brne loop%=\n\t" // '1' [+3] '0' [+4] + : "=&d" (ctr) + : "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo) + ); + } + + SREG=sreg_prev; +} diff --git a/keyboard/kimera/light_ws2812.h b/keyboard/kimera/light_ws2812.h new file mode 100644 index 00000000..bc2c4e86 --- /dev/null +++ b/keyboard/kimera/light_ws2812.h @@ -0,0 +1,63 @@ +/* + * light weight WS2812 lib include + * + * Version 2.0a3 - Jan 18th 2014 + * Author: Tim (cpldcpu@gmail.com) + * + * Please do not change this file! All configuration is handled in "ws2812_config.h" + * + * License: GNU GPL v2 (see License.txt) + + + */ + +#ifndef LIGHT_WS2812_H_ +#define LIGHT_WS2812_H_ + +#include +#include +#include "ws2812_config.h" + +/* + * Structure of the LED array + */ + +struct cRGB { uint8_t g; uint8_t r; uint8_t b; }; + +/* User Interface + * + * Input: + * ledarray: An array of GRB data describing the LED colors + * number_of_leds: The number of LEDs to write + * pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0) + * + * The functions will perform the following actions: + * - Set the data-out pin as output + * - Send out the LED data + * - Wait 50µs to reset the LEDs + */ + +void ws2812_setleds (struct cRGB *ledarray, uint16_t number_of_leds); +void ws2812_setleds_pin(struct cRGB *ledarray, uint16_t number_of_leds,uint8_t pinmask); + +/* + * Old interface / Internal functions + * + * The functions take a byte-array and send to the data output as WS2812 bitstream. + * The length is the number of bytes to send - three per LED. + */ + +void ws2812_sendarray (uint8_t *array,uint16_t length); +void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask); + + +/* + * Internal defines + */ + +#define CONCAT(a, b) a ## b +#define CONCAT_EXP(a, b) CONCAT(a, b) + +#define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port) +#define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port) + +#endif /* LIGHT_WS2812_H_ */ diff --git a/keyboard/kimera/matrix.c b/keyboard/kimera/matrix.c new file mode 100644 index 00000000..752d09ec --- /dev/null +++ b/keyboard/kimera/matrix.c @@ -0,0 +1,286 @@ +/* +Copyright 2014 Kai Ryu + +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 . +*/ + +/* + * scan matrix + */ +#include +#include +#include +#include +#include "print.h" +#include "debug.h" +#include "util.h" +#include "matrix.h" +#include "i2c_wrapper.h" +#include "kimera.h" +#include "keymap_in_eeprom.h" +#include "timer.h" + + +#ifndef DEBOUNCE +# define DEBOUNCE 5 +#endif + +/* matrix state(1:on, 0:off) */ +static matrix_row_t matrix[MATRIX_ROWS]; + +#define IMPROVED_DEBOUNCE 1 + +#if IMPROVED_DEBOUNCE +#define DEBOUNCE_MASK ((1 << DEBOUNCE) - 1) +static uint8_t matrix_current_row; +static uint16_t matrix_row_timestamp[MATRIX_ROWS]; +static uint8_t matrix_debouncing[MATRIX_ROWS][MATRIX_COLS]; +#else +static uint8_t debouncing = DEBOUNCE; +static matrix_row_t matrix_debouncing[MATRIX_ROWS]; +#endif + +static uint16_t kimera_scan_timestamp; + +inline +uint8_t matrix_rows(void) +{ + return kimera_matrix_rows(); +} + +inline +uint8_t matrix_cols(void) +{ + return kimera_matrix_cols(); +} + +void matrix_init(void) +{ + // disable JTAG + MCUCR = (1<= 1000) { + xprintf("Scan, %u\n", kimera_scan_timestamp); + kimera_scan_timestamp = timer_read(); + kimera_scan(); + } + +#if IMPROVED_DEBOUNCE + uint16_t elapsed = timer_elapsed(matrix_row_timestamp[matrix_current_row]); + if (elapsed >= 1) { + matrix_row_timestamp[matrix_current_row] = timer_read(); + kimera_select_row(matrix_current_row); + _delay_us(30); + kimera_read_cols(); + for (uint8_t i = 0; i < matrix_cols(); i++) { + uint8_t *debounce = &matrix_debouncing[matrix_current_row][i]; + uint8_t col = kimera_get_col(matrix_current_row, i); + uint8_t count = elapsed; + do { + *debounce <<= 1; + *debounce |= col; + } while (--count); + matrix_row_t *row = &matrix[matrix_current_row]; + matrix_row_t mask = ((matrix_row_t)1 << i); + switch (*debounce & DEBOUNCE_MASK) { + case DEBOUNCE_MASK: +#if DEBOUNCE > 1 + case (DEBOUNCE_MASK >> 1): +#if DEBOUNCE > 2 + case (DEBOUNCE_MASK >> 2): +#if DEBOUNCE > 3 + case (DEBOUNCE_MASK >> 3): +#if DEBOUNCE > 4 + case (DEBOUNCE_MASK >> 4): +#if DEBOUNCE > 5 + case (DEBOUNCE_MASK >> 5): +#if DEBOUNCE > 6 + case (DEBOUNCE_MASK >> 6): +#if DEBOUNCE > 7 + case (DEBOUNCE_MASK >> 7): +#if DEBOUNCE > 8 + case (DEBOUNCE_MASK >> 8): +#if DEBOUNCE > 9 + case (DEBOUNCE_MASK >> 9): +#if DEBOUNCE > 10 + case (DEBOUNCE_MASK >> 10): +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif + if ((*row & mask) == 0) { + *row |= mask; + } + break; +#if DEBOUNCE > 1 + case ((DEBOUNCE_MASK << 1) & DEBOUNCE_MASK): +#if DEBOUNCE > 2 + case ((DEBOUNCE_MASK << 2) & DEBOUNCE_MASK): +#if DEBOUNCE > 3 + case ((DEBOUNCE_MASK << 3) & DEBOUNCE_MASK): +#if DEBOUNCE > 4 + case ((DEBOUNCE_MASK << 4) & DEBOUNCE_MASK): +#if DEBOUNCE > 5 + case ((DEBOUNCE_MASK << 5) & DEBOUNCE_MASK): +#if DEBOUNCE > 6 + case ((DEBOUNCE_MASK << 6) & DEBOUNCE_MASK): +#if DEBOUNCE > 7 + case ((DEBOUNCE_MASK << 7) & DEBOUNCE_MASK): +#if DEBOUNCE > 8 + case ((DEBOUNCE_MASK << 8) & DEBOUNCE_MASK): +#if DEBOUNCE > 9 + case ((DEBOUNCE_MASK << 9) & DEBOUNCE_MASK): +#if DEBOUNCE > 10 + case ((DEBOUNCE_MASK << 10) & DEBOUNCE_MASK): +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif + break; + case 0: + if ((*row & mask) != 0) { + *row &= ~mask; + } + break; + default: + debug("bounce!: "); + debug_bin8(*debounce & DEBOUNCE_MASK); + debug("\n"); + break; + } + } + kimera_unselect_rows(); + } + + matrix_current_row++; + if (matrix_current_row >= matrix_rows()) { + matrix_current_row = 0; + } +#else + for (uint8_t i = 0; i < matrix_rows(); i++) { + kimera_select_row(i); + _delay_us(30); // without this wait read unstable value. + matrix_row_t cols = kimera_read_row(i); + if (matrix_debouncing[i] != cols) { + matrix_debouncing[i] = cols; + if (debouncing) { + debug("bounce!: "); debug_hex(debouncing); debug("\n"); + } + debouncing = DEBOUNCE; + } + kimera_unselect_rows(); + } + + if (debouncing) { + if (--debouncing) { + _delay_ms(1); + } else { + for (uint8_t i = 0; i < matrix_rows(); i++) { + matrix[i] = matrix_debouncing[i]; + } + } + } +#endif + + return 1; +} + +#if IMPROVED_DEBOUNCE +#else +bool matrix_is_modified(void) +{ + if (debouncing) return false; + return true; +} +#endif + +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & ((matrix_row_t)1< + +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 . +*/ + +#include +#include +#include "softpwm_led.h" +#include "backlight.h" +#include "rgb.h" +#include "light_ws2812.h" +#include "debug.h" + +#ifdef RGB_LED_ENABLE + +volatile static uint8_t rgb_fading_enable = 0; +static rgb_config_t rgb_config; +static struct cRGB rgb_color[RGB_LED_COUNT]; +static uint16_t rgb_hue = 0; +static uint8_t rgb_saturation = 255; +static uint8_t rgb_brightness = 16; +static uint8_t rgb_rainbow = 0; + +extern backlight_config_t backlight_config; +extern uint8_t backlight_brightness; + +static void rgb_write_config(void); +static void rgb_read_config(void); +static void rgb_set_level(uint8_t level); +static void rgb_refresh(void); +static void hue_to_rgb(uint16_t hue, struct cRGB *rgb); +static void hsb_to_rgb(uint16_t hue, uint8_t saturation, uint8_t brightness, struct cRGB *rgb); + +void rgb_init(void) +{ + rgb_read_config(); + if (rgb_config.raw == RGB_UNCONFIGURED) { + rgb_config.enable = 0; + rgb_config.level = RGB_OFF; + rgb_write_config(); + } + if (rgb_config.enable) { + rgb_set_level(rgb_config.level); + } +} + +void rgb_read_config(void) +{ + rgb_config.raw = eeprom_read_byte(EECONFIG_RGB); +} + +void rgb_write_config(void) +{ + eeprom_write_byte(EECONFIG_RGB, rgb_config.raw); +} + +void rgb_toggle(void) +{ + if (rgb_config.enable) { + rgb_off(); + } + else { + rgb_on(); + } +} + +void rgb_on(void) +{ + rgb_config.enable = 1; + rgb_set_level(rgb_config.level); + rgb_write_config(); +} + +void rgb_off(void) +{ + rgb_config.enable = 0; + rgb_set_level(RGB_OFF); + rgb_write_config(); +} + +void rgb_decrease(void) +{ + if(rgb_config.level > 0) { + rgb_config.level--; + rgb_config.enable = (rgb_config.level != 0); + rgb_write_config(); + } + rgb_set_level(rgb_config.level); +} + +void rgb_increase(void) +{ + if(rgb_config.level < RGB_LEVELS) { + rgb_config.level++; + rgb_config.enable = 1; + rgb_write_config(); + } + rgb_set_level(rgb_config.level); +} + +void rgb_step(void) +{ + rgb_config.level++; + if(rgb_config.level > RGB_LEVELS) + { + rgb_config.level = 0; + } + rgb_config.enable = (rgb_config.level != 0); + rgb_set_level(rgb_config.level); +} + +void rgb_set_level(uint8_t level) +{ + dprintf("RGB Level: %d\n", level); + if (level <= RGB_WHITE) { + rgb_fading_enable = 0; + rgb_rainbow = 0; + if (level == RGB_OFF) { + rgb_brightness = 0; + } + else { + if (level == RGB_WHITE) { + rgb_saturation = 0; + } + else { + rgb_hue = (level - 1) * 128; + rgb_saturation = 255; + } + if (backlight_config.enable) { + if (backlight_config.level >= 1 && backlight_config.level <= 3) { + rgb_brightness = backlight_brightness; + } + } + else { + rgb_brightness = 16; + } + } + rgb_refresh(); + } + else { + rgb_saturation = 255; + rgb_fading_enable = 1; + rgb_rainbow = (level >= RGB_RAINBOW) ? 1 : 0; + } +} + +void rgb_set_brightness(uint8_t brightness) +{ + if (rgb_config.enable) { + rgb_brightness = brightness; + rgb_refresh(); + } +} + +void rgb_refresh(void) +{ + struct cRGB rgb; + uint16_t hue; + uint8_t i; + if (rgb_rainbow) { + for (i = 0; i < RGB_LED_COUNT; i++) { + hue = rgb_hue + (768 / RGB_LED_COUNT) * i; + hsb_to_rgb(hue, rgb_saturation, rgb_brightness, &rgb); + rgb_color[i] = rgb; + } + } + else { + hsb_to_rgb(rgb_hue, rgb_saturation, rgb_brightness, &rgb); + for (i = 0; i < RGB_LED_COUNT; i++) { + rgb_color[i] = rgb; + } + } + /* xprintf("R%d G%d B%d\n", rgb_color[0].r, rgb_color[0].g, rgb_color[0].b); */ + ws2812_setleds(rgb_color, RGB_LED_COUNT); +} + +void hue_to_rgb(uint16_t hue, struct cRGB *rgb) +{ + uint8_t hi = hue / 60; + uint16_t f = (hue % 60) * 425 / 100; + uint8_t q = 255 - f; + switch (hi) { + case 0: rgb->r = 255; rgb->g = f; rgb->b = 0; break; + case 1: rgb->r = q; rgb->g = 255; rgb->b = 0; break; + case 2: rgb->r = 0; rgb->g = 255; rgb->b = f; break; + case 3: rgb->r = 0; rgb->g = q; rgb->b = 255; break; + case 4: rgb->r = f; rgb->g = 0; rgb->b = 255; break; + case 5: rgb->r = 255; rgb->g = 0; rgb->b = q; break; + } +} + +/* + * original code: https://blog.adafruit.com/2012/03/14/constant-brightness-hsb-to-rgb-algorithm/ + */ +void hsb_to_rgb(uint16_t hue, uint8_t saturation, uint8_t brightness, struct cRGB *rgb) +{ + uint8_t temp[5]; + uint8_t n = (hue >> 8) % 3; + uint8_t x = ((((hue & 255) * saturation) >> 8) * brightness) >> 8; + uint8_t s = ((256 - saturation) * brightness) >> 8; + temp[0] = temp[3] = s; + temp[1] = temp[4] = x + s; + temp[2] = brightness - x; + rgb->r = temp[n + 2]; + rgb->g = temp[n + 1]; + rgb->b = temp[n]; +} + +void rgb_fading(void) +{ + static uint8_t step = 0; + static uint16_t hue = 0; + if (rgb_fading_enable) { + if (++step > rgb_fading_enable) { + step = 0; + rgb_hue = hue; + rgb_refresh(); + if (++hue >= 768) { + hue = 0; + } + } + } +} + +#endif diff --git a/keyboard/kimera/rgb.h b/keyboard/kimera/rgb.h new file mode 100644 index 00000000..bde1db75 --- /dev/null +++ b/keyboard/kimera/rgb.h @@ -0,0 +1,60 @@ +/* +Copyright 2016 Kai Ryu + +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 . +*/ + +#ifndef RGB_H +#define RGB_H + +#include +#include + +typedef union { + uint8_t raw; + struct { + uint8_t level :7; + bool enable :1; + }; +} rgb_config_t; + +enum { + RGB_OFF = 0, + RGB_RED, + RGB_YELLOW, + RGB_GREEN, + RGB_CYAN, + RGB_BLUE, + RGB_MAGENTA, + RGB_WHITE, + RGB_FADE, + RGB_RAINBOW, + RGB_LEVELS = RGB_RAINBOW +}; + +#define EECONFIG_RGB (uint8_t *)15 +#define RGB_UNCONFIGURED 0xFF +#define RGB_LED_COUNT 16 + +void rgb_init(void); +void rgb_toggle(void); +void rgb_on(void); +void rgb_off(void); +void rgb_decrease(void); +void rgb_increase(void); +void rgb_step(void); +void rgb_set_brightness(uint8_t brightness); +void rgb_fading(void); + +#endif diff --git a/keyboard/kimera/twimaster.c b/keyboard/kimera/twimaster.c new file mode 100644 index 00000000..d55386c5 --- /dev/null +++ b/keyboard/kimera/twimaster.c @@ -0,0 +1,205 @@ +/************************************************************************* + * Title: I2C master library using hardware TWI interface + * Author: Peter Fleury 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 +#include + +#include +#include "debug.h" + + +/* define CPU frequency in Mhz here if not defined in Makefile */ +#ifndef F_CPU +#define F_CPU 4000000UL +#endif + +/* I2C clock in Hz */ +#define SCL_CLOCK 400000L + +volatile uint8_t i2c_force_stop = 0; +#define CHECK_FORCE_STOP() if(i2c_force_stop){i2c_force_stop=0;break;} + +/************************************************************************* + Initialization of the I2C bus interface. Need to be called only once + *************************************************************************/ +void i2c_init(void) +{ + /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ + + TWSR = 0; /* no prescaler */ + TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* 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<