From 5d29fe79d30f430ae326d9dc57ccfaed6fe61328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Tue, 8 Mar 2016 16:10:33 +0100 Subject: Another full update of current work --- .gitignore | 2 + .gitmodules | 3 + Kconfig | 152 ++++++++++++++++++++++++++++++++++++++++ Makefile | 145 ++++++++++++++++++++++++++++++++++++++ README.md | 10 ++- adc.h | 9 --- avr-ioe.h | 3 - avr-ioe.mk | 62 ----------------- buffers.h | 72 ------------------- can_mcp2515.h | 14 ---- doc/spi.md | 69 ------------------- docs/add_support.md | 0 docs/index.md | 10 +++ docs/modules/ioport.md | 153 +++++++++++++++++++++++++++++++++++++++++ docs/modules/spi.md | 69 +++++++++++++++++++ docs/modules/tasks.md | 37 ++++++++++ docs/modules/timer.md | 0 docs/modules/usart.md | 0 docs/modules/utils/buffer.md | 105 ++++++++++++++++++++++++++++ docs/modules/utils/narray.md | 64 +++++++++++++++++ docs/usage.md | 0 examples/blink/Makefile | 64 +++++++++++++++++ examples/blink/README.md | 0 examples/blink/blink.c | 14 ++++ examples/blink/config | 24 +++++++ examples/blink/config.orig | 24 +++++++ examples/spiblink/Makefile | 66 ++++++++++++++++++ examples/spiblink/config | 23 +++++++ examples/spiblink/config.orig | 23 +++++++ examples/spiblink/makefile | 32 --------- examples/spiblink/master.c | 2 +- examples/spiblink/slave.c | 2 +- examples/usartecho/Makefile | 64 +++++++++++++++++ examples/usartecho/config | 41 +++++++++++ examples/usartecho/config.orig | 41 +++++++++++ examples/usartecho/echo.c | 2 +- examples/usartecho/makefile | 36 ---------- include/adc.h | 15 ++++ include/avr-ioe.h | 2 + include/can/global.h | 20 ++++++ include/can/mcp2515.h | 36 ++++++++++ include/can/software.h | 9 +++ include/ioport.h | 55 +++++++++++++++ include/mcu/Kconfig | 11 +++ include/mcu/atmega328p.Kconfig | 8 +++ include/mcu/atmega328p.h | 63 +++++++++++++++++ include/mcu/atmega32u4.h | 19 +++++ include/mcu/atmega8a.h | 18 +++++ include/mcu/attiny4313.h | 46 +++++++++++++ include/mcu/attiny85.Kconfig | 4 ++ include/mcu/attiny85.h | 28 ++++++++ include/mcu/mcu.h | 18 +++++ include/mcu/mcu_def.h | 21 ++++++ include/pwm.h | 11 +++ include/sensors/dht22.h | 42 +++++++++++ include/spi.h | 66 ++++++++++++++++++ include/tasks.h | 94 +++++++++++++++++++++++++ include/timer.h | 28 ++++++++ include/twi.h | 24 +++++++ include/usart.h | 64 +++++++++++++++++ include/usi_spi.h | 66 ++++++++++++++++++ include/utils/buffer.h | 86 +++++++++++++++++++++++ include/utils/narray.h | 21 ++++++ include/utils/timers_div.h | 81 ++++++++++++++++++++++ include/wireless/nrf24l01p.h | 0 kconfig | 1 + makefile | 16 ----- mcu/ATmega328P.h | 29 -------- mcu/ATmega32U4.h | 19 ----- mcu/ATmega8A.h | 18 ----- mcu/ATtiny4313.h | 17 ----- mcu/ATtiny85.h | 15 ---- mcu/mcu.h | 18 ----- mcu/mcu_def.h | 21 ------ mkdocs.yml | 20 ++++++ pwm.h | 11 --- sensor_dht22.h | 39 ----------- spi.h | 69 ------------------- src/adc.c | 4 ++ src/can/mcp2515.c | 52 ++++++++++++++ src/can_mcp2515.c | 0 src/ioport.c | 113 ++++++++++++++++++++++++++++++ src/pcint.c | 32 --------- src/sensor_dht22.c | 117 ------------------------------- src/sensors/dht22.c | 117 +++++++++++++++++++++++++++++++ src/spi.c | 24 +++---- src/tasks.c | 64 ++++++++++++++--- src/timer.c | 130 +++++++++++++++++++++++++++++++++- src/usart.c | 131 +++++++++++++++++------------------ src/usi_spi.c | 4 +- src/utils/buffer.c | 70 +++++++++++++++++++ src/utils/narray.c | 36 ++++++++++ tasks.h | 44 ------------ template/Makefile | 72 +++++++++++++++++++ template/README.md | 9 +++ template/avr-ioe | 1 + template/main.c | 5 ++ time.h | 15 ---- timer.h | 147 --------------------------------------- twi.h | 25 ------- usart.h | 68 ------------------ usi_spi.h | 66 ------------------ 102 files changed, 2850 insertions(+), 1182 deletions(-) create mode 100644 .gitmodules create mode 100644 Kconfig create mode 100644 Makefile delete mode 100644 adc.h delete mode 100644 avr-ioe.h delete mode 100644 avr-ioe.mk delete mode 100644 buffers.h delete mode 100644 can_mcp2515.h delete mode 100644 doc/spi.md create mode 100644 docs/add_support.md create mode 100644 docs/index.md create mode 100644 docs/modules/ioport.md create mode 100644 docs/modules/spi.md create mode 100644 docs/modules/tasks.md create mode 100644 docs/modules/timer.md create mode 100644 docs/modules/usart.md create mode 100644 docs/modules/utils/buffer.md create mode 100644 docs/modules/utils/narray.md create mode 100644 docs/usage.md create mode 100644 examples/blink/Makefile create mode 100644 examples/blink/README.md create mode 100644 examples/blink/blink.c create mode 100644 examples/blink/config create mode 100644 examples/blink/config.orig create mode 100644 examples/spiblink/Makefile create mode 100644 examples/spiblink/config create mode 100644 examples/spiblink/config.orig delete mode 100644 examples/spiblink/makefile create mode 100644 examples/usartecho/Makefile create mode 100644 examples/usartecho/config create mode 100644 examples/usartecho/config.orig delete mode 100644 examples/usartecho/makefile create mode 100644 include/adc.h create mode 100644 include/avr-ioe.h create mode 100644 include/can/global.h create mode 100644 include/can/mcp2515.h create mode 100644 include/can/software.h create mode 100644 include/ioport.h create mode 100644 include/mcu/Kconfig create mode 100644 include/mcu/atmega328p.Kconfig create mode 100644 include/mcu/atmega328p.h create mode 100644 include/mcu/atmega32u4.h create mode 100644 include/mcu/atmega8a.h create mode 100644 include/mcu/attiny4313.h create mode 100644 include/mcu/attiny85.Kconfig create mode 100644 include/mcu/attiny85.h create mode 100644 include/mcu/mcu.h create mode 100644 include/mcu/mcu_def.h create mode 100644 include/pwm.h create mode 100644 include/sensors/dht22.h create mode 100644 include/spi.h create mode 100644 include/tasks.h create mode 100644 include/timer.h create mode 100644 include/twi.h create mode 100644 include/usart.h create mode 100644 include/usi_spi.h create mode 100644 include/utils/buffer.h create mode 100644 include/utils/narray.h create mode 100644 include/utils/timers_div.h create mode 100644 include/wireless/nrf24l01p.h create mode 160000 kconfig delete mode 100644 makefile delete mode 100644 mcu/ATmega328P.h delete mode 100644 mcu/ATmega32U4.h delete mode 100644 mcu/ATmega8A.h delete mode 100644 mcu/ATtiny4313.h delete mode 100644 mcu/ATtiny85.h delete mode 100644 mcu/mcu.h delete mode 100644 mcu/mcu_def.h create mode 100644 mkdocs.yml delete mode 100644 pwm.h delete mode 100644 sensor_dht22.h delete mode 100644 spi.h create mode 100644 src/adc.c create mode 100644 src/can/mcp2515.c delete mode 100644 src/can_mcp2515.c create mode 100644 src/ioport.c delete mode 100644 src/pcint.c delete mode 100644 src/sensor_dht22.c create mode 100644 src/sensors/dht22.c create mode 100644 src/utils/buffer.c create mode 100644 src/utils/narray.c delete mode 100644 tasks.h create mode 100644 template/Makefile create mode 100644 template/README.md create mode 120000 template/avr-ioe create mode 100644 template/main.c delete mode 100644 time.h delete mode 100644 timer.h delete mode 100644 twi.h delete mode 100644 usart.h delete mode 100644 usi_spi.h diff --git a/.gitignore b/.gitignore index 19ddade..a7c9ab6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ *~ .* !/.gitignore +!/.gitmodules *.o *.d *.hex *.elf trash +libioe.a diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a8be02a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "kconfig"] + path = kconfig + url = https://github.com/guillon/kconfig.git diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000..55d10f3 --- /dev/null +++ b/Kconfig @@ -0,0 +1,152 @@ +mainmenu "AVR-IOE configuration" + +source "include/mcu/Kconfig" + +config F_CPU + int "CPU frequency in kHz (F_CPU)" + default 16000 + +# Toolchain ##################################################################### + +menu "Compilation options" + +config GNUTOOLCHAIN_PREFIX + string "GNU Toolchain prefix" + default "avr-" + +config CONFCFLAGS + string "Compilation CFlags" + default "-Os -ffunction-sections -fdata-sections -fshort-enums -Wall" + +endmenu + +# IO Ports ###################################################################### + +config MCUSUPPORT_IOPORTS + bool + default n + +config CONFIG_IOPORTS + bool "Input/Output ports" + default y + depends on MCUSUPPORT_IOPORTS + +config MCUSUPPORT_PCINT0 + bool + default n +config MCUSUPPORT_PCINT1 + bool + default n +config MCUSUPPORT_PCINT2 + bool + default n + +config CONFIG_IOPORTS_PCINT + bool "Input/Output ports change interrupts" + depends on CONFIG_IOPORTS + depends on MCUSUPPORT_PCINT0 || MCUSUPPORT_PCINT1 || MCUSUPPORT_PCINT2 + +# SPI ########################################################################### + +config MCUSUPPORT_SPI + bool + default n + +config CONFIG_SPI + bool "Serial peripheral interface" + depends on MCUSUPPORT_SPI + +# USART ######################################################################### +config MCUSUPPORT_USART + bool + default n + +menuconfig CONFIG_USART + bool "Universal synchronous/asynchronous transceiver" + depends on MCUSUPPORT_USART + +if CONFIG_USART + +config CONFIG_USART_BAUD + int "Baudrate" + default 115200 + +choice USART_PARITY_C + prompt "Parity" +config USART_PARITY_C_NONE + bool "None" +config USART_PARITY_C_ODD + bool "Odd" +config USART_PARITY_C_EVEN + bool "Even" +endchoice +config CONFIG_USART_PARITY + string + default "USART_PARITY_NONE" if USART_PARITY_C_NONE + default "USART_PARITY_ODD" if USART_PARITY_C_ODD + default "USART_PARITY_EVEN" if USART_PARITY_C_EVEN + +config CONFIG_USART_DATABITS + int "Data bits" + default 8 + +choice USART_STOPBIT_C + prompt "Stop bit" +config USART_STOPBIT_C_SINGLE + bool "Single" +config USART_STOPBIT_C_DOUBLE + bool "Double" +endchoice +config CONFIG_USART_STOPBIT + string + default "USART_STOPBIT_SINGLE" if USART_STOPBIT_C_SINGLE + default "USART_STOPBIT_DOUBLE" if USART_STOPBIT_C_DOUBLE + +config CONFIG_USART_OUTPUT_BUFFER + bool "Use output buffer" + default n + +config CONFIG_USART_OUTBUFFER_SIZE + int "Output buffer size in bytes." if CONFIG_USART_OUTPUT_BUFFER + default 0 if CONFIG_USART_OUTPUT_BUFFER + default 32 + +choice USART_OUTBUFFER_MODE_C + prompt "Output buffer replacement policy" if CONFIG_USART_OUTPUT_BUFFER +config USART_OUTBUFFER_MODE_C_BLOCK + bool "Block" +config USART_OUTBUFFER_MODE_C_OVERWRITE + bool "Overwrite" +config USART_OUTBUFFER_MODE_C_DROP + bool "Drop" +endchoice +config CONFIG_USART_OUTBUFFER_MODE + int + default 1 if USART_OUTBUFFER_MODE_C_OVERWRITE + default 2 if USART_OUTBUFFER_MODE_C_DROP + default 0 + +config CONFIG_USART_INPUT_BUFFER + bool "Use input buffer" + +config CONFIG_USART_INBUFFER_SIZE + int "Input buffer size in bytes." if CONFIG_USART_INPUT_BUFFER + default 0 if CONFIG_USART_INPUT_BUFFER + default 32 + +choice USART_INBUFFER_MODE_C + prompt "Input buffer replacement policy" if CONFIG_USART_INPUT_BUFFER +config USART_INBUFFER_MODE_C_BLOCK + bool "Block" +config USART_INBUFFER_MODE_C_OVERWRITE + bool "Overwrite" +config USART_INBUFFER_MODE_C_DROP + bool "Drop" +endchoice +config CONFIG_USART_INBUFFER_MODE + int + default 1 if USART_INBUFFER_MODE_C_OVERWRITE + default 2 if USART_INBUFFER_MODE_C_DROP + default 0 + +endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..57c4095 --- /dev/null +++ b/Makefile @@ -0,0 +1,145 @@ +MAKEFLAGS += --no-builtin-rules + +SRC = src/spi.c \ + src/usart.c \ + src/timer.c \ + src/tasks.c \ + src/ioport.c \ + src/sensors/dht22.c \ + +OBJ = $(patsubst %.c,%.o,$(SRC)) +DEP = $(patsubst %.c,%.d,$(SRC)) + +# default configuration path. Can be changed by enviroment to build with +# separate configuration files. +CONFIG ?= .config + +.PHONY: all +# Check if we have configuration" +ifneq ("$(wildcard $(CONFIG))","") +all: libioe.a +else +all: help $(CONFIG) +endif + +$(CONFIG): + @echo Please generate configuration first using config or menuconfig target + @exit 1 + +.PHONY: oldconfig +oldconfig: + @[ ! -f "$(CONFIG)" ] || [ ! -f "$(CONFIG).orig" ] || mv "$(CONFIG).orig" config + @$(MAKE) -f kconfig/GNUmakefile --no-print-directory \ + TOPDIR=. SRCDIR=kconfig oldconfig + @[ ! -f config ] || sed 's/="\(.*\)"/=\1/' config > "$(CONFIG)" + @[ ! -f config ] || mv config "$(CONFIG).orig" + @[ ! -f config.old ] || mv config.old "$(CONFIG).old" + +.PHONY: config +config: + @[ ! -f "$(CONFIG)" ] || [ ! -f "$(CONFIG).orig" ] || mv "$(CONFIG).orig" config + @$(MAKE) -f kconfig/GNUmakefile --no-print-directory \ + TOPDIR=. SRCDIR=kconfig config + @[ ! -f config ] || sed 's/="\(.*\)"/=\1/' config > "$(CONFIG)" + @[ ! -f config ] || mv config "$(CONFIG).orig" + @[ ! -f config.old ] || mv config.old "$(CONFIG).old" + +.PHONY: menuconfig +menuconfig: + @[ ! -f "$(CONFIG)" ] || [ ! -f "$(CONFIG).orig" ] || mv "$(CONFIG).orig" config + @$(MAKE) -f kconfig/GNUmakefile --no-print-directory \ + TOPDIR=. SRCDIR=kconfig menuconfig + @[ ! -f config ] || sed 's/="\(.*\)"/=\1/' config > "$(CONFIG)" + @[ ! -f config ] || mv config "$(CONFIG).orig" + @[ ! -f config.old ] || mv config.old "$(CONFIG).old" +# Note about this file moving madness: +# avr-ioe is using Kconfig for configuration and it is not prepared too well for +# nested projects (at least I don't know way). This unfortunately means that to +# have configuration in parent project, We have to move it every time we are +# generating it. Also upper projects can't use Kconfig for its self configuration. + +# Check if we have configuration" +ifneq ("$(wildcard $(CONFIG))","") +ifeq (,$(findstring clean,$(MAKECMDGOALS))) +ifeq (,$(findstring help,$(MAKECMDGOALS))) +ifeq (,$(findstring docs,$(MAKECMDGOALS))) +ifeq (,$(findstring serve-docs,$(MAKECMDGOALS))) +ifeq (,$(findstring clean-docs,$(MAKECMDGOALS))) + +include $(CONFIG) +-include $(DEP) + +CFLAGS = $(shell echo $(CONFCFLAGS)) $(shell echo -DF_CPU=$(F_CPU)000L) \ + -mmcu=$(MMCU) -Iinclude -imacros .config.h +GCC = $(GNUTOOLCHAIN_PREFIX)gcc +AR = $(GNUTOOLCHAIN_PREFIX)ar + +libioe.a: $(OBJ) + @echo " AR $@" + @$(AR) -crs $@ $^ + +$(OBJ): %.o: %.c .config.h + @echo " CC $@" + @$(GCC) $(CFLAGS) -c -o $@ $< + +$(DEP): %.d: %.c .config.h + @echo " DEP $@" + @$(GCC) -MM -MG -MT '$*.o $@' $(CFLAGS) -c -o $@ $< + +.config.h: $(CONFIG) + @echo " GEN .config.h" + @grep -v "^#" $(CONFIG) | grep "CONFIG_" | sed 's/=/ /;s/^/#define /' > $@ +# This is not optimal because configuration change results to complete project +# rebuild instead of only rebuilding required files. + +endif +endif +endif +endif +endif +else + +libioe.a: + @echo Please generate configuration first using config or menuconfig target + +endif + +.PHONY: clean +clean: + @echo " CLEAN OBJ" + @$(RM) $(OBJ) + @echo " CLEAN DEP" + @$(RM) $(DEP) .config.h + @echo " CLEAN libioe.a" + @$(RM) libioe.a + +.PHONY: docs +docs: + @echo " DOC $@" + @mkdocs build + + +.PHONY: serve-docs +serve-docs: + @mkdocs serve + +.PHONY: clean-docs +clean-docs: + @echo " CLEAN docs" + @$(RM) -r site + +.PHONY: distclean +distclean: clean clean-docs + @echo " CLEAN CONFIG" + @$(RM) $(CONFIG) $(CONFIG).orig + +.PHONY: help +help: + @echo "all/libioe.a - Build library" + @echo "config - Start configuration program" + @echo "menuconfig - NCurses based configuration program" + @echo "docs - Build documentation" + @echo "server-docs - Start temporally http server with documentation" + @echo "help - Prints this text" + @echo "clean - Removing all object files generated from source files" + @echo "clean-docs - Remove generated documentation" diff --git a/README.md b/README.md index 17d3110..2682fb9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ #AVR-IOE ##AVR input/output expansion -This is package of code for SPI, TWI and USART interfaces from AVR -micro-controllers. +This is library that implements different input/output interfaces and other +utilities. Its target is to create simple and highly configurable pack of code for +simplifying development for AVR micro-controllers. Code is targeted for five different chips, ATmega328p, ATmega32u4, ATmega8A, ATtiny4313 and ATtiny85. But support for more chips can be added. + +### Getting started +To use this library, you have to create new project (you can copy template +directory). Then copy/clone this repository to your project. For more information +see file `doc/usage.md`. diff --git a/adc.h b/adc.h deleted file mode 100644 index 3eaea41..0000000 --- a/adc.h +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include - -#ifndef _IOE_ADC_H_ -#define _IOE_ADC_H_ - - -#endif /* _IOE_ADC_H_ */ diff --git a/avr-ioe.h b/avr-ioe.h deleted file mode 100644 index ac58ee7..0000000 --- a/avr-ioe.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "buffers.h" -#include "spi.h" -#include "usart.h" diff --git a/avr-ioe.mk b/avr-ioe.mk deleted file mode 100644 index fb818e8..0000000 --- a/avr-ioe.mk +++ /dev/null @@ -1,62 +0,0 @@ -ifndef IOE_PREFIX - IOE_PREFIX = . -endif - -IOE_SRC = $(IOE_PREFIX)/src/spi.c \ - $(IOE_PREFIX)/src/usart.c \ - $(IOE_PREFIX)/src/timer.c \ - $(IOE_PREFIX)/src/tasks.c \ - $(IOE_PREFIX)/src/pcint.c \ - $(IOE_PREFIX)/src/sensor_dht22.c \ - -IOE_OBJ = $(patsubst %.c,%.o,$(IOE_SRC)) -IOE_DEP = $(patsubst %.c,%.d,$(IOE_SRC)) - - -ifndef IOE_ONLYPATHS # Following section can be suppressed by defining this variable - -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),help) --include $(IOE_DEP) -endif -endif - -ifndef F_CPU - $(error Please define F_CPU variable in makefile before including avr-ioe.mk) -endif -ifndef MMCU - $(error Pleade define MMCU variable in makefile before including avr-ioe.mk) -endif -IOE_CFLAGS ?= -Os -ffunction-sections -fdata-sections -fshort-enums -Wall \ - -DF_CPU=$(F_CPU) -mmcu=$(MMCU) -IOE_GCC ?= avr-gcc - -ifndef IOE_SHORTOUTPUT -$(IOE_OBJ): %.o: %.c - $(IOE_GCC) $(IOE_CFLAGS) -c -o $@ $< - -$(IOE_DEP): %.d: %.c - $(IOE_GCC) -MM -MG -MT '$*.o $@' $(IOE_CFLAGS) -c -o $@ $< - -.PHONY: ioeclean -ioeclean:: - $(RM) $(IOE_OBJ) - $(RM) $(IOE_DEP) -else -$(IOE_OBJ): %.o: %.c - @echo " IOE CC $@" - @$(IOE_GCC) $(IOE_CFLAGS) -c -o $@ $< - -$(IOE_DEP): %.d: %.c - @echo " IOE DEP $@" - @$(IOE_GCC) -MM -MG -MT '$*.o $@' $(IOE_CFLAGS) -c -o $@ $< - -.PHONY: ioeclean -ioeclean:: - @echo " IOE CLEAN OBJ" - @$(RM) $(IOE_OBJ) - @echo " IOE CLEAN DEP" - @$(RM) $(IOE_DEP) -endif - -endif diff --git a/buffers.h b/buffers.h deleted file mode 100644 index 497a21c..0000000 --- a/buffers.h +++ /dev/null @@ -1,72 +0,0 @@ -/* This defines common buffer code for whole library. - * It is preprocessor generated code. - * Preprocessor variables chose different implementations. But final - * implementation is only few lines of code. This way it is included directly - * to code. - */ -#include "tasks.h" - -#ifndef _IOE_BUFFERS_H_ -#define _IOE_BUFFERS_H_ - -// Define new buffer -#define IOEBUFFER(name, size) struct { \ - uint8_t rindex, windex; \ - uint8_t 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, data, 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] = data; \ - 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; - -#endif /* _IOE_BUFFERS_H_ */ diff --git a/can_mcp2515.h b/can_mcp2515.h deleted file mode 100644 index 618051e..0000000 --- a/can_mcp2515.h +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include - -#include "spi.h" - -#ifndef _IOE_CAN_MCP2515_H_ -#define _IOE_CAN_MCP2515_H_ -#ifdef CONFIG_IOE_CAN_MCP2515 - -void can_mcp2515_init(void); - -#endif /* CONFIG_IOE_CAN_MCP2515 */ -#endif /* _IOE_CAN_MCP2515_H_ */ diff --git a/doc/spi.md b/doc/spi.md deleted file mode 100644 index 438d32d..0000000 --- a/doc/spi.md +++ /dev/null @@ -1,69 +0,0 @@ -Serial peripheral interface ---------------------------- -This interface is link to MOSI and MISO pins. Also SS pin is used when slave mode initialized. - -## Functions -### spi_init -```C -static inline void spi_init(enum spiMode mode) -``` -Initializes SPI interface. -Parameters: - mode - Specify mode of SPI interface - -NOTE: Global interrupt must be enabled for right function of SPI. - -### spi_busy -```C -static inline int8_t spi_busy(void) -``` -Returns NULL when device is not busy. -When device is busy return values in non-zero. - -### spi_join -```C -static inline void spi_join(void) -``` -Blocks processor until device is not busy. - -### spi_send -```C -static inline uint8_t spi_send(uint8_t data) -``` -Swap bytes with slave over SPI. -This function blocks execution until device isn't busy (transfer completed). -WARNING: Invoke this only when interface is initialized in MASTER mode. - -### spi_transfer -```C -static inline void spi_transfer(uint8_t data) -``` -Transfer byte to slave over SPI. -This function isn't blocking execution until transfer is complete. -Always call spi_join before this function when called outside of spi_receive(). -WARNING: Invoke this only when interface is initialized in MASTER mode. - -### spi_expose -```C -static inline void spi_expose(uint8_t data) -``` -Expose data for next master request. -Please don't use this when device is busy. -Best place to call this is spi_receive(). -WARNING: Invoke this only when interface is initialized in SLAVE mode. - -## Function pointer spi_receive -```C -extern void (*spi_receive)(uint8_t data) -``` -This function is called every time transfer is finished. -And until return from this function interrupts are disabled. - -## Enum spiMode -```C -enum spiMode { - SPI_MODE_MASTER, - SPI_MODE_SLAVE -}; -``` -This is used as parameter for spi_init function. diff --git a/docs/add_support.md b/docs/add_support.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..4c261ff --- /dev/null +++ b/docs/index.md @@ -0,0 +1,10 @@ +AVR Input/Output expansion +========================== + +Modules +------- +| Module | Header | Enable Config | Description | +|-------------------------------|----------|-------------------------------------------|--------------------------------------------------------| +| [IO Ports](modules/ioport.md) | ioport.h | CONFIG_IOPORTS and CONFIG_IOE_PCINTERRUPT | Simple input/output port access | +| [SPI](modules/spi.md) | spi.h | CONFIG_SPI | Serial peripheral interface | +| [USART](modules/usart.md) | usart.h | CONFIG_USART | Universal synchronous/asynchronous receive/transmitter | diff --git a/docs/modules/ioport.md b/docs/modules/ioport.md new file mode 100644 index 0000000..e777e0c --- /dev/null +++ b/docs/modules/ioport.md @@ -0,0 +1,153 @@ +IO port +======= +To use include: `ioport.md` +And define: `CONFIG_IOE_IOPORT` + +Defines simple access to io ports. This allows runtime access to any pin with just +serialized identifier. + +Most of the functions has group and mask arguments. Group is letter, but in this +library is represented as number and exact number is defined as macro definition. +Mask is one shifted by index number(use \_BV macro). This way can be +addressed all IO ports. Exact identification consult with datasheet. You can also +use more than one index number and control more ports in single group with single +command. + +WARNING: No check is implemented for right group number. Usage of unsupported +value is undefined (write to other parts of memory can happen). + +## References +### For output +#### Function io_setout +```C +static inline void io_setout(uint8_t group, uint8_t mask) +``` +Configures port of `group` with `mask` as output. +Parameters: + group - Character specifying exact port group + mask - Binary shifted 1. Shift is equal to port index in specified group. + +#### Function io_hight +```C +static inline void io_hight(uint8_t group, uint8_t mask) +``` +Sets output port to hight (also can be called as 1). +WARNING: Invoke this only if io_setout is called before. +Parameters: + group - Character specifying exact port group + mask - Binary shifted 1. Shift is equal to port index in specified group. + +#### Function io_low +```C +static inline void io_low(uint8_t group, uint8_t mask) +``` +Sets output port to low (also called as 0). +WARNING: Invoke this only if io_setout is called before. +Parameters: + group - Number specifying exact port group + mask - Binary shifted 1. Shift is equal to port index in specified group. + +#### Function io_set +```C +static inline void io_set(uint8_t group, uint8_t mask, int8_t val) +``` +Sets output port to value passed as argument. +WARNING: Invoke this only if io_setout is called before. +Parameters: + group - Number specifying exact port group + mask - Binary shifted 1. Shift is equal to port index in specified group. + +### For input +#### Function io_setin +```C +static inline void io_setin(uint8_t group, uint8_t mask, + enum ioeIOInResistor resistor) +``` +Configures port of `group` with `mask` as input with specified pull-up/down +resistor. +Parameters: + group - Number specifying exact port group + mask - Binary shifted 1. Shift is equal to port index in specified group. + +#### Function io_get +```C +static inline int8_t io_get(uint8_t group, uint8_t mask) +``` +Returns current value of port. Note that you can use this also if port is +configured as output. +Parameters: + group - Number specifying exact port group + mask - Binary shifted 1. Shift is equal to port index in specified group. + +#### Enum ioeIOInResistor +```C +enum ioeIOInResistor { + IOE_IO_PULLUP, + IOE_IO_PULLDOWN +}; +``` +This enum is used as argument for io_setin. Names should be self explanatory +in this case. + +### Pin change interrupts +#### Function io_change_sethook +```C +int8_t io_change_sethook(uint8_t group, uint8_t mask, uint8_t edge, + void (*change) (uint8_t group, uint8_t mask)) +``` +Registers function `change` as hook for pin change interrupt. `group` and `mask` +specifies port and edge specifies on what edge should hook be called. `edge` can +be IO_RISING or IO_FALLING or their binary combination with operator +`|`. +WARNING: `change` call is call during interrupt handling. You shouldn't be +blocking execution for long time. +Parameters: + group - Number specifying exact port group + mask - Binary shifted 1. Shift is equal to port index in specified group. + edge - Signals on what edge should be hook called. + change - Pointer to function used as interupt hook + +#### Function io_change_remhook +```C +int8_t io_change_remhook(void (*change) (uint8_t group, uint8_t mask)) +``` +Removes `change` hook. +Parameters: + change - Pointer to function used as hook + +### Others +#### Definitions IO_{GROUP} +This defines exact numbers related to data-sheet groups. Always use these +definition not direct numbers, you can ensure cross MCU support this way. + +#### Definitions IO_{GROUP}{INDEX} +Because specifying group and mask as separate parameters is not always optimal, +mcu support file should define all ports in form of single line definition in +format `IOE_IO_{GROUP}{INDEX}`. Disadvantage is that with these definitions you +can't use binary conjunction and so only one pin can be controlled with it. + +## Relevant examples +* blink +* pcinterrupt + +## Adding support +For more information on how add support, see `doc/add_support.md`. +Main definition is `MCUSUPPORT_IOPORT`. Define it to enable support. + +### IO_{GROUP} +This should define any number that is handy for implementation of `IOE_IOE_PIN`, +`IOE_IO_DDR` and `IOE_IO_PORT`. + +### IO_{PIN/DDR/PORT} +These should calculate exact pointers to register `PORT{GROUP}` for PORT variant +and likewise for others with group as argument. Common implementation would be +like this: +```C +#define IOE_IO_PIN(GROUP) (* (volatile uint8_t *)(PINB + 0x3*GROUP)) +``` +### IO_{GROUP}{INDEX} +This should be pair of group and one binary shifted to left relative to index. + +### MCUSUPPORT_PCINT{NUM} +This defines that MCU supports specific pin change interrupt group. Also it +defines value that is number of pins in group. diff --git a/docs/modules/spi.md b/docs/modules/spi.md new file mode 100644 index 0000000..3ae730c --- /dev/null +++ b/docs/modules/spi.md @@ -0,0 +1,69 @@ +Serial peripheral interface +=========================== +This interface is link to MOSI and MISO pins. Also SS pin is used when slave mode initialized. + +## References +### spi\_init +```C +static inline void spi_init(enum spiMode mode) +``` +Initializes SPI interface. +Parameters: + mode - Specify mode of SPI interface + +NOTE: Global interrupts must be enabled for right function of SPI. + +### spi\_busy +```C +static inline int8_t spi_busy(void) +``` +Returns NULL when device is not busy. +When device is busy return values in non-zero. + +### spi\_join +```C +static inline void spi_join(void) +``` +Blocks processor until device is not busy. + +### spi\_send +```C +static inline uint8_t spi_send(uint8_t data) +``` +Swap bytes with slave over SPI. +This function blocks execution until device isn't busy (transfer completed). +WARNING: Invoke this only when interface is initialized in MASTER mode. + +### spi\_transfer +```C +static inline void spi_transfer(uint8_t data) +``` +Transfer byte to slave over SPI. +This function isn't blocking execution until transfer is complete. +Always call spi\_join before this function when called outside of spi\_receive(). +WARNING: Invoke this only when interface is initialized in MASTER mode. + +### spi\_expose +```C +static inline void spi_expose(uint8_t data) +``` +Expose data for next master request. +Please don't use this when device is busy. +Best place to call this is spi\_receive(). +WARNING: Invoke this only when interface is initialized in SLAVE mode. + +## Function pointer spi\_receive +```C +extern void (*spi_receive)(uint8_t data) +``` +This function is called every time transfer is finished. +And until return from this function interrupts are disabled. + +## Enum spiMode +```C +enum spiMode { + SPI_MODE_MASTER, + SPI_MODE_SLAVE +}; +``` +This is used as parameter for spi\_init function. diff --git a/docs/modules/tasks.md b/docs/modules/tasks.md new file mode 100644 index 0000000..0078f00 --- /dev/null +++ b/docs/modules/tasks.md @@ -0,0 +1,37 @@ +Tasks +===== +Tasks allows separate jobs. + +## Functions +### tasks_run +```C +int8_t tasks_run(void) +``` +This function starts tasks execution. Should be called after all task slots are +prepared and at least one task is started. This function exits if no task exist or +all existing tasks exited. + +### task_init + +## Structures +### Task +```C +typedef struct { + uint8_t flags; + void (*func) (void); +} Task; +``` + +### TaskSlot +```C +typedef struct { + uint8_t flags; + Task *task; + uint8_t stack_size; + uint8_t stack[]; +} TaskSlot; +``` + +### Mutex + +### Semaphore diff --git a/docs/modules/timer.md b/docs/modules/timer.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/modules/usart.md b/docs/modules/usart.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/modules/utils/buffer.md b/docs/modules/utils/buffer.md new file mode 100644 index 0000000..4365c25 --- /dev/null +++ b/docs/modules/utils/buffer.md @@ -0,0 +1,105 @@ +buffer +====== +In whole project are used ring buffers. This is so common that handling them is +exported to separated header file. In fact it contains two implementations of +buffers. One implementation is defined using preprocessor macros. Another one is +plain C code. + +## Preprocessor implementation +Preprocessor implementation is expected to be faster and less memory intense. Also +more suitable for buffers of simple types (such us int). But this buffer has to be +defined with known size at compile time and can't be resized. All this makes it +good implementation for IO devices input and output buffers, but less for more +complicated tasks containing for example sorting. + +### Macros +#### IOEBUFFER +```C +IOEBUFFER(type, name, size) +``` +This macro defines buffer. Use it to define new buffer. +##### Parameters +| type | Specify type of elements in buffer. Can be any valid C type | +| name | Name of buffer. This is C variable name. | +| size | Numerical value of buffer size | + +#### IOEBUFFER_INIT +```C +IOEBUFFER_INIT(name, size) +``` +Use this to initialize buffer. Parameter `size` must be same as for IOEBUFFER +(definition of buffer). You can use this also to reset buffer (remove all data +from buffer). +##### Parameters +| name | Name if buffer. This is C variable name. | +| size | Numerical value of buffer size | + +#### IOEBUFFER_PUT +```C +IOEBUFFER_PUT(name, size, data, mode) +``` +Use this macro to add new data to buffer. +##### Parameters +| name | Name of buffer. This is C variable name. | +| size | Numerical value of buffer size | +| data | Data to be stored to buffer | +| mode | This specifies action if buffer is full. | +##### Modes +| IOEBUFFER_MODE_BLOCK | Block execution until buffer has some free space. | +| IOEBUFFER_MODE_OVERWRITE | Overwrites oldest added (fist to be read) | +| IOEBUFFER_MODE_DROP | New data won't be stored to buffer if full | + +#### IOEBUFFER_GET +```C +IOEBUFFER_GET(name, size, variable) +``` +Get value from buffer. Value is stored in `variable` (it is variable of same type +as buffer data, not pointer to variable of same type). If no data is in buffer, +variable is set to NULL. +##### Parameters +| name | Name of buffer. This is C variable name. | +| size | Numerical value of buffer size. | +| variable | Variable in which data will be stored in. | + +#### IOEBUFFER_CNT +```C +IOEBUFFER_CNT(name, size, variable) +``` +Counts number of data entries in buffer and saves value to variable. +##### Parameters +| name | Name of buffer. This is C variable name. | +| size | Numerical value of buffer size. | +| variable | Int/Unsigned type variable where data count will be stored. | + +## C implementation +C implementation is more general. Size is defined by calling initialization +function. But it is using general pointers, so it is only able store pointers. + +As buffer identification is used defined type `IOEBuffer`. All functions takes +pointer to this type as parameter. Because of this, it won't be described for +every function. + +### Functions +#### ioebuffer_init +```C +int8_t ioebuffer_init(IOEBuffer *buf, uint8_t size, uint8_t flags) +``` +Initialized buffer and allocates required resources. +##### Parameters +| size | Number of elements to be maximally stored in buffer | +| flags | TODO +##### Flags +TODO + +#### ioebuffer_uninit +```C +void ioebuffer_uninit(IOEBuffer *buf) +``` +Frees all resources allocated during initialization of buffer. Use this every time +you are freeing buffer. + +#### ioebuffer_put +```C +int8_t ioebuffer_put(IOEBuffer *buf, void *data) +``` +Add `data` to buffer diff --git a/docs/modules/utils/narray.md b/docs/modules/utils/narray.md new file mode 100644 index 0000000..3e64f67 --- /dev/null +++ b/docs/modules/utils/narray.md @@ -0,0 +1,64 @@ +narray.h +======== +This implements some helping functions for null terminated arrays. Null terminated +arrays are used across whole project because they are simple and don't waste +memory space. Their disadvantage is more complicated implementation of utility +functions and much longer adding time (they are reallocated every time new data +are added). + +This implementation is limited to only contains 255 elements(limited by uint8_t +type). But it should be enough for basic usage. If you need store more than that, +you should use different approach. Also only pointers can be stored. + +To define null terminated array just define pointer to you required pointer and set +it to NULL. Such narray is handled as empty. Example: +```C +int **narray = 0; +``` +After adding some data (in example case data of type `int*`) you can access them +same as if you would working with simple array (`narray[i]`). Last element it such +array is `NULL`. No more valid data are stored after `NULL` (This also means that +`NULL` can't be stored to narray). + +All functions are taking as parameter `void ***array`, which is pointer to null +terminated array. This parameter won't be described in functions. + +## Functions and macros +### narray_add +```C +void narray_add(void ***array, void *data) +``` +Add data to end of the array. This increases size of the array by one (two bytes). +#### Parameters +| data | data to be stored to array | + +### narray_remove +```C +void narray_remove(void ***array, void *data) +``` +Remove specified data from array. This effectively decreases size of the array by +one (two bytes). +#### Parameters +| data | data to be removed from array | + +### narray_size +```C +size_t narray_size(void ***array) +``` +Returns size of array. + +### narray_free +```C +inline void narray_free(void ***array) +``` +Frees whole array if allocated. + +### fornarray +```C +#define fornarray(array, i, data) for (i = 0; (data = array[i]) != 0; i++) +``` +This is macro. It implements simple foreach cycle. +#### Parameters +| array | array it self (void ** not pointer) | +| i | unsigned integer (uint8_t) | +| data | variable which will be used to access data | diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..e69de29 diff --git a/examples/blink/Makefile b/examples/blink/Makefile new file mode 100644 index 0000000..43941b6 --- /dev/null +++ b/examples/blink/Makefile @@ -0,0 +1,64 @@ +MAKEFLAGS += --no-builtin-rules +PROJNAME = blink + +SRC = blink.c + +OBJ = $(patsubst %.c,%.o,$(SRC)) # This creates list of *.o files from *.c + +.PHONY: all +ifneq ("$(wildcard config)","") # Checking if configuration exists +all: $(PROJNAME).hex + @echo Now you can flash $< to your chip. +else +all: help +endif + +# Edit here help like you ever want +.PHONY: help +help: + @echo "AVR-IOE blink example" + @echo " all - Build example" + @echo " config - Start configuration program" + @echo " menuconfig - NCurses based configuration program" + @echo " help - Prints this text" + @echo " clean - Removing all object files generated from source files" + +.PHONY: clean +clean: + @echo " CLEAN OBJ" + @$(RM) $(OBJ) + @echo " CLEAN $(PROJNAME).elf $(PROJNAME).hex" + @$(RM) $(PROJNAME).elf $(PROJNAME).hex + @$(MAKE) -C ../.. clean + +# Building targets are available only if configuration is generated +ifneq ("$(wildcard config)","") +-include config +# If you want change some standard CFLAGS, change them in configuration not here. +# Add here only options that should not be applied to avr-ioe also. +CFLAGS = -I../../include -mmcu=$(MMCU) -imacros ../../.config.h \ + $(shell echo $(CONFCFLAGS)) $(shell echo -DF_CPU=$(F_CPU)000L) + +$(PROJNAME).elf: ../../libioe.a +$(PROJNAME).elf: $(OBJ) + @echo " LD $@" + @avr-gcc -Os -mmcu=$(MMCU) $^ -o $@ -L../.. -lioe + +$(PROJNAME).hex: $(PROJNAME).elf + @echo " OBJCOPY $@" + @avr-objcopy -O ihex -R .eeprom $< $@ + +$(OBJ): %.o: %.c ../../libioe.a + @echo " CC $@" + @avr-gcc $(CFLAGS) -c -o $@ $< + +../../libioe.a: config + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. libioe.a +endif + +config: + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. config + +.PHONY: menuconfig +menuconfig: + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. menuconfig diff --git a/examples/blink/README.md b/examples/blink/README.md new file mode 100644 index 0000000..e69de29 diff --git a/examples/blink/blink.c b/examples/blink/blink.c new file mode 100644 index 0000000..8386d4b --- /dev/null +++ b/examples/blink/blink.c @@ -0,0 +1,14 @@ +#include +#include +#include + +int main() { + io_setout(IO_B3); + + while (1) { + io_hight(IO_B3); + _delay_ms(500); + io_low(IO_B3); + _delay_ms(500); + } +} diff --git a/examples/blink/config b/examples/blink/config new file mode 100644 index 0000000..09169d4 --- /dev/null +++ b/examples/blink/config @@ -0,0 +1,24 @@ +# +# Automatically generated file; DO NOT EDIT. +# AVR-IOE configuration +# +MMCU=atmega328p +ATMEGA328P=y +# ATTINY85 is not set +F_CPU=16000 + +# +# Compilation options +# +GNUTOOLCHAIN_PREFIX=avr- +CONFCFLAGS=-Os -ffunction-sections -fdata-sections -fshort-enums -Wall +MCUSUPPORT_IOPORTS=y +CONFIG_IOPORTS=y +MCUSUPPORT_PCINT0=y +MCUSUPPORT_PCINT1=y +MCUSUPPORT_PCINT2=y +# CONFIG_IOPORTS_PCINT is not set +MCUSUPPORT_SPI=y +# CONFIG_SPI is not set +MCUSUPPORT_USART=y +# CONFIG_USART is not set diff --git a/examples/blink/config.orig b/examples/blink/config.orig new file mode 100644 index 0000000..529a7d3 --- /dev/null +++ b/examples/blink/config.orig @@ -0,0 +1,24 @@ +# +# Automatically generated file; DO NOT EDIT. +# AVR-IOE configuration +# +MMCU="atmega328p" +ATMEGA328P=y +# ATTINY85 is not set +F_CPU=16000 + +# +# Compilation options +# +GNUTOOLCHAIN_PREFIX="avr-" +CONFCFLAGS="-Os -ffunction-sections -fdata-sections -fshort-enums -Wall" +MCUSUPPORT_IOPORTS=y +CONFIG_IOPORTS=y +MCUSUPPORT_PCINT0=y +MCUSUPPORT_PCINT1=y +MCUSUPPORT_PCINT2=y +# CONFIG_IOPORTS_PCINT is not set +MCUSUPPORT_SPI=y +# CONFIG_SPI is not set +MCUSUPPORT_USART=y +# CONFIG_USART is not set diff --git a/examples/spiblink/Makefile b/examples/spiblink/Makefile new file mode 100644 index 0000000..621f237 --- /dev/null +++ b/examples/spiblink/Makefile @@ -0,0 +1,66 @@ +MAKEFLAGS += --no-builtin-rules +PROJNAME = spiblink + +MSRC = master.c +SSRC = slave.c + +MOBJ = $(patsubst %.c,%.o,$(MSRC)) +SOBJ = $(patsubst %.c,%.o,$(SSRC)) + +.PHONY: all +ifneq ("$(wildcard config)","") # Checking if configuration exists +all: master.hex slave.hex + @echo Now you can flash $^ to your chips. +else +all: help +endif + +# Edit here help like you ever want +.PHONY: help +help: + @echo "AVR-IOE USART echo example" + @echo " all - Build example" + @echo " config - Start configuration program" + @echo " menuconfig - NCurses based configuration program" + @echo " help - Prints this text" + @echo " clean - Removing all object files generated from source files" + +.PHONY: clean +clean: + @echo " CLEAN OBJ" + @$(RM) $(MOBJ) $(SOBJ) + @echo " CLEAN master and slave *.hex, *.elf" + @$(RM) master.elf master.hex + @$(RM) slave.elf slave.hex + @$(MAKE) -C ../.. clean + +# Building targets are available only if configuration is generated +ifneq ("$(wildcard config)","") +-include config +# If you want change some standard CFLAGS, change them in configuration not here. +# Add here only options that should not be applied to avr-ioe also. +CFLAGS = -I../../include -mmcu=$(MMCU) -imacros ../../.config.h \ + $(shell echo $(CONFCFLAGS)) $(shell echo -DF_CPU=$(F_CPU)000L) + +master.elf slave.elf: %.elf: ../../libioe.a %.o + @echo " LD $@" + @avr-gcc -Os -mmcu=$(MMCU) $^ -o $@ -L../.. -lioe + +master.hex slave.hex: %.hex: %.elf + @echo " OBJCOPY $@" + @avr-objcopy -O ihex -R .eeprom $< $@ + +$(MOBJ) $(SOBJ): %.o: %.c ../../libioe.a + @echo " CC $@" + @avr-gcc $(CFLAGS) -c -o $@ $< + +../../libioe.a: config + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. libioe.a +endif + +config: + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. config + +.PHONY: menuconfig +menuconfig: + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. menuconfig diff --git a/examples/spiblink/config b/examples/spiblink/config new file mode 100644 index 0000000..7455947 --- /dev/null +++ b/examples/spiblink/config @@ -0,0 +1,23 @@ +# +# Automatically generated file; DO NOT EDIT. +# AVR-IOE configuration +# +MMCU=atmega328p +ATMEGA328P=y +# ATTINY85 is not set +F_CPU=16000 + +# +# Compilation options +# +GNUTOOLCHAIN_PREFIX=avr- +CONFCFLAGS=-Os -ffunction-sections -fdata-sections -fshort-enums -Wall +MCUSUPPORT_IOPORTS=y +# CONFIG_IOPORTS is not set +MCUSUPPORT_PCINT0=y +MCUSUPPORT_PCINT1=y +MCUSUPPORT_PCINT2=y +MCUSUPPORT_SPI=y +CONFIG_SPI=y +MCUSUPPORT_USART=y +# CONFIG_USART is not set diff --git a/examples/spiblink/config.orig b/examples/spiblink/config.orig new file mode 100644 index 0000000..af7b0a5 --- /dev/null +++ b/examples/spiblink/config.orig @@ -0,0 +1,23 @@ +# +# Automatically generated file; DO NOT EDIT. +# AVR-IOE configuration +# +MMCU="atmega328p" +ATMEGA328P=y +# ATTINY85 is not set +F_CPU=16000 + +# +# Compilation options +# +GNUTOOLCHAIN_PREFIX="avr-" +CONFCFLAGS="-Os -ffunction-sections -fdata-sections -fshort-enums -Wall" +MCUSUPPORT_IOPORTS=y +# CONFIG_IOPORTS is not set +MCUSUPPORT_PCINT0=y +MCUSUPPORT_PCINT1=y +MCUSUPPORT_PCINT2=y +MCUSUPPORT_SPI=y +CONFIG_SPI=y +MCUSUPPORT_USART=y +# CONFIG_USART is not set diff --git a/examples/spiblink/makefile b/examples/spiblink/makefile deleted file mode 100644 index 60ba9c9..0000000 --- a/examples/spiblink/makefile +++ /dev/null @@ -1,32 +0,0 @@ -MAKEFLAGS += --no-builtin-rules - -MMCU = atmega328p -F_CPU = 16000000L -IOE_PREFIX = ../.. -IOE_CFLAGS ?= -Os -ffunction-sections -fdata-sections -fshort-enums -g -Wall \ - -DF_CPU=$(F_CPU) -mmcu=$(MMCU) \ - -DCONFIG_IOE_SPI - -.PHONY: all -all: master.hex slave.hex - @echo - @echo Flash master.hex and slave.hex to two chips and... TODO - -.PHONY: all -clean: ioeclean - $(RM) master.o slave.o - $(RM) master.elf master.hex - $(RM) slave.elf slave.hex - -include ../../avr-ioe.mk - -master.elf: master.o -slave.elf: slave.o -master.elf slave.elf: %.elf: $(IOE_OBJ_SPI) - avr-gcc -Os -mmcu=$(MMCU) $^ -o $@ - -master.hex slave.hex: %.hex: %.elf - avr-objcopy -O ihex -R .eeprom $< $@ - -master.o slave.o: %.o: %.c - avr-gcc $(IOE_CFLAGS) -c -o $@ $< diff --git a/examples/spiblink/master.c b/examples/spiblink/master.c index 267d7b2..1cc4289 100644 --- a/examples/spiblink/master.c +++ b/examples/spiblink/master.c @@ -1,6 +1,6 @@ #include #include -#include "../../spi.h" +#include int main() { DDRB |= _BV(DDB1) | _BV(DDB2); diff --git a/examples/spiblink/slave.c b/examples/spiblink/slave.c index cf14408..91a8237 100644 --- a/examples/spiblink/slave.c +++ b/examples/spiblink/slave.c @@ -1,6 +1,6 @@ #include #include -#include "../../spi.h" +#include void receive(uint8_t data); diff --git a/examples/usartecho/Makefile b/examples/usartecho/Makefile new file mode 100644 index 0000000..900fe09 --- /dev/null +++ b/examples/usartecho/Makefile @@ -0,0 +1,64 @@ +MAKEFLAGS += --no-builtin-rules +PROJNAME = usartecho + +SRC = echo.c + +OBJ = $(patsubst %.c,%.o,$(SRC)) # This creates list of *.o files from *.c + +.PHONY: all +ifneq ("$(wildcard config)","") # Checking if configuration exists +all: $(PROJNAME).hex + @echo Now you can flash $< to your chip. +else +all: help +endif + +# Edit here help like you ever want +.PHONY: help +help: + @echo "AVR-IOE USART echo example" + @echo " all - Build example" + @echo " config - Start configuration program" + @echo " menuconfig - NCurses based configuration program" + @echo " help - Prints this text" + @echo " clean - Removing all object files generated from source files" + +.PHONY: clean +clean: + @echo " CLEAN OBJ" + @$(RM) $(OBJ) + @echo " CLEAN $(PROJNAME).elf $(PROJNAME).hex" + @$(RM) $(PROJNAME).elf $(PROJNAME).hex + @$(MAKE) -C ../.. clean + +# Building targets are available only if configuration is generated +ifneq ("$(wildcard config)","") +-include config +# If you want change some standard CFLAGS, change them in configuration not here. +# Add here only options that should not be applied to avr-ioe also. +CFLAGS = -I../../include -mmcu=$(MMCU) -imacros ../../.config.h \ + $(shell echo $(CONFCFLAGS)) $(shell echo -DF_CPU=$(F_CPU)000L) + +$(PROJNAME).elf: ../../libioe.a +$(PROJNAME).elf: $(OBJ) + @echo " LD $@" + @avr-gcc -Os -mmcu=$(MMCU) $^ -o $@ -L../.. -lioe + +$(PROJNAME).hex: $(PROJNAME).elf + @echo " OBJCOPY $@" + @avr-objcopy -O ihex -R .eeprom $< $@ + +$(OBJ): %.o: %.c ../../libioe.a + @echo " CC $@" + @avr-gcc $(CFLAGS) -c -o $@ $< + +../../libioe.a: config + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. libioe.a +endif + +config: + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. config + +.PHONY: menuconfig +menuconfig: + @CONFIG=$$(readlink -f config) $(MAKE) -C ../.. menuconfig diff --git a/examples/usartecho/config b/examples/usartecho/config new file mode 100644 index 0000000..052a5c4 --- /dev/null +++ b/examples/usartecho/config @@ -0,0 +1,41 @@ +# +# Automatically generated file; DO NOT EDIT. +# AVR-IOE configuration +# +MMCU=atmega328p +ATMEGA328P=y +# ATTINY85 is not set +F_CPU=16000 + +# +# Compilation options +# +GNUTOOLCHAIN_PREFIX=avr- +CONFCFLAGS=-Os -ffunction-sections -fdata-sections -fshort-enums -Wall +MCUSUPPORT_IOPORTS=y +# CONFIG_IOPORTS is not set +MCUSUPPORT_PCINT0=y +MCUSUPPORT_PCINT1=y +MCUSUPPORT_PCINT2=y +MCUSUPPORT_SPI=y +# CONFIG_SPI is not set +MCUSUPPORT_USART=y +CONFIG_USART=y +CONFIG_USART_BAUD=115200 +USART_PARITY_C_NONE=y +# USART_PARITY_C_ODD is not set +# USART_PARITY_C_EVEN is not set +CONFIG_USART_PARITY=USART_PARITY_NONE +CONFIG_USART_DATABITS=8 +USART_STOPBIT_C_SINGLE=y +# USART_STOPBIT_C_DOUBLE is not set +CONFIG_USART_STOPBIT=USART_STOPBIT_SINGLE +CONFIG_USART_OUTPUT_BUFFER=y +CONFIG_USART_OUTBUFFER_SIZE=64 +USART_OUTBUFFER_MODE_C_BLOCK=y +# USART_OUTBUFFER_MODE_C_OVERWRITE is not set +# USART_OUTBUFFER_MODE_C_DROP is not set +CONFIG_USART_OUTBUFFER_MODE=0 +# CONFIG_USART_INPUT_BUFFER is not set +CONFIG_USART_INBUFFER_SIZE=32 +CONFIG_USART_INBUFFER_MODE=0 diff --git a/examples/usartecho/config.orig b/examples/usartecho/config.orig new file mode 100644 index 0000000..8bc1db9 --- /dev/null +++ b/examples/usartecho/config.orig @@ -0,0 +1,41 @@ +# +# Automatically generated file; DO NOT EDIT. +# AVR-IOE configuration +# +MMCU="atmega328p" +ATMEGA328P=y +# ATTINY85 is not set +F_CPU=16000 + +# +# Compilation options +# +GNUTOOLCHAIN_PREFIX="avr-" +CONFCFLAGS="-Os -ffunction-sections -fdata-sections -fshort-enums -Wall" +MCUSUPPORT_IOPORTS=y +# CONFIG_IOPORTS is not set +MCUSUPPORT_PCINT0=y +MCUSUPPORT_PCINT1=y +MCUSUPPORT_PCINT2=y +MCUSUPPORT_SPI=y +# CONFIG_SPI is not set +MCUSUPPORT_USART=y +CONFIG_USART=y +CONFIG_USART_BAUD=115200 +USART_PARITY_C_NONE=y +# USART_PARITY_C_ODD is not set +# USART_PARITY_C_EVEN is not set +CONFIG_USART_PARITY="USART_PARITY_NONE" +CONFIG_USART_DATABITS=8 +USART_STOPBIT_C_SINGLE=y +# USART_STOPBIT_C_DOUBLE is not set +CONFIG_USART_STOPBIT="USART_STOPBIT_SINGLE" +CONFIG_USART_OUTPUT_BUFFER=y +CONFIG_USART_OUTBUFFER_SIZE=64 +USART_OUTBUFFER_MODE_C_BLOCK=y +# USART_OUTBUFFER_MODE_C_OVERWRITE is not set +# USART_OUTBUFFER_MODE_C_DROP is not set +CONFIG_USART_OUTBUFFER_MODE=0 +# CONFIG_USART_INPUT_BUFFER is not set +CONFIG_USART_INBUFFER_SIZE=32 +CONFIG_USART_INBUFFER_MODE=0 diff --git a/examples/usartecho/echo.c b/examples/usartecho/echo.c index 12b88f6..d685750 100644 --- a/examples/usartecho/echo.c +++ b/examples/usartecho/echo.c @@ -1,7 +1,7 @@ #include #include #include -#include "../../usart.h" +#include void rec(uint8_t data) { if (data == '\r') { diff --git a/examples/usartecho/makefile b/examples/usartecho/makefile deleted file mode 100644 index 15254c6..0000000 --- a/examples/usartecho/makefile +++ /dev/null @@ -1,36 +0,0 @@ -MAKEFLAGS += --no-builtin-rules - -MMCU = atmega328p -F_CPU = 16000000L -IOE_PREFIX = ../.. -IOE_SHORTOUTPUT=y -IOE_CFLAGS = -Os -fshort-enums -Wall \ - -DF_CPU=$(F_CPU) -mmcu=$(MMCU) \ - -DCONFIG_IOE_USART \ - -DCONFIG_IOE_USART_OUTBUFFER_SIZE=64 \ - -DCONFIG_IOE_USART_OUTBUFFER_MODE=0 \ - -DCONFIG_IOE_USART_BAUD=115200 \ - -DCONFIG_IOE_USART_PARITY=USART_PARITY_NONE \ - -DCONFIG_IOE_USART_STOPBIT=USART_STOPBIT_SINGLE \ - -DCONFIG_IOE_USART_DATABITS=8 - -all: usart.hex - @echo Now you can flash usart.hex to your chip. - -clean: ioeclean - $(RM) echo.o - $(RM) usart.elf usart.hex - -include ../../avr-ioe.mk - -usart.elf: %.elf: $(IOE_OBJ) echo.o - @echo " LD $@" - @avr-gcc -Os -mmcu=$(MMCU) $^ -o $@ - -usart.hex: %.hex: %.elf - @echo " OBJCOPY $@" - @avr-objcopy -O ihex -R .eeprom $< $@ - -echo.o: %.o: %.c - @echo " CC $@" - @avr-gcc $(IOE_CFLAGS) -c -o $@ $< 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 +#include +#include + +#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 + +#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 +#include +#include + +#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 +#include +#include + +#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 +#include +#include + +#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 + +// 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 + +// 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 + +// 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 + +// 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 + +// 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 +#include +#include + +#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 +#include +#include + +#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 +#include +#include + +#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 +#include +#include +#include +#include + +#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 +#include +#include + +#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 +#include +#include + +#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 +#include +#include +#include + +#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 +#include +#include + +#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 + +#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 +#include + +#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 diff --git a/kconfig b/kconfig new file mode 160000 index 0000000..6814159 --- /dev/null +++ b/kconfig @@ -0,0 +1 @@ +Subproject commit 6814159a0a618a145aa5786a0ec3d311ce81ee91 diff --git a/makefile b/makefile deleted file mode 100644 index 14aa590..0000000 --- a/makefile +++ /dev/null @@ -1,16 +0,0 @@ -.PHONY: all help clean - -IOE_ONLYPATHS = y -include avr-ioe.mk - -all: - $(error This is not library, please include "avr-ioe.mk" to your project makefile. For more informations refer to README.md) - -help: - @echo This makefile only implements these targets: - @echo help - prints this text - @echo clean - removing all object files generated from source files - -clean: - $(RM) $(IOE_OBJ) - $(RM) $(IOE_DEP) diff --git a/mcu/ATmega328P.h b/mcu/ATmega328P.h deleted file mode 100644 index e876295..0000000 --- a/mcu/ATmega328P.h +++ /dev/null @@ -1,29 +0,0 @@ -/* This is specific configuration for ATmega328P. - * Also applies on ATmega48A, ATmega48PA, ATmega88A, ATmega88PA, ATmega168A and - * ATmega168PA. - */ -#include - -// 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/mcu/ATmega32U4.h b/mcu/ATmega32U4.h deleted file mode 100644 index 16351e8..0000000 --- a/mcu/ATmega32U4.h +++ /dev/null @@ -1,19 +0,0 @@ -/* This is specific configuration for ATmega32U4. - * This configuration also applies on ATmega16U4. - */ -#include - -// 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/mcu/ATmega8A.h b/mcu/ATmega8A.h deleted file mode 100644 index a2d3adf..0000000 --- a/mcu/ATmega8A.h +++ /dev/null @@ -1,18 +0,0 @@ -/* This is specific configuration for ATmega8A. - */ -#include - -// 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/mcu/ATtiny4313.h b/mcu/ATtiny4313.h deleted file mode 100644 index efbc01d..0000000 --- a/mcu/ATtiny4313.h +++ /dev/null @@ -1,17 +0,0 @@ -/* This is specific configuration for ATtiny4313. - * This configuration also applies on ATtiny2313A. - */ -#include - -// 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/mcu/ATtiny85.h b/mcu/ATtiny85.h deleted file mode 100644 index 19db90d..0000000 --- a/mcu/ATtiny85.h +++ /dev/null @@ -1,15 +0,0 @@ -/* This is specific configuration for ATtiny85. - * This configuration also applies on ATtiny45 and ATtiny25. - */ -#include - -// 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/mcu/mcu.h b/mcu/mcu.h deleted file mode 100644 index e1272b9..0000000 --- a/mcu/mcu.h +++ /dev/null @@ -1,18 +0,0 @@ -#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/mcu/mcu_def.h b/mcu/mcu_def.h deleted file mode 100644 index 51b70fe..0000000 --- a/mcu/mcu_def.h +++ /dev/null @@ -1,21 +0,0 @@ -#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/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..a0724b4 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,20 @@ +site_name: AVR-IOE +repo_url: https://github.com/Cynerd/avr-ioe.git +site_description: AVR microcontroller input/output expansion code +copyright: GNU General Public License, version 2.0 +pages: +- Home: index.md +- Usage: usage.md +- Modules: + - IO Ports: modules/ioport.md + - SPI: modules/spi.md + - Tasks: modules/tasks.md + - Timer: modules/timer.md + - USART: modules/usart.md + - Utils: + - Buffer: modules/utils/buffer.md + - NArray: modules/utils/narray.md +- Adding MCU support: add_support.md +theme: readthedocs + +site_dir: html diff --git a/pwm.h b/pwm.h deleted file mode 100644 index 0dbc007..0000000 --- a/pwm.h +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include -#include - -#include "timer.h" - -#ifndef _IOE_PWM_H_ -#define _IOE_PWM_H_ - - -#endif /* _IOE_PWM_H_ */ diff --git a/sensor_dht22.h b/sensor_dht22.h deleted file mode 100644 index 6ddcf9c..0000000 --- a/sensor_dht22.h +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include - -#include "tasks.h" -#include "timer.h" - -#ifndef _IOE_SENSOR_DHT22_H_ -#define _IOE_SENSOR_DHT22_H_ - -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 /* _IOE_SENSOR_DHT22_H_ */ diff --git a/spi.h b/spi.h deleted file mode 100644 index 51f8f2a..0000000 --- a/spi.h +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include -#include - -#include "mcu/mcu_def.h" -#include "tasks.h" -#include "buffers.h" - -#ifndef _IOE_SPI_H_ -#define _IOE_SPI_H_ -#ifdef CONFIG_IOE_SPI - -#ifndef MCUSUPPORT_SPI -#error "No SPI interface is known on your mcu." -#endif - -enum spiMode { - SPI_MODE_MASTER, - SPI_MODE_SLAVE -}; - -volatile extern int8_t _spi_busy; - -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) { - taskDelayTill(_spi_busy); -} - -static inline uint8_t spi_send(uint8_t data) { - spi_transfer(data); - taskDelayTill(_spi_busy); - return SPDR; -} - -static inline void spi_transfer(uint8_t data) { - _spi_busy = 1; - SPDR = data; -} - -static inline void spi_expose(uint8_t data) { - SPDR = data; -} - -extern void (*spi_receive)(uint8_t data); - -#endif /* CONFIG_IOE_SPI */ -#endif /* _IOE_SPI_H_ */ diff --git a/src/adc.c b/src/adc.c new file mode 100644 index 0000000..03e979e --- /dev/null +++ b/src/adc.c @@ -0,0 +1,4 @@ +#include + +int8_t ioe_adc(uint8_t input) { +} diff --git a/src/can/mcp2515.c b/src/can/mcp2515.c new file mode 100644 index 0000000..8c9915c --- /dev/null +++ b/src/can/mcp2515.c @@ -0,0 +1,52 @@ +#include + +#ifdef CONFIG_IOE_CAN_MCP2515 +// TODO check +#define CAN_MCP2515_RESET 0xC0 +#define CAN_MCP2515_READ 0x03 +#define CAN_MCP2515_READRX 0x90 +#define CAN_MCP2515_WRITE 0x02 +#define CAN_MCP2515_LOADTX 0x40 +#define CAN_MCP2515_RTS 0x80 +#define CAN_MCP2515_RDSTAT 0xA0 +#define CAN_MCP2515_RXSTAT 0xB0 +#define CAN_MCP2515_BITMOD 0x05 + +inline void can_mcp2515_init(canMcp2515 * can, uint8_t group, uint8_t mask) { + can->group = group; + can->mask = mask; + can_mcp2515_reset(can); + // TODO + return 0; +}; + +inline void can_mcp2515_reset(canMcp2515 * can) { + take_mutex(spi_mutex); + spi_join(); + + release_mutex(spi_mutex); +}; + +inline uint8_t can_mcp2515_read(canMcp2515 * can, uint8_t address) { +}; + +inline uint8_t can_mcp2515_readrx(canMcp2515 * can, uint8_t buffer) { +}; + +inline void can_mcp2515_write(canMcp2515 * can, uint8_t address, uint8_t data) { +}; + +inline void can_mcp2515_loadrx(canMcp2515 * can, uint8_t buffer, uint8_t data) { +}; + +inline uint8_t can_mcp2515_rdstat(canMcp2515 * can) { +}; + +inline uint8_t can_mcp2515_rxstat(canMcp2515 * can) { +}; + +inline void can_mcp2515_bitmod(canMcp2515 * can, uint8_t address, uint8_t mask, + uint8_t data) { +}; + +#endif /* CONFIG_IOE_CAN_MCP2515 */ diff --git a/src/can_mcp2515.c b/src/can_mcp2515.c deleted file mode 100644 index e69de29..0000000 diff --git a/src/ioport.c b/src/ioport.c new file mode 100644 index 0000000..a77e564 --- /dev/null +++ b/src/ioport.c @@ -0,0 +1,113 @@ +#include +#ifdef CONFIG_IOPORTS +#ifdef CONFIG_PCINT + +struct PCIW { + uint8_t flags; + uint8_t mask; + void (*change) (uint8_t group, uint8_t mask); +}; + +// Exploiting implementation of libc malloc +#define PCIW_LEN(INPCIW) (*((uint16_t *) INPCIW - 1) / sizeof(struct PCIW) - 1) + +#if (defined MCUSUPPORT_PCINT0 && defined MCUSUPPORT_PCINT1 && defined MCUSUPPORT_PCINT2) +#define PCI_COUNT 3 +#elif (defined MCUSUPPORT_PCINT0 && defined MCUSUPPORT_PCINT1 || \ + defined MCUSUPPORT_PCINT1 && defined MCUSUPPORT_PCINT2 || \ + defined MCUSUPPORT_PCINT2 && defined MCUSUPPORT_PCINT0) +#define PCI_COUNT 2 +#elif (defined MCUSUPPORT_PCINT0 || defined MCUSUPPORT_PCINT1 || defined MCUSUPPORT_PCINT2) +#define PCI_COUNT 1 +#else +#define PCI_COUNT 0 +#endif + +#define GROUP2INDEX(GRP) (GRP - MCUSUPPORT_PCINT0) + +static struct PCIW *pciw[PCI_COUNT]; +static uint8_t pci_state[PCI_COUNT]; +static void pci(int8_t group, int8_t pinmax) { + int8_t i, y; + int8_t index = GROUP2INDEX(group); + int8_t len = (int8_t) PCIW_LEN(pciw[index]); + // WARN Is possible that PCINT0 is not corresponding with B group and so on? + uint8_t state = IOE_IO_PIN(group); + for (i = len; i >= 0; i--) { + uint8_t stA = state & pciw[index][i].mask; + uint8_t stB = pci_state[index] & pciw[index][i].mask; + if (((~stA & stB) && pciw[index][i].flags & IOE_IO_RISING) || + ((stA & ~stB) && pciw[index][i].flags & IOE_IO_FALLING)) { + pciw[index][i].change(IOE_IO_B, mask); + } + } + pci_state[index] = state; +} + +void io_change_sethook(uint8_t group, uint8_t mask, uint8_t edge, + void (*change) (uint8_t group, uint8_t mask)) { + int8_t index = (int8_t) GROUP2INDEX(group); + int8_t len = (int8_t) PCIW_LEN(pciw[index]); + pciw[index] = realloc(pciw[index], len + 1); + pciw[index][len].flags = edge; + pciw[index][len].mask = mask; + pciw[index][len].change = change; + switch (group) { +#ifdef MCUSUPPORT_PCINT0 // TODO this wont work with attiny4313 and meaby others + case IO_B: + PCICR |= (1<<0); + PCMSK0 |= mask; + break; +#endif +#ifdef MCUSUPPORT_PCINT1 + case IO_C: + PCICR |= (1<<1); + PCMSK1 |= mask; + break; +#endif +#ifdef MCUSUPPORT_PCINT2 + case IO_D: + PCICR |= (1<<2); + PCMSK2 |= mask; + break +#endif + } +} + +void io_change_remhook(void (*change) (uint8_t group, uint8_t mask)) { + int8_t i, y; + int8_t len; + for (i = PCI_COUNT - 1; i >= 0; i--) { + len = (int8_t)PCIW_LEN(pciw[index]); + for (y = len - 1; y >= 0; y--) { + if (pciw[i][y].change == change) { + + } + } + } +} + +void io_change_clearhooks(void) { +} + +// WARN This will work only if C is only defined on MCU with also B defined. +#ifdef MCUSUPPORT_PCINT0 +ISR(PCINT0_vect, ISR_BLOCK) { + pci(IO_B, MCUSUPPORT_PCINT0); +} +#endif /* MCUSUPPORT_PCINT0 */ + +#ifdef MCUSUPPORT_PCINT1 +ISR(PCINT1_vect, ISR_BLOCK) { + pci(IO_C, MCUSUPPORT_PCINT1); +} +#endif /* MCUSUPPORT_PCINT1 */ + +#ifdef MCUSUPPORT_PCINT2 +ISR(PCINT2_vect, ISR_BLOCK) { + pci(IO_D, MCUSUPPORT_PCINT2); +} +#endif /* MCUSUPPORT_PCINT2 */ + +#endif /* CONFIG_PCINT */ +#endif /* CONFIG_IOPORTS */ diff --git a/src/pcint.c b/src/pcint.c deleted file mode 100644 index 1dedb63..0000000 --- a/src/pcint.c +++ /dev/null @@ -1,32 +0,0 @@ -/* This file defines and handles Pin change interupts. - * This interupt can be used in different modules and sensors. Function call can - * be done from this interrupt handdler. - */ -#include - -#if (defined CONFIG_IOE_SENSOR_DHT22) - -#ifdef CONFIG_IOE_SENSOR_DHT22 -extern void dht22_read_pcint(void); -#endif - - -ISR(PCINT0_vect, ISR_BLOCK) { -#ifdef CONFIG_IOE_SENSOR_DHT22 - void dht22_read_pcint(); -#endif -} - -ISR(PCINT1_vect, ISR_BLOCK) { -#ifdef CONFIG_IOE_SENSOR_DHT22 - void dht22_read_pcint(); -#endif -} - -ISR(PCINT2_vect, ISR_BLOCK) { -#ifdef CONFIG_IOE_SENSOR_DHT22 - void dht22_read_pcint(); -#endif -} - -#endif diff --git a/src/sensor_dht22.c b/src/sensor_dht22.c deleted file mode 100644 index 7791060..0000000 --- a/src/sensor_dht22.c +++ /dev/null @@ -1,117 +0,0 @@ -#include "../sensor_dht22.h" - -#ifdef CONFIG_IOE_SENSOR_DHT22 - -#define PP dht22_ports[pi] -#define PPP dht22_ports[dht22_measurement.pi] - -#define TIMEOUT F_CPU/40000 - -#define STATUS_NONE 0 -#define STATUS_COMPLETE 1 -#define STATUS_TIMEOUT 2 - -#define PORT_SENSORW 4 -#define PORT_SENSORRESP_L 3 -#define PORT_SENSORRESP_H 2 -#define PORT_H 1 -#define PORT_L 0 - -struct { - uint8_t index; - uint8_t data[5]; - volatile uint8_t status; - uint8_t pi; - uint8_t port_status; -} dht22_measurement; - -inline void dht22_init(uint8_t pi) { - // Set port as output and set level hight - *(PP.DDR) |= PP.MASK; - *(PP.PORT) |= PP.MASK; - // Enable all pin change interrupts - PCIFR = 0xff; -} - - -inline void dht22_read_deac(uint8_t status) { - dht22_measurement.status = status; - // Disable pin change interrupt - *(PPP.PCMSK) &= ~PPP.PCMSK_MASK; - timer_disable(CONFIG_IOE_SENSOR_DHT22_TIMER); -} - -// This is called from pcint.c -void dht22_read_pcint(void) { - switch (dht22_measurement.port_status) { - case PORT_L: - if (!(*(PPP.PIN) & PPP.MASK)) - return; - dht22_measurement.port_status = PORT_H; - break; - case PORT_H: - if (*(PPP.PIN) & PPP.MASK) - return; - dht22_measurement.port_status = PORT_L; - register uint16_t val; - val = timer_value(CONFIG_IOE_SENSOR_DHT22_TIMER); - // TODO compare value - if (val < 1) { - dht22_measurement.data[dht22_measurement.index / 8] - } - if (++(dht22_measurement.index) == 40) { - dht22_read_deac(STATUS_COMPLETE); - return; - } - break; - default: - if (((*(PPP.PIN) & PPP.MASK) && dht22_measurement.port_status == 3) - || !(*(PPP.PIN & PPP.MASK))) - return; - dht22_measurement.port_status--; - } - timer_reset(CONFIG_IOE_SENSOR_DHT22_TIMER); -} - -void dht22_read_timer_overflow(void) { - dht22_read_deac(STATUS_TIMEOUT); -} - -int8_t dht22_read(uint8_t pi, struct dht22_value *rh, - struct dht22_value *t) { - dht22_measurement.index = 0; - dht22_measurement.status = STATUS_NONE; - dht22_measurement.pi = pi; - dht22_measurement.port_status = PORT_SENSORW; - - // Pull port down for 500us - *(PP.PORT) &= ~PP.MASK; - _delay_us(500); - // Initialize timer - timer_init(CONFIG_IOE_SENSOR_DHT22_TIMER, TIMER_DIVIDER_64); - timer_sethook(CONFIG_IOE_SENSOR_DHT22_TIMER, - dht22_read_timer_overflow); - // Set pin change interrupt - *(PP.PCMSK) |= PP.PCMSK_MASK; - // Set port as output and pull-up resistor - *(PP.DDR) &= ~PP.MASK; - *(PP.PORT) |= PP.MASK; - // Delay till reading is done - taskDelayTill(&(dht22_measurement.status)); - - // Copy data - rh->integral = dht22_measurement.data[0]; - rh->decimal = dht22_measurement.data[1]; - t->integral = dht22_measurement.data[2]; - t->decimal = dht22_measurement.data[3]; - // Check sum - uint8_t sum = dht22_measurement.data[0]; - sum += dht22_measurement.data[1]; - sum += dht22_measurement.data[2]; - sum += dht22_measurement.data[3]; - if (sum != dht22_measurement.data[4]) - return 1; - return dht22_measurement.status - 1; -} - -#endif /* CONFIG_IOE_SENSOR_SHT22 */ diff --git a/src/sensors/dht22.c b/src/sensors/dht22.c new file mode 100644 index 0000000..9653ba5 --- /dev/null +++ b/src/sensors/dht22.c @@ -0,0 +1,117 @@ +#include + +#ifdef CONFIG_IOE_SENSOR_DHT22 + +#define PP dht22_ports[pi] +#define PPP dht22_ports[dht22_measurement.pi] + +#define TIMEOUT F_CPU/40000 + +#define STATUS_NONE 0 +#define STATUS_COMPLETE 1 +#define STATUS_TIMEOUT 2 + +#define PORT_SENSORW 4 +#define PORT_SENSORRESP_L 3 +#define PORT_SENSORRESP_H 2 +#define PORT_H 1 +#define PORT_L 0 + +struct { + uint8_t index; + uint8_t data[5]; + volatile uint8_t status; + uint8_t pi; + uint8_t port_status; +} dht22_measurement; + +inline void dht22_init(uint8_t pi) { + // Set port as output and set level hight + *(PP.DDR) |= PP.MASK; + *(PP.PORT) |= PP.MASK; + // Enable all pin change interrupts + PCIFR = 0xff; +} + + +inline void dht22_read_deac(uint8_t status) { + dht22_measurement.status = status; + // Disable pin change interrupt + *(PPP.PCMSK) &= ~PPP.PCMSK_MASK; + timer_disable(CONFIG_IOE_SENSOR_DHT22_TIMER); +} + +// This is called from pcint.c +void dht22_read_pcint(void) { + switch (dht22_measurement.port_status) { + case PORT_L: + if (!(*(PPP.PIN) & PPP.MASK)) + return; + dht22_measurement.port_status = PORT_H; + break; + case PORT_H: + if (*(PPP.PIN) & PPP.MASK) + return; + dht22_measurement.port_status = PORT_L; + register uint16_t val; + val = timer_value(CONFIG_IOE_SENSOR_DHT22_TIMER); + // TODO compare value + if (val < 1) { + dht22_measurement.data[dht22_measurement.index / 8] + } + if (++(dht22_measurement.index) == 40) { + dht22_read_deac(STATUS_COMPLETE); + return; + } + break; + default: + if (((*(PPP.PIN) & PPP.MASK) && dht22_measurement.port_status == 3) + || !(*(PPP.PIN & PPP.MASK))) + return; + dht22_measurement.port_status--; + } + timer_reset(CONFIG_IOE_SENSOR_DHT22_TIMER); +} + +void dht22_read_timer_overflow(void) { + dht22_read_deac(STATUS_TIMEOUT); +} + +int8_t dht22_read(uint8_t pi, struct dht22_value *rh, + struct dht22_value *t) { + dht22_measurement.index = 0; + dht22_measurement.status = STATUS_NONE; + dht22_measurement.pi = pi; + dht22_measurement.port_status = PORT_SENSORW; + + // Pull port down for 500us + *(PP.PORT) &= ~PP.MASK; + _delay_us(500); + // Initialize timer + timer_init(CONFIG_IOE_SENSOR_DHT22_TIMER, TIMER_DIVIDER_64); + timer_sethook(CONFIG_IOE_SENSOR_DHT22_TIMER, + dht22_read_timer_overflow); + // Set pin change interrupt + *(PP.PCMSK) |= PP.PCMSK_MASK; + // Set port as output and pull-up resistor + *(PP.DDR) &= ~PP.MASK; + *(PP.PORT) |= PP.MASK; + // Delay till reading is done + taskDelayTill(&(dht22_measurement.status)); + + // Copy data + rh->integral = dht22_measurement.data[0]; + rh->decimal = dht22_measurement.data[1]; + t->integral = dht22_measurement.data[2]; + t->decimal = dht22_measurement.data[3]; + // Check sum + uint8_t sum = dht22_measurement.data[0]; + sum += dht22_measurement.data[1]; + sum += dht22_measurement.data[2]; + sum += dht22_measurement.data[3]; + if (sum != dht22_measurement.data[4]) + return 1; + return dht22_measurement.status - 1; +} + +#endif /* CONFIG_IOE_SENSOR_SHT22 */ diff --git a/src/spi.c b/src/spi.c index 4c0293c..69012fa 100644 --- a/src/spi.c +++ b/src/spi.c @@ -1,23 +1,19 @@ -#ifdef CONFIG_IOE_SPI -#ifdef MCUSUPPORT_USART +#include + +#ifdef CONFIG_SPI volatile int8_t _spi_busy; +volatile Mutex spi_mutex; -////// Interrupts //////////////////////////////// void (*spi_receive) (uint8_t data) = 0; -#ifdef CONFIG_IOE_CAN_MCP2515 -extern void can_mcp2515_spi_hook(uint8_t); -#endif /* CONFIG_IOE_CAN_MCP2515 */ - ISR(SPI_STC_vect, ISR_BLOCK) { + void (*spir_w) (uint8_t data) = spi_receive; _spi_busy = 0; -#ifdef CONFIG_IOE_CAN_MCP2515 - can_mcp2515_spi_hook(SPDR); -#endif /* CONFIG_IOE_CAN_MCP2515 */ - if (spi_receive) - spi_receive(SPDR); + while (spir_w != NULL) { + spir_w(SPDR); + spir_w++; + } } -#endif /* MCUSUPPORT_SPI */ -#endif /* CONFIG_IOE_SPI */ +#endif /* CONFIG_SPI */ diff --git a/src/tasks.c b/src/tasks.c index 1d94eaa..abc2add 100644 --- a/src/tasks.c +++ b/src/tasks.c @@ -1,16 +1,62 @@ -#include "../tasks.h" - +#include #ifdef CONFIG_IOE_TASKS +void tasks_run(void) { +} + +void task_init(Task * t, void (*func) (void)) { +} +void task_start(Task * t) { +} + +void task_delay(uint16_t us) { +} +void task_delay_ms(uint16_t ms) { +} +void task_delay_till(volatile int8_t * boolean, uint16_t timeout) { +} + +int8_t task_stack_init(TaskStack * ts, uint8_t stack_size, uint8_t flags) { + ts->stack = malloc(stack_size * sizeof(uint8_t)); + ts->flags = flags; + ts->running = NULL; + ts->pending = NULL; +} + +void task_stack_free(TaskStack * ts) { + free(ts->stack); +} + +void task_stack_reg(TaskStack * ts, Task * t) { +} + +void task_stack_unreg(TaskStack * ts, Task * t) { +} + +void init_mutex(Mutex * mtx, uint8_t flags) { +}; +void take_mutex(Mutex * mtx) { +}; +int8_t take_mutex_t(Mutex * mtx, uint16_t timeout) { +}; +void give_mutex(Mutex * mtx) { +}; + #else /* CONFIG_IOE_TASKS */ -int8_t taskDelayTillT(int8_t *condition, uint8_t timeout_10us) { - while(*condition == 0) { - if (timeout_10us == 0) - return 1; - timeout_10us--; - _delay_us(10); - } +int8_t task_delay_till(volatile int8_t * boolean, uint16_t timeout) { + if (timeout == 0) + while (!*boolean) + _delay_us(100); + else + // TODO this implementation should be improved to check boolean as often + // as possible + while (*boolean == 0) { + if (timeout == 0) + return 1; + timeout--; + _delay_ms(1); + } return 0; } diff --git a/src/timer.c b/src/timer.c index 68c6c06..1175bad 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,7 +1,133 @@ -#include "../timer.h" - +#include #ifdef CONFIG_IOE_TIMERS +void timer_init(uint8_t timer, enum timerDivider div) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + // Null counting register + TCNT0 = 0; + // Set interrupt flag + TIMSK0 = _BV(TOIE0); + // Set division and start counting + switch (div) { + case TIMER_DIVIDER_1: + TCCR0B = _BV(CS00); + break; + case TIMER_DIVIDER_8: + TCCR0B = _BV(CS01); + break; + case TIMER_DIVIDER_64: + TCCR0B = _BV(CS01) | _BV(CS00); + break; + case TIMER_DIVIDER_256: + TCCR0B = _BV(CS02); + break; + case TIMER_DIVIDER_1024: + TCCR0B = _BV(CS02) | _BV(CS01); + break; + default: + return; + } + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + break; +#endif /* COUNTER2_PWM_ASYNC */ + } +} + +void timer_disable(uint8_t timer) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + TCCR0B = 0; + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + break; +#endif /* COUNTER2_PWM_ASYNC */ + } +} + +void timer_reset(uint8_t timer) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + TCNT0 = 0; + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + break; +#endif /* COUNTER2_PWM_ASYNC */ + } +} + +uint16_t timer_value(uint8_t timer) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + return TCNT0; + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + break; +#endif /* COUNTER2_PWM_ASYNC */ + default: + return 0; + } +} + +#ifdef COUNTER0_PWM +static void *(*timer_0_pwm_overflow) (void); +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM +static void (*timer_1_16pwm_overflow) (void); +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC +static void (*timer_2_pwm_overflow) (void); +#endif /* COUNTER2_PWM_ASYNC */ + +void timer_sethook(uint8_t timer, void (*fnc) (void)) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + timer_0_pwm_overflow = fnc; + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + timer_1_16pwm_overflow = fnc; + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + timer_2_pwm_overflow = fnc; + break; +#endif /* COUNTER2_PWM_ASYNC */ + } +} + #ifdef COUNTER0_PWM ISR(TIMER0_OVF_vect, ISR_BLOCK) { if (timer_0_pwm_overflow) diff --git a/src/usart.c b/src/usart.c index bba83ac..6cfbc20 100644 --- a/src/usart.c +++ b/src/usart.c @@ -1,7 +1,5 @@ -#include "../usart.h" - -#ifdef CONFIG_IOE_USART -#ifdef MCUSUPPORT_USART +#include +#ifdef CONFIG_USART #define USART_PARITY_NONE 0 #define USART_PARITY_ODD 1 @@ -10,46 +8,46 @@ #define USART_STOPBIT_SINGLE 1 #define USART_STOPBIT_DOUBLE 2 -#ifndef CONFIG_IOE_USART_BAUD -#warning "CONFIG_IOE_USART_BAUD not defined. Setting default 9600." -#define CONFIG_IOE_USART_BAUD 9600 +#ifndef CONFIG_USART_BAUD +#warning "CONFIG_USART_BAUD not defined. Setting default 9600." +#define CONFIG_USART_BAUD 9600 #endif -#ifndef CONFIG_IOE_USART_PARITY -#warning "CONFIG_IOE_USART_PARITY not defined. Using default USART_PARITY_NONE." -#define CONFIG_IOE_USART_PARITY USART_PARITY_NONE +#ifndef CONFIG_USART_PARITY +#warning "CONFIG_USART_PARITY not defined. Using default USART_PARITY_NONE." +#define CONFIG_USART_PARITY USART_PARITY_NONE #endif -#ifndef CONFIG_IOE_USART_STOPBIT -#warning "CONFIG_IOE_USART_STOPBIT not defined. Using default USART_STOPBIT_SINGLE." -#define CONFIG_IOE_USART_STOPBIT USART_STOPBIT_SINGLE +#ifndef CONFIG_USART_STOPBIT +#warning "CONFIG_USART_STOPBIT not defined. Using default USART_STOPBIT_SINGLE." +#define CONFIG_USART_STOPBIT USART_STOPBIT_SINGLE #endif -#ifndef CONFIG_IOE_USART_DATABITS -#warning "CONFIG_IOE_USART_DATABITS not defined. Using default 8." -#define CONFIG_IOE_USART_DATABITS 8 +#ifndef CONFIG_USART_DATABITS +#warning "CONFIG_USART_DATABITS not defined. Using default 8." +#define CONFIG_USART_DATABITS 8 #endif -#if !((CONFIG_IOE_USART_PARITY == USART_PARITY_NONE) || \ - (CONFIG_IOE_USART_PARITY == USART_PARITY_ODD) || \ - (CONFIG_IOE_USART_PARITY == USART_PARITY_EVEN)) -#error "CONFIG_IOE_USART_PARITY has value, that is not allowed." +#if !((CONFIG_USART_PARITY == USART_PARITY_NONE) || \ + (CONFIG_USART_PARITY == USART_PARITY_ODD) || \ + (CONFIG_USART_PARITY == USART_PARITY_EVEN)) +#error "CONFIG_USART_PARITY has value, that is not allowed." #endif -#if !((CONFIG_IOE_USART_STOPBIT == USART_STOPBIT_SINGLE) || \ - (CONFIG_IOE_USART_STOPBIT == USART_STOPBIT_DOUBLE)) -#error "CONFIG_IOE_USART_STOPBIT has value, that is not allowed." +#if !((CONFIG_USART_STOPBIT == USART_STOPBIT_SINGLE) || \ + (CONFIG_USART_STOPBIT == USART_STOPBIT_DOUBLE)) +#error "CONFIG_USART_STOPBIT has value, that is not allowed." #endif -#if !((CONFIG_IOE_USART_DATABITS == 5) || \ - (CONFIG_IOE_USART_DATABITS == 6) || \ - (CONFIG_IOE_USART_DATABITS == 7) || \ - (CONFIG_IOE_USART_DATABITS == 8)) +#if !((CONFIG_USART_DATABITS == 5) || \ + (CONFIG_USART_DATABITS == 6) || \ + (CONFIG_USART_DATABITS == 7) || \ + (CONFIG_USART_DATABITS == 8)) // TODO DATABITS 9 is not supported -#error "CONFIG_IOE_USART_DATABITS has value, that is not allowed." +#error "CONFIG_USART_DATABITS has value, that is not allowed." #endif -#if (defined CONFIG_IOE_USART_INFILE) && (CONFIG_IOE_USART_INBUFFER_SIZE <= 0) +#if (defined CONFIG_USART_INFILE) && (CONFIG_USART_INBUFFER_SIZE <= 0) #error "USART Input file can't be enabled without input buffer" #endif -#if (defined CONFIG_IOE_USART_OUTFILE) && (CONFIG_IOE_USART_OUTBUFFER_SIZE <= 0) +#if (defined CONFIG_USART_OUTFILE) && (CONFIG_USART_OUTBUFFER_SIZE <= 0) #error "USART Input file can't be enabled without output buffer" #endif @@ -58,7 +56,7 @@ volatile int8_t _usart_busy; void usart_init_async(void) { _usart_busy = 0; -#define BAUD CONFIG_IOE_USART_BAUD +#define BAUD CONFIG_USART_BAUD #include UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; @@ -70,95 +68,95 @@ void usart_init_async(void) { UCSR0C = 0 | // USART_PARITY_NONE are both UMP01 and UMP00 zero -#if CONFIG_IOE_USART_PARITY == USART_PARITY_ODD +#if CONFIG_USART_PARITY == USART_PARITY_ODD _BV(UPM01) | -#elif CONFIG_IOE_USART_PARITY == USART_PARITY_EVEN +#elif CONFIG_USART_PARITY == USART_PARITY_EVEN _BV(UPM00) | _BV(UPM01) | #endif // USART_STOPBIT_SINGLE is USBS0 zero -#if CONFIG_IOE_USART_STOPBIT == USART_STOPBIT_DOUBLE +#if CONFIG_USART_STOPBIT == USART_STOPBIT_DOUBLE _BV(USBS0) | #endif // For 5 databits are UCSZ00 and UCSZ01 zero -#if CONFIG_IOE_USART_DATABITS == 6 +#if CONFIG_USART_DATABITS == 6 _BV(UCSZ00) -#elif CONFIG_IOE_USART_DATABITS == 7 +#elif CONFIG_USART_DATABITS == 7 _BV(UCSZ01) -#elif CONFIG_IOE_USART_DATABITS == 8 +#elif CONFIG_USART_DATABITS == 8 _BV(UCSZ00) | _BV(UCSZ01) #endif ; // Enable receiver, transmitter and RX complete, // Data register empty interrupts UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UDRIE0); -#ifdef _IOE_USART_INBUFFER - IOEBUFFER_INIT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE); +#ifdef _USART_INBUFFER + IOEBUFFER_INIT(_ioe_usart_inbuffer, CONFIG_USART_INBUFFER_SIZE); #endif -#ifdef _IOE_USART_OUTBUFFER - IOEBUFFER_INIT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE); +#ifdef _USART_OUTBUFFER + IOEBUFFER_INIT(_ioe_usart_outbuffer, CONFIG_USART_OUTBUFFER_SIZE); #endif } inline void usart_send(uint8_t data) { -#ifdef _IOE_USART_OUTBUFFER +#ifdef _USART_OUTBUFFER if (!_usart_busy) { _usart_busy = 1; UDR0 = data; } else { IOEBUFFER_PUT(_ioe_usart_outbuffer, - CONFIG_IOE_USART_OUTBUFFER_SIZE, data, - CONFIG_IOE_USART_OUTBUFFER_MODE); + CONFIG_USART_OUTBUFFER_SIZE, data, + CONFIG_USART_OUTBUFFER_MODE); } #else _usart_busy = 1; UDR0 = data; -#endif /* _IOE_USART_OUTBUFFER */ +#endif /* _USART_OUTBUFFER */ } -#ifdef _IOE_USART_OUTBUFFER +#ifdef _USART_OUTBUFFER inline void usart_send_str(char *str) { while (*str != '\0') { usart_send((uint8_t) * str); str++; } } -#endif /* _IOE_USART_OUTBUFFER */ +#endif /* _USART_OUTBUFFER */ -#ifdef _IOE_USART_INBUFFER +#ifdef _USART_INBUFFER uint8_t usart_get(void) { uint8_t rtn; - IOEBUFFER_GET(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE, + IOEBUFFER_GET(_ioe_usart_inbuffer, CONFIG_USART_INBUFFER_SIZE, rtn); return rtn; } #endif -#ifdef _IOE_USART_INBUFFER +#ifdef _USART_INBUFFER uint8_t usart_inbuffered(void) { uint8_t rtn; - IOEBUFFER_CNT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE, + IOEBUFFER_CNT(_ioe_usart_inbuffer, CONFIG_USART_INBUFFER_SIZE, rtn); return rtn; } #endif -#ifdef _IOE_USART_OUTBUFFER +#ifdef _USART_OUTBUFFER uint8_t usart_outbuffered(void) { uint8_t rtn; - IOEBUFFER_CNT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE, + IOEBUFFER_CNT(_ioe_usart_outbuffer, CONFIG_USART_OUTBUFFER_SIZE, rtn); return rtn; } #endif -#ifdef CONFIG_IOE_USART_OUTFILE +#ifdef CONFIG_USART_OUTFILE static int usartput(char c, FILE * f) { usart_send((uint8_t) c); return 0; } #endif -#ifdef CONFIG_IOE_USART_INBUFFER +#ifdef CONFIG_USART_INBUFFER static int usartget(FILE * f) { uint8_t v; while (!(v = usart_get())); @@ -166,11 +164,11 @@ static int usartget(FILE * f) { } #endif -#if (defined CONFIG_IOE_USART_INFILE) || (defined CONFIG_IOE_USART_OUTFILE) +#if (defined CONFIG_USART_INFILE) || (defined CONFIG_USART_OUTFILE) FILE *usart_async_open(void) { usart_init_async(); -#ifdef CONFIG_IOE_USART_OUTFILE -#ifdef CONFIG_IOE_USART_INFILE +#ifdef CONFIG_USART_OUTFILE +#ifdef CONFIG_USART_INFILE return fdevopen(usartput, usartget); #else return fdevopen(usartput, 0); @@ -186,19 +184,19 @@ void (*usart_receive) (uint8_t data) = 0; void (*usart_sent) (void) = 0; SIGNAL(USART_RX_vect) { -#ifdef _IOE_USART_INBUFFER +#ifdef _USART_INBUFFER uint8_t val = UDR0; - IOEBUFFER_PUT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE, - val, CONFIG_IOE_USART_INBUFFER_MODE); -#endif /* _IOE_USART_INBUFFER */ + IOEBUFFER_PUT(_ioe_usart_inbuffer, CONFIG_USART_INBUFFER_SIZE, + val, CONFIG_USART_INBUFFER_MODE); +#endif /* _USART_INBUFFER */ if (usart_receive) usart_receive(UDR0); } SIGNAL(USART_UDRE_vect) { -#ifdef _IOE_USART_OUTBUFFER +#ifdef _USART_OUTBUFFER uint8_t val; - IOEBUFFER_GET(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE, + IOEBUFFER_GET(_ioe_usart_outbuffer, CONFIG_USART_OUTBUFFER_SIZE, val); if (val) UDR0 = val; @@ -206,10 +204,9 @@ SIGNAL(USART_UDRE_vect) { _usart_busy = 0; #else _usart_busy = 0; -#endif /* _IOE_USART_OUTBUFFER */ +#endif /* _USART_OUTBUFFER */ if (usart_sent) usart_sent(); } -#endif /* MCUSUPPORT_USART */ -#endif /* CONFIG_IOE_USART */ +#endif /* CONFIG_USART */ diff --git a/src/usi_spi.c b/src/usi_spi.c index 01c37f7..3291721 100644 --- a/src/usi_spi.c +++ b/src/usi_spi.c @@ -1,5 +1,5 @@ -#include "../usi_spi.h" -#include "../mcu/mcu_def.h" +#include +#include inline void usi_spi_init(enum spiMode mode) { if (mode == USI_SPI_MODE_MASTER) { diff --git a/src/utils/buffer.c b/src/utils/buffer.c new file mode 100644 index 0000000..3a5c15e --- /dev/null +++ b/src/utils/buffer.c @@ -0,0 +1,70 @@ +#include + +#ifdef CONFIG_IOE_BUFFER + +int8_t ioebuffer_init(IOEBuffer * buf, uint8_t size, uint8_t flags) { + buf->windex = 0; + buf->rindex = 0; + buf->size = size; + buf->flags = flags; + buf->data = malloc(size * sizeof(void *)); +} + +void ioebuffer_uninit(IOEBuffer * buf) { + free(buf->data); +} + +int8_t ioebuffer_put(IOEBuffer * buf, void *data) { + uint8_t mode = buf->flags & 0x3; + if (mode == IOEBUFFER_F_MODE_BLOCK) { + if (bud->windex == 0) { + while (bud->rindex == size - 1); + } else { + while (bud->rindex == bud->windex - 1); + } + } + bud->data[bud->windex] = data; + if (mode != IOEBUFFER_F_MODE_DROP || + (bud->windex == 0 && bud->rindex == size - 1) || + (bud->rindex + 1 == bud->windex)) { + if (bud->windex == 0) + bud->windex = size - 1; + else + bud->windex--; + } + if (mode == IOEBUFFER_F_MODE_OVERWRITE && bud->windex == bud->rindex) { + if (bud->windex == size - 1) + bud->windex = 0; + else + bud->windex++; + } else + return -1; + return 0; +} + +int8_t ioebuffer_get(IOEBuffer * buf, void **data) { + if (buf->rindex != buf->windex) { + *data = buf->data[buf->rindex]; + if (buf->rindex == 0) + buf->rindex = buf->size - 1; + else + buf->rindex--; + } else + *data = NULL; +} + +void ioebuffer_clean(IOEBuffer * buf) { + buf->windex = 0; + bud->rindex = 0; +} + +uint8_t ioebuffer_cnt(IOEBuffer * buf) { + if (buf->windex < buf->rindex) + return buf->rindex - buf->windex; + else if (buf->windex > buf->rindex) + return buf->size - buf->windex + buf->rindex; + else + return 0; +} + +#endif /* CONFIG_IOE_BUFFER */ diff --git a/src/utils/narray.c b/src/utils/narray.c new file mode 100644 index 0000000..f2cf0ed --- /dev/null +++ b/src/utils/narray.c @@ -0,0 +1,36 @@ +#include + +#ifdef CONFIG_IOE_NARRAY + +void narray_add(void ***array, void *data) { + if (*array == NULL) { + *array = malloc(2 * sizeof(void *)); + (*array)[0] = data; + (*array)[1] = NULL; + } else { + uint8_t size = narray_size(array); + *array = realloc(*array, (size + 2) * sizeof(void *)); + (*array)[size] = data; + (*array)[size + 1] = NULL; + } +} + +void narray_remove(void ***array, void *data) { + uint8_t i = 0; + while ((*array)[i] != NULL || (*array)[i] != data) + i++; + while ((*array)[i + 1] != NULL) { + (*array)[i] = (*array)[i + 1]; + i++; + } + (*array)[i] = NULL; + *array = realloc(*array, (i + 1) * sizeof(void *)); +} + +uint8_t narray_size(void ***array) { + uint8_t size = 0; + while ((*array)[size++] != NULL); + return size; +} + +#endif /* CONFIG_IOE_NARRAY */ diff --git a/tasks.h b/tasks.h deleted file mode 100644 index 60653b3..0000000 --- a/tasks.h +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include -#include - -#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 - -struct Task { - -}; - -void taskDelay(uint16_t us); -void taskDelayMS(uint16_t ms); -void taskDelayTill(int8_t *boolean); -int8_t taskDelayTillT(int8_t *boolean, uin16_t us); -void taskDelayTillF(int8_t (*fnc)(void)); -void taskDelayTillFT(int8_t (*fnc)(void), uint16_t us); - -struct Mutex { -}; -void takeMutex(void); -int8_t takeMutexT(uint16_t timeout); -void giveMutex(void); - -struct Semaphore { -}; - -#else /* CONFIG_IOE_TASKS */ - -#define taskDelay(US) _delay_us(US) -#define taskDelayTill(BOOL) while(*BOOL == 0) -int8_t taskDelayTillT(int8_t *condition, uint8_t timeout_10us); - -#endif /* CONFIG_IOE_TASKS */ -#endif /* _IOE_TASKS_H_ */ diff --git a/template/Makefile b/template/Makefile new file mode 100644 index 0000000..f67d0c2 --- /dev/null +++ b/template/Makefile @@ -0,0 +1,72 @@ +MAKEFLAGS += --no-builtin-rules +# Change PROJNAME value to you project name +# Care to not make any space at the end! +PROJNAME = template + +# Add new source files to this variable +SRC = main.c + +OBJ = $(patsubst %.c,%.o,$(SRC)) # This creates list of *.o files from *.c + +.PHONY: all +ifneq ("$(wildcard .config)","") # Checking if configuration exists +all: $(PROJNAME).hex + @echo Now you can flash $< to your chip. +else +all: help .config +endif + +# Edit here help like you ever want +.PHONY: help +help: + @echo "This is avr-ioe template project" + @echo " all - Build project" + @echo " config - Start configuration program" + @echo " menuconfig - NCurses based configuration program" + @echo " help - Prints this text" + @echo " clean - Removing all object files generated from source files" + +.PHONY: clean +clean: + @echo " CLEAN OBJ" + @$(RM) $(OBJ) + @echo " CLEAN $(PROJNAME).elf $(PROJNAME).hex" + @$(RM) $(PROJNAME).elf $(PROJNAME).hex + @$(MAKE) -C avr-ioe clean + +# Building targets are available only if configuration is generated +ifneq ("$(wildcard .config)","") +-include .config +# If you want change some standard CFLAGS, change them in configuration not here. +# Add here only options that should not be applied to avr-ioe also. +CFLAGS = -Iavr-ioe/include -mmcu=$(MMCU) -imacros avr-ioe/.config.h \ + $(shell echo $(CONFCFLAGS)) $(shell echo -DF_CPU=$(F_CPU)000L) + +$(PROJNAME).elf: avr-ioe/libioe.a +$(PROJNAME).elf: $(OBJ) + @echo " LD $@" + @avr-gcc -Os -mmcu=$(MMCU) $^ -o $@ -Lavr-ioe -lioe + +$(PROJNAME).hex: $(PROJNAME).elf + @echo " OBJCOPY $@" + @avr-objcopy -O ihex -R .eeprom $< $@ + +$(OBJ): %.o: %.c avr-ioe/libioe.a + @echo " CC $@" + @avr-gcc $(CFLAGS) -c -o $@ $< + +avr-ioe/libioe.a: .config + @CONFIG=$$(readlink -f .config) $(MAKE) -C avr-ioe libioe.a +endif + +.config: + @echo Please generate configuration first using config or menuconfig target + @exit 1 + +.PHONY: config +config: + @CONFIG=$$(readlink -f .config) $(MAKE) -C avr-ioe menuconfig + +.PHONY: menuconfig +menuconfig: + @CONFIG=$$(readlink -f .config) $(MAKE) -C avr-ioe menuconfig diff --git a/template/README.md b/template/README.md new file mode 100644 index 0000000..bdafb7f --- /dev/null +++ b/template/README.md @@ -0,0 +1,9 @@ +AVR-IOE template project +======================== +Use can use this as template for our project. Just move it where you want it and +change symbolic link to avr-ioe. Or if you are going to use git, just remove +symbolic link and add avr-ioe as submodule. + +In Makefile you can change project name and add or change source files. + +To configure avr-ioe just run `make menuconfig` in this folder. diff --git a/template/avr-ioe b/template/avr-ioe new file mode 120000 index 0000000..a96aa0e --- /dev/null +++ b/template/avr-ioe @@ -0,0 +1 @@ +.. \ No newline at end of file diff --git a/template/main.c b/template/main.c new file mode 100644 index 0000000..90bb878 --- /dev/null +++ b/template/main.c @@ -0,0 +1,5 @@ +#include + +int main() { + return 0; +}; diff --git a/time.h b/time.h deleted file mode 100644 index 945511d..0000000 --- a/time.h +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -#include "mcu/mcu_def.h" - -#ifndef _IOE_TIME_H_ -#define _IOE_TIME_H_ - -#ifndef CONFIG_IOE_TIME_TIMER -#error "To use Time you must specify CONFIG_IOE_TIME_TIMER macro." -#endif - - -#endif /* _IOE_TIME_H_ */ diff --git a/timer.h b/timer.h deleted file mode 100644 index 192c15d..0000000 --- a/timer.h +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include -#include - -#include "mcu/mcu_def.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 -}; - -static inline void timer_init(uint8_t timer, enum timerDivider div) { - switch (timer) { -#ifdef COUNTER0_PWM - case COUNTER0_PWM: - // Null counting register - TCNT0 = 0; - // Set interrupt flag - TIMSK0 = _BV(TOIE0); - // Set division and start counting - switch (div) { - case TIMER_DIVIDER_1: - TCCR0B = _BV(CS00); - break; - case TIMER_DIVIDER_8: - TCCR0B = _BV(CS01); - break; - case TIMER_DIVIDER_64: - TCCR0B = _BV(CS01) | _BV(CS00); - break; - case TIMER_DIVIDER_256: - TCCR0B = _BV(CS02); - break; - case TIMER_DIVIDER_1024: - TCCR0B = _BV(CS02) | _BV(CS01); - break; - default: - return; - } - break; -#endif /* COUNTER0_PWM */ -#ifdef COUNTER1_16PWM - case COUNTER1_16PWM: - break; -#endif /* COUNTER1_16PWM */ -#ifdef COUNTER2_PWM_ASYNC - case COUNTER2_PWM_ASYNC: - break; -#endif /* COUNTER2_PWM_ASYNC */ - } -} - -static inline void timer_disable(uint8_t timer) { - switch (timer) { -#ifdef COUNTER0_PWM - case COUNTER0_PWM: - TCCR0B = 0; - break; -#endif /* COUNTER0_PWM */ -#ifdef COUNTER1_16PWM - case COUNTER1_16PWM: - break; -#endif /* COUNTER1_16PWM */ -#ifdef COUNTER2_PWM_ASYNC - case COUNTER2_PWM_ASYNC: - break; -#endif /* COUNTER2_PWM_ASYNC */ - } -} - -static inline void timer_reset(uint8_t timer) { - switch (timer) { -#ifdef COUNTER0_PWM - case COUNTER0_PWM: - TCNT0 = 0; - break; -#endif /* COUNTER0_PWM */ -#ifdef COUNTER1_16PWM - case COUNTER1_16PWM: - break; -#endif /* COUNTER1_16PWM */ -#ifdef COUNTER2_PWM_ASYNC - case COUNTER2_PWM_ASYNC: - break; -#endif /* COUNTER2_PWM_ASYNC */ - } -} - -static inline uint16_t timer_value(uint8_t timer) { - switch (timer) { -#ifdef COUNTER0_PWM - case COUNTER0_PWM: - return TCNT0; - break; -#endif /* COUNTER0_PWM */ -#ifdef COUNTER1_16PWM - case COUNTER1_16PWM: - break; -#endif /* COUNTER1_16PWM */ -#ifdef COUNTER2_PWM_ASYNC - case COUNTER2_PWM_ASYNC: - break; -#endif /* COUNTER2_PWM_ASYNC */ - default: - return 0; - } -} - -#ifdef COUNTER0_PWM -void (*timer_0_pwm_overflow) (void); -#endif /* COUNTER0_PWM */ -#ifdef COUNTER1_16PWM -void (*timer_1_16pwm_overflow) (void); -#endif /* COUNTER1_16PWM */ -#ifdef COUNTER2_PWM_ASYNC -void (*timer_2_pwm_overflow) (void); -#endif /* COUNTER2_PWM_ASYNC */ - -static inline void timer_sethook(uint8_t timer, void (*fnc) (void)) { - switch (timer) { -#ifdef COUNTER0_PWM - case COUNTER0_PWM: - timer_0_pwm_overflow = fnc; - break; -#endif /* COUNTER0_PWM */ -#ifdef COUNTER1_16PWM - case COUNTER1_16PWM: - timer_1_16pwm_overflow = fnc; - break; -#endif /* COUNTER1_16PWM */ -#ifdef COUNTER2_PWM_ASYNC - case COUNTER2_PWM_ASYNC: - timer_2_pwm_overflow = fnc; - break; -#endif /* COUNTER2_PWM_ASYNC */ - } -} - -#endif /* CONFIG_IOE_TIMERS */ -#endif /* _IOE_TIMER_H_ */ diff --git a/twi.h b/twi.h deleted file mode 100644 index 514b17a..0000000 --- a/twi.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include -#include - -#include "mcu/mcu_def.h" -#include "buffers.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/usart.h b/usart.h deleted file mode 100644 index a67b141..0000000 --- a/usart.h +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include -#include - -#include "mcu/mcu_def.h" -#include "tasks.h" -#include "buffers.h" - -#ifndef _IOE_USART_H_ -#define _IOE_USART_H_ -#ifdef CONFIG_IOE_USART - -#ifndef MCUSUPPORT_USART -#error "No USART interface is known on your mcu." -#endif - -// TODO clock polarity and synchronous mode - -#define USART_FRAMEERROR _BV(FE0) -#define USART_DATAOVERRUN _BV(DOR0) -#define USART_PARITYERROR _BV(UPE0) - -#if CONFIG_IOE_USART_INBUFFER_SIZE > 0 -#define _IOE_USART_INBUFFER -volatile IOEBUFFER(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE); -#endif -#if CONFIG_IOE_USART_OUTBUFFER_SIZE > 0 -#define _IOE_USART_OUTBUFFER -volatile IOEBUFFER(_ioe_usart_outbuffer, CONFIG_IOE_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 _IOE_USART_OUTBUFFER -void usart_send_str(char *str); -#endif -#ifdef _IOE_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 _IOE_USART_INBUFFER -uint8_t usart_inbuffered(void); -#endif -#ifdef _IOE_USART_OUTBUFFER -uint8_t usart_outbuffered(void); -#endif -#if (defined CONFIG_IOE_USART_INFILE) || (defined CONFIG_IOE_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_IOE_USART */ -#endif /* _IOE_USART_H_ */ diff --git a/usi_spi.h b/usi_spi.h deleted file mode 100644 index 18534ab..0000000 --- a/usi_spi.h +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include - -#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_ */ -- cgit v1.2.3