From 217ddb1e32dcb4cde11ecca88418be428895f2dc Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Sun, 22 Dec 2013 16:44:10 +0100 Subject: Makefile separator errors fixed --- twi_master_driver.c | 399 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 twi_master_driver.c (limited to 'twi_master_driver.c') 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; +} -- cgit v1.2.3