From b0d8f22f3492fbb3f6dc0e8026e63c803af59007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Sat, 17 Oct 2015 15:40:51 +0200 Subject: Complete commit of current work --- KNOWN-PROBLEMS.md | 2 + adc.h | 0 avr-ioe.h | 3 + avr-ioe.mk | 31 ++++++--- buffers.h | 2 + can_mcp2515.h | 14 +++++ conffile | 65 +++++++++++++++++++ doc/spi.html | 13 ++++ doc/spi.md | 60 ++++++++++++++++++ examples/dht22usart/dht22.c | 26 ++++++++ examples/dht22usart/makefile | 39 ++++++++++++ examples/spiblink/makefile | 3 +- examples/usartecho/makefile | 17 +++-- mcu/ATmega328P.h | 9 +++ pwm.h | 11 ++++ sensor_dht22.h | 39 ++++++++++++ spi.h | 88 +++++++++++++------------- src/can_mcp2515.c | 0 src/pcint.c | 32 ++++++++++ src/sensor_dht22.c | 116 ++++++++++++++++++++++++++++++++++ src/spi.c | 59 +++++------------ src/tasks.c | 17 +++++ src/timer.c | 26 ++++++++ src/twi.c | 0 src/usart.c | 53 ++++++---------- src/usi_spi.c | 54 ++++++++++++++++ tasks.h | 35 +++++++++++ time.h | 15 +++++ timer.h | 147 +++++++++++++++++++++++++++++++++++++++++++ twi.h | 25 ++++++++ usart.h | 13 +++- usi_spi.h | 66 +++++++++++++++++++ 32 files changed, 942 insertions(+), 138 deletions(-) create mode 100644 adc.h create mode 100644 avr-ioe.h create mode 100644 can_mcp2515.h create mode 100644 conffile create mode 100644 doc/spi.html create mode 100644 doc/spi.md create mode 100644 examples/dht22usart/dht22.c create mode 100644 examples/dht22usart/makefile create mode 100644 pwm.h create mode 100644 sensor_dht22.h create mode 100644 src/can_mcp2515.c create mode 100644 src/pcint.c create mode 100644 src/sensor_dht22.c create mode 100644 src/tasks.c create mode 100644 src/timer.c create mode 100644 src/twi.c create mode 100644 src/usi_spi.c create mode 100644 tasks.h create mode 100644 time.h create mode 100644 timer.h create mode 100644 usi_spi.h diff --git a/KNOWN-PROBLEMS.md b/KNOWN-PROBLEMS.md index 1f6332d..a5862c8 100644 --- a/KNOWN-PROBLEMS.md +++ b/KNOWN-PROBLEMS.md @@ -1,3 +1,5 @@ +USART +----- * Third char is lost when USART is used with output buffer. Probably buffer problem or some synchronization problem. This happens only after start. So problem is probably connected with buffers initialization. But simulation not diff --git a/adc.h b/adc.h new file mode 100644 index 0000000..e69de29 diff --git a/avr-ioe.h b/avr-ioe.h new file mode 100644 index 0000000..ac58ee7 --- /dev/null +++ b/avr-ioe.h @@ -0,0 +1,3 @@ +#include "buffers.h" +#include "spi.h" +#include "usart.h" diff --git a/avr-ioe.mk b/avr-ioe.mk index 34967a5..fb818e8 100644 --- a/avr-ioe.mk +++ b/avr-ioe.mk @@ -2,16 +2,14 @@ ifndef IOE_PREFIX IOE_PREFIX = . endif -IOE_SRC_SPI = $(IOE_PREFIX)/src/spi.c -IOE_SRC_USART = $(IOE_PREFIX)/src/usart.c -IOE_SRC = $(IOE_SRC_SPI) $(IOE_SRC_USART) +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_SPI = $(patsubst %.c,%.o,$(IOE_SRC_SPI)) -IOE_OBJ_USART = $(patsubst %.c,%.o,$(IOE_SRC_USART)) IOE_OBJ = $(patsubst %.c,%.o,$(IOE_SRC)) - -IOE_DEP_SPI = $(patsubst %.c,%.d,$(IOE_SRC_SPI)) -IOE_DEP_USART = $(patsubst %.c,%.d,$(IOE_SRC_USART)) IOE_DEP = $(patsubst %.c,%.d,$(IOE_SRC)) @@ -33,6 +31,7 @@ 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 $@ $< @@ -43,5 +42,21 @@ $(IOE_DEP): %.d: %.c ioeclean:: $(RM) $(IOE_OBJ) $(RM) $(IOE_DEP) +else +$(IOE_OBJ): %.o: %.c + @echo " IOE CC $@" + @$(IOE_GCC) $(IOE_CFLAGS) -c -o $@ $< + +$(IOE_DEP): %.d: %.c + @echo " IOE DEP $@" + @$(IOE_GCC) -MM -MG -MT '$*.o $@' $(IOE_CFLAGS) -c -o $@ $< + +.PHONY: ioeclean +ioeclean:: + @echo " IOE CLEAN OBJ" + @$(RM) $(IOE_OBJ) + @echo " IOE CLEAN DEP" + @$(RM) $(IOE_DEP) +endif endif diff --git a/buffers.h b/buffers.h index 19edd2d..497a21c 100644 --- a/buffers.h +++ b/buffers.h @@ -4,6 +4,8 @@ * 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_ diff --git a/can_mcp2515.h b/can_mcp2515.h new file mode 100644 index 0000000..618051e --- /dev/null +++ b/can_mcp2515.h @@ -0,0 +1,14 @@ +#include +#include +#include + +#include "spi.h" + +#ifndef _IOE_CAN_MCP2515_H_ +#define _IOE_CAN_MCP2515_H_ +#ifdef CONFIG_IOE_CAN_MCP2515 + +void can_mcp2515_init(void); + +#endif /* CONFIG_IOE_CAN_MCP2515 */ +#endif /* _IOE_CAN_MCP2515_H_ */ diff --git a/conffile b/conffile new file mode 100644 index 0000000..b8f280c --- /dev/null +++ b/conffile @@ -0,0 +1,65 @@ +MCU:: + type string + default "atmega328p" + menu "MCU name" + +F_CPU:: + type int + default 16000000 + menu "CPU frequency" +################################################################################# + +if MCU == "atmega328p" +MCUSUPPORT_SPI: +MCUSUPPORT_USART: +endif + +################################################################################# + +IOE_SPI: MCUSUPPORT_USART + menu "SPI interface" + +group IOE_USART: MCUSUPPORT_SPI + type bool + menu "USART interface" + +IOE_USART_BAUD: + type int<0,> + menu "Baud" + +IOE_USART_PARITY: + type {!None("USART_PARITY_NONE"), Odd("USART_PARITY_ODD"), Even("USART_PARITY_EVEN")} + menu "Parity" + +IOE_USART_STOPBIT: + type {!Single("USART_STOPBIT_SINGLE"), Double("USART_STOPBIT_DOUBLE")} + menu "Number of stop bits" + +IOE_USART_DATABITS: + type int<5,8> + default 8 + menu "Number of data bits" + +IOE_USART_INBUFFER_SIZE: + type int<0,> + menu "USART input buffer size" + help "Defines size of input buffer for USART interface." + " If size is set to 0, no buffer is used." + +IOE_USART_OUTBUFFER_SIZE: + type int<0,> + menu "USART output buffer size" + help "Defines size of output buffer for USART interface." + " If size is set to 0, no buffer is used." +endgroup # IOE_USART + +IOE_CAN_MCP2515: IOE_SPI + menu "MCP2515 CAN controller" + +group SENSORS: + menu "Sensors" + +IOE_SENSOR_DHT22: + menu "DHT22 temperature and humidity sensor" + +endgroup # SENSORS diff --git a/doc/spi.html b/doc/spi.html new file mode 100644 index 0000000..e81637f --- /dev/null +++ b/doc/spi.html @@ -0,0 +1,13 @@ +

