diff options
author | Karel Kočí <cynerd@email.cz> | 2016-03-08 16:10:33 +0100 |
---|---|---|
committer | Karel Kočí <cynerd@email.cz> | 2016-03-08 16:10:33 +0100 |
commit | 5d29fe79d30f430ae326d9dc57ccfaed6fe61328 (patch) | |
tree | 8341804d561c0060176cbebc3f9a57c7c07f7816 | |
parent | 4e773191d447ac434536262a6f204dd991d4ad77 (diff) | |
download | avr-ioe-5d29fe79d30f430ae326d9dc57ccfaed6fe61328.tar.gz avr-ioe-5d29fe79d30f430ae326d9dc57ccfaed6fe61328.tar.bz2 avr-ioe-5d29fe79d30f430ae326d9dc57ccfaed6fe61328.zip |
Another full update of current work
86 files changed, 2292 insertions, 625 deletions
@@ -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 @@ -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" @@ -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`. @@ -1,9 +0,0 @@ -#include <avr/io.h> -#include <avr/interrupt.h> -#include <stdint.h> - -#ifndef _IOE_ADC_H_ -#define _IOE_ADC_H_ - - -#endif /* _IOE_ADC_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/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 <avr/io.h> -#include <avr/interrupt.h> -#include <stdio.h> - -#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/src/can_mcp2515.c b/docs/add_support.md index e69de29..e69de29 100644 --- a/src/can_mcp2515.c +++ b/docs/add_support.md 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/doc/spi.md b/docs/modules/spi.md index 438d32d..3ae730c 100644 --- a/doc/spi.md +++ b/docs/modules/spi.md @@ -1,9 +1,9 @@ Serial peripheral interface ---------------------------- +=========================== This interface is link to MOSI and MISO pins. Also SS pin is used when slave mode initialized. -## Functions -### spi_init +## References +### spi\_init ```C static inline void spi_init(enum spiMode mode) ``` @@ -11,22 +11,22 @@ Initializes SPI interface. Parameters: mode - Specify mode of SPI interface -NOTE: Global interrupt must be enabled for right function of SPI. +NOTE: Global interrupts must be enabled for right function of SPI. -### spi_busy +### 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 +### spi\_join ```C static inline void spi_join(void) ``` Blocks processor until device is not busy. -### spi_send +### spi\_send ```C static inline uint8_t spi_send(uint8_t data) ``` @@ -34,25 +34,25 @@ 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 +### 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(). +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 +### 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(). +Best place to call this is spi\_receive(). WARNING: Invoke this only when interface is initialized in SLAVE mode. -## Function pointer spi_receive +## Function pointer spi\_receive ```C extern void (*spi_receive)(uint8_t data) ``` @@ -66,4 +66,4 @@ enum spiMode { SPI_MODE_SLAVE }; ``` -This is used as parameter for spi_init function. +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 --- /dev/null +++ b/docs/modules/timer.md diff --git a/docs/modules/usart.md b/docs/modules/usart.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/modules/usart.md 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 --- /dev/null +++ b/docs/usage.md 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 --- /dev/null +++ b/examples/blink/README.md 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 <avr/io.h> +#include <util/delay.h> +#include <ioport.h> + +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 <avr/io.h> #include <util/delay.h> -#include "../../spi.h" +#include <spi.h> 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 <avr/io.h> #include <util/delay.h> -#include "../../spi.h" +#include <spi.h> 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 <avr/io.h> #include <util/delay.h> #include <string.h> -#include "../../usart.h" +#include <usart.h> 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 <avr/io.h> +#include <avr/interrupt.h> +#include <stdint.h> + +#ifndef _IOE_ADC_H_ +#define _IOE_ADC_H_ +#ifdef CONFIG_IOE_ADC +#ifndef MCUSUPPORT_ADC +#error "No ADC support for your mcu. Probably just not implemented yet." +#endif + +int8_t ioe_adc(uint8_t input); + +#endif /* CONFIG_IOE_ADC */ +#endif /* _IOE_ADC_H_ */ diff --git a/avr-ioe.h b/include/avr-ioe.h index ac58ee7..cb84ad9 100644 --- a/avr-ioe.h +++ b/include/avr-ioe.h @@ -1,3 +1,2 @@ -#include "buffers.h" #include "spi.h" #include "usart.h" diff --git a/include/can/global.h b/include/can/global.h new file mode 100644 index 0000000..5d88fe6 --- /dev/null +++ b/include/can/global.h @@ -0,0 +1,20 @@ +#include <stdint.h> + +#ifndef _IOE_CAN_GLOBAL_ +#define _IOE_CAN_GLOBAL_ + +typedef struct { + uint16_t id; + uint8_t length; + uint8_t data[8]; +} CanFrame; + +typedef struct { + CanFrame **buffer; + void *udata; +} Can; + + +void can_send(Can *can, CanFrame *frame); + +#endif /* _IOE_CAN_GLOBAL_ */ diff --git a/include/can/mcp2515.h b/include/can/mcp2515.h new file mode 100644 index 0000000..59376f7 --- /dev/null +++ b/include/can/mcp2515.h @@ -0,0 +1,36 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <stdint.h> + +#include "spi.h" +#include "global.h" + +#ifndef _IOE_CAN_MCP2515_H_ +#define _IOE_CAN_MCP2515_H_ +#ifdef CONFIG_IOE_CAN_MCP2515 +#ifndef CONFIG_IOE_SPI +#error "Please define CONFIG_IOE_SPI. MCP2515 requires SPI." +#endif + +// TODO registers +#define CAN_MCP2515_CANCTL +// TODO buffers + +typedef struct { + uint8_t group, mask; +} CanMcp2515; + +int8_t can_mcp2515_init(CanMcp2515 * can, uint8_t group, uint8_t mask); + +void can_mcp2515_reset(CanMcp2515 * can); +uint8_t can_mcp2515_read(CanMcp2515 * can, uint8_t address); +uint8_t can_mcp2515_readrx(CanMcp2515 * can, uint8_t buffer); +void can_mcp2515_write(CanMcp2515 * can, uint8_t address, uint8_t data); +void can_mcp2515_loadrx(CanMcp2515 * can, uint8_t buffer, uint8_t data); +uint8_t can_mcp2515_rdstat(CanMcp2515 * can); +uint8_t can_mcp2515_rxstat(CanMcp2515 * can); +void can_mcp2515_bitmod(CanMcp2515 * can, uint8_t address, uint8_t mask, + uint8_t data); + +#endif /* CONFIG_IOE_CAN_MCP2515 */ +#endif /* _IOE_CAN_MCP2515_H_ */ diff --git a/include/can/software.h b/include/can/software.h new file mode 100644 index 0000000..b443e42 --- /dev/null +++ b/include/can/software.h @@ -0,0 +1,9 @@ +#include <avr/io.h> +#include <util/delay.h> +#include <stdint.h> + +#ifndef _IOE_CAN_SOFTWARE_H_ +#define _IOE_CAN_SOFTWARE_H_ + + +#endif /* _IOE_CAN_SOFTWARE_H_ */ diff --git a/include/ioport.h b/include/ioport.h new file mode 100644 index 0000000..1022493 --- /dev/null +++ b/include/ioport.h @@ -0,0 +1,55 @@ +#include <stdlib.h> +#include <avr/io.h> +#include <avr/interrupt.h> + +#include "mcu/mcu_def.h" + +#ifndef _IOE_IOPORT_H_ +#define _IOE_IOPORT_H_ +#ifdef CONFIG_IOPORTS + +enum ioInResistor { + IO_PULLUP, + IO_PULLDOWN +}; + +static inline void io_setout(uint8_t group, uint8_t mask) { + IO_DDR(group) |= mask; +} +static inline void io_hight(uint8_t group, uint8_t mask) { + IO_PORT(group) |= mask; +} +static inline void io_low(uint8_t group, uint8_t mask) { + IO_PORT(group) &= ~mask; +} +static inline void io_set(uint8_t group, uint8_t mask, int8_t val) { + if (val) + io_hight(group, mask); + else + io_low(group, mask); +} + +static inline void io_setin(uint8_t group, uint8_t mask, + enum ioInResistor resistor) { + IO_DDR(group) &= ~mask; + if (resistor == IO_PULLUP) + IO_PORT(group) |= mask; + else + IO_PORT(group) &= ~mask; +} +static inline int8_t io_get(uint8_t group, uint8_t mask) { + return (int8_t) IO_PIN(group) & mask; +} + +#ifdef CONFIG_PCINT + +#define IO_RISING (1 << 0) +#define IO_FALLING (1 << 1) +void io_change_sethook(uint8_t group, uint8_t mask, uint8_t edge, + void (*change) (uint8_t group, uint8_t mask)); +void io_change_remhook(void (*change) (uint8_t group, uint8_t mask)); +void io_change_clearhooks(void); + +#endif /* CONFIG_PCINT */ +#endif /* CONFIG_IOPORTS */ +#endif /* _IOE_IOPORT_H_ */ diff --git a/include/mcu/Kconfig b/include/mcu/Kconfig new file mode 100644 index 0000000..a69903f --- /dev/null +++ b/include/mcu/Kconfig @@ -0,0 +1,11 @@ +config MMCU + string + default "atmega328p" if ATMEGA328P + +choice MCU + prompt "Microcontroller (MMCU)" + +source include/mcu/atmega328p.Kconfig +source include/mcu/attiny85.Kconfig + +endchoice diff --git a/include/mcu/atmega328p.Kconfig b/include/mcu/atmega328p.Kconfig new file mode 100644 index 0000000..5b4bf27 --- /dev/null +++ b/include/mcu/atmega328p.Kconfig @@ -0,0 +1,8 @@ +config ATMEGA328P + bool "atmega328p" + select MCUSUPPORT_IOPORTS + select MCUSUPPORT_PCINT0 + select MCUSUPPORT_PCINT1 + select MCUSUPPORT_PCINT2 + select MCUSUPPORT_SPI + select MCUSUPPORT_USART diff --git a/include/mcu/atmega328p.h b/include/mcu/atmega328p.h new file mode 100644 index 0000000..994e9e6 --- /dev/null +++ b/include/mcu/atmega328p.h @@ -0,0 +1,63 @@ +/* This is specific configuration for ATmega328P. + * Also applies on ATmega48A, ATmega48PA, ATmega88A, ATmega88PA, ATmega168A and + * ATmega168PA. + */ +#include <avr/io.h> + +// IO Ports +#define MCUSUPPORT_IOPORTS +#define IO_B 0 +#define IO_C 1 +#define IO_D 2 +#define IO_PIN(GROUP) (* (volatile uint8_t *)(PINB + 0x3*GROUP)) +#define IO_DDR(GROUP) (* (volatile uint8_t *)(DDRB + 0x3*GROUP)) +#define IO_PORT(GROUP) (* (volatile uint8_t *)(PORTB + 0x3*GROUP)) +#define IO_B0 IO_B, (1 << 0) +#define IO_B1 IO_B, (1 << 1) +#define IO_B2 IO_B, (1 << 2) +#define IO_B3 IO_B, (1 << 3) +#define IO_B4 IO_B, (1 << 4) +#define IO_B5 IO_B, (1 << 5) +#define IO_B6 IO_B, (1 << 6) +#define IO_B7 IO_B, (1 << 7) +#define IO_C0 IO_C, (1 << 0) +#define IO_C1 IO_C, (1 << 1) +#define IO_C2 IO_C, (1 << 2) +#define IO_C3 IO_C, (1 << 3) +#define IO_C4 IO_C, (1 << 4) +#define IO_C5 IO_C, (1 << 5) +#define IO_C6 IO_C, (1 << 6) +#define IO_D0 IO_D, (1 << 0) +#define IO_D1 IO_D, (1 << 1) +#define IO_D2 IO_D, (1 << 2) +#define IO_D3 IO_D, (1 << 3) +#define IO_D4 IO_D, (1 << 4) +#define IO_D5 IO_D, (1 << 5) +#define IO_D6 IO_D, (1 << 6) +#define IO_D7 IO_D, (1 << 7) +#define MCUSUPPORT_PCINT0 8 +#define MCUSUPPORT_PCINT1 8 +#define MCUSUPPORT_PCINT2 8 +// SPI +#define MCUSUPPORT_SPI +#define DDR_SPI DDRB +#define DD_SS DDB2 +#define DD_MOSI DDB3 +#define DD_MISO DDB4 +#define DD_SCLK DDB5 +#define PORT_SPI PORTB +#define PORT_SS PORTB2 +#define PORT_MOSI PORTB3 +#define PORT_MISO PORTB4 +#define PORT_SCLK PORTB5 +// USART +#define MCUSUPPORT_USART +// TWI +#define MCUSUPPORT_TWI +// TIMERS +#define MCUSUPPORT_TIMER_0 +#define MCUSUPPORT_TIMER_1 +#define MCUSUPPORT_TIMER_2 +#define COUNTER0_PWM 0 +#define COUNTER1_16PWM 1 +#define COUNTER2_PWM_ASYNC 2 diff --git a/mcu/ATmega32U4.h b/include/mcu/atmega32u4.h index 16351e8..16351e8 100644 --- a/mcu/ATmega32U4.h +++ b/include/mcu/atmega32u4.h diff --git a/mcu/ATmega8A.h b/include/mcu/atmega8a.h index a2d3adf..a2d3adf 100644 --- a/mcu/ATmega8A.h +++ b/include/mcu/atmega8a.h diff --git a/include/mcu/attiny4313.h b/include/mcu/attiny4313.h new file mode 100644 index 0000000..3a2d0b9 --- /dev/null +++ b/include/mcu/attiny4313.h @@ -0,0 +1,46 @@ +/* This is specific configuration for ATtiny4313. + * This configuration also applies on ATtiny2313A. + */ +#include <avr/io.h> + +// IO Ports +#define MCUSUPPORT_IOPORTS +#define IO_A 0 +#define IO_B 1 +#define IO_D 3 +#define IO_PIN(GROUP) (* (volatile uint8_t *)(PINB + 0x3*GROUP)) +#define IO_DDR(GROUP) (* (volatile uint8_t *)(DDRB + 0x3*GROUP)) +#define IO_PORT(GROUP) (* (volatile uint8_t *)(PORTB + 0x3*GROUP)) +#define IO_A0 IO_A, (1 << 0) +#define IO_A1 IO_A, (1 << 1) +#define IO_A2 IO_A, (1 << 2) +#define IO_B0 IO_B, (1 << 0) +#define IO_B1 IO_B, (1 << 1) +#define IO_B2 IO_B, (1 << 2) +#define IO_B3 IO_B, (1 << 3) +#define IO_B4 IO_B, (1 << 4) +#define IO_B5 IO_B, (1 << 5) +#define IO_B6 IO_B, (1 << 6) +#define IO_B7 IO_B, (1 << 7) +#define IO_D0 IO_D, (1 << 0) +#define IO_D1 IO_D, (1 << 1) +#define IO_D2 IO_D, (1 << 2) +#define IO_D3 IO_D, (1 << 3) +#define IO_D4 IO_D, (1 << 4) +#define IO_D5 IO_D, (1 << 5) +#define IO_D6 IO_D, (1 << 6) +#define MCUSUPPORT_PCINT0 8 // TODO this is B +#define MCUSUPPORT_PCINT1 7 // But this is D +#define MCUSUPPORT_PCINT2 3 // And this is A, this is not expected in ioport.c +// SPI USI +#define MCUSUPPORT_USI +#define DDR_USI DDRB +#define DD_DI DDB5 +#define DD_DO DDB6 +#define DD_USCK DDB7 +#define PORT_USI PORTB +#define PORT_DI PORTB5 +#define PORT_DO PORTB6 +#define PORT_USCK PORTB7 +// USART +#define MCUSUPPORT_USART0 diff --git a/include/mcu/attiny85.Kconfig b/include/mcu/attiny85.Kconfig new file mode 100644 index 0000000..d58c1d8 --- /dev/null +++ b/include/mcu/attiny85.Kconfig @@ -0,0 +1,4 @@ +config ATTINY85 + bool "attiny85" + select MCUSUPPORT_IOPORTS + select MCUSUPPORT_PCINT0 diff --git a/mcu/ATtiny85.h b/include/mcu/attiny85.h index 19db90d..c342bbb 100644 --- a/mcu/ATtiny85.h +++ b/include/mcu/attiny85.h @@ -3,6 +3,19 @@ */ #include <avr/io.h> +// IO Ports +#define MCUSUPPORT_IOPORTS +#define IO_B 0 +#define IO_PIN(GROUP) PINB +#define IO_DDR(GROUP) DDRB +#define IO_PORT(GROUP) PORTB +#define IO_B0 IO_B, (1 << 0) +#define IO_B1 IO_B, (1 << 1) +#define IO_B2 IO_B, (1 << 2) +#define IO_B3 IO_B, (1 << 3) +#define IO_B4 IO_B, (1 << 4) +#define IO_B5 IO_B, (1 << 5) +#define MCUSUPPORT_PCINT0 6 // SPI USI #define MCUSUPPORT_USI #define DDR_USI DDRB diff --git a/mcu/mcu.h b/include/mcu/mcu.h index e1272b9..e1272b9 100644 --- a/mcu/mcu.h +++ b/include/mcu/mcu.h diff --git a/mcu/mcu_def.h b/include/mcu/mcu_def.h index 51b70fe..472b607 100644 --- a/mcu/mcu_def.h +++ b/include/mcu/mcu_def.h @@ -1,21 +1,21 @@ #include "mcu.h" #if __MCU_ATmega328p__ -#include "ATmega328P.h" +#include "atmega328p.h" #endif #if __MCU_ATmega32U4__ -#include "ATmega32U4.h" +#include "atmega32u4.h" #endif #if __MCU_ATmega8A__ -#include "ATmega8A.h" +#include "atmega8a.h" #endif #if __MCU_ATtiny4313__ -#include "ATtiny4313.h" +#include "attiny4313.h" #endif #if __MCU_ATtiny85__ -#include "ATtiny85.h" +#include "attiny85.h" #endif diff --git a/sensor_dht22.h b/include/sensors/dht22.h index 6ddcf9c..aabb442 100644 --- a/sensor_dht22.h +++ b/include/sensors/dht22.h @@ -2,11 +2,12 @@ #include <util/delay.h> #include <stdint.h> -#include "tasks.h" -#include "timer.h" +#include "../tasks.h" +#include "../timer.h" #ifndef _IOE_SENSOR_DHT22_H_ #define _IOE_SENSOR_DHT22_H_ +#ifdef CONFIG_IOE_SENSOR_DHT22 struct dht22_value { uint8_t integral; @@ -28,6 +29,7 @@ extern const struct dht22_port dht22_ports[]; * Initialize port for sensor */ void dht22_init(uint8_t port); + /* * Read values from dht22 * rh - relative @@ -36,4 +38,5 @@ void dht22_init(uint8_t port); 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_ */ @@ -4,15 +4,10 @@ #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 +#ifdef CONFIG_SPI enum spiMode { SPI_MODE_MASTER, @@ -20,6 +15,7 @@ enum spiMode { }; volatile extern int8_t _spi_busy; +volatile extern Mutex spi_mutex; static inline void spi_init(enum spiMode mode) { _spi_busy = 0; @@ -45,13 +41,7 @@ static inline int8_t spi_busy(void) { } 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; + task_delay_till(&_spi_busy, 0); } static inline void spi_transfer(uint8_t data) { @@ -59,11 +49,18 @@ static inline void spi_transfer(uint8_t data) { 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_IOE_SPI */ +#endif /* CONFIG_SPI */ #endif /* _IOE_SPI_H_ */ diff --git a/include/tasks.h b/include/tasks.h new file mode 100644 index 0000000..27bd968 --- /dev/null +++ b/include/tasks.h @@ -0,0 +1,94 @@ +#include <avr/io.h> +#include <util/delay.h> +#include <avr/interrupt.h> +#include <stdint.h> +#include <stdlib.h> + +#include "mcu/mcu_def.h" +#include "timer.h" + +#ifndef _IOE_TASKS_H_ +#define _IOE_TASKS_H_ + +#ifdef CONFIG_IOE_TASKS + +#ifndef CONFIG_IOE_TIMERS +#error "To use tasks you must enable timers (CONFIG_IOE_TIMERS)." +#endif + +int8_t tasks_run(void); + +union StackPointer { + uint8_t lh8[2]; + uint16_t lh16; +}; +typedef struct { + uint8_t flags; + void (*func) (void *data); + void *data; + uint8_t _rflags; + uint8_t _stack_size; + union StackPointer _sp; +} Task; +int8_t task_spawn(Task * t, uint8_t stack_size); +void taks_exit(void); +int8_t task_kill(Task * t); +int8_t task_safe(void); +int8_t task_unsafe(void); + +int8_t task_delay(uint16_t cycles); +int8_t task_delay_ms(uint16_t ms); +int8_t task_delay_till(volatile int8_t * boolean, uint16_t ms); + +#define MUTEX_F_TIMED (1<<0) +#define MUTEX_F_TAKEN (1<<7) +typedef struct { + uint8_t flags; + Task *_task_took; +} Mutex; +int8_t mutex_init(Mutex * mtx); +int8_t mutex_free(Mutex * mtx); +int8_t mutex_take(Mutex * mtx, uint16_t timeout); +int8_t mutex_give(Mutex * mtx); + +typedef struct { + uint8_t flags; + uint8_t _count; + Task **_tasks; + uint8_t _tasks_len; +} Semaphore; +int8_t semaphore_init(Semaphore * sem, uint8_t count); +int8_t semaphore_free(Semaphore * sem); +int8_t semaphore_take(Semaphore * sem, uint16_t timeout); +int8_t semaphore_give(Semaphore * sem); + +#else /* CONFIG_IOE_TASKS */ + +typedef struct { +} Task; +#define task_spawn(T, STACK_SIZE) +#define task_exit() +#define task_kill(T) +#define task_safe() +#define task_unsafe() + +#define task_delay(US) _delay_us(US) // TODO this should be cycles +#define task_delay_ms(MS) _delay_ms(MS) +int8_t task_delay_till(volatile int8_t * boolean, uint16_t ms); + +typedef struct { +} Mutex; +#define mutex_init(MTX, FLAGS) +#define mutex_free(MTX) +#define mutex_take(MTX, TIMEOUT) +#define mutex_give(MTX); + +typedef struct { +} Semaphore; +#define semaphore_init(SEM, FLAGS, COUNT) +#define semaphore_free(SEM) +#define semaphore_take(SEM, TIMEOUT) +#define semaphore_give(SEM) + +#endif /* CONFIG_IOE_TASKS */ +#endif /* _IOE_TASKS_H_ */ diff --git a/include/timer.h b/include/timer.h new file mode 100644 index 0000000..4fef95c --- /dev/null +++ b/include/timer.h @@ -0,0 +1,28 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <stdint.h> + +#include "mcu/mcu_def.h" +#include "utils/narray.h" + +#ifndef _IOE_TIMER_H_ +#define _IOE_TIMER_H_ +#ifdef CONFIG_IOE_TIMERS + +enum timerDivider { + TIMER_DIVIDER_1, + TIMER_DIVIDER_8, + TIMER_DIVIDER_64, + TIMER_DIVIDER_256, + TIMER_DIVIDER_1024 +}; + +void timer_init(uint8_t timer, enum timerDivider div); +void timer_disable(uint8_t timer); +void timer_reset(uint8_t timer); +uint16_t timer_value(uint8_t timer); +void timer_sethook(uint8_t timer, void (*fnc) (void)); +void timer_remhook(uint8_t timer, void (*fnc) (void)); + +#endif /* CONFIG_IOE_TIMERS */ +#endif /* _IOE_TIMER_H_ */ @@ -3,7 +3,6 @@ #include <stdint.h> #include "mcu/mcu_def.h" -#include "buffers.h" #ifndef _IOE_TWI_H_ #define _IOE_TWI_H_ diff --git a/usart.h b/include/usart.h index a67b141..3ba5382 100644 --- a/usart.h +++ b/include/usart.h @@ -5,15 +5,11 @@ #include "mcu/mcu_def.h" #include "tasks.h" -#include "buffers.h" +#include "utils/buffer.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 +#ifndef _USART_H_ +#define _USART_H_ +#ifdef CONFIG_USART // TODO clock polarity and synchronous mode @@ -21,13 +17,13 @@ #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); +#if CONFIG_USART_INBUFFER_SIZE > 0 +#define _USART_INBUFFER +volatile IOEBUFFER(uint8_t, _ioe_usart_inbuffer, CONFIG_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); +#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; @@ -38,10 +34,10 @@ extern volatile int8_t _usart_busy; */ void usart_init_async(void); void usart_send(uint8_t data); -#ifdef _IOE_USART_OUTBUFFER +#ifdef _USART_OUTBUFFER void usart_send_str(char *str); #endif -#ifdef _IOE_USART_INBUFFER +#ifdef _USART_INBUFFER uint8_t usart_get(void); #endif static inline uint8_t usart_queryerror(void) { @@ -50,13 +46,13 @@ static inline uint8_t usart_queryerror(void) { static inline int8_t usart_busy(void) { return _usart_busy; } -#ifdef _IOE_USART_INBUFFER +#ifdef _USART_INBUFFER uint8_t usart_inbuffered(void); #endif -#ifdef _IOE_USART_OUTBUFFER +#ifdef _USART_OUTBUFFER uint8_t usart_outbuffered(void); #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); #endif @@ -64,5 +60,5 @@ FILE *usart_async_open(void); extern void (*usart_receive)(uint8_t data); extern void (*usart_sent)(void); -#endif /* CONFIG_IOE_USART */ -#endif /* _IOE_USART_H_ */ +#endif /* CONFIG_USART */ +#endif /* _USART_H_ */ diff --git a/usi_spi.h b/include/usi_spi.h index 18534ab..18534ab 100644 --- a/usi_spi.h +++ b/include/usi_spi.h diff --git a/buffers.h b/include/utils/buffer.h index 497a21c..66b68ad 100644 --- a/buffers.h +++ b/include/utils/buffer.h @@ -1,18 +1,10 @@ -/* 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_ +#ifndef _IOE_BUFFER_H_ +#define _IOE_BUFFER_H_ // Define new buffer -#define IOEBUFFER(name, size) struct { \ +#define IOEBUFFER(type, name, size) struct { \ uint8_t rindex, windex; \ - uint8_t data[size]; \ + type data[size]; \ } name; #define IOEBUFFER_INIT(name, size) { \ @@ -24,7 +16,7 @@ #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) \ +#define IOEBUFFER_PUT(name, size, idata, mode) \ if (mode == IOEBUFFER_MODE_BLOCK) { \ if (name.windex == 0) { \ while (name.rindex == size - 1); \ @@ -32,7 +24,7 @@ while (name.rindex == name.windex - 1); \ } \ } \ - name.data[name.windex] = data; \ + name.data[name.windex] = idata; \ if (mode != IOEBUFFER_MODE_DROP || \ (name.windex == 0 && name.rindex == size - 1) || \ (name.rindex + 1 == name.windex)) { \ @@ -69,4 +61,26 @@ else \ variable = 0; -#endif /* _IOE_BUFFERS_H_ */ +///////////////////////////////////////////////////////////////////// + +#ifdef CONFIG_IOE_BUFFER +#include <stdint.h> + +#define IOEBUFFER_F_MODE_BLOCK 0x0 +#define IOEBUFFER_F_MODE_OVERWRITE 0x1 +#define IOEBUFFER_F_MODE_DROP 0x2 + +typedef struct { + uint8_t rindex, windex, size, flags; + void **data; +} IOEBuffer; + +int8_t ioebuffer_init(IOEBuffer * buf, uint8_t size, uint8_t flags); +void ioebuffer_uninit(IOEBuffer * buf); +int8_t ioebuffer_put(IOEBuffer * buf, void *data); +int8_t ioebuffer_get(IOEBuffer * buf, void **data); +void ioebuffer_clean(IOEBuffer * buf); +uint8_t ioebuffer_cnt(IOEBuffer * buf); + +#endif /* CONFIG_IOE_BUFFER */ +#endif /* _IOE_BUFFER_H_ */ diff --git a/include/utils/narray.h b/include/utils/narray.h new file mode 100644 index 0000000..814d87d --- /dev/null +++ b/include/utils/narray.h @@ -0,0 +1,21 @@ +#include <stdlib.h> +#include <stdint.h> + +#ifndef _IOE_NARRAY_H_ +#define _IOE_NARRAY_H_ +#ifdef CONFIG_IOE_NARRAY + +void narray_add(void ***array, void *data); +void narray_remove(void ***array, void *data); +size_t narray_size(void ***array); +inline void narray_free(void ***array) { + if (array != NULL) { + free(*array); + *array = NULL; + } +} + +#define fornarray(array, i, data) for (i = 0; (data = array[i]) != 0; i++) + +#endif /* CONFIG_IOE_NARRAY */ +#endif /* _IOE_NARRAY_H_ */ diff --git a/include/utils/timers_div.h b/include/utils/timers_div.h new file mode 100644 index 0000000..9077aac --- /dev/null +++ b/include/utils/timers_div.h @@ -0,0 +1,81 @@ +//#include "../timer.h" +enum timerDivider { + TIMER_DIVIDER_1, + TIMER_DIVIDER_8, + TIMER_DIVIDER_64, + TIMER_DIVIDER_256, + TIMER_DIVIDER_1024 +}; + +#ifndef TIMER_DIV_RESTIME +#error Please define minimal time (us) before include timers_div.h in TIMER_DIV_RESTIME +#endif + +// Calculate optimal division +#define _TD_OPTIMAL (TIMER_DIV_RESTIME * F_CPU/1000000L) + +// Set minimal and maximal division closest to optimal +#if _TD_OPTIMAL < 8 +#define _TD_MIN 1 +#define _TD_MAX 8 +#elif _TD_OPTIMAL < 64 +#define _TD_MIN 8 +#define _TD_MAX 64 +#elif _TD_OPTIMAL < 256 +#define _TD_MIN 64 +#define _TD_MAX 256 +#elif _TD_OPTIMAL < 1024 +#define _TD_MIN 256 +#define _TD_MAX 1024 +#else +#define _TD_MIN 1024 +#define _TD_MAX 1024 +#endif + +// Calculate time difference between required time and got time resolution +#define _TD_MIN_TIME (TIMER_DIV_RESTIME - (_TD_MIN * 1000000L / F_CPU)) +#define _TD_MAX_TIME (TIMER_DIV_RESTIME - (_TD_MAX * 1000000L / F_CPU)) + +// Do absolute value of calculated numbers +#if _TD_MIN_TIME < 0 +#define _TD_MIN_TIMEF (_TD_MIN_TIME * -1) +#else +#define _TD_MIN_TIMEF _TD_MIN_TIME +#endif +#if _TD_MAX_TIME < 0 +#define _TD_MAX_TIMEF (_TD_MAX_TIME * -1) +#else +#define _TD_MAX_TIMEF _TD_MAX_TIME +#endif + +// Select closest one +#if _TD_MIN_TIMEF < _TD_MAX_TIMEF +#define _TD_TIMER_DIV _TD_MIN +#else +#define _TD_TIMER_DIV _TD_MAX +#endif + +// Set macro to enum value +#if _TD_TIMER_DIV == 1 +#define TIMER_DIV TIMER_DIVIDER_1 +#elif _TD_TIMER_DIV == 8 +#define TIMER_DIV TIMER_DIVIDER_8 +#elif _TD_TIMER_DIV == 64 +#define TIMER_DIV TIMER_DIVIDER_64 +#elif _TD_TIMER_DIV == 256 +#define TIMER_DIV TIMER_DIVIDER_256 +#elif _TD_TIMER_DIV == 1024 +#define TIMER_DIV TIMER_DIVIDER_1024 +#else +#error Generated unknown timer division. Something is wrong with timers_div.h +#endif + +// Undefine all used variables +#undef _TD_OPTIMAL +#undef _TD_MIN +#undef _TD_MAX +#undef _TD_MIN_TIME +#undef _TD_MAX_TIME +#undef _TD_MIN_TIMEF +#undef _TD_MAX_TIMEF +#undef _TD_TIMER_DIV diff --git a/include/wireless/nrf24l01p.h b/include/wireless/nrf24l01p.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/include/wireless/nrf24l01p.h diff --git a/kconfig b/kconfig new file mode 160000 +Subproject 6814159a0a618a145aa5786a0ec3d311ce81ee9 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 <avr/io.h> - -// 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/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 <avr/io.h> - -// 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/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/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 <adc.h> + +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 <can/mcp2515.h> + +#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/ioport.c b/src/ioport.c new file mode 100644 index 0000000..a77e564 --- /dev/null +++ b/src/ioport.c @@ -0,0 +1,113 @@ +#include <ioport.h> +#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 <avr/interrupt.h> - -#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/sensors/dht22.c index 7791060..9653ba5 100644 --- a/src/sensor_dht22.c +++ b/src/sensors/dht22.c @@ -1,4 +1,4 @@ -#include "../sensor_dht22.h" +#include <sensors/dht22.h> #ifdef CONFIG_IOE_SENSOR_DHT22 @@ -1,23 +1,19 @@ -#ifdef CONFIG_IOE_SPI -#ifdef MCUSUPPORT_USART +#include <spi.h> + +#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 <tasks.h> #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 <timer.h> #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 <usart.h> +#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 <util/setbaud.h> 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 <usi_spi.h> +#include <mcu/mcu_def.h> 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 <utils/buffer.h> + +#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 <utils/narray.h> + +#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 <avr/io.h> -#include <util/delay.h> -#include <avr/interrupt.h> -#include <stdint.h> - -#include "mcu/mcu_def.h" -#include "timer.h" - -#ifndef _IOE_TASKS_H_ -#define _IOE_TASKS_H_ -#ifdef CONFIG_IOE_TASKS - -#ifndef CONFIG_IOE_TIMERS -#error "To use tasks you must enable timers (CONFIG_IOE_TIMERS)." -#endif - -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 <avr-ioe.h> + +int main() { + return 0; +}; @@ -1,15 +0,0 @@ -#include <avr/io.h> -#include <avr/interrupt.h> -#include <stdint.h> - -#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 <avr/io.h> -#include <avr/interrupt.h> -#include <stdint.h> - -#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_ */ |