diff options
-rw-r--r-- | examples/spiblink/README.md | 18 | ||||
-rw-r--r-- | examples/spiblink/makefile | 30 | ||||
-rw-r--r-- | examples/spiblink/master.c | 20 | ||||
-rw-r--r-- | examples/spiblink/slave.c | 21 | ||||
-rw-r--r-- | spi.h | 70 | ||||
-rw-r--r-- | spi_usart.h | 14 | ||||
-rw-r--r-- | spi_usi.h | 53 | ||||
-rw-r--r-- | src/spi.c | 66 | ||||
-rw-r--r-- | src/spi_usart.c | 14 | ||||
-rw-r--r-- | src/spi_usi.c | 54 | ||||
-rw-r--r-- | src/usb_cdc.c | 4 | ||||
-rw-r--r-- | twi_usi.h | 0 | ||||
-rw-r--r-- | usb_cdc.h | 10 |
13 files changed, 182 insertions, 192 deletions
diff --git a/examples/spiblink/README.md b/examples/spiblink/README.md new file mode 100644 index 0000000..3b18a8f --- /dev/null +++ b/examples/spiblink/README.md @@ -0,0 +1,18 @@ +This example shows simple SPI communication. It uses two MCUs. One is configured +as master. Other is configured as slave. Master has button connected to its input +and slave has output led. Button status is mirrored by slave led. + +Connection +---------- +Both MCUs needs basic power connections and crystal. +Except of that, they need following other connections. + +| Mater pin | Slave pin | Other connections | Description | +|-----------|-----------|-------------------|----------------------| +| PB1 | | Led | Indication of button | +| | PB1 | Led | Receive led | +| PB2 | PB2 | | SS | +| PB3 | PB3 | | MOSI | +| PB4 | PB4 | | MISO | +| PB5 | PB5 | | SCL | +| PC1 | | Pull down button | Input button | diff --git a/examples/spiblink/makefile b/examples/spiblink/makefile new file mode 100644 index 0000000..a831f86 --- /dev/null +++ b/examples/spiblink/makefile @@ -0,0 +1,30 @@ +MAKEFLAGS += --no-builtin-rules + +MMCU = atmega328p +F_CPU = 16000000L +IOE_PREFIX = ../.. +IOE_CFLAGS ?= -Os -ffunction-sections -fdata-sections -fshort-enums -g -Wall + +.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 new file mode 100644 index 0000000..267d7b2 --- /dev/null +++ b/examples/spiblink/master.c @@ -0,0 +1,20 @@ +#include <avr/io.h> +#include <util/delay.h> +#include "../../spi.h" + +int main() { + DDRB |= _BV(DDB1) | _BV(DDB2); + PORTC |= _BV(PORTC1); + spi_init(SPI_MODE_MASTER); + SREG |= _BV(7); + while (1) { + if (PINC & _BV(PINC1)) { + PORTB &= ~_BV(PORTB1); + } else { + PORTB |= _BV(PORTB1); + } + PORTB &= ~_BV(PORTB2); + spi_send(!(PINC & _BV(PINC1))); + PORTB |= _BV(PORTB2); + } +} diff --git a/examples/spiblink/slave.c b/examples/spiblink/slave.c new file mode 100644 index 0000000..cf14408 --- /dev/null +++ b/examples/spiblink/slave.c @@ -0,0 +1,21 @@ +#include <avr/io.h> +#include <util/delay.h> +#include "../../spi.h" + +void receive(uint8_t data); + +int main() { + DDRB |= _BV(DDB1); + spi_receive = receive; + spi_init(SPI_MODE_SLAVE); + SREG |= _BV(7); + while (1) { + } +} + +void receive(uint8_t data) { + if (data) + PORTB |= _BV(PORTB1); + else + PORTB &= ~_BV(PORTB1); +} @@ -1,23 +1,67 @@ #include <avr/io.h> +#include <avr/interrupt.h> #include <stdint.h> +#include "mcu/mcu_def.h" +#include "buffers.h" + #ifndef _IOE_SPI_H_ #define _IOE_SPI_H_ -inline void ioe_spi_init(void); -inline int ioe_spi_bussy(void); -inline void ioe_spi_join(void); -#ifdef IOE_SPI_MASTER -inline int8_t ioe_spi_transfer(int8_t data); -#else /* IOE_SPI_MASTER */ -inline void ioe_spi_expose(int8_t data); -#endif /* IOE_SPI_MASTER */ +#ifndef MCUSUPPORT_SPI +#error "No SPI interface is known on your mcu." +#endif -// Following function must be user defined -inline void ioe_spi_retrieve(int8_t); +enum spiMode { + SPI_MODE_MASTER, + SPI_MODE_SLAVE +}; -#if !(__MCU_ATmega328p__ || __MCU_ATmega32U4p__) -#error "SPI is not probably supported by your hardware." -#endif + +/* + * 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); + +/* + * 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 /* _IOE_SPI_H_ */ diff --git a/spi_usart.h b/spi_usart.h deleted file mode 100644 index f29ac5b..0000000 --- a/spi_usart.h +++ /dev/null @@ -1,14 +0,0 @@ -#include <stdio.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include <inttypes.h> - -#ifndef _IOE_SPI_USART_H_ -#define _IOE_SPI_USART_H_ - -inline void ioe_spi_usart_init(void); -inline int8_t ioe_spi_usart_transfer(int8_t); -inline int ioe_spi_usart_bussy(void); -inline void ioe_spi_usart_join(void); - -#endif /* _IOE_SPI_USART_H_ */ diff --git a/spi_usi.h b/spi_usi.h deleted file mode 100644 index 900999f..0000000 --- a/spi_usi.h +++ /dev/null @@ -1,53 +0,0 @@ -#include <stdio.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include <inttypes.h> - -#include "mcu/mcu.h" - -#ifndef _IOE_SPI_USI_H_ -#define _IOE_SPI_USI_H_ - -/* - * Initialize USI as SPI - * - * NOTE: Global interrupt must be enabled for right function. - * { SREG |= _BV(7) } - */ -inline void ioe_spi_usi_init(void); -#ifdef IOE_SPI_USI_MASTER -/* - * Swaps byte with slave over SPI. - */ -inline int8_t ioe_spi_usi_transfer(int8_t data); -#else -/* - * Expose data for next master request. - * Please don't use this when device is busy. - * Best place to call this is ioe_spi_usi_retrieve(). - */ -inline void ioe_spi_usi_expose(int8_t data); -/* - * Returns NULL when device is no busy. - * When device is busy, returned value is number of already send bits. - */ -inline uint8_t ioe_spi_usi_busy(void); -/* - * Blocks processor until device is not busy. - */ -inline void ioe_spi_usi_join(void); - -/* - * 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. - */ -inline void ioe_spi_usi_retrieve(int8_t data); -#endif /* IOE_SPI_USI_MASTER */ - -#if !(__MCU_ATtiny4313__ || __MCU_ATtiny85__) -#error "USI is not probably supported by your MCU." -#endif - -#endif /* _IOE_SPI_USI_H_ */ @@ -1,48 +1,54 @@ #include "../spi.h" -#include "mcu/mcu_def.h" -inline void ioe_spi_join(void) { - // TODO +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 int ioe_spi_bussy(void) { - // TODO +inline int8_t spi_busy(void) { + return _spi_busy; } -#ifdef IOE_SPI_MASTER -inline void ioe_spi_init(void) { - // 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 interrupt - SPCR |= _BV(SPIE); - // Enable SPI master and set clock rate fck/16 - SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0); +inline void spi_join(void) { + while (spi_busy()); } -inline void ioe_spi_transfer(int8_t data) { - SPDR = data; +inline uint8_t spi_send(uint8_t data) { + spi_transfer(data); + while (spi_busy()); + return SPDR; } -#else /* IOE_SPI_MASTER */ -inline void ioe_spi_init(void) { - // 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 interrupt - SPCR |= _BV(SPIE); - // Enable SPI - SPCR = _BV(SPE); +inline void spi_transfer(uint8_t data) { + _spi_busy = 1; + SPDR = data; } -inline void ioe_spi_expose(int8_t data) { +inline void spi_expose(uint8_t data) { SPDR = data; } -#endif /* IOE_SPI_MASTER */ +////// Interrupts //////////////////////////////// +void (*spi_receive)(uint8_t data) = 0; SIGNAL(SPI_STC_vect) { - ioe_spi_retrieve(SPDR); + _spi_busy = 0; + if (spi_receive) + spi_receive(SPDR); } diff --git a/src/spi_usart.c b/src/spi_usart.c deleted file mode 100644 index 2e5d612..0000000 --- a/src/spi_usart.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "../spi_usart.h" -#include "../mcu/mcu_def.h" - -inline void ioe_spi_usart_init(void) { -} - -inline int8_t ioe_spi_usart_transfer(int8_t d) { -} - -inline int ioe_spi_usart_bussy(void) { -} - -inline void ioe_spi_usart_join(void) { -} diff --git a/src/spi_usi.c b/src/spi_usi.c deleted file mode 100644 index 8baa8e2..0000000 --- a/src/spi_usi.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "../spi_usi.h" -#include "../mcu/mcu_def.h" - -#ifdef IOE_SPI_USI_MASTER - -// TODO counter settings with interups -inline void ioe_spi_usi_init(void) { - // 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); -} - -inline int8_t ioe_spi_usi_transfer(int8_t d) { - USISR |= _BV(USIOIF); - USIDR = d; - do { - USICR |= _BV(USITC); - } while (!(USISR & _BV(USIOIF))); - return USIDR; -} - -#else /* IOE_SPI_USI_MASTER */ - -inline void ioe_spi_usi_init(void) { - // 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 void ioe_spi_usi_expose(int8_t data) { - USIDR = data; -} - -inline uint8_t ioe_spi_usi_busy(void) { - return USISR & 0x0F; -} - -inline void ioe_spi_usi_join(void) { - while (ioe_spi_usi_busy()) { - } -} - -SIGNAL(USI_OVF_vect) { - ioe_spi_usi_retrieve(USIDR); - USISR |= _BV(USIOIF); -} - -#endif /* IOE_SPI_USI_MASTER */ diff --git a/src/usb_cdc.c b/src/usb_cdc.c deleted file mode 100644 index 2a1ba3a..0000000 --- a/src/usb_cdc.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "../usb_cdc.h" - -void ioe_usb_cdc_init(void) { -} diff --git a/twi_usi.h b/twi_usi.h deleted file mode 100644 index e69de29..0000000 --- a/twi_usi.h +++ /dev/null diff --git a/usb_cdc.h b/usb_cdc.h deleted file mode 100644 index 17bd2cf..0000000 --- a/usb_cdc.h +++ /dev/null @@ -1,10 +0,0 @@ -#include <stdio.h> -#include <avr/io.h> - -#ifndef _IOE_USB_CDC_H_ -#define _IOE_USB_CDC_H_ - -void ioe_usb_cdc_init(void); - - -#endif /* _IOE_USB_CDC_H_ */ |