Serial peripheral interface

+ +

spi_init

+ +
static inline void spi_init(enum spiMode mode)
+
+ +

Initializes SPI interface. +Parameters: + mode - Specify mode of SPI interface

+ +

NOTE: Global interrupt must be enabled for right function of SPI. + { SREG |= _BV(7) }

diff --git a/doc/spi.md b/doc/spi.md new file mode 100644 index 0000000..3237882 --- /dev/null +++ b/doc/spi.md @@ -0,0 +1,60 @@ +Serial peripheral interface +--------------------------- + +## Functions +### spi_init +```C +static inline void spi_init(enum spiMode mode) +``` +Initializes SPI interface. +Parameters: + mode - Specify mode of SPI interface + +NOTE: Global interrupt must be enabled for right function of SPI. + { SREG |= _BV(7) } + +### spi_busy +```C +static inline int8_t spi_busy(void) +``` +Returns NULL when device is not busy. +When device is busy return values in non-zero. + +### spi_join +```C +static inline void spi_join(void) +``` +Blocks processor until device is not busy. + +### spi_send +```C +static inline uint8_t spi_send(uint8_t data) +``` +Swap bytes with slave over SPI. +This function blocks execution until device isn't busy (transfer completed). +WARNING: Invoke this only when interface is initialized in MASTER mode. + +### spi_transfer +```C +static inline void spi_transfer(uint8_t data) +``` +Transfer byte to slave over SPI. +This function isn't blocking execution until transfer is complete. +Always call spi_join before this function when called outside of spi_receive(). +WARNING: Invoke this only when interface is initialized in MASTER mode. + +### spi_expose +```C +static inline void spi_expose(uint8_t data) +``` +Expose data for next master request. +Please don't use this when device is busy. +Best place to call this is spi_receive(). +WARNING: Invoke this only when interface is initialized in SLAVE mode. + +## Function pointer spi_receive +```C +extern void (*spi_receive)(uint8_t data) +``` +This function is called every time transfer is finished. +And until return from this function interrupts are disabled. diff --git a/examples/dht22usart/dht22.c b/examples/dht22usart/dht22.c new file mode 100644 index 0000000..97a91ee --- /dev/null +++ b/examples/dht22usart/dht22.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include "../../usart.h" +#include "../../sensor_dht22.h" + +void rec(uint8_t data) { + if (data == '\r') { + // TODO read sensor and send data + } +} + +const struct dht22_port dht22_ports[] = { + {&DDRC, &PORTC, &PINC, _BV(PORTC4), NULL, 0} +}; + +int main() { + //usart_async_open(); + //sei(); + //usart_receive = rec; + //dht22_init(0); + + timer_init(COUNTER0_PWM); + while (1); +} diff --git a/examples/dht22usart/makefile b/examples/dht22usart/makefile new file mode 100644 index 0000000..214aa63 --- /dev/null +++ b/examples/dht22usart/makefile @@ -0,0 +1,39 @@ +MAKEFLAGS += --no-builtin-rules + +MMCU = atmega328p +F_CPU = 16000000L +IOE_PREFIX = ../.. +IOE_SHORTOUTPUT=y +IOE_CFLAGS = -Os -ffunction-sections -fdata-sections -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_OUTFILE \ + -DCONFIG_IOE_USART_BAUD=115200 \ + -DCONFIG_IOE_USART_PARITY=USART_PARITY_NONE \ + -DCONFIG_IOE_USART_STOPBIT=USART_STOPBIT_SINGLE \ + -DCONFIG_IOE_USART_DATABITS=8 \ + -DCONFIG_IOE_TIMERS \ + -DCONFIG_IOE_SENSOR_DHT22 + +all: dht22.hex + @echo Now you can flash dht22.hex to your chip. + +clean: ioeclean + $(RM) dht22.o + $(RM) dht22.elf dht22.hex + +include ../../avr-ioe.mk + +dht22.elf: %.elf: $(IOE_OBJ) dht22.o + @echo " LD $@" + @avr-gcc -Os -mmcu=$(MMCU) $^ -o $@ + +dht22.hex: %.hex: %.elf + @echo " OBJCOPY $@" + @avr-objcopy -O ihex -R .eeprom $< $@ + +dht22.o: %.o: %.c + @echo " CC $@" + @avr-gcc $(IOE_CFLAGS) -c -o $@ $< diff --git a/examples/spiblink/makefile b/examples/spiblink/makefile index bb3b94a..60ba9c9 100644 --- a/examples/spiblink/makefile +++ b/examples/spiblink/makefile @@ -4,7 +4,8 @@ MMCU = atmega328p F_CPU = 16000000L IOE_PREFIX = ../.. IOE_CFLAGS ?= -Os -ffunction-sections -fdata-sections -fshort-enums -g -Wall \ - -DF_CPU=$(F_CPU) -mmcu=$(MMCU) + -DF_CPU=$(F_CPU) -mmcu=$(MMCU) \ + -DCONFIG_IOE_SPI .PHONY: all all: master.hex slave.hex diff --git a/examples/usartecho/makefile b/examples/usartecho/makefile index fa10cd2..15254c6 100644 --- a/examples/usartecho/makefile +++ b/examples/usartecho/makefile @@ -3,8 +3,10 @@ MAKEFLAGS += --no-builtin-rules MMCU = atmega328p F_CPU = 16000000L IOE_PREFIX = ../.. -IOE_CFLAGS = -Os -ffunction-sections -fdata-sections -fshort-enums -Wall \ - -DF_CPU=$(F_CPU) -mmcu=$(MMCU) \ +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 \ @@ -21,11 +23,14 @@ clean: ioeclean include ../../avr-ioe.mk -usart.elf: %.elf: $(IOE_OBJ_USART) echo.o - avr-gcc -mmcu=$(MMCU) $^ -o $@ +usart.elf: %.elf: $(IOE_OBJ) echo.o + @echo " LD $@" + @avr-gcc -Os -mmcu=$(MMCU) $^ -o $@ usart.hex: %.hex: %.elf - avr-objcopy -O ihex -R .eeprom $< $@ + @echo " OBJCOPY $@" + @avr-objcopy -O ihex -R .eeprom $< $@ echo.o: %.o: %.c - avr-gcc $(IOE_CFLAGS) -c -o $@ $< + @echo " CC $@" + @avr-gcc $(IOE_CFLAGS) -c -o $@ $< diff --git a/mcu/ATmega328P.h b/mcu/ATmega328P.h index b5527bf..e876295 100644 --- a/mcu/ATmega328P.h +++ b/mcu/ATmega328P.h @@ -18,3 +18,12 @@ #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/pwm.h b/pwm.h new file mode 100644 index 0000000..0dbc007 --- /dev/null +++ b/pwm.h @@ -0,0 +1,11 @@ +#include +#include +#include + +#include "timer.h" + +#ifndef _IOE_PWM_H_ +#define _IOE_PWM_H_ + + +#endif /* _IOE_PWM_H_ */ diff --git a/sensor_dht22.h b/sensor_dht22.h new file mode 100644 index 0000000..0776b77 --- /dev/null +++ b/sensor_dht22.h @@ -0,0 +1,39 @@ +#include +#include +#include + +#include "tasks.h" +#include "timer.h" + +#ifndef _DHT22_H_ +#define _DHT22_H_ + +struct dht22_value { + uint8_t integral; + uint8_t decimal; +}; + +struct dht22_port { + volatile uint8_t *DDR; // Address of DDR register + volatile uint8_t *PORT; // Address of PORT register + volatile uint8_t *PIN; // Address of PIN register + uint8_t MASK; // _BV() of index of port + volatile uint8_t *PCMSK; // Address of relevant PCMSK register + uint8_t PCMSK_MASK; // _BV() of index of PCMSK +}; + +extern const struct dht22_port dht22_ports[]; + +/* + * Initialize port for sensor + */ +void dht22_init(uint8_t port); +/* + * Read values from dht22 + * rh - relative + * t - temperature + */ +int8_t dht22_read(uint8_t portindex, struct dht22_value *rh, + struct dht22_value *t); + +#endif /* _DHT22_H_ */ diff --git a/spi.h b/spi.h index e1a1a5c..51f8f2a 100644 --- a/spi.h +++ b/spi.h @@ -3,10 +3,12 @@ #include #include "mcu/mcu_def.h" +#include "tasks.h" #include "buffers.h" #ifndef _IOE_SPI_H_ #define _IOE_SPI_H_ +#ifdef CONFIG_IOE_SPI #ifndef MCUSUPPORT_SPI #error "No SPI interface is known on your mcu." @@ -17,51 +19,51 @@ enum spiMode { SPI_MODE_SLAVE }; +volatile extern int8_t _spi_busy; -/* - * Initialize SPI - * - * Parameters: - * mode - Specify mode of SPI interface - * - * NOTE: Global interrupt must be enabled for right function of SPI. - * { SREG |= _BV(7) } - */ -void spi_init(enum spiMode mode); -/* - * Returns NULL when device is not busy. - * When device is busy return values in non-zero. - */ -int8_t spi_busy(void); -/* - * Blocks processor until device is not busy. - */ -void spi_join(void); -/* - * 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. - */ -uint8_t spi_send(uint8_t data); -/* - * Transfer byte to slave over SPI. - * This function isn't blocking execution until transfer is complete. - * Always call spi_join before this function when called outside of spi_receive(). - * WARNING: Invoke this only when interface is initialized in MASTER mode. - */ -void spi_transfer(uint8_t data); -/* - * Expose data for next master request. - * Please don't use this when device is busy. - * Best place to call this is spi_receive(). - * WARNING: Invoke this only when interface is initialized in SLAVE mode. - */ -void spi_expose(uint8_t data); +static inline void spi_init(enum spiMode mode) { + _spi_busy = 0; + if (mode == SPI_MODE_MASTER) { + // Set MOSI and SCK output + DDR_SPI |= _BV(DD_MOSI) | _BV(DD_SCLK); + // Set MISO pull up resistor + PORT_SPI |= _BV(PORT_MISO); + // Enable SPI master, set clock rate fck/16 and enable SPI interrupt + SPCR = _BV(SPE) | _BV(SPIE) | _BV(MSTR) | _BV(SPR0); + } else { + // Set MISO as output + DDR_SPI |= _BV(DD_MISO); + // Set SCLK and MOSI pull up resistor + PORT_SPI |= _BV(PORT_SCLK) | _BV(PORT_MOSI); + // Enable SPI and interrupt + SPCR = _BV(SPE) | _BV(SPIE); + } +} + +static inline int8_t spi_busy(void) { + return _spi_busy; +} + +static inline void spi_join(void) { + taskDelayTill(_spi_busy); +} + +static inline uint8_t spi_send(uint8_t data) { + spi_transfer(data); + taskDelayTill(_spi_busy); + return SPDR; +} + +static inline void spi_transfer(uint8_t data) { + _spi_busy = 1; + SPDR = data; +} + +static inline void spi_expose(uint8_t data) { + SPDR = data; +} -/* - * This function is called every time transfer is finished. - * And until return from this function interrupts are disabled. - */ extern void (*spi_receive)(uint8_t data); +#endif /* CONFIG_IOE_SPI */ #endif /* _IOE_SPI_H_ */ diff --git a/src/can_mcp2515.c b/src/can_mcp2515.c new file mode 100644 index 0000000..e69de29 diff --git a/src/pcint.c b/src/pcint.c new file mode 100644 index 0000000..1dedb63 --- /dev/null +++ b/src/pcint.c @@ -0,0 +1,32 @@ +/* This file defines and handles Pin change interupts. + * This interupt can be used in different modules and sensors. Function call can + * be done from this interrupt handdler. + */ +#include + +#if (defined CONFIG_IOE_SENSOR_DHT22) + +#ifdef CONFIG_IOE_SENSOR_DHT22 +extern void dht22_read_pcint(void); +#endif + + +ISR(PCINT0_vect, ISR_BLOCK) { +#ifdef CONFIG_IOE_SENSOR_DHT22 + void dht22_read_pcint(); +#endif +} + +ISR(PCINT1_vect, ISR_BLOCK) { +#ifdef CONFIG_IOE_SENSOR_DHT22 + void dht22_read_pcint(); +#endif +} + +ISR(PCINT2_vect, ISR_BLOCK) { +#ifdef CONFIG_IOE_SENSOR_DHT22 + void dht22_read_pcint(); +#endif +} + +#endif diff --git a/src/sensor_dht22.c b/src/sensor_dht22.c new file mode 100644 index 0000000..0ae7c01 --- /dev/null +++ b/src/sensor_dht22.c @@ -0,0 +1,116 @@ +#include "../sensor_dht22.h" + +#ifdef CONFIG_IOE_SENSOR_DHT22 + +#define PP dht22_ports[pi] +#define PPP dht22_ports[dht22_measurement.pi] + +#define TIMEOUT F_CPU/40000 + +#define STATUS_NONE 0 +#define STATUS_COMPLETE 1 +#define STATUS_TIMEOUT 2 + +#define PORT_SENSORW 4 +#define PORT_SENSORRESP_L 3 +#define PORT_SENSORRESP_H 2 +#define PORT_H 1 +#define PORT_L 0 + +struct { + uint8_t index; + uint8_t data[5]; + volatile uint8_t status; + uint8_t pi; + uint8_t port_status; +} dht22_measurement; + +inline void dht22_init(uint8_t pi) { + // Set port as output and set level hight + *(PP.DDR) |= PP.MASK; + *(PP.PORT) |= PP.MASK; + // Enable all pin change interrupts + PCIFR = 0xff; +} + + +inline void dht22_read_deac(uint8_t status) { + dht22_measurement.status = status; + // Disable pin change interrupt + *(PPP.PCMSK) &= ~PPP.PCMSK_MASK; + timer_disable(CONFIG_IOE_SENSOR_DHT22_TIMER); +} + +// This is called from pcint.c +void dht22_read_pcint(void) { + switch (dht22_measurement.port_status) { + case PORT_L: + if (!(*(PPP.PIN) & PPP.MASK)) + return; + dht22_measurement.port_status = PORT_H; + break; + case PORT_H: + if (*(PPP.PIN) & PPP.MASK) + return; + dht22_measurement.port_status = PORT_L; + register uint16_t val; + val = timer_value(CONFIG_IOE_SENSOR_DHT22_TIMER); + // TODO compare value + if (val < 1) { + dht22_measurement.data[dht22_measurement.index / 8] + } + if (++(dht22_measurement.index) == 40) { + dht22_read_deac(STATUS_COMPLETE); + return; + } + break; + default: + if (((*(PPP.PIN) & PPP.MASK) && dht22_measurement.port_status == 3) || + !(*(PPP.PIN & PPP.MASK))) + return; + dht22_measurement.port_status--; + } + timer_reset(CONFIG_IOE_SENSOR_DHT22_TIMER); +} + +void dht22_read_timer_overflow(void) { + dht22_read_deac(STATUS_TIMEOUT); +} + +int8_t dht22_read(uint8_t pi, struct dht22_value *rh, + struct dht22_value *t) { + dht22_measurement.index = 0; + dht22_measurement.status = STATUS_NONE; + dht22_measurement.pi = pi; + dht22_measurement.port_status = PORT_SENSORW; + + // Pull port down for 500us + *(PP.PORT) &= ~PP.MASK; + _delay_us(500); + // Initialize timer + timer_init(CONFIG_IOE_SENSOR_DHT22_TIMER, TIMER_DIVIDER_64); + timer_sethook(CONFIG_IOE_SENSOR_DHT22_TIMER, dht22_read_timer_overflow); + // Set pin change interrupt + *(PP.PCMSK) |= PP.PCMSK_MASK; + // Set port as output and pull-up resistor + *(PP.DDR) &= ~PP.MASK; + *(PP.PORT) |= PP.MASK; + // Delay till reading is done + taskDelayTill(&(dht22_measurement.status)); + + // Copy data + rh->integral = dht22_measurement.data[0]; + rh->decimal = dht22_measurement.data[1]; + t->integral = dht22_measurement.data[2]; + t->decimal = dht22_measurement.data[3]; + // Check sum + uint8_t sum = dht22_measurement.data[0]; + sum += dht22_measurement.data[1]; + sum += dht22_measurement.data[2]; + sum += dht22_measurement.data[3]; + if (sum != dht22_measurement.data[4]) + return 1; + return dht22_measurement.status - 1; +} + +#endif /* CONFIG_IOE_SENSOR_SHT22 */ diff --git a/src/spi.c b/src/spi.c index 262f402..4c0293c 100644 --- a/src/spi.c +++ b/src/spi.c @@ -1,54 +1,23 @@ -#include "../spi.h" +#ifdef CONFIG_IOE_SPI +#ifdef MCUSUPPORT_USART volatile int8_t _spi_busy; -inline void spi_init(enum spiMode mode) { - _spi_busy = 0; - if (mode == SPI_MODE_MASTER) { - // Set MOSI and SCK output - DDR_SPI |= _BV(DD_MOSI) | _BV(DD_SCLK); - // Set MISO pull up resistor - PORT_SPI |= _BV(PORT_MISO); - // Enable SPI master, set clock rate fck/16 and enable SPI interrupt - SPCR = _BV(SPE) | _BV(SPIE) | _BV(MSTR) | _BV(SPR0); - } else { - // Set MISO as output - DDR_SPI |= _BV(DD_MISO); - // Set SCLK and MOSI pull up resistor - PORT_SPI |= _BV(PORT_SCLK) | _BV(PORT_MOSI); - // Enable SPI and interrupt - SPCR = _BV(SPE) | _BV(SPIE); - } -} - -inline int8_t spi_busy(void) { - return _spi_busy; -} - -inline void spi_join(void) { - while (spi_busy()); -} - -inline uint8_t spi_send(uint8_t data) { - spi_transfer(data); - while (spi_busy()); - return SPDR; -} - -inline void spi_transfer(uint8_t data) { - _spi_busy = 1; - SPDR = data; -} - -inline void spi_expose(uint8_t data) { - SPDR = data; -} - ////// Interrupts //////////////////////////////// -void (*spi_receive)(uint8_t data) = 0; +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 */ -SIGNAL(SPI_STC_vect) { +ISR(SPI_STC_vect, ISR_BLOCK) { _spi_busy = 0; +#ifdef CONFIG_IOE_CAN_MCP2515 + can_mcp2515_spi_hook(SPDR); +#endif /* CONFIG_IOE_CAN_MCP2515 */ if (spi_receive) spi_receive(SPDR); } + +#endif /* MCUSUPPORT_SPI */ +#endif /* CONFIG_IOE_SPI */ diff --git a/src/tasks.c b/src/tasks.c new file mode 100644 index 0000000..1d94eaa --- /dev/null +++ b/src/tasks.c @@ -0,0 +1,17 @@ +#include "../tasks.h" + +#ifdef CONFIG_IOE_TASKS + +#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); + } + return 0; +} + +#endif /* CONFIG_IOE_TASKS */ diff --git a/src/timer.c b/src/timer.c new file mode 100644 index 0000000..68c6c06 --- /dev/null +++ b/src/timer.c @@ -0,0 +1,26 @@ +#include "../timer.h" + +#ifdef CONFIG_IOE_TIMERS + +#ifdef COUNTER0_PWM +ISR(TIMER0_OVF_vect, ISR_BLOCK) { + if (timer_0_pwm_overflow) + timer_0_pwm_overflow(); +} +#endif /* COUNTER0_PWM */ + +#ifdef COUNTER0_PWM +ISR(TIMER1_OVF_vect, ISR_BLOCK) { + if (timer_1_16pwm_overflow) + timer_1_16pwm_overflow(); +} +#endif /* COUNTER0_PWM */ + +#ifdef COUNTER0_PWM +ISR(TIMER2_OVF_vect, ISR_BLOCK) { + if (timer_2_pwm_overflow) + timer_2_pwm_overflow(); +} +#endif /* COUNTER0_PWM */ + +#endif /* CONFIG_IOE_TIMERS */ diff --git a/src/twi.c b/src/twi.c new file mode 100644 index 0000000..e69de29 diff --git a/src/usart.c b/src/usart.c index 5dd14b3..bba83ac 100644 --- a/src/usart.c +++ b/src/usart.c @@ -1,5 +1,6 @@ #include "../usart.h" +#ifdef CONFIG_IOE_USART #ifdef MCUSUPPORT_USART #define USART_PARITY_NONE 0 @@ -10,7 +11,7 @@ #define USART_STOPBIT_DOUBLE 2 #ifndef CONFIG_IOE_USART_BAUD -#warning "CONFIG_IOE_USART_BAUNDRATE not defined. Setting default 9600." +#warning "CONFIG_IOE_USART_BAUD not defined. Setting default 9600." #define CONFIG_IOE_USART_BAUD 9600 #endif #ifndef CONFIG_IOE_USART_PARITY @@ -67,33 +68,26 @@ void usart_init_async(void) { UCSR0A &= ~_BV(U2X0); #endif -#if CONFIG_IOE_USART_PARITY == USART_PARITY_NONE - UCSR0C &= ~(_BV(UPM00) | _BV(UPM01)); -#elif CONFIG_IOE_USART_PARITY == USART_PARITY_ODD - UCSR0C &= ~_BV(UPM00); - UCSR0C |= _BV(UPM01); -#else // USART_PARITY_EVEN - UCSR0C |= _BV(UPM00) | _BV(UPM01); + UCSR0C = 0 | +// USART_PARITY_NONE are both UMP01 and UMP00 zero +#if CONFIG_IOE_USART_PARITY == USART_PARITY_ODD + _BV(UPM01) | +#elif CONFIG_IOE_USART_PARITY == USART_PARITY_EVEN + _BV(UPM00) | _BV(UPM01) | #endif - -#if CONFIG_IOE_USART_STOPBIT == USART_STOPBIT_SINGLE - UCSR0C &= ~_BV(USBS0); -#else - UCSR0C |= _BV(USBS0); +// USART_STOPBIT_SINGLE is USBS0 zero +#if CONFIG_IOE_USART_STOPBIT == USART_STOPBIT_DOUBLE + _BV(USBS0) | #endif - -#if CONFIG_IOE_USART_DATABITS == 5 - UCSR0C &= ~(_BV(UCSZ00) | _BV(UCSZ01)); -#elif CONFIG_IOE_USART_DATABITS == 6 - UCSR0C &= ~_BV(UCSZ01); - UCSR0C |= _BV(UCSZ00); +// For 5 databits are UCSZ00 and UCSZ01 zero +#if CONFIG_IOE_USART_DATABITS == 6 + _BV(UCSZ00) #elif CONFIG_IOE_USART_DATABITS == 7 - UCSR0C &= ~_BV(UCSZ00); - UCSR0C |= _BV(UCSZ01); + _BV(UCSZ01) #elif CONFIG_IOE_USART_DATABITS == 8 - UCSR0C |= _BV(UCSZ00) | _BV(UCSZ01); + _BV(UCSZ00) | _BV(UCSZ01) #endif - + ; // Enable receiver, transmitter and RX complete, // Data register empty interrupts UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UDRIE0); @@ -122,7 +116,7 @@ inline void usart_send(uint8_t data) { } #ifdef _IOE_USART_OUTBUFFER -void usart_send_str(char *str) { +inline void usart_send_str(char *str) { while (*str != '\0') { usart_send((uint8_t) * str); str++; @@ -139,14 +133,6 @@ uint8_t usart_get(void) { } #endif -inline uint8_t usart_queryerror(void) { - return UCSR0A & (_BV(FE0) | _BV(DOR0) | _BV(UPE0)); -} - -inline int8_t usart_busy(void) { - return _usart_busy; -} - #ifdef _IOE_USART_INBUFFER uint8_t usart_inbuffered(void) { uint8_t rtn; @@ -225,4 +211,5 @@ SIGNAL(USART_UDRE_vect) { usart_sent(); } -#endif +#endif /* MCUSUPPORT_USART */ +#endif /* CONFIG_IOE_USART */ diff --git a/src/usi_spi.c b/src/usi_spi.c new file mode 100644 index 0000000..01c37f7 --- /dev/null +++ b/src/usi_spi.c @@ -0,0 +1,54 @@ +#include "../usi_spi.h" +#include "../mcu/mcu_def.h" + +inline void usi_spi_init(enum spiMode mode) { + if (mode == USI_SPI_MODE_MASTER) { + // Set USCK and DO as output + DDR_USI |= _BV(DD_USCK) | _BV(DD_DO); + // Set DI pull up resistor + PORT_USI |= _BV(PORT_DI); + + USICR |= _BV(USIWM0) | _BV(USICS1) | _BV(USICLK); + } else { + // Set DO as output + DDR_USI |= _BV(DD_DO); + // Set USCK and DI pull up resistor + PORT_USI |= _BV(PORT_USCK) | _BV(PORT_DI); + + USICR |= _BV(USIWM0) | _BV(USICS1) | _BV(USIOIE); + } +} + +inline int8_t usi_spi_busy(void) { + if (interface == SPI_INTERFACE_USI) + return USISR & 0x0F; +} + +inline void usi_spi_join(void) { + while (spi_busy(interface)); +} + +inline uint8_t usi_spi_send(uint8_t data) { + while (spi_busy(interface)); + return spi_transfer(interface, data); +} + +inline uint8_t usi_spi_transfer(uint8_t data) { + // TODO rewrite and this for noninterupt + if (interface == SPI_INTERFACE_USI) { + _spi_usi_busy = 1; + USISR |= _BV(USIOIF); + USIDR = d; + do { + USICR |= _BV(USITC); + } while (!(USISR & _BV(USIOIF))); + return USIDR; + } +} + +inline void usi_spi_expose(uint8_t data) { + if (interface == SPI_INTERFACE_USI) + USIDR = data; +} + +////// Interrupts //////////////////////////////// diff --git a/tasks.h b/tasks.h new file mode 100644 index 0000000..f773e17 --- /dev/null +++ b/tasks.h @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +#include "mcu/mcu_def.h" +#include "timer.h" + +#ifndef _IOE_TASKS_H_ +#define _IOE_TASKS_H_ +#ifdef CONFIG_IOE_TASKS + +#ifndef CONFIG_IOE_TIMERS +#error "To use tasks you must enable timers (CONFIG_IOE_TIMERS)." +#endif + +struct Task { + +}; + +void taskDelay(uint16_t us); +void taskDelayMS(uint16_t ms); +void taskDelayTill(int8_t *boolean); +int8_t taskDelayTillT(int8_t *boolean, uin16_t us); +void taskDelayTillF(int8_t (*fnc)(void)); +void taskDelayTillFT(int8_t (*fnc)(void), uint16_t us); + +#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/time.h b/time.h new file mode 100644 index 0000000..945511d --- /dev/null +++ b/time.h @@ -0,0 +1,15 @@ +#include +#include +#include + +#include "mcu/mcu_def.h" + +#ifndef _IOE_TIME_H_ +#define _IOE_TIME_H_ + +#ifndef CONFIG_IOE_TIME_TIMER +#error "To use Time you must specify CONFIG_IOE_TIME_TIMER macro." +#endif + + +#endif /* _IOE_TIME_H_ */ diff --git a/timer.h b/timer.h new file mode 100644 index 0000000..192c15d --- /dev/null +++ b/timer.h @@ -0,0 +1,147 @@ +#include +#include +#include + +#include "mcu/mcu_def.h" + +#ifndef _IOE_TIMER_H_ +#define _IOE_TIMER_H_ +#ifdef CONFIG_IOE_TIMERS + +enum timerDivider { + TIMER_DIVIDER_1, + TIMER_DIVIDER_8, + TIMER_DIVIDER_64, + TIMER_DIVIDER_256, + TIMER_DIVIDER_1024 +}; + +static inline void timer_init(uint8_t timer, enum timerDivider div) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + // Null counting register + TCNT0 = 0; + // Set interrupt flag + TIMSK0 = _BV(TOIE0); + // Set division and start counting + switch (div) { + case TIMER_DIVIDER_1: + TCCR0B = _BV(CS00); + break; + case TIMER_DIVIDER_8: + TCCR0B = _BV(CS01); + break; + case TIMER_DIVIDER_64: + TCCR0B = _BV(CS01) | _BV(CS00); + break; + case TIMER_DIVIDER_256: + TCCR0B = _BV(CS02); + break; + case TIMER_DIVIDER_1024: + TCCR0B = _BV(CS02) | _BV(CS01); + break; + default: + return; + } + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + break; +#endif /* COUNTER2_PWM_ASYNC */ + } +} + +static inline void timer_disable(uint8_t timer) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + TCCR0B = 0; + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + break; +#endif /* COUNTER2_PWM_ASYNC */ + } +} + +static inline void timer_reset(uint8_t timer) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + TCNT0 = 0; + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + break; +#endif /* COUNTER2_PWM_ASYNC */ + } +} + +static inline uint16_t timer_value(uint8_t timer) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + return TCNT0; + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + break; +#endif /* COUNTER2_PWM_ASYNC */ + default: + return 0; + } +} + +#ifdef COUNTER0_PWM +void (*timer_0_pwm_overflow) (void); +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM +void (*timer_1_16pwm_overflow) (void); +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC +void (*timer_2_pwm_overflow) (void); +#endif /* COUNTER2_PWM_ASYNC */ + +static inline void timer_sethook(uint8_t timer, void (*fnc) (void)) { + switch (timer) { +#ifdef COUNTER0_PWM + case COUNTER0_PWM: + timer_0_pwm_overflow = fnc; + break; +#endif /* COUNTER0_PWM */ +#ifdef COUNTER1_16PWM + case COUNTER1_16PWM: + timer_1_16pwm_overflow = fnc; + break; +#endif /* COUNTER1_16PWM */ +#ifdef COUNTER2_PWM_ASYNC + case COUNTER2_PWM_ASYNC: + timer_2_pwm_overflow = fnc; + break; +#endif /* COUNTER2_PWM_ASYNC */ + } +} + +#endif /* CONFIG_IOE_TIMERS */ +#endif /* _IOE_TIMER_H_ */ diff --git a/twi.h b/twi.h index e69de29..514b17a 100644 --- a/twi.h +++ b/twi.h @@ -0,0 +1,25 @@ +#include +#include +#include + +#include "mcu/mcu_def.h" +#include "buffers.h" + +#ifndef _IOE_TWI_H_ +#define _IOE_TWI_H_ + +#ifndef MCUSUPPORT_TWI +#error "No TWI interface is known on your mcu." +#endif + +enum twiMode { + TWI_MODE_MASTER, + TWI_MODE_SLAVE +}; + +void twi_init(enum twiMode); +int8_t twi_busy(void); +void twi_join(void); +void twi_send(uint8_t data); + +#endif /* _IOE_TWI_H_ */ diff --git a/usart.h b/usart.h index fec7a1a..a67b141 100644 --- a/usart.h +++ b/usart.h @@ -4,10 +4,12 @@ #include #include "mcu/mcu_def.h" +#include "tasks.h" #include "buffers.h" #ifndef _IOE_USART_H_ #define _IOE_USART_H_ +#ifdef CONFIG_IOE_USART #ifndef MCUSUPPORT_USART #error "No USART interface is known on your mcu." @@ -28,6 +30,8 @@ volatile IOEBUFFER(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE); volatile IOEBUFFER(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE); #endif +extern volatile int8_t _usart_busy; + /* * Initialize USART device. @@ -40,8 +44,12 @@ void usart_send_str(char *str); #ifdef _IOE_USART_INBUFFER uint8_t usart_get(void); #endif -uint8_t usart_queryerror(void); -int8_t usart_busy(void); +static inline uint8_t usart_queryerror(void) { + return UCSR0A & (_BV(FE0) | _BV(DOR0) | _BV(UPE0)); +} +static inline int8_t usart_busy(void) { + return _usart_busy; +} #ifdef _IOE_USART_INBUFFER uint8_t usart_inbuffered(void); #endif @@ -56,4 +64,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_ */ diff --git a/usi_spi.h b/usi_spi.h new file mode 100644 index 0000000..18534ab --- /dev/null +++ b/usi_spi.h @@ -0,0 +1,66 @@ +#include +#include +#include + +#include "mcu/mcu_def.h" + +#ifndef _IOE_USI_SPI_H_ +#define _IOE_USI_SPI_H_ + +#ifndef MCUSUPPORT_USI +#error "No USI interface is known on your mcu." +#endif + +enum usiSpiMode { + // Device is initialized as master + USI_SPI_MODE_MASTER, + // Device is initialized as slave + USI_SPI_MODE_SLAVE, +}; + +/* + * Initialize SPI on USI device + * + * Parameters: + * mode - Specify mode of SPI interface + */ +void usi_spi_init(enum usiSpiMode mode); +/* + * Returns NULL when device is not busy. + * When device is busy return values in non-zero. + */ +int8_t usi_spi_busy(void); +/* + * Blocks processor until device is not busy. + */ +void usi_spi_join(void); +/* + * Swap bytes with slave over SPI. + * This function blocks execution until device isn't busy. + * WARNING: Invoke this only when interface is initialized in MASTER mode. + */ +uint8_t usi_spi_send(uint8_t data); +/* + * Swaps byte with slave over SPI. + * This function isn't checking if device is busy, but it's not blocking execution. + * WARNING: Invoke this only when interface is initialized in MASTER mode. + */ +uint8_t usi_spi_transfer(uint8_t data); +/* + * Expose data for next master request. + * Please don't use this when device is busy. + * Best place to call this is usi_spi_retrieve(). + * WARNING: Invoke this only when interface is initialized in SLAVE mode. + */ +void usi_spi_expose(uint8_t data); + +/* + * This function must be defined by user. + * This function is called every time transfer is finished. + * And until return from this function interrupts are disabled. + * WARNING: Please define this function in your code. + */ +void usi_spi_receive(uint8_t data); + + +#endif /* _IOE_USI_SPI_H_ */ -- cgit v1.2.3