@@ -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 |
@@ -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 |
@@ -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 |
@@ -0,0 +1,236 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include <avr/io.h> | |||
#include <avr/interrupt.h> | |||
#include <avr/pgmspace.h> | |||
#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<<LED4_BIT); | |||
cli(); | |||
TCCR1A |= ((1<<WGM10) | (1<<COM1B1)); | |||
TCCR1B |= ((1<<CS11) | (1<<CS10)); | |||
sei(); | |||
} | |||
#endif | |||
#ifndef SOFTPWM_LED_ENABLE | |||
void backlight_disable(void) | |||
{ | |||
// Turn off PWM | |||
LED4_DDR &= ~(1<<LED4_BIT); | |||
cli(); | |||
TCCR1A &= ~((1<<WGM10) | (1<<COM1B1)); | |||
TCCR1B &= ~((1<<CS11) | (1<<CS10)); | |||
sei(); | |||
LED4_OCR = 0; | |||
} | |||
#endif | |||
void backlight_set(uint8_t level) | |||
{ | |||
#ifdef SOFTPWM_LED_ENABLE | |||
softpwm_enable(); | |||
#endif | |||
#ifdef BREATHING_LED_ENABLE | |||
switch (level) { | |||
case 1: | |||
case 2: | |||
case 3: | |||
#ifdef SOFTPWM_LED_ENABLE | |||
softpwm_led_enable_all(); | |||
#ifdef FADING_LED_ENABLE | |||
fading_led_disable_all(); | |||
#endif | |||
breathing_led_disable_all(); | |||
#else | |||
backlight_enable(); | |||
breathing_led_disable(); | |||
#endif | |||
backlight_brightness = pgm_read_byte(&backlight_table[level]); | |||
#ifdef RGB_LED_ENABLE | |||
rgb_set_brightness(backlight_brightness); | |||
#endif | |||
backlight_set_raw(backlight_brightness); | |||
break; | |||
case 4: | |||
case 5: | |||
case 6: | |||
#ifdef SOFTPWM_LED_ENABLE | |||
softpwm_led_enable_all(); | |||
#ifdef FADING_LED_ENABLE | |||
fading_led_disable_all(); | |||
#endif | |||
breathing_led_enable_all(); | |||
#else | |||
backlight_enable(); | |||
breathing_led_enable(); | |||
#endif | |||
breathing_led_set_duration(6 - level); | |||
break; | |||
#ifdef SOFTPWM_LED_ENABLE | |||
#ifdef FADING_LED_ENABLE | |||
case 7: | |||
softpwm_led_enable_all(); | |||
fading_led_enable_all(); | |||
breathing_led_disable_all(); | |||
fading_led_set_direction_all(FADING_LED_FADE_IN); | |||
fading_led_set_duration(3); | |||
break; | |||
case 8: | |||
softpwm_led_enable_all(); | |||
fading_led_enable_all(); | |||
breathing_led_disable_all(); | |||
fading_led_set_direction_all(FADING_LED_FADE_OUT); | |||
fading_led_set_duration(3); | |||
break; | |||
#endif | |||
#endif | |||
case 0: | |||
default: | |||
#ifdef SOFTPWM_LED_ENABLE | |||
#ifdef FADING_LED_ENABLE | |||
fading_led_disable_all(); | |||
#endif | |||
breathing_led_disable_all(); | |||
backlight_brightness = 0; | |||
backlight_set_raw(backlight_brightness); | |||
softpwm_led_disable_all(); | |||
#else | |||
breathing_led_disable(); | |||
backlight_disable(); | |||
#endif | |||
break; | |||
} | |||
#else | |||
if (level > 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<<LED4_BIT); | |||
} | |||
void softpwm_led_on(uint8_t index) | |||
{ | |||
LED4_PORT |= (1<<LED4_BIT); | |||
} | |||
void softpwm_led_off(uint8_t index) | |||
{ | |||
LED4_PORT &= ~(1<<LED4_BIT); | |||
} | |||
#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 | |||
#ifdef RGB_LED_ENABLE | |||
#ifdef CUSTOM_LED_ENABLE | |||
void softpwm_led_custom(void) | |||
{ | |||
rgb_fading(); | |||
} | |||
void fading_led_custom(uint8_t *value) | |||
{ | |||
rgb_set_brightness(value[0]); | |||
} | |||
void breathing_led_custom(uint8_t *value) | |||
{ | |||
rgb_set_brightness(value[0]); | |||
} | |||
#endif | |||
#endif | |||
#endif | |||
#endif |
@@ -0,0 +1,96 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef CONFIG_H | |||
#define CONFIG_H | |||
/* USB Device descriptor parameter */ | |||
#define VENDOR_ID 0x16c0 | |||
#define PRODUCT_ID 0x27db | |||
#define DEVICE_VER 0x0005 | |||
#define MANUFACTURER [email protected] | |||
#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 |
@@ -0,0 +1,95 @@ | |||
/* | |||
Copyright 2016 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include <avr/interrupt.h> | |||
#include <avr/wdt.h> | |||
#include <util/delay.h> | |||
#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<<PD0); | |||
DDRD &= ~(1<<PD1); | |||
if (!(PIND & (1<<PD1))) { | |||
for (uint8_t i = 0; i < 9; i++) { | |||
PORTD &= ~(1<<PD0); | |||
_delay_us(SCL_DURATION); | |||
PORTD |= (1<<PD0); | |||
_delay_us(SCL_DURATION); | |||
} | |||
} | |||
/* send stop condition */ | |||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | |||
/* escape from loop */ | |||
i2c_force_stop = 1; | |||
} |
@@ -0,0 +1,25 @@ | |||
/* | |||
Copyright 2016 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef I2C_WRAPPER_H | |||
#define I2C_WRAPPER_H | |||
void i2c_wrapper_init(void); | |||
void i2c_wrapper_task(void); | |||
#endif | |||
@@ -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 <[email protected]> http://jump.to/fleury | |||
* File: $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $ | |||
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 | |||
* Target: any AVR device | |||
* Usage: see Doxygen manual | |||
**************************************************************************/ | |||
#ifdef DOXYGEN | |||
/** | |||
@defgroup pfleury_ic2master I2C Master library | |||
@code #include <i2cmaster.h> @endcode | |||
@brief I2C (TWI) Master Software Library | |||
Basic routines for communicating with I2C slave devices. This single master | |||
implementation is limited to one bus master on the I2C bus. | |||
This I2c library is implemented as a compact assembler software implementation of the I2C protocol | |||
which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c). | |||
Since the API for these two implementations is exactly the same, an application can be linked either against the | |||
software I2C implementation or the hardware I2C implementation. | |||
Use 4.7k pull-up resistor on the SDA and SCL pin. | |||
Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module | |||
i2cmaster.S to your target when using the software I2C implementation ! | |||
Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion. | |||
@note | |||
The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted | |||
to GNU assembler and AVR-GCC C call interface. | |||
Replaced the incorrect quarter period delays found in AVR300 with | |||
half period delays. | |||
@author Peter Fleury [email protected] http://jump.to/fleury | |||
@par API Usage Example | |||
The following code shows typical usage of this library, see example test_i2cmaster.c | |||
@code | |||
#include <i2cmaster.h> | |||
#define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet | |||
int main(void) | |||
{ | |||
unsigned char ret; | |||
i2c_init(); // initialize I2C library | |||
// write 0x75 to EEPROM address 5 (Byte Write) | |||
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode | |||
i2c_write(0x05); // write address = 5 | |||
i2c_write(0x75); // write value 0x75 to EEPROM | |||
i2c_stop(); // set stop conditon = release bus | |||
// read previously written value back from EEPROM address 5 | |||
i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode | |||
i2c_write(0x05); // write address = 5 | |||
i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode | |||
ret = i2c_readNak(); // read one byte from EEPROM | |||
i2c_stop(); | |||
for(;;); | |||
} | |||
@endcode | |||
*/ | |||
#endif /* DOXYGEN */ | |||
/**@{*/ | |||
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 | |||
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" | |||
#endif | |||
#include <avr/io.h> | |||
/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */ | |||
#define I2C_READ 1 | |||
/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */ | |||
#define I2C_WRITE 0 | |||
/** | |||
@brief initialize the I2C master interace. Need to be called only once | |||
@param void | |||
@return none | |||
*/ | |||
extern void i2c_init(void); | |||
/** | |||
@brief Terminates the data transfer and releases the I2C bus | |||
@param void | |||
@return none | |||
*/ | |||
extern void i2c_stop(void); | |||
/** | |||
@brief Issues a start condition and sends address and transfer direction | |||
@param addr address and transfer direction of I2C device | |||
@retval 0 device accessible | |||
@retval 1 failed to access device | |||
*/ | |||
extern unsigned char i2c_start(unsigned char addr); | |||
/** | |||
@brief Issues a repeated start condition and sends address and transfer direction | |||
@param addr address and transfer direction of I2C device | |||
@retval 0 device accessible | |||
@retval 1 failed to access device | |||
*/ | |||
extern unsigned char i2c_rep_start(unsigned char addr); | |||
/** | |||
@brief Issues a start condition and sends address and transfer direction | |||
If device is busy, use ack polling to wait until device ready | |||
@param addr address and transfer direction of I2C device | |||
@return none | |||
*/ | |||
extern void i2c_start_wait(unsigned char addr); | |||
/** | |||
@brief Send one byte to I2C device | |||
@param data byte to be transfered | |||
@retval 0 write successful | |||
@retval 1 write failed | |||
*/ | |||
extern unsigned char i2c_write(unsigned char data); | |||
/** | |||
@brief read one byte from the I2C device, request more data from device | |||
@return byte read from I2C device | |||
*/ | |||
extern unsigned char i2c_readAck(void); | |||
/** | |||
@brief read one byte from the I2C device, read is followed by a stop condition | |||
@return byte read from I2C device | |||
*/ | |||
extern unsigned char i2c_readNak(void); | |||
/** | |||
@brief read one byte from the I2C device | |||
Implemented as a macro, which calls either i2c_readAck or i2c_readNak | |||
@param ack 1 send ack, request more data from device<br> | |||
0 send nak, read is followed by a stop condition | |||
@return byte read from I2C device | |||
*/ | |||
extern unsigned char i2c_read(unsigned char ack); | |||
#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak(); | |||
/**@}*/ | |||
#endif |
@@ -0,0 +1,50 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "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 |
@@ -0,0 +1,179 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef KEYMAP_COMMON_H | |||
#define KEYMAP_COMMON_H | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
#include <avr/pgmspace.h> | |||
#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 |
@@ -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 |
@@ -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 |
@@ -0,0 +1,386 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#define KIMERA_C | |||
#include <stdbool.h> | |||
#include <avr/eeprom.h> | |||
#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<<exp); | |||
} | |||
} | |||
else { | |||
row_mapping[i] = UNCONFIGURED; | |||
} | |||
} | |||
/* read col mapping*/ | |||
for (uint8_t i = 0; i < PX_COUNT; i++) { | |||
if (i < col_count) { | |||
col_mapping[i] = eeprom_read_byte(mapping++); | |||
if (col_mapping[i] >= PX_COUNT) { | |||
error++; | |||
} | |||
else { | |||
exp = PX_TO_EXP(col_mapping[i]); | |||
exp_in_use |= (1<<exp); | |||
} | |||
} | |||
else { | |||
col_mapping[i] = UNCONFIGURED; | |||
} | |||
} | |||
return error; | |||
} | |||
void write_matrix_mapping(void) | |||
{ | |||
/* write number of rows and cols */ | |||
eeprom_write_byte(EECONFIG_ROW_COUNT, row_count); | |||
eeprom_write_byte(EECONFIG_COL_COUNT, col_count); | |||
/* write row mapping */ | |||
uint8_t *mapping = EECONFIG_ROW_COL_MAPPING; | |||
for (uint8_t row = 0; row < row_count; row++) { | |||
eeprom_write_byte(mapping++, row_mapping[row]); | |||
} | |||
/* write col mapping */ | |||
for (uint8_t col = 0; col < col_count; col++) { | |||
eeprom_write_byte(mapping++, col_mapping[col]); | |||
} | |||
} | |||
void kimera_scan(void) | |||
{ | |||
uint8_t ret; | |||
dprintf("exp in use: %d\n", exp_in_use); | |||
dprintf("exp online: %d\n", exp_online); | |||
for (uint8_t exp = 0; exp < EXP_COUNT; exp++) { | |||
if (exp_in_use & (1<<exp)) { | |||
ret = i2c_start(EXP_ADDR(exp) | I2C_WRITE); | |||
if (ret == 0) { | |||
i2c_stop(); | |||
if ((exp_online & (1<<exp)) == 0) { | |||
xprintf("found: %d\n", exp); | |||
exp_online |= (1<<exp); | |||
expander_init(exp); | |||
clear_keyboard(); | |||
} | |||
} | |||
else { | |||
if ((exp_online & (1<<exp)) != 0) { | |||
xprintf("lost: %d\n", exp); | |||
exp_online &= ~(1<<exp); | |||
clear_keyboard(); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
inline | |||
uint8_t kimera_matrix_rows(void) | |||
{ | |||
if (combining == COMBINING_ROW) { | |||
return row_left_count; | |||
} | |||
else { | |||
return row_count; | |||
} | |||
} | |||
inline | |||
uint8_t kimera_matrix_cols(void) | |||
{ | |||
if (combining == COMBINING_COL) { | |||
return col_left_count; | |||
} | |||
else { | |||
return col_count; | |||
} | |||
} | |||
void kimera_read_cols(void) | |||
{ | |||
/* read all input registers */ | |||
init_data(0xFF); | |||
for (uint8_t exp = 0; exp < EXP_COUNT; exp++) { | |||
expander_read_input(exp, data[exp]); | |||
} | |||
} | |||
uint8_t kimera_get_col(uint8_t row, uint8_t col) | |||
{ | |||
if (combining == COMBINING_ROW) { | |||
if (row >= 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<<exp)) == 0) { | |||
return 0; | |||
} | |||
uint8_t addr = EXP_ADDR(exp); | |||
uint8_t ret; | |||
ret = i2c_start(addr | I2C_WRITE); | |||
if (ret) goto stop; | |||
ret = i2c_write(command); | |||
if (ret) goto stop; | |||
ret = i2c_write(*data++); | |||
if (ret) goto stop; | |||
ret = i2c_write(*data); | |||
stop: | |||
i2c_stop(); | |||
return ret; | |||
} | |||
uint8_t expander_read(uint8_t exp, uint8_t command, uint8_t *data) | |||
{ | |||
if ((exp_online & (1<<exp)) == 0) { | |||
return 0; | |||
} | |||
uint8_t addr = EXP_ADDR(exp); | |||
uint8_t ret; | |||
ret = i2c_start(addr | I2C_WRITE); | |||
if (ret) goto stop; | |||
ret = i2c_write(command); | |||
if (ret) goto stop; | |||
ret = i2c_rep_start(addr | I2C_READ); | |||
if (ret) goto stop; | |||
*data++ = i2c_readAck(); | |||
*data = i2c_readNak(); | |||
stop: | |||
i2c_stop(); | |||
return ret; | |||
} | |||
inline | |||
uint8_t expander_write_output(uint8_t exp, uint8_t *data) | |||
{ | |||
return expander_write(exp, EXP_COMM_OUTPUT_0, data); | |||
} | |||
inline | |||
uint8_t expander_write_inversion(uint8_t exp, uint8_t *data) | |||
{ | |||
return expander_write(exp, EXP_COMM_INVERSION_0, data); | |||
} | |||
inline | |||
uint8_t expander_write_config(uint8_t exp, uint8_t *data) | |||
{ | |||
return expander_write(exp, EXP_COMM_CONFIG_0, data); | |||
} | |||
inline | |||
uint8_t expander_read_input(uint8_t exp, uint8_t *data) | |||
{ | |||
return expander_read(exp, EXP_COMM_INPUT_0, data); | |||
} | |||
void init_data(uint8_t value) | |||
{ | |||
for (uint8_t exp = 0; exp < EXP_COUNT; exp++) { | |||
for (uint8_t port = 0; port < EXP_PORT_COUNT; port++) { | |||
data[exp][port] = value; | |||
} | |||
} | |||
} |
@@ -0,0 +1,171 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef KIMERA_H | |||
#define KIMERA_H | |||
#include <stdint.h> | |||
#include <avr/pgmspace.h> | |||
#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 |
@@ -0,0 +1,56 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include <avr/io.h> | |||
#include "stdint.h" | |||
#include "led.h" | |||
#include "kimera.h" | |||
#ifndef LEDMAP_ENABLE | |||
void led_set(uint8_t usb_led) | |||
{ | |||
if (usb_led & (1<<USB_LED_NUM_LOCK)) { | |||
// output low | |||
LED1_DDR |= (1<<LED1_BIT); | |||
LED1_PORT &= ~(1<<LED1_BIT); | |||
} else { | |||
// Hi-Z | |||
LED1_DDR &= ~(1<<LED1_BIT); | |||
LED1_PORT &= ~(1<<LED1_BIT); | |||
} | |||
if (usb_led & (1<<USB_LED_CAPS_LOCK)) { | |||
// output low | |||
LED2_DDR |= (1<<LED2_BIT); | |||
LED2_PORT &= ~(1<<LED2_BIT); | |||
} else { | |||
// Hi-Z | |||
LED2_DDR &= ~(1<<LED2_BIT); | |||
LED2_PORT &= ~(1<<LED2_BIT); | |||
} | |||
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) { | |||
// output low | |||
LED3_DDR |= (1<<LED3_BIT); | |||
LED3_PORT &= ~(1<<LED3_BIT); | |||
} else { | |||
// Hi-Z | |||
LED3_DDR &= ~(1<<LED3_BIT); | |||
LED3_PORT &= ~(1<<LED3_BIT); | |||
} | |||
} | |||
#endif |
@@ -0,0 +1,88 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include <avr/pgmspace.h> | |||
#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<<LED1_BIT); | |||
LED1_PORT |= (1<<LED1_BIT); | |||
LED2_DDR |= (1<<LED2_BIT); | |||
LED2_PORT |= (1<<LED2_BIT); | |||
LED3_DDR |= (1<<LED3_BIT); | |||
LED3_PORT |= (1<<LED3_BIT); | |||
LED4_DDR |= (1<<LED4_BIT); | |||
LED4_PORT &= ~(1<<LED4_BIT); | |||
} | |||
void ledmap_led_on(uint8_t index) | |||
{ | |||
switch (index) { | |||
case 0: | |||
LED1_PORT &= ~(1<<LED1_BIT); | |||
break; | |||
case 1: | |||
LED2_PORT &= ~(1<<LED2_BIT); | |||
break; | |||
case 2: | |||
#if 0 | |||
LED3_PORT &= ~(1<<LED3_BIT); | |||
#endif | |||
break; | |||
case 3: | |||
LED4_PORT |= (1<<LED4_BIT); | |||
break; | |||
} | |||
} | |||
void ledmap_led_off(uint8_t index) | |||
{ | |||
switch (index) { | |||
case 0: | |||
LED1_PORT |= (1<<LED1_BIT); | |||
break; | |||
case 1: | |||
LED2_PORT |= (1<<LED2_BIT); | |||
break; | |||
case 2: | |||
#if 0 | |||
LED3_PORT |= (1<<LED3_BIT); | |||
#endif | |||
break; | |||
case 3: | |||
LED4_PORT &= ~(1<<LED4_BIT); | |||
break; | |||
} | |||
} | |||
#endif |
@@ -0,0 +1,170 @@ | |||
/* | |||
* light weight WS2812 lib V2.0b | |||
* | |||
* Controls WS2811/WS2812/WS2812B RGB-LEDs | |||
* Author: Tim ([email protected]) | |||
* | |||
* Jan 18th, 2014 v2.0b Initial Version | |||
* | |||
* License: GNU GPL v2 (see License.txt) | |||
*/ | |||
#include "light_ws2812.h" | |||
#include <avr/interrupt.h> | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
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; | |||
} |
@@ -0,0 +1,63 @@ | |||
/* | |||
* light weight WS2812 lib include | |||
* | |||
* Version 2.0a3 - Jan 18th 2014 | |||
* Author: Tim ([email protected]) | |||
* | |||
* 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 <avr/io.h> | |||
#include <avr/interrupt.h> | |||
#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_ */ |
@@ -0,0 +1,286 @@ | |||
/* | |||
Copyright 2014 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
/* | |||
* scan matrix | |||
*/ | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
#include "print.h" | |||
#include "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<<JTD); | |||
MCUCR = (1<<JTD); | |||
i2c_wrapper_init(); | |||
_delay_ms(1); | |||
kimera_init(); | |||
kimera_scan_timestamp = timer_read(); | |||
// initialize row and col | |||
kimera_unselect_rows(); | |||
// initialize matrix state: all keys off | |||
#if IMPROVED_DEBOUNCE | |||
for (uint8_t i = 0; i < matrix_rows(); i++) { | |||
matrix[i] = 0; | |||
matrix_current_row = 0; | |||
matrix_row_timestamp[i] = timer_read(); | |||
for (uint8_t j = 0; j < matrix_cols(); j++) { | |||
matrix_debouncing[i][j] = 0; | |||
} | |||
} | |||
#else | |||
for (uint8_t i=0; i < matrix_rows(); i++) { | |||
matrix[i] = 0; | |||
matrix_debouncing[i] = 0; | |||
} | |||
#endif | |||
PORTD &= ~(1<<PD4); | |||
} | |||
uint8_t matrix_scan(void) | |||
{ | |||
i2c_wrapper_task(); | |||
/* xprintf("Row: %d, %u\n", matrix_current_row, timer_read()); */ | |||
if (timer_elapsed(kimera_scan_timestamp) >= 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<<col)); | |||
} | |||
inline | |||
matrix_row_t matrix_get_row(uint8_t row) | |||
{ | |||
return matrix[row]; | |||
} | |||
void matrix_print(void) | |||
{ | |||
print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n"); | |||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||
phex(row); print(": "); | |||
print_bin_reverse32(matrix_get_row(row)); | |||
print("\n"); | |||
} | |||
} | |||
uint8_t matrix_key_count(void) | |||
{ | |||
uint8_t count = 0; | |||
for (uint8_t i = 0; i < matrix_rows(); i++) { | |||
count += bitpop32(matrix[i]); | |||
} | |||
return count; | |||
} |
@@ -0,0 +1,237 @@ | |||
/* | |||
Copyright 2016 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include <avr/pgmspace.h> | |||
#include <avr/eeprom.h> | |||
#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 |
@@ -0,0 +1,60 @@ | |||
/* | |||
Copyright 2016 Kai Ryu <[email protected]> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#ifndef RGB_H | |||
#define RGB_H | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
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 |
@@ -0,0 +1,205 @@ | |||
/************************************************************************* | |||
* Title: I2C master library using hardware TWI interface | |||
* Author: Peter Fleury <[email protected]> http://jump.to/fleury | |||
* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $ | |||
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 | |||
* Target: any AVR device with hardware TWI | |||
* Usage: API compatible with I2C Software Library i2cmaster.h | |||
**************************************************************************/ | |||
#include <inttypes.h> | |||
#include <compat/twi.h> | |||
#include <i2cmaster.h> | |||
#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<<TWINT) | (1<<TWSTA) | (1<<TWEN); | |||
// wait until transmission completed | |||
while(!(TWCR & (1<<TWINT))) { CHECK_FORCE_STOP(); }; | |||
// check value of TWI Status Register. Mask prescaler bits. | |||
twst = TW_STATUS & 0xF8; | |||
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1; | |||
// send device address | |||
TWDR = address; | |||
TWCR = (1<<TWINT) | (1<<TWEN); | |||
// wail until transmission completed and ACK/NACK has been received | |||
while(!(TWCR & (1<<TWINT))) { CHECK_FORCE_STOP(); }; | |||
// check value of TWI Status Register. Mask prescaler bits. | |||
twst = TW_STATUS & 0xF8; | |||
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1; | |||
return 0; | |||
}/* i2c_start */ | |||
/************************************************************************* | |||
Issues a start condition and sends address and transfer direction. | |||
If device is busy, use ack polling to wait until device is ready | |||
Input: address and transfer direction of I2C device | |||
*************************************************************************/ | |||
void i2c_start_wait(unsigned char address) | |||
{ | |||
uint8_t twst; | |||
while ( 1 ) | |||
{ | |||
// send START condition | |||
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); | |||
// wait until transmission completed | |||
while(!(TWCR & (1<<TWINT))); | |||
// check value of TWI Status Register. Mask prescaler bits. | |||
twst = TW_STATUS & 0xF8; | |||
if ( (twst != TW_START) && (twst != TW_REP_START)) continue; | |||
// send device address | |||
TWDR = address; | |||
TWCR = (1<<TWINT) | (1<<TWEN); | |||
// wail until transmission completed | |||
while(!(TWCR & (1<<TWINT))); | |||
// check value of TWI Status Register. Mask prescaler bits. | |||
twst = TW_STATUS & 0xF8; | |||
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) | |||
{ | |||
/* device busy, send stop condition to terminate write operation */ | |||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | |||
// wait until stop condition is executed and bus released | |||
while(TWCR & (1<<TWSTO)) { CHECK_FORCE_STOP(); }; | |||
continue; | |||
} | |||
//if( twst != TW_MT_SLA_ACK) return 1; | |||
break; | |||
} | |||
}/* i2c_start_wait */ | |||
/************************************************************************* | |||
Issues a repeated start condition and sends address and transfer direction | |||
Input: address and transfer direction of I2C device | |||
Return: 0 device accessible | |||
1 failed to access device | |||
*************************************************************************/ | |||
unsigned char i2c_rep_start(unsigned char address) | |||
{ | |||
return i2c_start( address ); | |||
}/* i2c_rep_start */ | |||
/************************************************************************* | |||
Terminates the data transfer and releases the I2C bus | |||
*************************************************************************/ | |||
void i2c_stop(void) | |||
{ | |||
/* send stop condition */ | |||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | |||
// wait until stop condition is executed and bus released | |||
while(TWCR & (1<<TWSTO)) { CHECK_FORCE_STOP(); }; | |||
}/* i2c_stop */ | |||
/************************************************************************* | |||
Send one byte to I2C device | |||
Input: byte to be transfered | |||
Return: 0 write successful | |||
1 write failed | |||
*************************************************************************/ | |||
unsigned char i2c_write( unsigned char data ) | |||
{ | |||
uint8_t twst; | |||
// send data to the previously addressed device | |||
TWDR = data; | |||
TWCR = (1<<TWINT) | (1<<TWEN); | |||
// wait until transmission completed | |||
while(!(TWCR & (1<<TWINT))) { CHECK_FORCE_STOP() }; | |||
// check value of TWI Status Register. Mask prescaler bits | |||
twst = TW_STATUS & 0xF8; | |||
if( twst != TW_MT_DATA_ACK) return 1; | |||
return 0; | |||
}/* i2c_write */ | |||
/************************************************************************* | |||
Read one byte from the I2C device, request more data from device | |||
Return: byte read from I2C device | |||
*************************************************************************/ | |||
unsigned char i2c_readAck(void) | |||
{ | |||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); | |||
while(!(TWCR & (1<<TWINT))) { CHECK_FORCE_STOP(); }; | |||
return TWDR; | |||
}/* i2c_readAck */ | |||
/************************************************************************* | |||
Read one byte from the I2C device, read is followed by a stop condition | |||
Return: byte read from I2C device | |||
*************************************************************************/ | |||
unsigned char i2c_readNak(void) | |||
{ | |||
TWCR = (1<<TWINT) | (1<<TWEN); | |||
while(!(TWCR & (1<<TWINT))) { CHECK_FORCE_STOP(); }; | |||
return TWDR; | |||
}/* i2c_readNak */ |
@@ -0,0 +1,21 @@ | |||
/* | |||
* light_ws2812_config.h | |||
* | |||
* Created: 18.01.2014 09:58:15 | |||
* | |||
* User Configuration file for the light_ws2812_lib | |||
* | |||
*/ | |||
#ifndef WS2812_CONFIG_H_ | |||
#define WS2812_CONFIG_H_ | |||
/////////////////////////////////////////////////////////////////////// | |||
// Define I/O pin | |||
/////////////////////////////////////////////////////////////////////// | |||
#define ws2812_port C // Data port | |||
#define ws2812_pin 6 // Data out pin | |||
#endif /* WS2812_CONFIG_H_ */ |