From d5a709a0578789f860e646cf1e2861522396392f Mon Sep 17 00:00:00 2001 From: Kai Ryu Date: Thu, 25 Aug 2016 18:27:47 +0900 Subject: [PATCH] ergodone: Initial working version --- keyboard/ergodone/Makefile | 160 +++++++++++ keyboard/ergodone/Makefile.pjrc | 127 +++++++++ keyboard/ergodone/backlight.c | 208 +++++++++++++++ keyboard/ergodone/config.h | 100 +++++++ keyboard/ergodone/expander.c | 137 ++++++++++ keyboard/ergodone/expander.h | 65 +++++ keyboard/ergodone/i2cmaster.h | 178 +++++++++++++ keyboard/ergodone/keymap_common.c | 53 ++++ keyboard/ergodone/keymap_common.h | 43 +++ keyboard/ergodone/keymap_default.c | 107 ++++++++ keyboard/ergodone/led.c | 55 ++++ keyboard/ergodone/ledmap.c | 88 ++++++ keyboard/ergodone/matrix.c | 415 +++++++++++++++++++++++++++++ keyboard/ergodone/twimaster.c | 258 ++++++++++++++++++ 14 files changed, 1994 insertions(+) create mode 100644 keyboard/ergodone/Makefile create mode 100644 keyboard/ergodone/Makefile.pjrc create mode 100644 keyboard/ergodone/backlight.c create mode 100644 keyboard/ergodone/config.h create mode 100644 keyboard/ergodone/expander.c create mode 100644 keyboard/ergodone/expander.h create mode 100644 keyboard/ergodone/i2cmaster.h create mode 100644 keyboard/ergodone/keymap_common.c create mode 100644 keyboard/ergodone/keymap_common.h create mode 100644 keyboard/ergodone/keymap_default.c create mode 100644 keyboard/ergodone/led.c create mode 100644 keyboard/ergodone/ledmap.c create mode 100644 keyboard/ergodone/matrix.c create mode 100644 keyboard/ergodone/twimaster.c diff --git a/keyboard/ergodone/Makefile b/keyboard/ergodone/Makefile new file mode 100644 index 00000000..a97aa28d --- /dev/null +++ b/keyboard/ergodone/Makefile @@ -0,0 +1,160 @@ +#---------------------------------------------------------------------------- +# 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 = ergodone_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 \ + expander.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 += -DVER_$(REV) +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/ergodone/Makefile.pjrc b/keyboard/ergodone/Makefile.pjrc new file mode 100644 index 00000000..f597b2a4 --- /dev/null +++ b/keyboard/ergodone/Makefile.pjrc @@ -0,0 +1,127 @@ +#---------------------------------------------------------------------------- +# 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 = ergodone_pjrc + +# 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 \ + expander.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 + +# PCB Version +ifdef VER + OPT_DEFS += -DVER_$(REV) +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 + + +# Search Path +VPATH += $(TARGET_DIR) +VPATH += $(TMK_DIR) + +include $(TMK_DIR)/protocol/pjrc.mk +include $(TMK_DIR)/common.mk +include $(TMK_DIR)/rules.mk diff --git a/keyboard/ergodone/backlight.c b/keyboard/ergodone/backlight.c new file mode 100644 index 00000000..297e5819 --- /dev/null +++ b/keyboard/ergodone/backlight.c @@ -0,0 +1,208 @@ +/* +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 "backlight.h" +#ifdef SOFTPWM_LED_ENABLE +#include "softpwm_led.h" +#else +#include "breathing_led.h" +#endif +#include "action.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 +#endif +} + +#ifndef LEDMAP_ENABLE +#ifdef SOFTPWM_LED_ENABLE +void softpwm_led_init(void) +{ +} + +void softpwm_led_on(uint8_t index) +{ +} + +void softpwm_led_off(uint8_t index) +{ +} +#endif +#endif + +#ifdef SOFTPWM_LED_ENABLE +#ifdef FADING_LED_ENABLE +void action_keyevent(keyevent_t event) +{ + if (backlight_config.enable) { + if (backlight_config.level == 7) { + if (event.pressed) { + fading_led_set_delay_all(64); + softpwm_led_decrease_all(32); + } + } + if (backlight_config.level == 8) { + if (event.pressed) { + fading_led_set_delay_all(64); + softpwm_led_increase_all(32); + } + } + } +} +#endif +#endif + +#endif diff --git a/keyboard/ergodone/config.h b/keyboard/ergodone/config.h new file mode 100644 index 00000000..941f4325 --- /dev/null +++ b/keyboard/ergodone/config.h @@ -0,0 +1,100 @@ +/* +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 CONFIG_H +#define CONFIG_H + + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0x1209 +#define PRODUCT_ID 0x2333 +#ifdef VER_PROTOTYPE +#define DEVICE_VER 0x0300 +#else +#define DEVICE_VER 0x0301 +#endif +#define MANUFACTURER K.T.E.C. +#define PRODUCT ErgoDone +#define DESCRIPTION t.m.k. keyboard firmware for ErgoDone + +/* key matrix size */ +#define MATRIX_ROWS 6 +#define MATRIX_COLS 14 + +/* keymap in eeprom */ +#define FN_ACTIONS_COUNT 32 +#define KEYMAPS_COUNT 3 +#define EECONFIG_KEYMAP_IN_EEPROM 17 + +/* 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 + +/* number of leds */ +#define LED_COUNT 5 + +/* 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)) \ +) + +/* for debug */ +//#define SUART_OUT_PORT PORTF +//#define SUART_OUT_BIT 5 +//#define SUART_IN_PIN PINF +//#define SUART_IN_BIT 6 + +/* + * 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/ergodone/expander.c b/keyboard/ergodone/expander.c new file mode 100644 index 00000000..ef9be510 --- /dev/null +++ b/keyboard/ergodone/expander.c @@ -0,0 +1,137 @@ +/* +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 "action.h" +#include "i2cmaster.h" +#include "expander.h" +#include "debug.h" + +static uint8_t expander_status = 0; +static uint8_t expander_input = 0; + +void expander_config(void); +uint8_t expander_write(uint8_t reg, uint8_t data); +uint8_t expander_read(uint8_t reg, uint8_t *data); + +void expander_init(void) +{ + i2c_init(); + expander_scan(); +} + +void expander_scan(void) +{ + dprintf("expander status: %d ... ", expander_status); + uint8_t ret = i2c_start(EXPANDER_ADDR | I2C_WRITE); + if (ret == 0) { + i2c_stop(); + if (expander_status == 0) { + dprintf("attached\n"); + expander_status = 1; + expander_config(); + clear_keyboard(); + } + } + else { + if (expander_status == 1) { + dprintf("detached\n"); + expander_status = 0; + clear_keyboard(); + } + } + dprintf("%d\n", expander_status); +} + +void expander_read_cols(void) +{ + expander_read(EXPANDER_REG_GPIOA, &expander_input); +} + +uint8_t expander_get_col(uint8_t col) +{ + if (col > 4) { + col++; + } + return expander_input & (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 EXPANDER_H +#define EXPANDER_H + +#include +#include "matrix.h" + +#define MCP23017 +#define MCP23017_A0 0 +#define MCP23017_A1 0 +#define MCP23017_A2 0 + +#ifdef MCP23017 +#define EXPANDER_ADDR ((0x20|(MCP23017_A0<<0)|(MCP23017_A1<<1)|(MCP23017_A2<<2)) << 1) +enum EXPANDER_REG_BANK0 { + EXPANDER_REG_IODIRA = 0, + EXPANDER_REG_IODIRB, + EXPANDER_REG_IPOLA, + EXPANDER_REG_IPOLB, + EXPANDER_REG_GPINTENA, + EXPANDER_REG_GPINTENB, + EXPANDER_REG_DEFVALA, + EXPANDER_REG_DEFVALB, + EXPANDER_REG_INTCONA, + EXPANDER_REG_INTCONB, + EXPANDER_REG_IOCONA, + EXPANDER_REG_IOCONB, + EXPANDER_REG_GPPUA, + EXPANDER_REG_GPPUB, + EXPANDER_REG_INTFA, + EXPANDER_REG_INTFB, + EXPANDER_REG_INTCAPA, + EXPANDER_REG_INTCAPB, + EXPANDER_REG_GPIOA, + EXPANDER_REG_GPIOB, + EXPANDER_REG_OLATA, + EXPANDER_REG_OLATB +}; +#endif + +void expander_init(void); +void expander_scan(void); +void expander_read_cols(void); +uint8_t expander_get_col(uint8_t col); +matrix_row_t expander_read_row(void); +void expander_unselect_rows(void); +void expander_select_row(uint8_t row); + +#endif diff --git a/keyboard/ergodone/i2cmaster.h b/keyboard/ergodone/i2cmaster.h new file mode 100644 index 00000000..3917b9e6 --- /dev/null +++ b/keyboard/ergodone/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/ergodone/keymap_common.c b/keyboard/ergodone/keymap_common.c new file mode 100644 index 00000000..f956cc4c --- /dev/null +++ b/keyboard/ergodone/keymap_common.c @@ -0,0 +1,53 @@ +/* +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 "keymap.h" +#include "keymap_in_eeprom.h" +#include "keymap_common.h" + +/* translates key to keycode */ +uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key) +{ + /* xprintf("Layer: %d, Row: %d, Col: %d, ", layer, key.row, key.col); */ +#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/ergodone/keymap_common.h b/keyboard/ergodone/keymap_common.h new file mode 100644 index 00000000..1bab9b51 --- /dev/null +++ b/keyboard/ergodone/keymap_common.h @@ -0,0 +1,43 @@ +/* +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 + +extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; +extern const uint16_t fn_actions[]; + +#define KEYMAP( \ + K0A, K0B, K0C, K0D, K0E, K0F, K0G, K0H, K0J, K0K, K0L, K0M, K0N, K0P, \ + K1A, K1B, K1C, K1D, K1E, K1F, K1G, K1H, K1J, K1K, K1L, K1M, K1N, K1P, \ + K2A, K2B, K2C, K2D, K2E, K2F, K2J, K2K, K2L, K2M, K2N, K2P, \ + K3A, K3B, K3C, K3D, K3E, K3F, K3G, K3H, K3J, K3K, K3L, K3M, K3N, K3P, \ + K4A, K4B, K4C, K4D, K4E, K4K, K4L, K4M, K4N, K4P, \ + K5F, K5G, K5H, K5J, \ + K5E, K5K, \ + K5D, K5C, K5B, K5N, K5M, K5L \ +) { \ + { KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F, KC_##K0G, KC_##K0H, KC_##K0J, KC_##K0K, KC_##K0L, KC_##K0M, KC_##K0N, KC_##K0P }, \ + { KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_##K1F, KC_##K1G, KC_##K1H, KC_##K1J, KC_##K1K, KC_##K1L, KC_##K1M, KC_##K1N, KC_##K1P }, \ + { KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F, KC_NO, KC_NO, KC_##K2J, KC_##K2K, KC_##K2L, KC_##K2M, KC_##K2N, KC_##K2P }, \ + { KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F, KC_##K3G, KC_##K3H, KC_##K3J, KC_##K3K, KC_##K3L, KC_##K3M, KC_##K3N, KC_##K3P }, \ + { KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_NO, KC_NO, KC_NO, KC_NO, KC_##K4K, KC_##K4L, KC_##K4M, KC_##K4N, KC_##K4P }, \ + { KC_NO, KC_##K5B, KC_##K5C, KC_##K5D, KC_##K5E, KC_##K5F, KC_##K5G, KC_##K5H, KC_##K5J, KC_##K5K, KC_##K5L, KC_##K5M, KC_##K5N, KC_NO } \ +} + +#endif diff --git a/keyboard/ergodone/keymap_default.c b/keyboard/ergodone/keymap_default.c new file mode 100644 index 00000000..5e566b97 --- /dev/null +++ b/keyboard/ergodone/keymap_default.c @@ -0,0 +1,107 @@ +/* +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 "keycode.h" +#include "action.h" +#include "keymap_common.h" + +// Default +#ifdef KEYMAP_SECTION_ENABLE +const uint8_t keymaps[KEYMAPS_COUNT][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = { +#else +const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { +#endif + /* Keymap 0: Default Layer + * ,-----------------------------. ,-----------------------------. + * | `| 1| 2| 3| 4| 5| -| | =| 6| 7| 8| 9| 0| '| + * |-----+---+---+---+---+-------| |---+---+---+---+---+---+-----| + * |Tab | Q| W| E| R| T| | | | Y| U| I| O| P| \| + * |-----+---+---+---+---|---| Fn| | Fn|---+---+---+---+---+-----| + * |Caps | A| S| D| F| G|---| |---| H| J| K| L| ;|Retur| + * |-----+---+---+---+---|---| | | |---+---+---+---+---+-----| + * |Shift| Z| X| C| V| B| Fn| | Fn| N| M| ,| .| /|Shift| + * `-----+---+---+---+---+-------' `-------+---+---+---+---+-----' + * |Ctr|Gui|Alt|Lef|Rig| ,-------. ,-------. | Up|Dow| [| ]|Ctr| + * `-------------------' |Esc|Ins| |Del|Alt| `-------------------' + * ,---+---+---| |---+---+---. + * | | |Hom| |PgU| | | + * |Spc|BS |---| |---|Tab|Ent| + * | | |End| |PgD| | | + * `-----------' `-----------' + */ + KEYMAP( + GRV, 1, 2, 3, 4, 5, MINS, EQL, 6, 7, 8, 9, 0, QUOT, \ + TAB, Q, W, E, R, T, FN0, FN1, Y, U, I, O, P, BSLS, \ + CAPS,A, S, D, F, G, H, J, K, L, SCLN,ENT, \ + LSFT,Z, X, C, V, B, FN2, FN3, N, M, COMM,DOT, SLSH,RSFT, \ + LCTL,LGUI,LALT,LEFT,RGHT, UP, DOWN,LBRC,RBRC,RCTL, \ + ESC, INS, DEL, RALT, \ + HOME, PGUP, \ + SPC, BSPC,END, PGDN,TAB, ENT ), + /* Keymap 1: Fn Layer + * ,-----------------------------. ,-----------------------------. + * | |F1 |F2 |F3 |F4 |F5 | | | |F6 |F7 |F8 |F9 |F10| | + * |-----+---+---+---+---+-------| |---+---+---+---+---+---+-----| + * | | | | | | | | | | | | | | | | + * |-----+---+---+---+---|---| | | |---+---+---+---+---+-----| + * | | | | | | |---| |---| | | | | | | + * |-----+---+---+---+---|---| | | |---+---+---+---+---+-----| + * | | | | | | | | | | | | | | | | + * `-----+---+---+---+---+-------' `-------+---+---+---+---+-----' + * | | | | | | ,-------. ,-------. | | | | | | + * `-------------------' | | | | | | `-------------------' + * ,---+---+---| |---+---+---. + * | | | | | | | | + * | | |---| |---| | | + * | | | | | | | | + * `-----------' `-----------' + */ + KEYMAP( + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS,TRNS,TRNS, \ + TRNS,TRNS, TRNS,TRNS, \ + TRNS, TRNS, \ + TRNS,TRNS,TRNS, TRNS,TRNS,TRNS ) +}; + +/* + * 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 + [0] = ACTION_LAYER_MOMENTARY(1), + [1] = ACTION_LAYER_MOMENTARY(1), + [2] = ACTION_LAYER_MOMENTARY(1), + [3] = ACTION_LAYER_MOMENTARY(1) +}; + +#ifdef KEYMAP_IN_EEPROM_ENABLE +uint16_t keys_count(void) { + return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_ROWS * MATRIX_COLS; +} + +uint16_t fn_actions_count(void) { + return sizeof(fn_actions) / sizeof(fn_actions[0]); +} +#endif diff --git a/keyboard/ergodone/led.c b/keyboard/ergodone/led.c new file mode 100644 index 00000000..22b32d61 --- /dev/null +++ b/keyboard/ergodone/led.c @@ -0,0 +1,55 @@ +/* +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 "stdint.h" +#include "led.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" + +#ifdef LEDMAP_ENABLE + +static const uint16_t ledmaps[LED_COUNT] PROGMEM = { + [0] = LEDMAP_NUM_LOCK, // LED_A - PB5 + [1] = LEDMAP_CAPS_LOCK, // LED_B - PB6 + [2] = LEDMAP_SCROLL_LOCK, // LED_C - PB3 + [3] = LEDMAP_LAYER(1), // RX - PB0 + [4] = LEDMAP_LAYER(2), // TX - PD5 +}; + +ledmap_t ledmap_get_code(uint8_t index) +{ + return (ledmap_t) { .code = pgm_read_word(&ledmaps[index]) }; +} + +void ledmap_led_init(void) +{ + DDRB |= (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 . +*/ + +/* + * scan matrix + */ +#include +#include +#include +#include +#include "debug.h" +#include "util.h" +#include "matrix.h" +#include "expander.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]; +static matrix_row_t read_row(void); +#endif + +static uint16_t matrix_scan_timestamp; + +static void read_cols(void); +static uint8_t get_col(uint8_t col); +static void init_cols(void); +static void unselect_rows(void); +static void select_row(uint8_t row); + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + // disable JTAG + MCUCR = (1<= 1000) { + dprintf("======== 1s task ========\n"); + dprintf("Scan: %u\n", matrix_scan_timestamp); + matrix_scan_timestamp = timer_read(); + expander_scan(); + dprintf("=========================\n"); + } + +#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(); + select_row(matrix_current_row); + _delay_us(30); + read_cols(); + for (uint8_t i = 0; i < matrix_cols(); i++) { + uint8_t *debounce = &matrix_debouncing[matrix_current_row][i]; + uint8_t col = get_col(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; + } + } + 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++) { + select_row(i); + _delay_us(30); // without this wait read unstable value. + matrix_row_t cols = read_row(); + 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]; + } + } + } +#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< 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 +#include "timer.h" +#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 +#define SCL_DURATION (1000000L/SCL_CLOCK)/2 + +volatile uint8_t i2c_force_stop = 0; +#define TIMEOUT 3000 +#define CHECK_FORCE_STOP() if(i2c_force_stop){i2c_force_stop=0;break;} +#define CHECK_TIMEOUT_PRE() \ + uint16_t start; \ + uint8_t once = 1; +#define CHECK_TIMEOUT_PRE2() \ + once = 1; +#define CHECK_TIMEOUT(retval) { \ + if (once) { \ + start = timer_read(); \ + once = 0; \ + } \ + else { \ + if (timer_elapsed(start) >= TIMEOUT) { \ + i2c_forceStop(); \ + return retval; \ + } \ + } \ +} + +static void i2c_forceStop(void); + +/************************************************************************* + 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<