diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/adc.h | 15 | ||||
-rw-r--r-- | include/avr-ioe.h | 2 | ||||
-rw-r--r-- | include/can/global.h | 20 | ||||
-rw-r--r-- | include/can/mcp2515.h | 36 | ||||
-rw-r--r-- | include/can/software.h | 9 | ||||
-rw-r--r-- | include/ioport.h | 55 | ||||
-rw-r--r-- | include/mcu/Kconfig | 11 | ||||
-rw-r--r-- | include/mcu/atmega328p.Kconfig | 8 | ||||
-rw-r--r-- | include/mcu/atmega328p.h | 63 | ||||
-rw-r--r-- | include/mcu/atmega32u4.h | 19 | ||||
-rw-r--r-- | include/mcu/atmega8a.h | 18 | ||||
-rw-r--r-- | include/mcu/attiny4313.h | 46 | ||||
-rw-r--r-- | include/mcu/attiny85.Kconfig | 4 | ||||
-rw-r--r-- | include/mcu/attiny85.h | 28 | ||||
-rw-r--r-- | include/mcu/mcu.h | 18 | ||||
-rw-r--r-- | include/mcu/mcu_def.h | 21 | ||||
-rw-r--r-- | include/pwm.h | 11 | ||||
-rw-r--r-- | include/sensors/dht22.h | 42 | ||||
-rw-r--r-- | include/spi.h | 66 | ||||
-rw-r--r-- | include/tasks.h | 94 | ||||
-rw-r--r-- | include/timer.h | 28 | ||||
-rw-r--r-- | include/twi.h | 24 | ||||
-rw-r--r-- | include/usart.h | 64 | ||||
-rw-r--r-- | include/usi_spi.h | 66 | ||||
-rw-r--r-- | include/utils/buffer.h | 86 | ||||
-rw-r--r-- | include/utils/narray.h | 21 | ||||
-rw-r--r-- | include/utils/timers_div.h | 81 | ||||
-rw-r--r-- | include/wireless/nrf24l01p.h | 0 |
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 |