aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/spiblink/README.md18
-rw-r--r--examples/spiblink/makefile30
-rw-r--r--examples/spiblink/master.c20
-rw-r--r--examples/spiblink/slave.c21
-rw-r--r--spi.h70
-rw-r--r--spi_usart.h14
-rw-r--r--spi_usi.h53
-rw-r--r--src/spi.c66
-rw-r--r--src/spi_usart.c14
-rw-r--r--src/spi_usi.c54
-rw-r--r--src/usb_cdc.c4
-rw-r--r--twi_usi.h0
-rw-r--r--usb_cdc.h10
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);
+}
diff --git a/spi.h b/spi.h
index 86149f7..e1a1a5c 100644
--- a/spi.h
+++ b/spi.h
@@ -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_ */
diff --git a/src/spi.c b/src/spi.c
index 9562e6a..262f402 100644
--- a/src/spi.c
+++ b/src/spi.c
@@ -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_ */