aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/adc.h15
-rw-r--r--include/avr-ioe.h2
-rw-r--r--include/can/global.h20
-rw-r--r--include/can/mcp2515.h36
-rw-r--r--include/can/software.h9
-rw-r--r--include/ioport.h55
-rw-r--r--include/mcu/Kconfig11
-rw-r--r--include/mcu/atmega328p.Kconfig8
-rw-r--r--include/mcu/atmega328p.h63
-rw-r--r--include/mcu/atmega32u4.h19
-rw-r--r--include/mcu/atmega8a.h18
-rw-r--r--include/mcu/attiny4313.h46
-rw-r--r--include/mcu/attiny85.Kconfig4
-rw-r--r--include/mcu/attiny85.h28
-rw-r--r--include/mcu/mcu.h18
-rw-r--r--include/mcu/mcu_def.h21
-rw-r--r--include/pwm.h11
-rw-r--r--include/sensors/dht22.h42
-rw-r--r--include/spi.h66
-rw-r--r--include/tasks.h94
-rw-r--r--include/timer.h28
-rw-r--r--include/twi.h24
-rw-r--r--include/usart.h64
-rw-r--r--include/usi_spi.h66
-rw-r--r--include/utils/buffer.h86
-rw-r--r--include/utils/narray.h21
-rw-r--r--include/utils/timers_div.h81
-rw-r--r--include/wireless/nrf24l01p.h0
28 files changed, 956 insertions, 0 deletions
diff --git a/include/adc.h b/include/adc.h
new file mode 100644
index 0000000..86429a1
--- /dev/null
+++ b/include/adc.h
@@ -0,0 +1,15 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#ifndef _IOE_ADC_H_
+#define _IOE_ADC_H_
+#ifdef CONFIG_IOE_ADC
+#ifndef MCUSUPPORT_ADC
+#error "No ADC support for your mcu. Probably just not implemented yet."
+#endif
+
+int8_t ioe_adc(uint8_t input);
+
+#endif /* CONFIG_IOE_ADC */
+#endif /* _IOE_ADC_H_ */
diff --git a/include/avr-ioe.h b/include/avr-ioe.h
new file mode 100644
index 0000000..cb84ad9
--- /dev/null
+++ b/include/avr-ioe.h
@@ -0,0 +1,2 @@
+#include "spi.h"
+#include "usart.h"
diff --git a/include/can/global.h b/include/can/global.h
new file mode 100644
index 0000000..5d88fe6
--- /dev/null
+++ b/include/can/global.h
@@ -0,0 +1,20 @@
+#include <stdint.h>
+
+#ifndef _IOE_CAN_GLOBAL_
+#define _IOE_CAN_GLOBAL_
+
+typedef struct {
+ uint16_t id;
+ uint8_t length;
+ uint8_t data[8];
+} CanFrame;
+
+typedef struct {
+ CanFrame **buffer;
+ void *udata;
+} Can;
+
+
+void can_send(Can *can, CanFrame *frame);
+
+#endif /* _IOE_CAN_GLOBAL_ */
diff --git a/include/can/mcp2515.h b/include/can/mcp2515.h
new file mode 100644
index 0000000..59376f7
--- /dev/null
+++ b/include/can/mcp2515.h
@@ -0,0 +1,36 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#include "spi.h"
+#include "global.h"
+
+#ifndef _IOE_CAN_MCP2515_H_
+#define _IOE_CAN_MCP2515_H_
+#ifdef CONFIG_IOE_CAN_MCP2515
+#ifndef CONFIG_IOE_SPI
+#error "Please define CONFIG_IOE_SPI. MCP2515 requires SPI."
+#endif
+
+// TODO registers
+#define CAN_MCP2515_CANCTL
+// TODO buffers
+
+typedef struct {
+ uint8_t group, mask;
+} CanMcp2515;
+
+int8_t can_mcp2515_init(CanMcp2515 * can, uint8_t group, uint8_t mask);
+
+void can_mcp2515_reset(CanMcp2515 * can);
+uint8_t can_mcp2515_read(CanMcp2515 * can, uint8_t address);
+uint8_t can_mcp2515_readrx(CanMcp2515 * can, uint8_t buffer);
+void can_mcp2515_write(CanMcp2515 * can, uint8_t address, uint8_t data);
+void can_mcp2515_loadrx(CanMcp2515 * can, uint8_t buffer, uint8_t data);
+uint8_t can_mcp2515_rdstat(CanMcp2515 * can);
+uint8_t can_mcp2515_rxstat(CanMcp2515 * can);
+void can_mcp2515_bitmod(CanMcp2515 * can, uint8_t address, uint8_t mask,
+ uint8_t data);
+
+#endif /* CONFIG_IOE_CAN_MCP2515 */
+#endif /* _IOE_CAN_MCP2515_H_ */
diff --git a/include/can/software.h b/include/can/software.h
new file mode 100644
index 0000000..b443e42
--- /dev/null
+++ b/include/can/software.h
@@ -0,0 +1,9 @@
+#include <avr/io.h>
+#include <util/delay.h>
+#include <stdint.h>
+
+#ifndef _IOE_CAN_SOFTWARE_H_
+#define _IOE_CAN_SOFTWARE_H_
+
+
+#endif /* _IOE_CAN_SOFTWARE_H_ */
diff --git a/include/ioport.h b/include/ioport.h
new file mode 100644
index 0000000..1022493
--- /dev/null
+++ b/include/ioport.h
@@ -0,0 +1,55 @@
+#include <stdlib.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#include "mcu/mcu_def.h"
+
+#ifndef _IOE_IOPORT_H_
+#define _IOE_IOPORT_H_
+#ifdef CONFIG_IOPORTS
+
+enum ioInResistor {
+ IO_PULLUP,
+ IO_PULLDOWN
+};
+
+static inline void io_setout(uint8_t group, uint8_t mask) {
+ IO_DDR(group) |= mask;
+}
+static inline void io_hight(uint8_t group, uint8_t mask) {
+ IO_PORT(group) |= mask;
+}
+static inline void io_low(uint8_t group, uint8_t mask) {
+ IO_PORT(group) &= ~mask;
+}
+static inline void io_set(uint8_t group, uint8_t mask, int8_t val) {
+ if (val)
+ io_hight(group, mask);
+ else
+ io_low(group, mask);
+}
+
+static inline void io_setin(uint8_t group, uint8_t mask,
+ enum ioInResistor resistor) {
+ IO_DDR(group) &= ~mask;
+ if (resistor == IO_PULLUP)
+ IO_PORT(group) |= mask;
+ else
+ IO_PORT(group) &= ~mask;
+}
+static inline int8_t io_get(uint8_t group, uint8_t mask) {
+ return (int8_t) IO_PIN(group) & mask;
+}
+
+#ifdef CONFIG_PCINT
+
+#define IO_RISING (1 << 0)
+#define IO_FALLING (1 << 1)
+void io_change_sethook(uint8_t group, uint8_t mask, uint8_t edge,
+ void (*change) (uint8_t group, uint8_t mask));
+void io_change_remhook(void (*change) (uint8_t group, uint8_t mask));
+void io_change_clearhooks(void);
+
+#endif /* CONFIG_PCINT */
+#endif /* CONFIG_IOPORTS */
+#endif /* _IOE_IOPORT_H_ */
diff --git a/include/mcu/Kconfig b/include/mcu/Kconfig
new file mode 100644
index 0000000..a69903f
--- /dev/null
+++ b/include/mcu/Kconfig
@@ -0,0 +1,11 @@
+config MMCU
+ string
+ default "atmega328p" if ATMEGA328P
+
+choice MCU
+ prompt "Microcontroller (MMCU)"
+
+source include/mcu/atmega328p.Kconfig
+source include/mcu/attiny85.Kconfig
+
+endchoice
diff --git a/include/mcu/atmega328p.Kconfig b/include/mcu/atmega328p.Kconfig
new file mode 100644
index 0000000..5b4bf27
--- /dev/null
+++ b/include/mcu/atmega328p.Kconfig
@@ -0,0 +1,8 @@
+config ATMEGA328P
+ bool "atmega328p"
+ select MCUSUPPORT_IOPORTS
+ select MCUSUPPORT_PCINT0
+ select MCUSUPPORT_PCINT1
+ select MCUSUPPORT_PCINT2
+ select MCUSUPPORT_SPI
+ select MCUSUPPORT_USART
diff --git a/include/mcu/atmega328p.h b/include/mcu/atmega328p.h
new file mode 100644
index 0000000..994e9e6
--- /dev/null
+++ b/include/mcu/atmega328p.h
@@ -0,0 +1,63 @@
+/* This is specific configuration for ATmega328P.
+ * Also applies on ATmega48A, ATmega48PA, ATmega88A, ATmega88PA, ATmega168A and
+ * ATmega168PA.
+ */
+#include <avr/io.h>
+
+// IO Ports
+#define MCUSUPPORT_IOPORTS
+#define IO_B 0
+#define IO_C 1
+#define IO_D 2
+#define IO_PIN(GROUP) (* (volatile uint8_t *)(PINB + 0x3*GROUP))
+#define IO_DDR(GROUP) (* (volatile uint8_t *)(DDRB + 0x3*GROUP))
+#define IO_PORT(GROUP) (* (volatile uint8_t *)(PORTB + 0x3*GROUP))
+#define IO_B0 IO_B, (1 << 0)
+#define IO_B1 IO_B, (1 << 1)
+#define IO_B2 IO_B, (1 << 2)
+#define IO_B3 IO_B, (1 << 3)
+#define IO_B4 IO_B, (1 << 4)
+#define IO_B5 IO_B, (1 << 5)
+#define IO_B6 IO_B, (1 << 6)
+#define IO_B7 IO_B, (1 << 7)
+#define IO_C0 IO_C, (1 << 0)
+#define IO_C1 IO_C, (1 << 1)
+#define IO_C2 IO_C, (1 << 2)
+#define IO_C3 IO_C, (1 << 3)
+#define IO_C4 IO_C, (1 << 4)
+#define IO_C5 IO_C, (1 << 5)
+#define IO_C6 IO_C, (1 << 6)
+#define IO_D0 IO_D, (1 << 0)
+#define IO_D1 IO_D, (1 << 1)
+#define IO_D2 IO_D, (1 << 2)
+#define IO_D3 IO_D, (1 << 3)
+#define IO_D4 IO_D, (1 << 4)
+#define IO_D5 IO_D, (1 << 5)
+#define IO_D6 IO_D, (1 << 6)
+#define IO_D7 IO_D, (1 << 7)
+#define MCUSUPPORT_PCINT0 8
+#define MCUSUPPORT_PCINT1 8
+#define MCUSUPPORT_PCINT2 8
+// SPI
+#define MCUSUPPORT_SPI
+#define DDR_SPI DDRB
+#define DD_SS DDB2
+#define DD_MOSI DDB3
+#define DD_MISO DDB4
+#define DD_SCLK DDB5
+#define PORT_SPI PORTB
+#define PORT_SS PORTB2
+#define PORT_MOSI PORTB3
+#define PORT_MISO PORTB4
+#define PORT_SCLK PORTB5
+// USART
+#define MCUSUPPORT_USART
+// TWI
+#define MCUSUPPORT_TWI
+// TIMERS
+#define MCUSUPPORT_TIMER_0
+#define MCUSUPPORT_TIMER_1
+#define MCUSUPPORT_TIMER_2
+#define COUNTER0_PWM 0
+#define COUNTER1_16PWM 1
+#define COUNTER2_PWM_ASYNC 2
diff --git a/include/mcu/atmega32u4.h b/include/mcu/atmega32u4.h
new file mode 100644
index 0000000..16351e8
--- /dev/null
+++ b/include/mcu/atmega32u4.h
@@ -0,0 +1,19 @@
+/* This is specific configuration for ATmega32U4.
+ * This configuration also applies on ATmega16U4.
+ */
+#include <avr/io.h>
+
+// SPI
+#define MCUSUPPORT_SPI
+#define DDR_SPI DDRB
+#define DD_SS DDB0
+#define DD_SCLK DDB1
+#define DD_MOSI DDB2
+#define DD_MISO DDB3
+#define PORT_SPI PORTB
+#define PORT_SS PORTB0
+#define PORT_SCLK PORTB1
+#define PORT_MOSI PORTB2
+#define PORT_MISO PORTB3
+// USART
+#define MCUSUPPORT_USART0
diff --git a/include/mcu/atmega8a.h b/include/mcu/atmega8a.h
new file mode 100644
index 0000000..a2d3adf
--- /dev/null
+++ b/include/mcu/atmega8a.h
@@ -0,0 +1,18 @@
+/* This is specific configuration for ATmega8A.
+ */
+#include <avr/io.h>
+
+// SPI
+#define MCUSUPPORT_SPI
+#define DDR_SPI DDRB
+#define DD_SS DDB2
+#define DD_SCLK DDB5
+#define DD_MOSI DDB3
+#define DD_MISO DDB4
+#define PORT_SPI PORTB
+#define PORT_SS PORTB2
+#define PORT_SCLK PORTB5
+#define PORT_MOSI PORTB3
+#define PORT_MISO PORTB4
+// USART
+#define MCUSUPPORT_USART0
diff --git a/include/mcu/attiny4313.h b/include/mcu/attiny4313.h
new file mode 100644
index 0000000..3a2d0b9
--- /dev/null
+++ b/include/mcu/attiny4313.h
@@ -0,0 +1,46 @@
+/* This is specific configuration for ATtiny4313.
+ * This configuration also applies on ATtiny2313A.
+ */
+#include <avr/io.h>
+
+// IO Ports
+#define MCUSUPPORT_IOPORTS
+#define IO_A 0
+#define IO_B 1
+#define IO_D 3
+#define IO_PIN(GROUP) (* (volatile uint8_t *)(PINB + 0x3*GROUP))
+#define IO_DDR(GROUP) (* (volatile uint8_t *)(DDRB + 0x3*GROUP))
+#define IO_PORT(GROUP) (* (volatile uint8_t *)(PORTB + 0x3*GROUP))
+#define IO_A0 IO_A, (1 << 0)
+#define IO_A1 IO_A, (1 << 1)
+#define IO_A2 IO_A, (1 << 2)
+#define IO_B0 IO_B, (1 << 0)
+#define IO_B1 IO_B, (1 << 1)
+#define IO_B2 IO_B, (1 << 2)
+#define IO_B3 IO_B, (1 << 3)
+#define IO_B4 IO_B, (1 << 4)
+#define IO_B5 IO_B, (1 << 5)
+#define IO_B6 IO_B, (1 << 6)
+#define IO_B7 IO_B, (1 << 7)
+#define IO_D0 IO_D, (1 << 0)
+#define IO_D1 IO_D, (1 << 1)
+#define IO_D2 IO_D, (1 << 2)
+#define IO_D3 IO_D, (1 << 3)
+#define IO_D4 IO_D, (1 << 4)
+#define IO_D5 IO_D, (1 << 5)
+#define IO_D6 IO_D, (1 << 6)
+#define MCUSUPPORT_PCINT0 8 // TODO this is B
+#define MCUSUPPORT_PCINT1 7 // But this is D
+#define MCUSUPPORT_PCINT2 3 // And this is A, this is not expected in ioport.c
+// SPI USI
+#define MCUSUPPORT_USI
+#define DDR_USI DDRB
+#define DD_DI DDB5
+#define DD_DO DDB6
+#define DD_USCK DDB7
+#define PORT_USI PORTB
+#define PORT_DI PORTB5
+#define PORT_DO PORTB6
+#define PORT_USCK PORTB7
+// USART
+#define MCUSUPPORT_USART0
diff --git a/include/mcu/attiny85.Kconfig b/include/mcu/attiny85.Kconfig
new file mode 100644
index 0000000..d58c1d8
--- /dev/null
+++ b/include/mcu/attiny85.Kconfig
@@ -0,0 +1,4 @@
+config ATTINY85
+ bool "attiny85"
+ select MCUSUPPORT_IOPORTS
+ select MCUSUPPORT_PCINT0
diff --git a/include/mcu/attiny85.h b/include/mcu/attiny85.h
new file mode 100644
index 0000000..c342bbb
--- /dev/null
+++ b/include/mcu/attiny85.h
@@ -0,0 +1,28 @@
+/* This is specific configuration for ATtiny85.
+ * This configuration also applies on ATtiny45 and ATtiny25.
+ */
+#include <avr/io.h>
+
+// IO Ports
+#define MCUSUPPORT_IOPORTS
+#define IO_B 0
+#define IO_PIN(GROUP) PINB
+#define IO_DDR(GROUP) DDRB
+#define IO_PORT(GROUP) PORTB
+#define IO_B0 IO_B, (1 << 0)
+#define IO_B1 IO_B, (1 << 1)
+#define IO_B2 IO_B, (1 << 2)
+#define IO_B3 IO_B, (1 << 3)
+#define IO_B4 IO_B, (1 << 4)
+#define IO_B5 IO_B, (1 << 5)
+#define MCUSUPPORT_PCINT0 6
+// SPI USI
+#define MCUSUPPORT_USI
+#define DDR_USI DDRB
+#define DD_DI DDB0
+#define DD_DO DDB1
+#define DD_USCK DDB2
+#define PORT_USI PORTB
+#define PORT_DI PORTB0
+#define PORT_DO PORTB1
+#define PORT_USCK PORTB2
diff --git a/include/mcu/mcu.h b/include/mcu/mcu.h
new file mode 100644
index 0000000..e1272b9
--- /dev/null
+++ b/include/mcu/mcu.h
@@ -0,0 +1,18 @@
+#define __MCU_ATmega328p__ \
+ ((defined __AVR_ATmega328P__ || defined __AVR_ATmega328__ || \
+ defined __AVR_ATmega1688PA__ || defined __AVR_ATmega168A__ || \
+ defined __AVR_ATmega88PA__ || defined __AVR_ATmega88A__ || \
+ defined __AVR_ATmega48PA__ || defined AVR_ATmega48A__))
+
+#define __MCU_ATmega32U4__ \
+ ((defined __AVR_ATmega32U4__ || defined __AVR_ATmega16U4))
+
+#define __MCU_ATmega8A__ \
+ (defined __AVR_ATmega8A__)
+
+#define __MCU_ATtiny4313__ \
+ ((defined __AVR_ATtiny4313__ || defined __AVR_ATtiny2313A__))
+
+#define __MCU_ATtiny85__ \
+ ((defined __AVR_ATtiny85__ || defined __AVR_ATtiny45__ || \
+ defined __AVR_ATtiny25__))
diff --git a/include/mcu/mcu_def.h b/include/mcu/mcu_def.h
new file mode 100644
index 0000000..472b607
--- /dev/null
+++ b/include/mcu/mcu_def.h
@@ -0,0 +1,21 @@
+#include "mcu.h"
+
+#if __MCU_ATmega328p__
+#include "atmega328p.h"
+#endif
+
+#if __MCU_ATmega32U4__
+#include "atmega32u4.h"
+#endif
+
+#if __MCU_ATmega8A__
+#include "atmega8a.h"
+#endif
+
+#if __MCU_ATtiny4313__
+#include "attiny4313.h"
+#endif
+
+#if __MCU_ATtiny85__
+#include "attiny85.h"
+#endif
diff --git a/include/pwm.h b/include/pwm.h
new file mode 100644
index 0000000..0dbc007
--- /dev/null
+++ b/include/pwm.h
@@ -0,0 +1,11 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#include "timer.h"
+
+#ifndef _IOE_PWM_H_
+#define _IOE_PWM_H_
+
+
+#endif /* _IOE_PWM_H_ */
diff --git a/include/sensors/dht22.h b/include/sensors/dht22.h
new file mode 100644
index 0000000..aabb442
--- /dev/null
+++ b/include/sensors/dht22.h
@@ -0,0 +1,42 @@
+#include <avr/io.h>
+#include <util/delay.h>
+#include <stdint.h>
+
+#include "../tasks.h"
+#include "../timer.h"
+
+#ifndef _IOE_SENSOR_DHT22_H_
+#define _IOE_SENSOR_DHT22_H_
+#ifdef CONFIG_IOE_SENSOR_DHT22
+
+struct dht22_value {
+ uint8_t integral;
+ uint8_t decimal;
+};
+
+struct dht22_port {
+ volatile uint8_t *DDR; // Address of DDR register
+ volatile uint8_t *PORT; // Address of PORT register
+ volatile uint8_t *PIN; // Address of PIN register
+ uint8_t MASK; // _BV() of index of port
+ volatile uint8_t *PCMSK; // Address of relevant PCMSK register
+ uint8_t PCMSK_MASK; // _BV() of index of PCMSK
+};
+
+extern const struct dht22_port dht22_ports[];
+
+/*
+ * Initialize port for sensor
+ */
+void dht22_init(uint8_t port);
+
+/*
+ * Read values from dht22
+ * rh - relative
+ * t - temperature
+ */
+int8_t dht22_read(uint8_t portindex, struct dht22_value *rh,
+ struct dht22_value *t);
+
+#endif /* CONFIG_IOE_SENSOR_DHT22 */
+#endif /* _IOE_SENSOR_DHT22_H_ */
diff --git a/include/spi.h b/include/spi.h
new file mode 100644
index 0000000..8d51eb9
--- /dev/null
+++ b/include/spi.h
@@ -0,0 +1,66 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#include "mcu/mcu_def.h"
+#include "tasks.h"
+
+#ifndef _IOE_SPI_H_
+#define _IOE_SPI_H_
+#ifdef CONFIG_SPI
+
+enum spiMode {
+ SPI_MODE_MASTER,
+ SPI_MODE_SLAVE
+};
+
+volatile extern int8_t _spi_busy;
+volatile extern Mutex spi_mutex;
+
+static inline void spi_init(enum spiMode mode) {
+ _spi_busy = 0;
+ if (mode == SPI_MODE_MASTER) {
+ // Set MOSI and SCK output
+ DDR_SPI |= _BV(DD_MOSI) | _BV(DD_SCLK);
+ // Set MISO pull up resistor
+ PORT_SPI |= _BV(PORT_MISO);
+ // Enable SPI master, set clock rate fck/16 and enable SPI interrupt
+ SPCR = _BV(SPE) | _BV(SPIE) | _BV(MSTR) | _BV(SPR0);
+ } else {
+ // Set MISO as output
+ DDR_SPI |= _BV(DD_MISO);
+ // Set SCLK and MOSI pull up resistor
+ PORT_SPI |= _BV(PORT_SCLK) | _BV(PORT_MOSI);
+ // Enable SPI and interrupt
+ SPCR = _BV(SPE) | _BV(SPIE);
+ }
+}
+
+static inline int8_t spi_busy(void) {
+ return _spi_busy;
+}
+
+static inline void spi_join(void) {
+ task_delay_till(&_spi_busy, 0);
+}
+
+static inline void spi_transfer(uint8_t data) {
+ _spi_busy = 1;
+ SPDR = data;
+}
+
+static inline uint8_t spi_send(uint8_t data) {
+ spi_transfer(data);
+ task_delay_till(&_spi_busy, 0);
+ return SPDR;
+}
+
+static inline void spi_expose(uint8_t data) {
+ SPDR = data;
+}
+
+// Null terminated array
+extern void (*spi_receive)(uint8_t data);
+
+#endif /* CONFIG_SPI */
+#endif /* _IOE_SPI_H_ */
diff --git a/include/tasks.h b/include/tasks.h
new file mode 100644
index 0000000..27bd968
--- /dev/null
+++ b/include/tasks.h
@@ -0,0 +1,94 @@
+#include <avr/io.h>
+#include <util/delay.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "mcu/mcu_def.h"
+#include "timer.h"
+
+#ifndef _IOE_TASKS_H_
+#define _IOE_TASKS_H_
+
+#ifdef CONFIG_IOE_TASKS
+
+#ifndef CONFIG_IOE_TIMERS
+#error "To use tasks you must enable timers (CONFIG_IOE_TIMERS)."
+#endif
+
+int8_t tasks_run(void);
+
+union StackPointer {
+ uint8_t lh8[2];
+ uint16_t lh16;
+};
+typedef struct {
+ uint8_t flags;
+ void (*func) (void *data);
+ void *data;
+ uint8_t _rflags;
+ uint8_t _stack_size;
+ union StackPointer _sp;
+} Task;
+int8_t task_spawn(Task * t, uint8_t stack_size);
+void taks_exit(void);
+int8_t task_kill(Task * t);
+int8_t task_safe(void);
+int8_t task_unsafe(void);
+
+int8_t task_delay(uint16_t cycles);
+int8_t task_delay_ms(uint16_t ms);
+int8_t task_delay_till(volatile int8_t * boolean, uint16_t ms);
+
+#define MUTEX_F_TIMED (1<<0)
+#define MUTEX_F_TAKEN (1<<7)
+typedef struct {
+ uint8_t flags;
+ Task *_task_took;
+} Mutex;
+int8_t mutex_init(Mutex * mtx);
+int8_t mutex_free(Mutex * mtx);
+int8_t mutex_take(Mutex * mtx, uint16_t timeout);
+int8_t mutex_give(Mutex * mtx);
+
+typedef struct {
+ uint8_t flags;
+ uint8_t _count;
+ Task **_tasks;
+ uint8_t _tasks_len;
+} Semaphore;
+int8_t semaphore_init(Semaphore * sem, uint8_t count);
+int8_t semaphore_free(Semaphore * sem);
+int8_t semaphore_take(Semaphore * sem, uint16_t timeout);
+int8_t semaphore_give(Semaphore * sem);
+
+#else /* CONFIG_IOE_TASKS */
+
+typedef struct {
+} Task;
+#define task_spawn(T, STACK_SIZE)
+#define task_exit()
+#define task_kill(T)
+#define task_safe()
+#define task_unsafe()
+
+#define task_delay(US) _delay_us(US) // TODO this should be cycles
+#define task_delay_ms(MS) _delay_ms(MS)
+int8_t task_delay_till(volatile int8_t * boolean, uint16_t ms);
+
+typedef struct {
+} Mutex;
+#define mutex_init(MTX, FLAGS)
+#define mutex_free(MTX)
+#define mutex_take(MTX, TIMEOUT)
+#define mutex_give(MTX);
+
+typedef struct {
+} Semaphore;
+#define semaphore_init(SEM, FLAGS, COUNT)
+#define semaphore_free(SEM)
+#define semaphore_take(SEM, TIMEOUT)
+#define semaphore_give(SEM)
+
+#endif /* CONFIG_IOE_TASKS */
+#endif /* _IOE_TASKS_H_ */
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..4fef95c
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,28 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#include "mcu/mcu_def.h"
+#include "utils/narray.h"
+
+#ifndef _IOE_TIMER_H_
+#define _IOE_TIMER_H_
+#ifdef CONFIG_IOE_TIMERS
+
+enum timerDivider {
+ TIMER_DIVIDER_1,
+ TIMER_DIVIDER_8,
+ TIMER_DIVIDER_64,
+ TIMER_DIVIDER_256,
+ TIMER_DIVIDER_1024
+};
+
+void timer_init(uint8_t timer, enum timerDivider div);
+void timer_disable(uint8_t timer);
+void timer_reset(uint8_t timer);
+uint16_t timer_value(uint8_t timer);
+void timer_sethook(uint8_t timer, void (*fnc) (void));
+void timer_remhook(uint8_t timer, void (*fnc) (void));
+
+#endif /* CONFIG_IOE_TIMERS */
+#endif /* _IOE_TIMER_H_ */
diff --git a/include/twi.h b/include/twi.h
new file mode 100644
index 0000000..0763c4b
--- /dev/null
+++ b/include/twi.h
@@ -0,0 +1,24 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#include "mcu/mcu_def.h"
+
+#ifndef _IOE_TWI_H_
+#define _IOE_TWI_H_
+
+#ifndef MCUSUPPORT_TWI
+#error "No TWI interface is known on your mcu."
+#endif
+
+enum twiMode {
+ TWI_MODE_MASTER,
+ TWI_MODE_SLAVE
+};
+
+void twi_init(enum twiMode);
+int8_t twi_busy(void);
+void twi_join(void);
+void twi_send(uint8_t data);
+
+#endif /* _IOE_TWI_H_ */
diff --git a/include/usart.h b/include/usart.h
new file mode 100644
index 0000000..3ba5382
--- /dev/null
+++ b/include/usart.h
@@ -0,0 +1,64 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "mcu/mcu_def.h"
+#include "tasks.h"
+#include "utils/buffer.h"
+
+#ifndef _USART_H_
+#define _USART_H_
+#ifdef CONFIG_USART
+
+// TODO clock polarity and synchronous mode
+
+#define USART_FRAMEERROR _BV(FE0)
+#define USART_DATAOVERRUN _BV(DOR0)
+#define USART_PARITYERROR _BV(UPE0)
+
+#if CONFIG_USART_INBUFFER_SIZE > 0
+#define _USART_INBUFFER
+volatile IOEBUFFER(uint8_t, _ioe_usart_inbuffer, CONFIG_USART_INBUFFER_SIZE);
+#endif
+#if CONFIG_USART_OUTBUFFER_SIZE > 0
+#define _USART_OUTBUFFER
+volatile IOEBUFFER(uint8_t, _ioe_usart_outbuffer, CONFIG_USART_OUTBUFFER_SIZE);
+#endif
+
+extern volatile int8_t _usart_busy;
+
+
+/*
+ * Initialize USART device.
+ */
+void usart_init_async(void);
+void usart_send(uint8_t data);
+#ifdef _USART_OUTBUFFER
+void usart_send_str(char *str);
+#endif
+#ifdef _USART_INBUFFER
+uint8_t usart_get(void);
+#endif
+static inline uint8_t usart_queryerror(void) {
+ return UCSR0A & (_BV(FE0) | _BV(DOR0) | _BV(UPE0));
+}
+static inline int8_t usart_busy(void) {
+ return _usart_busy;
+}
+#ifdef _USART_INBUFFER
+uint8_t usart_inbuffered(void);
+#endif
+#ifdef _USART_OUTBUFFER
+uint8_t usart_outbuffered(void);
+#endif
+#if (defined CONFIG_USART_INFILE) || (defined CONFIG_USART_OUTFILE)
+FILE *usart_async_open(void);
+#endif
+
+// Following function must be user defined if relevant buffers not used.
+extern void (*usart_receive)(uint8_t data);
+extern void (*usart_sent)(void);
+
+#endif /* CONFIG_USART */
+#endif /* _USART_H_ */
diff --git a/include/usi_spi.h b/include/usi_spi.h
new file mode 100644
index 0000000..18534ab
--- /dev/null
+++ b/include/usi_spi.h
@@ -0,0 +1,66 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#include "mcu/mcu_def.h"
+
+#ifndef _IOE_USI_SPI_H_
+#define _IOE_USI_SPI_H_
+
+#ifndef MCUSUPPORT_USI
+#error "No USI interface is known on your mcu."
+#endif
+
+enum usiSpiMode {
+ // Device is initialized as master
+ USI_SPI_MODE_MASTER,
+ // Device is initialized as slave
+ USI_SPI_MODE_SLAVE,
+};
+
+/*
+ * Initialize SPI on USI device
+ *
+ * Parameters:
+ * mode - Specify mode of SPI interface
+ */
+void usi_spi_init(enum usiSpiMode mode);
+/*
+ * Returns NULL when device is not busy.
+ * When device is busy return values in non-zero.
+ */
+int8_t usi_spi_busy(void);
+/*
+ * Blocks processor until device is not busy.
+ */
+void usi_spi_join(void);
+/*
+ * Swap bytes with slave over SPI.
+ * This function blocks execution until device isn't busy.
+ * WARNING: Invoke this only when interface is initialized in MASTER mode.
+ */
+uint8_t usi_spi_send(uint8_t data);
+/*
+ * Swaps byte with slave over SPI.
+ * This function isn't checking if device is busy, but it's not blocking execution.
+ * WARNING: Invoke this only when interface is initialized in MASTER mode.
+ */
+uint8_t usi_spi_transfer(uint8_t data);
+/*
+ * Expose data for next master request.
+ * Please don't use this when device is busy.
+ * Best place to call this is usi_spi_retrieve().
+ * WARNING: Invoke this only when interface is initialized in SLAVE mode.
+ */
+void usi_spi_expose(uint8_t data);
+
+/*
+ * This function must be defined by user.
+ * This function is called every time transfer is finished.
+ * And until return from this function interrupts are disabled.
+ * WARNING: Please define this function in your code.
+ */
+void usi_spi_receive(uint8_t data);
+
+
+#endif /* _IOE_USI_SPI_H_ */
diff --git a/include/utils/buffer.h b/include/utils/buffer.h
new file mode 100644
index 0000000..66b68ad
--- /dev/null
+++ b/include/utils/buffer.h
@@ -0,0 +1,86 @@
+#ifndef _IOE_BUFFER_H_
+#define _IOE_BUFFER_H_
+
+// Define new buffer
+#define IOEBUFFER(type, name, size) struct { \
+ uint8_t rindex, windex; \
+ type data[size]; \
+ } name;
+
+#define IOEBUFFER_INIT(name, size) { \
+ name.windex = size - 1; \
+ name.rindex = size - 1; \
+ }
+
+#define IOEBUFFER_MODE_BLOCK 0
+#define IOEBUFFER_MODE_OVERWRITE 1
+#define IOEBUFFER_MODE_DROP 2
+// Add data to buffer. If buffer is full then behavior is defined by selected mode.
+#define IOEBUFFER_PUT(name, size, idata, mode) \
+ if (mode == IOEBUFFER_MODE_BLOCK) { \
+ if (name.windex == 0) { \
+ while (name.rindex == size - 1); \
+ } else { \
+ while (name.rindex == name.windex - 1); \
+ } \
+ } \
+ name.data[name.windex] = idata; \
+ if (mode != IOEBUFFER_MODE_DROP || \
+ (name.windex == 0 && name.rindex == size - 1) || \
+ (name.rindex + 1 == name.windex)) { \
+ if (name.windex == 0) \
+ name.windex = size - 1; \
+ else \
+ name.windex--; \
+ } \
+ if (mode == IOEBUFFER_MODE_OVERWRITE && name.windex == name.rindex) { \
+ if (name.windex == size - 1) \
+ name.windex = 0; \
+ else \
+ name.windex++; \
+ } else;
+
+// Get data from buffer and store it to variable
+#define IOEBUFFER_GET(name, size, variable) \
+ if (name.rindex != name.windex) { \
+ variable = name.data[name.rindex]; \
+ if (name.rindex == 0) \
+ name.rindex = size - 1; \
+ else \
+ name.rindex--; \
+ } else { \
+ variable = 0; \
+ }
+
+// Set count of buffered data to variable
+#define IOEBUFFER_CNT(name, size, variable) \
+ if (name.windex < name.rindex) \
+ variable = name.rindex - name.windex; \
+ else if (name.windex > name.rindex) \
+ variable = size - name.windex + name.rindex; \
+ else \
+ variable = 0;
+
+/////////////////////////////////////////////////////////////////////
+
+#ifdef CONFIG_IOE_BUFFER
+#include <stdint.h>
+
+#define IOEBUFFER_F_MODE_BLOCK 0x0
+#define IOEBUFFER_F_MODE_OVERWRITE 0x1
+#define IOEBUFFER_F_MODE_DROP 0x2
+
+typedef struct {
+ uint8_t rindex, windex, size, flags;
+ void **data;
+} IOEBuffer;
+
+int8_t ioebuffer_init(IOEBuffer * buf, uint8_t size, uint8_t flags);
+void ioebuffer_uninit(IOEBuffer * buf);
+int8_t ioebuffer_put(IOEBuffer * buf, void *data);
+int8_t ioebuffer_get(IOEBuffer * buf, void **data);
+void ioebuffer_clean(IOEBuffer * buf);
+uint8_t ioebuffer_cnt(IOEBuffer * buf);
+
+#endif /* CONFIG_IOE_BUFFER */
+#endif /* _IOE_BUFFER_H_ */
diff --git a/include/utils/narray.h b/include/utils/narray.h
new file mode 100644
index 0000000..814d87d
--- /dev/null
+++ b/include/utils/narray.h
@@ -0,0 +1,21 @@
+#include <stdlib.h>
+#include <stdint.h>
+
+#ifndef _IOE_NARRAY_H_
+#define _IOE_NARRAY_H_
+#ifdef CONFIG_IOE_NARRAY
+
+void narray_add(void ***array, void *data);
+void narray_remove(void ***array, void *data);
+size_t narray_size(void ***array);
+inline void narray_free(void ***array) {
+ if (array != NULL) {
+ free(*array);
+ *array = NULL;
+ }
+}
+
+#define fornarray(array, i, data) for (i = 0; (data = array[i]) != 0; i++)
+
+#endif /* CONFIG_IOE_NARRAY */
+#endif /* _IOE_NARRAY_H_ */
diff --git a/include/utils/timers_div.h b/include/utils/timers_div.h
new file mode 100644
index 0000000..9077aac
--- /dev/null
+++ b/include/utils/timers_div.h
@@ -0,0 +1,81 @@
+//#include "../timer.h"
+enum timerDivider {
+ TIMER_DIVIDER_1,
+ TIMER_DIVIDER_8,
+ TIMER_DIVIDER_64,
+ TIMER_DIVIDER_256,
+ TIMER_DIVIDER_1024
+};
+
+#ifndef TIMER_DIV_RESTIME
+#error Please define minimal time (us) before include timers_div.h in TIMER_DIV_RESTIME
+#endif
+
+// Calculate optimal division
+#define _TD_OPTIMAL (TIMER_DIV_RESTIME * F_CPU/1000000L)
+
+// Set minimal and maximal division closest to optimal
+#if _TD_OPTIMAL < 8
+#define _TD_MIN 1
+#define _TD_MAX 8
+#elif _TD_OPTIMAL < 64
+#define _TD_MIN 8
+#define _TD_MAX 64
+#elif _TD_OPTIMAL < 256
+#define _TD_MIN 64
+#define _TD_MAX 256
+#elif _TD_OPTIMAL < 1024
+#define _TD_MIN 256
+#define _TD_MAX 1024
+#else
+#define _TD_MIN 1024
+#define _TD_MAX 1024
+#endif
+
+// Calculate time difference between required time and got time resolution
+#define _TD_MIN_TIME (TIMER_DIV_RESTIME - (_TD_MIN * 1000000L / F_CPU))
+#define _TD_MAX_TIME (TIMER_DIV_RESTIME - (_TD_MAX * 1000000L / F_CPU))
+
+// Do absolute value of calculated numbers
+#if _TD_MIN_TIME < 0
+#define _TD_MIN_TIMEF (_TD_MIN_TIME * -1)
+#else
+#define _TD_MIN_TIMEF _TD_MIN_TIME
+#endif
+#if _TD_MAX_TIME < 0
+#define _TD_MAX_TIMEF (_TD_MAX_TIME * -1)
+#else
+#define _TD_MAX_TIMEF _TD_MAX_TIME
+#endif
+
+// Select closest one
+#if _TD_MIN_TIMEF < _TD_MAX_TIMEF
+#define _TD_TIMER_DIV _TD_MIN
+#else
+#define _TD_TIMER_DIV _TD_MAX
+#endif
+
+// Set macro to enum value
+#if _TD_TIMER_DIV == 1
+#define TIMER_DIV TIMER_DIVIDER_1
+#elif _TD_TIMER_DIV == 8
+#define TIMER_DIV TIMER_DIVIDER_8
+#elif _TD_TIMER_DIV == 64
+#define TIMER_DIV TIMER_DIVIDER_64
+#elif _TD_TIMER_DIV == 256
+#define TIMER_DIV TIMER_DIVIDER_256
+#elif _TD_TIMER_DIV == 1024
+#define TIMER_DIV TIMER_DIVIDER_1024
+#else
+#error Generated unknown timer division. Something is wrong with timers_div.h
+#endif
+
+// Undefine all used variables
+#undef _TD_OPTIMAL
+#undef _TD_MIN
+#undef _TD_MAX
+#undef _TD_MIN_TIME
+#undef _TD_MAX_TIME
+#undef _TD_MIN_TIMEF
+#undef _TD_MAX_TIMEF
+#undef _TD_TIMER_DIV
diff --git a/include/wireless/nrf24l01p.h b/include/wireless/nrf24l01p.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/wireless/nrf24l01p.h