summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Draxinger <Wolfgang.Draxinger@draxit.de>2013-12-22 16:44:10 +0100
committerWolfgang Draxinger <Wolfgang.Draxinger@draxit.de>2013-12-22 16:44:10 +0100
commit217ddb1e32dcb4cde11ecca88418be428895f2dc (patch)
tree8e84c0cecc506f9da54f87d82af95f59d348b3de
parent3e8ce25f77700dcef050601412435950dc7dfa7b (diff)
downloadvgaedidinjector-217ddb1e32dcb4cde11ecca88418be428895f2dc.tar.gz
vgaedidinjector-217ddb1e32dcb4cde11ecca88418be428895f2dc.tar.bz2
Makefile separator errors fixed
-rw-r--r--Makefile92
-rw-r--r--avr_compiler.h154
-rw-r--r--edid_injector.c132
-rw-r--r--eeprom_driver.c330
-rw-r--r--eeprom_driver.h142
-rw-r--r--twi_master_driver.c399
-rw-r--r--twi_master_driver.h147
-rw-r--r--twi_slave_driver.c321
-rw-r--r--twi_slave_driver.h135
9 files changed, 1852 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..fc74b31
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,92 @@
+## Change these:
+## HWREV:
+## 0 -> initial revision
+MMCU = atxmega16a4
+DEFINES = -DF_CPU=32000000 -DHWREV=0
+
+# -b baudrate
+AVRDUDE = avrdude -P usb -c jtag3pdi -p $(MMCU)
+
+#-------------------------------------------------------------------------------
+
+HEADERS = twi_master_driver.h twi_slave_driver.h eeprom_driver.h avr_compiler.h
+SOURCES = twi_master_driver.c twi_slave_driver.c eeprom_driver.c edid_injector.c
+OBJECTS = $(SOURCES:.c=.o)
+
+INCLUDES = -I.
+
+VPATH = .
+
+#-------------------------------------------------------------------------------
+CC = avr-gcc
+CFLAGS = -W -Wall -Os -std=gnu99 -Werror-implicit-function-declaration
+
+all: firmware.bin firmware.hex firmware-eeprom.bin
+
+run: all prg
+
+firmware.elf: $(OBJECTS)
+ $(CC) -s -mmcu=$(MMCU) $(OBJECTS) -o firmware.elf
+
+%.o: %.c $(HEADERS)
+ $(CC) $(INCLUDES) -mmcu=$(MMCU) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c $<
+
+# FUSEBYTE0: JTAG user ID (arbitrary)
+# FUSEBYTE1:
+# bits 7..4: Watchdog Window Timeout Period
+# bits 3..0: Watchdog Timeout Period
+# FUSEBYTE2:
+# bit 6: BOOTRST
+# 0: Reset vector = Boot loader reset
+# 1: Reset vector = Application reset (address 0x0000)
+# bit 5: TOSCSEL (32768 kHz osc pin position; usually 1)
+# bits 1..0: BODPD[1:0]: (in power-down mode)
+# 10 = BOD enabled continuously
+# 11 = BOD disabled
+# FUSEBYTE4:
+# bit 4: RSTDISBL 0: disable reset
+# bits 3..2: STARTUPTIME[1:0] 11/01/00: wait 0/4/64 cycles
+# bit 1: WDLOCK 1: watchdog timer not locked
+# bit 0: JTAGEN 1: JTAG disabled
+# FUSEBYTE5:
+# bits 5..4: BODACT[1:0]
+# 10 = BOD enabled continuously
+# 11 = BOD disabled
+# bit 3: EESAVE 0: EEPROM is preserved during chip erase
+# bits 2..0: BODLEVEL[2:0]
+# 111: 1.6 011: 2.4
+# 110: 1.8 010: 2.6
+# 101: 2.0 001: 2.8
+# 100: 2.2 000: 3.0
+program_fuses:
+ $(AVRDUDE) \
+ -Ufuse0:w:0xff:m -Ufuse1:w:0x66:m -Ufuse2:w:0xfe:m
+ -Ufuse5:w:0xeb:m -Ufuse4:w:0xff:m
+
+prg: firmware.hex
+ $(AVRDUDE) -Uflash:w:firmware.hex:i
+
+program_bootloader:
+ $(AVRDUDE) -e -Uflash:w:bootload.hex:i
+
+dump: firmware.elf
+ avr-objdump -D firmware.elf
+
+clean:
+ -rm -f firmware.bin firmware.elf firmware-eeprom.bin firmware.hex
+ -rm -f *.o
+
+firmware-eeprom.bin: firmware.elf
+ avr-objcopy -j .eeprom -O binary firmware.elf firmware-eeprom.bin
+ @ls -l firmware-eeprom.bin
+
+firmware.hex: firmware.elf
+ avr-objcopy -j .text -j .data -O ihex firmware.elf firmware.hex
+
+firmware.bin: firmware.elf
+ avr-objcopy -j .text -j .data -O binary firmware.elf firmware.bin
+ @ls -l firmware.bin
+
+asm:
+ $(CC) -W -Wall -O2 -mmcu=$(MMCU) -S main.c -o main.asm
+
diff --git a/avr_compiler.h b/avr_compiler.h
new file mode 100644
index 0000000..5d1c738
--- /dev/null
+++ b/avr_compiler.h
@@ -0,0 +1,154 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief This file implements some macros that makes the IAR C-compiler and
+ * avr-gcc work with the same code base for the AVR architecture.
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation: http://www.atmel.com \n
+ * Support email: avr@atmel.com
+ *
+ * $Revision: 613 $
+ * $Date: 2006-04-07 14:40:07 +0200 (fr, 07 apr 2006) $ \n
+ *
+ * Copyright (c) 2008, Atmel Corporation All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************/
+
+#ifndef COMPILER_AVR_H
+#define COMPILER_AVR_H
+
+#ifndef F_CPU
+/*! \brief Define default CPU frequency, if this is not already defined. */
+#define F_CPU 2000000UL
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+/*! \brief This macro will protect the following code from interrupts. */
+#define AVR_ENTER_CRITICAL_REGION( ) uint8_t volatile saved_sreg = SREG; \
+ cli();
+
+/*! \brief This macro must always be used in conjunction with AVR_ENTER_CRITICAL_REGION
+ * so the interrupts are enabled again.
+ */
+#define AVR_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg;
+
+#if defined( __ICCAVR__ )
+
+#include <inavr.h>
+#include <ioavr.h>
+#include <intrinsics.h>
+#include <pgmspace.h>
+
+#ifndef __HAS_ELPM__
+#define _MEMATTR __flash
+#else /* __HAS_ELPM__ */
+#define _MEMATTR __farflash
+#endif /* __HAS_ELPM__ */
+
+/*! \brief Perform a delay of \c us microseconds.
+ *
+ * The macro F_CPU is supposed to be defined to a constant defining the CPU
+ * clock frequency (in Hertz).
+ *
+ * The maximal possible delay is 262.14 ms / F_CPU in MHz.
+ *
+ * \note For the IAR compiler, currently F_CPU must be a
+ * multiple of 1000000UL (1 MHz).
+ */
+#define delay_us( us ) ( __delay_cycles( ( F_CPU / 1000000UL ) * ( us ) ) )
+
+/*! \brief Preprocessor magic.
+ *
+ * Some preprocessor magic to allow for a header file abstraction of
+ * interrupt service routine declarations for the IAR compiler. This
+ * requires the use of the C99 _Pragma() directive (rather than the
+ * old #pragma one that could not be used as a macro replacement), as
+ * well as two different levels of preprocessor concetanations in
+ * order to do both, assign the correct interrupt vector name, as well
+ * as construct a unique function name for the ISR.
+ *
+ * \note Do *NOT* try to reorder the macros below, as this will only
+ * work in the given order.
+ */
+#define PRAGMA(x) _Pragma( #x )
+#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
+#define sei( ) (__enable_interrupt( ))
+#define cli( ) (__disable_interrupt( ))
+
+/*! \brief Define the no operation macro. */
+#define nop( ) (__no_operation())
+
+/*! \brief Define the watchdog reset macro. */
+#define watchdog_reset( ) (__watchdog_reset( ))
+
+
+#define INLINE PRAGMA( inline=forced ) static
+
+#define FLASH_DECLARE(x) _MEMATTR x
+#define FLASH_STRING(x) ((_MEMATTR const char *)(x))
+#define FLASH_STRING_T char const _MEMATTR *
+#define FLASH_BYTE_ARRAY_T uint8_t const _MEMATTR *
+#define PGM_READ_BYTE(x) *(x)
+#define PGM_READ_WORD(x) *(x)
+
+#define SHORTENUM /**/
+
+#elif defined( __GNUC__ )
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include <util/delay.h>
+
+/*! \brief Define the delay_us macro for GCC. */
+#define delay_us( us ) (_delay_us( us ))
+
+#define INLINE static inline
+
+/*! \brief Define the no operation macro. */
+#define nop() do { __asm__ __volatile__ ("nop"); } while (0)
+
+#define MAIN_TASK_PROLOGUE int
+
+
+#define MAIN_TASK_EPILOGUE() return -1;
+
+#define SHORTENUM __attribute__ ((packed))
+
+#else
+#error Compiler not supported.
+#endif
+
+#endif
+
diff --git a/edid_injector.c b/edid_injector.c
new file mode 100644
index 0000000..5a539e4
--- /dev/null
+++ b/edid_injector.c
@@ -0,0 +1,132 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief EDID Injector firmware
+ *
+ * \author
+ * Wolfgang 'datenwolf' Draxinger
+ * Support email: projects+edid_injector@datenwolf.net
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#include "avr_compiler.h"
+#include "twi_master_driver.h"
+#include "twi_slave_driver.h"
+#include "eeprom_driver.h"
+
+/*! AUDRATE 100kHz and Baudrate Register Settings */
+#define BAUDRATE 100000
+#define TWI_BAUDSETTING TWI_BAUD(F_CPU, BAUDRATE)
+
+/* TWIC is on the display side */
+TWI_t * const twiDisplay = &TWIC;
+TWI_Master_t twimDisplay; /*!< TWI master module. Used for talking with display */
+
+/* TWIE is on the host side */
+TWI_t * const twiHost = &TWIE;
+TWI_Slave_t twimHost; /*!< TWI slave module. Used for talking with host */
+
+
+void TWIC_SlaveProcessData(void)
+{
+}
+
+void edid_initHostTWI(void)
+{
+}
+
+void edid_initDisplayTWI(void)
+{
+}
+
+void edid_readFromDisplayToEEPROM(void)
+{
+ uint8_t buffer[128];
+ memset(buffer, 0, sizeof(buffer);
+
+}
+
+int main(void)
+{
+ edid_initHostTWI();
+
+ edid_initDisplayTWI();
+
+ /* Initialize PORTE for output and PORTD for inverted input. */
+ PORTE.DIRSET = 0xFF;
+ PORTD.DIRCLR = 0xFF;
+ PORTCFG.MPCMASK = 0xFF;
+ PORTD.PIN0CTRL |= PORT_INVEN_bm;
+// PORTCFG.MPCMASK = 0xFF;
+// PORTD.PIN0CTRL = (PORTD.PIN0CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLUP_gc;
+
+ // Enable internal pull-up on PC0, PC1.. Uncomment if you don't have external pullups
+// PORTCFG.MPCMASK = 0x03; // Configure several PINxCTRL registers at the same time
+// PORTC.PIN0CTRL = (PORTC.PIN0CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLUP_gc; //Enable pull-up to get a defined level on the switches
+
+
+
+ /* Initialize TWI master. */
+ TWI_MasterInit(&twiMaster,
+ &TWIC,
+ TWI_MASTER_INTLVL_LO_gc,
+ TWI_BAUDSETTING);
+
+ /* Initialize TWI slave. */
+ TWI_SlaveInitializeDriver(&twiSlave, &TWIC, TWIC_SlaveProcessData);
+ TWI_SlaveInitializeModule(&twiSlave,
+ SLAVE_ADDRESS,
+ TWI_SLAVE_INTLVL_LO_gc);
+
+ /* Enable LO interrupt level. */
+ PMIC.CTRL |= PMIC_LOLVLEN_bm;
+ sei();
+
+
+ #if 0
+ TWI_MasterWriteRead(&twiMaster,
+ SLAVE_ADDRESS,
+ &sendBuffer[BufPos],
+ 1,
+ 1);
+
+
+ while (twiMaster.status != TWIM_STATUS_READY) {
+ /* Wait until transaction is complete. */
+ }
+ #endif
+}
+
+/*! TWIC Master Interrupt vector. */
+ISR(TWIC_TWIM_vect)
+{
+ TWI_MasterInterruptHandler(&twiMaster);
+}
+
+/*! TWIC Slave Interrupt vector. */
+ISR(TWIC_TWIS_vect)
+{
+ TWI_SlaveInterruptHandler(&twiSlave);
+}
diff --git a/eeprom_driver.c b/eeprom_driver.c
new file mode 100644
index 0000000..cc849a6
--- /dev/null
+++ b/eeprom_driver.c
@@ -0,0 +1,330 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief XMEGA EEPROM driver source file.
+ *
+ * This file contains the function implementations for the XMEGA EEPROM driver.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA EEPROM module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * \par Application note:
+ * AVR1315: Accessing the XMEGA EEPROM
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation: http://www.atmel.com \n
+ * Support email: avr@atmel.com
+ *
+ * $Revision: 1569 $
+ * $Date: 2008-04-22 13:03:43 +0200 (ti, 22 apr 2008) $ \n
+ *
+ * Copyright (c) 2008, Atmel Corporation All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "eeprom_driver.h"
+
+/*! \brief Write one byte to EEPROM using IO mapping.
+ *
+ * This function writes one byte to EEPROM using IO-mapped access.
+ * If memory mapped EEPROM is enabled, this function will not work.
+ * This functiom will cancel all ongoing EEPROM page buffer loading
+ * operations, if any.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ * \param byteAddr EEPROM Byte address, between 0 and EEPROM_PAGESIZE.
+ * \param value Byte value to write to EEPROM.
+ */
+void EEPROM_WriteByte( uint8_t pageAddr, uint8_t byteAddr, uint8_t value )
+{
+ /* Flush buffer to make sure no unintetional data is written and load
+ * the "Page Load" command into the command register.
+ */
+ EEPROM_FlushBuffer();
+ NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;
+
+ /* Calculate address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE)
+ |(byteAddr & (EEPROM_PAGESIZE-1));
+
+ /* Set address to write to. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Load data to write, which triggers the loading of EEPROM page buffer. */
+ NVM.DATA0 = value;
+
+ /* Issue EEPROM Atomic Write (Erase&Write) command. Load command, write
+ * the protection signature and execute command.
+ */
+ NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc;
+ NVM_EXEC();
+}
+
+
+/*! \brief Read one byte from EEPROM using IO mapping.
+ *
+ * This function reads one byte from EEPROM using IO-mapped access.
+ * If memory mapped EEPROM is enabled, this function will not work.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ * \param byteAddr EEPROM Byte address, between 0 and EEPROM_PAGESIZE.
+ *
+ * \return Byte value read from EEPROM.
+ */
+uint8_t EEPROM_ReadByte( uint8_t pageAddr, uint8_t byteAddr )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Calculate address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE)
+ |(byteAddr & (EEPROM_PAGESIZE-1));
+
+ /* Set address to read from. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Issue EEPROM Read command. */
+ NVM.CMD = NVM_CMD_READ_EEPROM_gc;
+ NVM_EXEC();
+
+ return NVM.DATA0;
+}
+
+
+/*! \brief Wait for any NVM access to finish, including EEPROM.
+ *
+ * This function is blcoking and waits for any NVM access to finish,
+ * including EEPROM. Use this function before any EEPROM accesses,
+ * if you are not certain that any previous operations are finished yet,
+ * like an EEPROM write.
+ */
+void EEPROM_WaitForNVM( void )
+{
+ do {
+ /* Block execution while waiting for the NVM to be ready. */
+ } while ((NVM.STATUS & NVM_NVMBUSY_bm) == NVM_NVMBUSY_bm);
+}
+
+
+/*! \brief Flush temporary EEPROM page buffer.
+ *
+ * This function flushes the EEPROM page buffers. This function will cancel
+ * any ongoing EEPROM page buffer loading operations, if any.
+ * This function also works for memory mapped EEPROM access.
+ *
+ * \note The EEPROM write operations will automatically flush the buffer for you.
+ */
+void EEPROM_FlushBuffer( void )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Flush EEPROM page buffer if necessary. */
+ if ((NVM.STATUS & NVM_EELOAD_bm) != 0) {
+ NVM.CMD = NVM_CMD_ERASE_EEPROM_BUFFER_gc;
+ NVM_EXEC();
+ }
+}
+
+
+/*! \brief Load single byte into temporary page buffer.
+ *
+ * This function loads one byte into the temporary EEPROM page buffers.
+ * If memory mapped EEPROM is enabled, this function will not work.
+ * Make sure that the buffer is flushed before starting to load bytes.
+ * Also, if multiple bytes are loaded into the same location, they will
+ * be ANDed together, thus 0x55 and 0xAA will result in 0x00 in the buffer.
+ *
+ * \note Only one page buffer exist, thus only one page can be loaded with
+ * data and programmed into one page. If data needs to be written to
+ * different pages, the loading and writing needs to be repeated.
+ *
+ * \param byteAddr EEPROM Byte address, between 0 and EEPROM_PAGESIZE.
+ * \param value Byte value to write to buffer.
+ */
+void EEPROM_LoadByte( uint8_t byteAddr, uint8_t value )
+{
+ /* Wait until NVM is not busy and prepare NVM command.*/
+ EEPROM_WaitForNVM();
+ NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;
+
+ /* Set address. */
+ NVM.ADDR0 = byteAddr & 0xFF;
+ NVM.ADDR1 = 0x00;
+ NVM.ADDR2 = 0x00;
+
+ /* Set data, which triggers loading of EEPROM page buffer. */
+ NVM.DATA0 = value;
+}
+
+
+/*! \brief Load entire page into temporary EEPROM page buffer.
+ *
+ * This function loads an entire EEPROM page from an SRAM buffer to
+ * the EEPROM page buffers. If memory mapped EEPROM is enabled, this
+ * function will not work. Make sure that the buffer is flushed before
+ * starting to load bytes.
+ *
+ * \note Only the lower part of the address is used to address the buffer.
+ * Therefore, no address parameter is needed. In the end, the data
+ * is written to the EEPROM page given by the address parameter to the
+ * EEPROM write page operation.
+ *
+ * \param values Pointer to SRAM buffer containing an entire page.
+ */
+void EEPROM_LoadPage( const uint8_t * values )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+ NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;
+
+ /* Set address to zero, as only the lower bits matters. ADDR0 is
+ * maintained inside the loop below.
+ */
+ NVM.ADDR1 = 0x00;
+ NVM.ADDR2 = 0x00;
+
+ /* Load multible bytes into page buffer. */
+ for (uint8_t i = 0; i < EEPROM_PAGESIZE; ++i) {
+ NVM.ADDR0 = i;
+ NVM.DATA0 = *values;
+ ++values;
+ }
+}
+
+/*! \brief Write already loaded page into EEPROM.
+ *
+ * This function writes the contents of an already loaded EEPROM page
+ * buffer into EEPROM memory.
+ *
+ * As this is an atomic write, the page in EEPROM will be erased
+ * automatically before writing. Note that only the page buffer locations
+ * that have been loaded will be used when writing to EEPROM. Page buffer
+ * locations that have not been loaded will be left untouched in EEPROM.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ */
+void EEPROM_AtomicWritePage( uint8_t pageAddr )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Calculate page address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE);
+
+ /* Set address. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Issue EEPROM Atomic Write (Erase&Write) command. */
+ NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc;
+ NVM_EXEC();
+}
+
+
+/*! \brief Erase EEPROM page.
+ *
+ * This function erases one EEPROM page, so that every location reads 0xFF.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ */
+void EEPROM_ErasePage( uint8_t pageAddr )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Calculate page address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE);
+
+ /* Set address. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Issue EEPROM Erase command. */
+ NVM.CMD = NVM_CMD_ERASE_EEPROM_PAGE_gc;
+ NVM_EXEC();
+}
+
+
+/*! \brief Write (without erasing) EEPROM page.
+ *
+ * This function writes the contents of an already loaded EEPROM page
+ * buffer into EEPROM memory.
+ *
+ * As this is a split write, the page in EEPROM will _not_ be erased
+ * before writing.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ */
+void EEPROM_SplitWritePage( uint8_t pageAddr )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Calculate page address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE);
+
+ /* Set address. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Issue EEPROM Split Write command. */
+ NVM.CMD = NVM_CMD_WRITE_EEPROM_PAGE_gc;
+ NVM_EXEC();
+}
+
+/*! \brief Erase entire EEPROM memory.
+ *
+ * This function erases the entire EEPROM memory block to 0xFF.
+ */
+void EEPROM_EraseAll( void )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Issue EEPROM Erase All command. */
+ NVM.CMD = NVM_CMD_ERASE_EEPROM_gc;
+ NVM_EXEC();
+}
+
diff --git a/eeprom_driver.h b/eeprom_driver.h
new file mode 100644
index 0000000..90cc8e3
--- /dev/null
+++ b/eeprom_driver.h
@@ -0,0 +1,142 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief XMEGA EEPROM driver header file.
+ *
+ * This file contains the function prototypes and enumerator definitions
+ * for various configuration parameters for the XMEGA EEPROM driver.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA EEPROM module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * \par Application note:
+ * AVR1315: Accessing the XMEGA EEPROM
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation: http://www.atmel.com \n
+ * Support email: avr@atmel.com
+ *
+ * $Revision: 1569 $
+ * $Date: 2008-04-22 13:03:43 +0200 (ti, 22 apr 2008) $ \n
+ *
+ * Copyright (c) 2008, Atmel Corporation All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#ifndef EEPROM_DRIVER_H
+#define EEPROM_DRIVER_H
+
+#include "avr_compiler.h"
+
+#define MAPPED_EEPROM_START 0x1000
+#define EEPROM_PAGESIZE 32
+#define EEPROM(_pageAddr, _byteAddr) \
+ ((uint8_t *) MAPPED_EEPROM_START)[_pageAddr*EEPROM_PAGESIZE + _byteAddr]
+
+
+
+/* Definitions of macros. */
+
+/*! \brief Enable EEPROM block sleep-when-not-used mode.
+ *
+ * This macro enables power reduction mode for EEPROM.
+ * It means that the EEPROM block is disabled when not used.
+ * Note that there will be a penalty of 6 CPU cycles if EEPROM
+ * is accessed.
+ */
+#define EEPROM_EnablePowerReduction() ( NVM.CTRLB |= NVM_EPRM_bm )
+
+/*! \brief Disable EEPROM block sleep-when-not-used mode.
+ *
+ * This macro disables power reduction mode for EEPROM.
+ */
+#define EEPROM_DisablePowerReduction() ( NVM.CTRLB &= ~NVM_EPRM_bm )
+
+/*! \brief Enable EEPROM mapping into data space.
+ *
+ * This macro enables mapping of EEPROM into data space.
+ * EEPROM starts at EEPROM_START in data memory. Read access
+ * can be done similar to ordinary SRAM access.
+ *
+ * \note This disables IO-mapped access to EEPROM, although page erase and
+ * write operations still needs to be done through IO register.
+ */
+#define EEPROM_EnableMapping() ( NVM.CTRLB |= NVM_EEMAPEN_bm )
+
+/*! \brief Disable EEPROM mapping into data space.
+ *
+ * This macro disables mapping of EEPROM into data space.
+ * IO mapped access is now enabled.
+ */
+#define EEPROM_DisableMapping() ( NVM.CTRLB &= ~NVM_EEMAPEN_bm )
+
+/*! \brief Non-Volatile Memory Execute Command
+ *
+ * This macro set the CCP register before setting the CMDEX bit in the
+ * NVM.CTRLA register.
+ *
+ * \note The CMDEX bit must be set within 4 clock cycles after setting the
+ * protection byte in the CCP register.
+ */
+#define NVM_EXEC() asm("push r30" "\n\t" \
+ "push r31" "\n\t" \
+ "push r16" "\n\t" \
+ "push r18" "\n\t" \
+ "ldi r30, 0xCB" "\n\t" \
+ "ldi r31, 0x01" "\n\t" \
+ "ldi r16, 0xD8" "\n\t" \
+ "ldi r18, 0x01" "\n\t" \
+ "out 0x34, r16" "\n\t" \
+ "st Z, r18" "\n\t" \
+ "pop r18" "\n\t" \
+ "pop r16" "\n\t" \
+ "pop r31" "\n\t" \
+ "pop r30" "\n\t" \
+ )
+
+/* Prototyping of functions. */
+void EEPROM_WriteByte( uint8_t pageAddr, uint8_t byteAddr, uint8_t value );
+uint8_t EEPROM_ReadByte( uint8_t pageAddr, uint8_t byteAddr );
+void EEPROM_WaitForNVM( void );
+void EEPROM_FlushBuffer( void );
+void EEPROM_LoadByte( uint8_t byteAddr, uint8_t value );
+void EEPROM_LoadPage( const uint8_t * values );
+void EEPROM_AtomicWritePage( uint8_t pageAddr );
+void EEPROM_ErasePage( uint8_t pageAddress );
+void EEPROM_SplitWritePage( uint8_t pageAddr );
+void EEPROM_EraseAll( void );
+
+#endif
diff --git a/twi_master_driver.c b/twi_master_driver.c
new file mode 100644
index 0000000..c7f9695
--- /dev/null
+++ b/twi_master_driver.c
@@ -0,0 +1,399 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief
+ * XMEGA TWI master driver source file.
+ *
+ * This file contains the function implementations the XMEGA master TWI
+ * driver.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA TWI master module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * Several functions use the following construct:
+ * "some_register = ... | (some_parameter ? SOME_BIT_bm : 0) | ..."
+ * Although the use of the ternary operator ( if ? then : else ) is
+ * discouraged, in some occasions the operator makes it possible to write
+ * pretty clean and neat code. In this driver, the construct is used to
+ * set or not set a configuration bit based on a boolean input parameter,
+ * such as the "some_parameter" in the example above.
+ *
+ * \par Application note:
+ * AVR1308: Using the XMEGA TWI
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation: http://www.atmel.com \n
+ * Support email: avr@atmel.com
+ *
+ * $Revision: 1569 $
+ * $Date: 2008-04-22 13:03:43 +0200 (ti, 22 apr 2008) $ \n
+ *
+ * Copyright (c) 2008, Atmel Corporation All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "twi_master_driver.h"
+
+
+/*! \brief Initialize the TWI module.
+ *
+ * TWI module initialization function.
+ * Enables master read and write interrupts.
+ * Remember to enable interrupts globally from the main application.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ * \param module The TWI module to use.
+ * \param intLevel Master interrupt level.
+ * \param baudRateRegisterSetting The baud rate register value.
+ */
+void TWI_MasterInit(TWI_Master_t *twi,
+ TWI_t *module,
+ TWI_MASTER_INTLVL_t intLevel,
+ uint8_t baudRateRegisterSetting)
+{
+ twi->interface = module;
+ twi->interface->MASTER.CTRLA = intLevel |
+ TWI_MASTER_RIEN_bm |
+ TWI_MASTER_WIEN_bm |
+ TWI_MASTER_ENABLE_bm;
+ twi->interface->MASTER.BAUD = baudRateRegisterSetting;
+ twi->interface->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
+}
+
+
+/*! \brief Returns the TWI bus state.
+ *
+ * Returns the TWI bus state (type defined in device headerfile),
+ * unknown, idle, owner or busy.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ *
+ * \retval TWI_MASTER_BUSSTATE_UNKNOWN_gc Bus state is unknown.
+ * \retval TWI_MASTER_BUSSTATE_IDLE_gc Bus state is idle.
+ * \retval TWI_MASTER_BUSSTATE_OWNER_gc Bus state is owned by the master.
+ * \retval TWI_MASTER_BUSSTATE_BUSY_gc Bus state is busy.
+ */
+TWI_MASTER_BUSSTATE_t TWI_MasterState(TWI_Master_t *twi)
+{
+ TWI_MASTER_BUSSTATE_t twi_status;
+ twi_status = (TWI_MASTER_BUSSTATE_t) (twi->interface->MASTER.STATUS &
+ TWI_MASTER_BUSSTATE_gm);
+ return twi_status;
+}
+
+
+/*! \brief Returns true if transaction is ready.
+ *
+ * This function returns a boolean whether the TWI Master is ready
+ * for a new transaction.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ *
+ * \retval true If transaction could be started.
+ * \retval false If transaction could not be started.
+ */
+bool TWI_MasterReady(TWI_Master_t *twi)
+{
+ bool twi_status = (twi->status & TWIM_STATUS_READY);
+ return twi_status;
+}
+
+
+/*! \brief TWI write transaction.
+ *
+ * This function is TWI Master wrapper for a write-only transaction.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ * \param address Slave address.
+ * \param writeData Pointer to data to write.
+ * \param bytesToWrite Number of data bytes to write.
+ *
+ * \retval true If transaction could be started.
+ * \retval false If transaction could not be started.
+ */
+bool TWI_MasterWrite(TWI_Master_t *twi,
+ uint8_t address,
+ uint8_t *writeData,
+ uint8_t bytesToWrite)
+{
+ bool twi_status = TWI_MasterWriteRead(twi, address, writeData, bytesToWrite, 0);
+ return twi_status;
+}
+
+
+/*! \brief TWI read transaction.
+ *
+ * This function is a TWI Maste wrapper for read-only transaction.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ * \param address The slave address.
+ * \param bytesToRead The number of bytes to read.
+ *
+ * \retval true If transaction could be started.
+ * \retval false If transaction could not be started.
+ */
+bool TWI_MasterRead(TWI_Master_t *twi,
+ uint8_t address,
+ uint8_t bytesToRead)
+{
+ bool twi_status = TWI_MasterWriteRead(twi, address, 0, 0, bytesToRead);
+ return twi_status;
+}
+
+
+/*! \brief TWI write and/or read transaction.
+ *
+ * This function is a TWI Master write and/or read transaction. The function
+ * can be used to both write and/or read bytes to/from the TWI Slave in one
+ * transaction.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ * \param address The slave address.
+ * \param writeData Pointer to data to write.
+ * \param bytesToWrite Number of bytes to write.
+ * \param bytesToRead Number of bytes to read.
+ *
+ * \retval true If transaction could be started.
+ * \retval false If transaction could not be started.
+ */
+bool TWI_MasterWriteRead(TWI_Master_t *twi,
+ uint8_t address,
+ uint8_t *writeData,
+ uint8_t bytesToWrite,
+ uint8_t bytesToRead)
+{
+ /*Parameter sanity check. */
+ if (bytesToWrite > TWIM_WRITE_BUFFER_SIZE) {
+ return false;
+ }
+ if (bytesToRead > TWIM_READ_BUFFER_SIZE) {
+ return false;
+ }
+
+ /*Initiate transaction if bus is ready. */
+ if (twi->status == TWIM_STATUS_READY) {
+
+ twi->status = TWIM_STATUS_BUSY;
+ twi->result = TWIM_RESULT_UNKNOWN;
+
+ twi->address = address<<1;
+
+ /* Fill write data buffer. */
+ for (uint8_t bufferIndex=0; bufferIndex < bytesToWrite; bufferIndex++) {
+ twi->writeData[bufferIndex] = writeData[bufferIndex];
+ }
+
+ twi->bytesToWrite = bytesToWrite;
+ twi->bytesToRead = bytesToRead;
+ twi->bytesWritten = 0;
+ twi->bytesRead = 0;
+
+ /* If write command, send the START condition + Address +
+ * 'R/_W = 0'
+ */
+ if (twi->bytesToWrite > 0) {
+ uint8_t writeAddress = twi->address & ~0x01;
+ twi->interface->MASTER.ADDR = writeAddress;
+ }
+
+ /* If read command, send the START condition + Address +
+ * 'R/_W = 1'
+ */
+ else if (twi->bytesToRead > 0) {
+ uint8_t readAddress = twi->address | 0x01;
+ twi->interface->MASTER.ADDR = readAddress;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+/*! \brief Common TWI master interrupt service routine.
+ *
+ * Check current status and calls the appropriate handler.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ */
+void TWI_MasterInterruptHandler(TWI_Master_t *twi)
+{
+ uint8_t currentStatus = twi->interface->MASTER.STATUS;
+
+ /* If arbitration lost or bus error. */
+ if ((currentStatus & TWI_MASTER_ARBLOST_bm) ||
+ (currentStatus & TWI_MASTER_BUSERR_bm)) {
+
+ TWI_MasterArbitrationLostBusErrorHandler(twi);
+ }
+
+ /* If master write interrupt. */
+ else if (currentStatus & TWI_MASTER_WIF_bm) {
+ TWI_MasterWriteHandler(twi);
+ }
+
+ /* If master read interrupt. */
+ else if (currentStatus & TWI_MASTER_RIF_bm) {
+ TWI_MasterReadHandler(twi);
+ }
+
+ /* If unexpected state. */
+ else {
+ TWI_MasterTransactionFinished(twi, TWIM_RESULT_FAIL);
+ }
+}
+
+
+/*! \brief TWI master arbitration lost and bus error interrupt handler.
+ *
+ * Handles TWI responses to lost arbitration and bus error.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ */
+void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi)
+{
+ uint8_t currentStatus = twi->interface->MASTER.STATUS;
+
+ /* If bus error. */
+ if (currentStatus & TWI_MASTER_BUSERR_bm) {
+ twi->result = TWIM_RESULT_BUS_ERROR;
+ }
+ /* If arbitration lost. */
+ else {
+ twi->result = TWIM_RESULT_ARBITRATION_LOST;
+ }
+
+ /* Clear interrupt flag. */
+ twi->interface->MASTER.STATUS = currentStatus | TWI_MASTER_ARBLOST_bm;
+
+ twi->status = TWIM_STATUS_READY;
+}
+
+
+/*! \brief TWI master write interrupt handler.
+ *
+ * Handles TWI transactions (master write) and responses to (N)ACK.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ */
+void TWI_MasterWriteHandler(TWI_Master_t *twi)
+{
+ /* Local variables used in if tests to avoid compiler warning. */
+ uint8_t bytesToWrite = twi->bytesToWrite;
+ uint8_t bytesToRead = twi->bytesToRead;
+
+ /* If NOT acknowledged (NACK) by slave cancel the transaction. */
+ if (twi->interface->MASTER.STATUS & TWI_MASTER_RXACK_bm) {
+ twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
+ twi->result = TWIM_RESULT_NACK_RECEIVED;
+ twi->status = TWIM_STATUS_READY;
+ }
+
+ /* If more bytes to write, send data. */
+ else if (twi->bytesWritten < bytesToWrite) {
+ uint8_t data = twi->writeData[twi->bytesWritten];
+ twi->interface->MASTER.DATA = data;
+ ++twi->bytesWritten;
+ }
+
+ /* If bytes to read, send repeated START condition + Address +
+ * 'R/_W = 1'
+ */
+ else if (twi->bytesRead < bytesToRead) {
+ uint8_t readAddress = twi->address | 0x01;
+ twi->interface->MASTER.ADDR = readAddress;
+ }
+
+ /* If transaction finished, send STOP condition and set RESULT OK. */
+ else {
+ twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
+ TWI_MasterTransactionFinished(twi, TWIM_RESULT_OK);
+ }
+}
+
+
+/*! \brief TWI master read interrupt handler.
+ *
+ * This is the master read interrupt handler that takes care of
+ * reading bytes from the TWI slave.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ */
+void TWI_MasterReadHandler(TWI_Master_t *twi)
+{
+ /* Fetch data if bytes to be read. */
+ if (twi->bytesRead < TWIM_READ_BUFFER_SIZE) {
+ uint8_t data = twi->interface->MASTER.DATA;
+ twi->readData[twi->bytesRead] = data;
+ twi->bytesRead++;
+ }
+
+ /* If buffer overflow, issue STOP and BUFFER_OVERFLOW condition. */
+ else {
+ twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
+ TWI_MasterTransactionFinished(twi, TWIM_RESULT_BUFFER_OVERFLOW);
+ }
+
+ /* Local variable used in if test to avoid compiler warning. */
+ uint8_t bytesToRead = twi->bytesToRead;
+
+ /* If more bytes to read, issue ACK and start a byte read. */
+ if (twi->bytesRead < bytesToRead) {
+ twi->interface->MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
+ }
+
+ /* If transaction finished, issue NACK and STOP condition. */
+ else {
+ twi->interface->MASTER.CTRLC = TWI_MASTER_ACKACT_bm |
+ TWI_MASTER_CMD_STOP_gc;
+ TWI_MasterTransactionFinished(twi, TWIM_RESULT_OK);
+ }
+}
+
+
+/*! \brief TWI transaction finished handler.
+ *
+ * Prepares module for new transaction.
+ *
+ * \param twi The TWI_Master_t struct instance.
+ * \param result The result of the operation.
+ */
+void TWI_MasterTransactionFinished(TWI_Master_t *twi, uint8_t result)
+{
+ twi->result = result;
+ twi->status = TWIM_STATUS_READY;
+}
diff --git a/twi_master_driver.h b/twi_master_driver.h
new file mode 100644
index 0000000..c6620f7
--- /dev/null
+++ b/twi_master_driver.h
@@ -0,0 +1,147 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief XMEGA TWI master driver header file.
+ *
+ * This file contains the function prototypes and enumerator definitions
+ * for various configuration parameters for the XMEGA TWI master driver.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA TWI master module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * \par Application note:
+ * AVR1308: Using the XMEGA TWI
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation: http://www.atmel.com \n
+ * Support email: avr@atmel.com
+ *
+ * $Revision: 1569 $
+ * $Date: 2008-04-22 13:03:43 +0200 (ti, 22 apr 2008) $ \n
+ *
+ * Copyright (c) 2008, Atmel Corporation All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#ifndef TWI_MASTER_DRIVER_H
+#define TWI_MASTER_DRIVER_H
+
+#include "avr_compiler.h"
+
+/*! Baud register setting calculation. Formula described in datasheet. */
+#define TWI_BAUD(F_SYS, F_TWI) ((F_SYS / (2 * F_TWI)) - 5)
+
+
+/*! Transaction status defines. */
+#define TWIM_STATUS_READY 0
+#define TWIM_STATUS_BUSY 1
+
+
+/*! Transaction result enumeration. */
+typedef enum TWIM_RESULT_enum {
+ TWIM_RESULT_UNKNOWN = (0x00<<0),
+ TWIM_RESULT_OK = (0x01<<0),
+ TWIM_RESULT_BUFFER_OVERFLOW = (0x02<<0),
+ TWIM_RESULT_ARBITRATION_LOST = (0x03<<0),
+ TWIM_RESULT_BUS_ERROR = (0x04<<0),
+ TWIM_RESULT_NACK_RECEIVED = (0x05<<0),
+ TWIM_RESULT_FAIL = (0x06<<0),
+} TWIM_RESULT_t;
+
+/*! Buffer size defines */
+#define TWIM_WRITE_BUFFER_SIZE 8
+#define TWIM_READ_BUFFER_SIZE 8
+
+
+/*! \brief TWI master driver struct
+ *
+ * TWI master struct. Holds pointer to TWI module,
+ * buffers and necessary varibles.
+ */
+typedef struct TWI_Master {
+ TWI_t *interface; /*!< Pointer to what interface to use */
+ register8_t address; /*!< Slave address */
+ register8_t writeData[TWIM_WRITE_BUFFER_SIZE]; /*!< Data to write */
+ register8_t readData[TWIM_READ_BUFFER_SIZE]; /*!< Read data */
+ register8_t bytesToWrite; /*!< Number of bytes to write */
+ register8_t bytesToRead; /*!< Number of bytes to read */
+ register8_t bytesWritten; /*!< Number of bytes written */
+ register8_t bytesRead; /*!< Number of bytes read */
+ register8_t status; /*!< Status of transaction */
+ register8_t result; /*!< Result of transaction */
+}TWI_Master_t;
+
+
+
+void TWI_MasterInit(TWI_Master_t *twi,
+ TWI_t *module,
+ TWI_MASTER_INTLVL_t intLevel,
+ uint8_t baudRateRegisterSetting);
+TWI_MASTER_BUSSTATE_t TWI_MasterState(TWI_Master_t *twi);
+bool TWI_MasterReady(TWI_Master_t *twi);
+bool TWI_MasterWrite(TWI_Master_t *twi,
+ uint8_t address,
+ uint8_t * writeData,
+ uint8_t bytesToWrite);
+bool TWI_MasterRead(TWI_Master_t *twi,
+ uint8_t address,
+ uint8_t bytesToRead);
+bool TWI_MasterWriteRead(TWI_Master_t *twi,
+ uint8_t address,
+ uint8_t *writeData,
+ uint8_t bytesToWrite,
+ uint8_t bytesToRead);
+void TWI_MasterInterruptHandler(TWI_Master_t *twi);
+void TWI_MasterArbitrationLostBusErrorHandler(TWI_Master_t *twi);
+void TWI_MasterWriteHandler(TWI_Master_t *twi);
+void TWI_MasterReadHandler(TWI_Master_t *twi);
+void TWI_MasterTransactionFinished(TWI_Master_t *twi, uint8_t result);
+
+
+/*! TWI master interrupt service routine.
+ *
+ * Interrupt service routine for the TWI master. Copy the needed vectors
+ * into your code.
+ *
+ ISR(TWIC_TWIM_vect)
+ {
+ TWI_MasterInterruptHandler(&twiMaster);
+ }
+
+ *
+ */
+
+#endif /* TWI_MASTER_DRIVER_H */
diff --git a/twi_slave_driver.c b/twi_slave_driver.c
new file mode 100644
index 0000000..d6eecc2
--- /dev/null
+++ b/twi_slave_driver.c
@@ -0,0 +1,321 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief
+ * XMEGA TWI slave driver source file.
+ *
+ * This file contains the function implementations the XMEGA TWI slave
+ * driver.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA TWI slave module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * Several functions use the following construct:
+ * "some_register = ... | (some_parameter ? SOME_BIT_bm : 0) | ..."
+ * Although the use of the ternary operator ( if ? then : else ) is
+ * discouraged, in some occasions the operator makes it possible to write
+ * pretty clean and neat code. In this driver, the construct is used to
+ * set or not set a configuration bit based on a boolean input parameter,
+ * such as the "some_parameter" in the example above.
+ *
+ * \par Application note:
+ * AVR1308: Using the XMEGA TWI
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation: http://www.atmel.com \n
+ * Support email: avr@atmel.com
+ *
+ * $Revision: 2660 $
+ * $Date: 2009-08-11 12:28:58 +0200 (ti, 11 aug 2009) $ \n
+ *
+ * Copyright (c) 2008, Atmel Corporation All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "twi_slave_driver.h"
+
+
+/*! \brief Initalizes TWI slave driver structure.
+ *
+ * Initialize the instance of the TWI Slave and set the appropriate values.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ * \param module Pointer to the TWI module.
+ * \param processDataFunction Pointer to the function that handles incoming data.
+ */
+void TWI_SlaveInitializeDriver(TWI_Slave_t *twi,
+ TWI_t *module,
+ void (*processDataFunction) (void))
+{
+ twi->interface = module;
+ twi->Process_Data = processDataFunction;
+ twi->bytesReceived = 0;
+ twi->bytesSent = 0;
+ twi->status = TWIS_STATUS_READY;
+ twi->result = TWIS_RESULT_UNKNOWN;
+ twi->abort = false;
+}
+
+
+/*! \brief Initialize the TWI module.
+ *
+ * Enables interrupts on address recognition and data available.
+ * Remember to enable interrupts globally from the main application.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ * \param address Slave address for this module.
+ * \param intLevel Interrupt level for the TWI slave interrupt handler.
+ */
+void TWI_SlaveInitializeModule(TWI_Slave_t *twi,
+ uint8_t address,
+ TWI_SLAVE_INTLVL_t intLevel)
+{
+ twi->interface->SLAVE.CTRLA = intLevel |
+ TWI_SLAVE_DIEN_bm |
+ TWI_SLAVE_APIEN_bm |
+ TWI_SLAVE_ENABLE_bm;
+ twi->interface->SLAVE.ADDR = (address<<1);
+}
+
+
+/*! \brief Common TWI slave interrupt service routine.
+ *
+ * Handles all TWI transactions and responses to address match, data reception,
+ * data transmission, bus error and data collision.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ */
+void TWI_SlaveInterruptHandler(TWI_Slave_t *twi)
+{
+ uint8_t currentStatus = twi->interface->SLAVE.STATUS;
+
+ /* If bus error. */
+ if (currentStatus & TWI_SLAVE_BUSERR_bm) {
+ twi->bytesReceived = 0;
+ twi->bytesSent = 0;
+ twi->result = TWIS_RESULT_BUS_ERROR;
+ twi->status = TWIS_STATUS_READY;
+ }
+
+ /* If transmit collision. */
+ else if (currentStatus & TWI_SLAVE_COLL_bm) {
+ twi->bytesReceived = 0;
+ twi->bytesSent = 0;
+ twi->result = TWIS_RESULT_TRANSMIT_COLLISION;
+ twi->status = TWIS_STATUS_READY;
+ }
+
+ /* If address match. */
+ else if ((currentStatus & TWI_SLAVE_APIF_bm) &&
+ (currentStatus & TWI_SLAVE_AP_bm)) {
+
+ TWI_SlaveAddressMatchHandler(twi);
+ }
+
+ /* If stop (only enabled through slave read transaction). */
+ else if (currentStatus & TWI_SLAVE_APIF_bm) {
+ TWI_SlaveStopHandler(twi);
+ }
+
+ /* If data interrupt. */
+ else if (currentStatus & TWI_SLAVE_DIF_bm) {
+ TWI_SlaveDataHandler(twi);
+ }
+
+ /* If unexpected state. */
+ else {
+ TWI_SlaveTransactionFinished(twi, TWIS_RESULT_FAIL);
+ }
+}
+
+/*! \brief TWI address match interrupt handler.
+ *
+ * Prepares TWI module for transaction when an address match occures.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ */
+void TWI_SlaveAddressMatchHandler(TWI_Slave_t *twi)
+{
+ /* If application signalling need to abort (error occured). */
+ if (twi->abort) {
+ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc;
+ TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED);
+ twi->abort = false;
+ } else {
+ twi->status = TWIS_STATUS_BUSY;
+ twi->result = TWIS_RESULT_UNKNOWN;
+
+ /* Disable stop interrupt. */
+ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA;
+ twi->interface->SLAVE.CTRLA = currentCtrlA & ~TWI_SLAVE_PIEN_bm;
+
+ twi->bytesReceived = 0;
+ twi->bytesSent = 0;
+
+ /* Send ACK, wait for data interrupt. */
+ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc;
+ }
+}
+
+
+/*! \brief TWI stop condition interrupt handler.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ */
+void TWI_SlaveStopHandler(TWI_Slave_t *twi)
+{
+ /* Disable stop interrupt. */
+ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA;
+ twi->interface->SLAVE.CTRLA = currentCtrlA & ~TWI_SLAVE_PIEN_bm;
+
+ /* Clear APIF, according to flowchart don't ACK or NACK */
+ uint8_t currentStatus = twi->interface->SLAVE.STATUS;
+ twi->interface->SLAVE.STATUS = currentStatus | TWI_SLAVE_APIF_bm;
+
+ TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK);
+
+}
+
+
+/*! \brief TWI data interrupt handler.
+ *
+ * Calls the appropriate slave read or write handler.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ */
+void TWI_SlaveDataHandler(TWI_Slave_t *twi)
+{
+ if (twi->interface->SLAVE.STATUS & TWI_SLAVE_DIR_bm) {
+ TWI_SlaveWriteHandler(twi);
+ } else {
+ TWI_SlaveReadHandler(twi);
+ }
+}
+
+
+/*! \brief TWI slave read interrupt handler.
+ *
+ * Handles TWI slave read transactions and responses.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ */
+void TWI_SlaveReadHandler(TWI_Slave_t *twi)
+{
+ /* Enable stop interrupt. */
+ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA;
+ twi->interface->SLAVE.CTRLA = currentCtrlA | TWI_SLAVE_PIEN_bm;
+
+ /* If free space in buffer. */
+ if (twi->bytesReceived < TWIS_RECEIVE_BUFFER_SIZE) {
+ /* Fetch data */
+ uint8_t data = twi->interface->SLAVE.DATA;
+ twi->receivedData[twi->bytesReceived] = data;
+
+ /* Process data. */
+ twi->Process_Data();
+
+ twi->bytesReceived++;
+
+ /* If application signalling need to abort (error occured),
+ * complete transaction and wait for next START. Otherwise
+ * send ACK and wait for data interrupt.
+ */
+ if (twi->abort) {
+ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc;
+ TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED);
+ twi->abort = false;
+ } else {
+ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc;
+ }
+ }
+ /* If buffer overflow, send NACK and wait for next START. Set
+ * result buffer overflow.
+ */
+ else {
+ twi->interface->SLAVE.CTRLB = TWI_SLAVE_ACKACT_bm |
+ TWI_SLAVE_CMD_COMPTRANS_gc;
+ TWI_SlaveTransactionFinished(twi, TWIS_RESULT_BUFFER_OVERFLOW);
+ }
+}
+
+
+/*! \brief TWI slave write interrupt handler.
+ *
+ * Handles TWI slave write transactions and responses.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ */
+void TWI_SlaveWriteHandler(TWI_Slave_t *twi)
+{
+ /* If NACK, slave write transaction finished. */
+ if ((twi->bytesSent > 0) && (twi->interface->SLAVE.STATUS &
+ TWI_SLAVE_RXACK_bm)) {
+
+ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc;
+ TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK);
+ }
+ /* If ACK, master expects more data. */
+ else {
+ if (twi->bytesSent < TWIS_SEND_BUFFER_SIZE) {
+ uint8_t data = twi->sendData[twi->bytesSent];
+ twi->interface->SLAVE.DATA = data;
+ twi->bytesSent++;
+
+ /* Send data, wait for data interrupt. */
+ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc;
+ }
+ /* If buffer overflow. */
+ else {
+ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc;
+ TWI_SlaveTransactionFinished(twi, TWIS_RESULT_BUFFER_OVERFLOW);
+ }
+ }
+}
+
+
+/*! \brief TWI transaction finished function.
+ *
+ * Prepares module for new transaction.
+ *
+ * \param twi The TWI_Slave_t struct instance.
+ * \param result The result of the transaction.
+ */
+void TWI_SlaveTransactionFinished(TWI_Slave_t *twi, uint8_t result)
+{
+ twi->result = result;
+ twi->status = TWIS_STATUS_READY;
+}
diff --git a/twi_slave_driver.h b/twi_slave_driver.h
new file mode 100644
index 0000000..c09c43b
--- /dev/null
+++ b/twi_slave_driver.h
@@ -0,0 +1,135 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief XMEGA TWI slave driver header file.
+ *
+ * This file contains the function prototypes and enumerator definitions
+ * for various configuration parameters for the XMEGA TWI slave driver.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA TWI slave module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * \par Application note:
+ * AVR1307: Using the XMEGA TWI
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation: http://www.atmel.com \n
+ * Support email: avr@atmel.com
+ *
+ * $Revision: 1569 $
+ * $Date: 2008-04-22 13:03:43 +0200 (ti, 22 apr 2008) $ \n
+ *
+ * Copyright (c) 2008, Atmel Corporation All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#ifndef TWI_DRIVER_H
+#define TWI_DRIVER_H
+
+#include "avr_compiler.h"
+
+
+/* Transaction status defines.*/
+#define TWIS_STATUS_READY 0
+#define TWIS_STATUS_BUSY 1
+
+/* Transaction result enumeration */
+typedef enum TWIS_RESULT_enum {
+ TWIS_RESULT_UNKNOWN = (0x00<<0),
+ TWIS_RESULT_OK = (0x01<<0),
+ TWIS_RESULT_BUFFER_OVERFLOW = (0x02<<0),
+ TWIS_RESULT_TRANSMIT_COLLISION = (0x03<<0),
+ TWIS_RESULT_BUS_ERROR = (0x04<<0),
+ TWIS_RESULT_FAIL = (0x05<<0),
+ TWIS_RESULT_ABORTED = (0x06<<0),
+} TWIS_RESULT_t;
+
+/* Buffer size defines. */
+#define TWIS_RECEIVE_BUFFER_SIZE 8
+#define TWIS_SEND_BUFFER_SIZE 8
+
+
+
+/*! \brief TWI slave driver struct.
+ *
+ * TWI slave struct. Holds pointer to TWI module and data processing routine,
+ * buffers and necessary varibles.
+ */
+typedef struct TWI_Slave {
+ TWI_t *interface; /*!< Pointer to what interface to use*/
+ void (*Process_Data) (void); /*!< Pointer to process data function*/
+ register8_t receivedData[TWIS_RECEIVE_BUFFER_SIZE]; /*!< Read data*/
+ register8_t sendData[TWIS_SEND_BUFFER_SIZE]; /*!< Data to write*/
+ register8_t bytesReceived; /*!< Number of bytes received*/
+ register8_t bytesSent; /*!< Number of bytes sent*/
+ register8_t status; /*!< Status of transaction*/
+ register8_t result; /*!< Result of transaction*/
+ bool abort; /*!< Strobe to abort*/
+} TWI_Slave_t;
+
+
+
+void TWI_SlaveInitializeDriver(TWI_Slave_t *twi,
+ TWI_t *module,
+ void (*processDataFunction) (void));
+
+void TWI_SlaveInitializeModule(TWI_Slave_t *twi,
+ uint8_t address,
+ TWI_SLAVE_INTLVL_t intLevel);
+
+void TWI_SlaveInterruptHandler(TWI_Slave_t *twi);
+void TWI_SlaveAddressMatchHandler(TWI_Slave_t *twi);
+void TWI_SlaveStopHandler(TWI_Slave_t *twi);
+void TWI_SlaveDataHandler(TWI_Slave_t *twi);
+void TWI_SlaveReadHandler(TWI_Slave_t *twi);
+void TWI_SlaveWriteHandler(TWI_Slave_t *twi);
+void TWI_SlaveTransactionFinished(TWI_Slave_t *twi, uint8_t result);
+
+
+/*! TWI slave interrupt service routine.
+ *
+ * Interrupt service routine for the TWI slave. Copy the interrupt vector
+ * into your code if needed.
+ *
+ ISR(TWIC_TWIS_vect)
+ {
+ TWI_SlaveInterruptHandler(&twiSlaveC);
+ }
+ *
+ */
+
+
+#endif /* TWI_DRIVER_H */