Makefile separator errors fixed
This commit is contained in:
92
Makefile
Normal file
92
Makefile
Normal file
@@ -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
|
||||||
|
|
||||||
154
avr_compiler.h
Normal file
154
avr_compiler.h
Normal file
@@ -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
|
||||||
|
|
||||||
132
edid_injector.c
Normal file
132
edid_injector.c
Normal file
@@ -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);
|
||||||
|
}
|
||||||
330
eeprom_driver.c
Normal file
330
eeprom_driver.c
Normal file
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
142
eeprom_driver.h
Normal file
142
eeprom_driver.h
Normal file
@@ -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
|
||||||
399
twi_master_driver.c
Normal file
399
twi_master_driver.c
Normal file
@@ -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;
|
||||||
|
}
|
||||||
147
twi_master_driver.h
Normal file
147
twi_master_driver.h
Normal file
@@ -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 */
|
||||||
321
twi_slave_driver.c
Normal file
321
twi_slave_driver.c
Normal file
@@ -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;
|
||||||
|
}
|
||||||
135
twi_slave_driver.h
Normal file
135
twi_slave_driver.h
Normal file
@@ -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 */
|
||||||
Reference in New Issue
Block a user