@@ -54,6 +54,7 @@ SRC = keymap_common.c \ | |||
backlight.c \ | |||
ledmap.c \ | |||
twimaster.c \ | |||
i2c_wrapper.c \ | |||
kimera.c \ | |||
light_ws2812.c \ | |||
rgb.c |
@@ -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 | |||
@@ -19,34 +19,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include <stdbool.h> | |||
#include <avr/eeprom.h> | |||
#include <avr/interrupt.h> | |||
#include <avr/wdt.h> | |||
#include <util/delay.h> | |||
#include "action.h" | |||
#include "i2cmaster.h" | |||
#include "kimera.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 | |||
extern uint8_t i2c_force_stop; | |||
static uint8_t row_mapping[PX_COUNT] = { | |||
#ifndef TWO_HEADED_KIMERA | |||
0, 1, 2, 3, 4, 5, 6, 7, | |||
@@ -106,24 +83,10 @@ void kimera_init(void) | |||
write_matrix_mapping(); | |||
} | |||
/* init i2c */ | |||
i2c_init(); | |||
/* init watch dog */ | |||
wdt_init(); | |||
/* init i/o expanders */ | |||
kimera_scan(); | |||
} | |||
void wdt_init(void) | |||
{ | |||
cli(); | |||
wdt_reset(); | |||
wdt_intr_enable(WDTO_1S); | |||
sei(); | |||
} | |||
uint8_t read_matrix_mapping(void) | |||
{ | |||
uint8_t error = 0; | |||
@@ -396,7 +359,6 @@ void expander_init(uint8_t exp) | |||
uint8_t expander_write(uint8_t exp, uint8_t command, uint8_t *data) | |||
{ | |||
wdt_reset(); | |||
if ((exp_online & (1<<exp)) == 0) { | |||
return 0; | |||
} | |||
@@ -416,7 +378,6 @@ stop: | |||
uint8_t expander_read(uint8_t exp, uint8_t command, uint8_t *data) | |||
{ | |||
wdt_reset(); | |||
if ((exp_online & (1<<exp)) == 0) { | |||
return 0; | |||
} | |||
@@ -467,27 +428,3 @@ void init_data(uint8_t value) | |||
} | |||
} | |||
} | |||
ISR(WDT_vect) | |||
{ | |||
dprintf("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; | |||
} |
@@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "debug.h" | |||
#include "util.h" | |||
#include "matrix.h" | |||
#include "i2c_wrapper.h" | |||
#include "kimera.h" | |||
#include "keymap_in_eeprom.h" | |||
#include "timer.h" | |||
@@ -70,6 +71,9 @@ void matrix_init(void) | |||
MCUCR = (1<<JTD); | |||
MCUCR = (1<<JTD); | |||
i2c_wrapper_init(); | |||
_delay_ms(1); | |||
kimera_init(); | |||
kimera_scan_timestamp = timer_read(); | |||
@@ -99,6 +103,7 @@ void matrix_init(void) | |||
uint8_t matrix_scan(void) | |||
{ | |||
i2c_wrapper_task(); | |||
/* xprintf("Row: %d, %u\n", matrix_current_row, timer_read()); */ | |||