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_slave_driver.c | 321 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 twi_slave_driver.c (limited to 'twi_slave_driver.c') diff --git a/twi_slave_driver.c b/twi_slave_driver.c new file mode 100644 index 0000000..d6eecc2 --- /dev/null +++ b/twi_slave_driver.c @@ -0,0 +1,321 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * XMEGA TWI slave driver source file. + * + * This file contains the function implementations the XMEGA TWI slave + * driver. + * + * The driver is not intended for size and/or speed critical code, since + * most functions are just a few lines of code, and the function call + * overhead would decrease code performance. The driver is intended for + * rapid prototyping and documentation purposes for getting started with + * the XMEGA TWI slave module. + * + * For size and/or speed critical code, it is recommended to copy the + * function contents directly into your application instead of making + * a function call. + * + * Several functions use the following construct: + * "some_register = ... | (some_parameter ? SOME_BIT_bm : 0) | ..." + * Although the use of the ternary operator ( if ? then : else ) is + * discouraged, in some occasions the operator makes it possible to write + * pretty clean and neat code. In this driver, the construct is used to + * set or not set a configuration bit based on a boolean input parameter, + * such as the "some_parameter" in the example above. + * + * \par Application note: + * AVR1308: Using the XMEGA TWI + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * $Revision: 2660 $ + * $Date: 2009-08-11 12:28:58 +0200 (ti, 11 aug 2009) $ \n + * + * Copyright (c) 2008, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "twi_slave_driver.h" + + +/*! \brief Initalizes TWI slave driver structure. + * + * Initialize the instance of the TWI Slave and set the appropriate values. + * + * \param twi The TWI_Slave_t struct instance. + * \param module Pointer to the TWI module. + * \param processDataFunction Pointer to the function that handles incoming data. + */ +void TWI_SlaveInitializeDriver(TWI_Slave_t *twi, + TWI_t *module, + void (*processDataFunction) (void)) +{ + twi->interface = module; + twi->Process_Data = processDataFunction; + twi->bytesReceived = 0; + twi->bytesSent = 0; + twi->status = TWIS_STATUS_READY; + twi->result = TWIS_RESULT_UNKNOWN; + twi->abort = false; +} + + +/*! \brief Initialize the TWI module. + * + * Enables interrupts on address recognition and data available. + * Remember to enable interrupts globally from the main application. + * + * \param twi The TWI_Slave_t struct instance. + * \param address Slave address for this module. + * \param intLevel Interrupt level for the TWI slave interrupt handler. + */ +void TWI_SlaveInitializeModule(TWI_Slave_t *twi, + uint8_t address, + TWI_SLAVE_INTLVL_t intLevel) +{ + twi->interface->SLAVE.CTRLA = intLevel | + TWI_SLAVE_DIEN_bm | + TWI_SLAVE_APIEN_bm | + TWI_SLAVE_ENABLE_bm; + twi->interface->SLAVE.ADDR = (address<<1); +} + + +/*! \brief Common TWI slave interrupt service routine. + * + * Handles all TWI transactions and responses to address match, data reception, + * data transmission, bus error and data collision. + * + * \param twi The TWI_Slave_t struct instance. + */ +void TWI_SlaveInterruptHandler(TWI_Slave_t *twi) +{ + uint8_t currentStatus = twi->interface->SLAVE.STATUS; + + /* If bus error. */ + if (currentStatus & TWI_SLAVE_BUSERR_bm) { + twi->bytesReceived = 0; + twi->bytesSent = 0; + twi->result = TWIS_RESULT_BUS_ERROR; + twi->status = TWIS_STATUS_READY; + } + + /* If transmit collision. */ + else if (currentStatus & TWI_SLAVE_COLL_bm) { + twi->bytesReceived = 0; + twi->bytesSent = 0; + twi->result = TWIS_RESULT_TRANSMIT_COLLISION; + twi->status = TWIS_STATUS_READY; + } + + /* If address match. */ + else if ((currentStatus & TWI_SLAVE_APIF_bm) && + (currentStatus & TWI_SLAVE_AP_bm)) { + + TWI_SlaveAddressMatchHandler(twi); + } + + /* If stop (only enabled through slave read transaction). */ + else if (currentStatus & TWI_SLAVE_APIF_bm) { + TWI_SlaveStopHandler(twi); + } + + /* If data interrupt. */ + else if (currentStatus & TWI_SLAVE_DIF_bm) { + TWI_SlaveDataHandler(twi); + } + + /* If unexpected state. */ + else { + TWI_SlaveTransactionFinished(twi, TWIS_RESULT_FAIL); + } +} + +/*! \brief TWI address match interrupt handler. + * + * Prepares TWI module for transaction when an address match occures. + * + * \param twi The TWI_Slave_t struct instance. + */ +void TWI_SlaveAddressMatchHandler(TWI_Slave_t *twi) +{ + /* If application signalling need to abort (error occured). */ + if (twi->abort) { + twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; + TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED); + twi->abort = false; + } else { + twi->status = TWIS_STATUS_BUSY; + twi->result = TWIS_RESULT_UNKNOWN; + + /* Disable stop interrupt. */ + uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; + twi->interface->SLAVE.CTRLA = currentCtrlA & ~TWI_SLAVE_PIEN_bm; + + twi->bytesReceived = 0; + twi->bytesSent = 0; + + /* Send ACK, wait for data interrupt. */ + twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; + } +} + + +/*! \brief TWI stop condition interrupt handler. + * + * \param twi The TWI_Slave_t struct instance. + */ +void TWI_SlaveStopHandler(TWI_Slave_t *twi) +{ + /* Disable stop interrupt. */ + uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; + twi->interface->SLAVE.CTRLA = currentCtrlA & ~TWI_SLAVE_PIEN_bm; + + /* Clear APIF, according to flowchart don't ACK or NACK */ + uint8_t currentStatus = twi->interface->SLAVE.STATUS; + twi->interface->SLAVE.STATUS = currentStatus | TWI_SLAVE_APIF_bm; + + TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK); + +} + + +/*! \brief TWI data interrupt handler. + * + * Calls the appropriate slave read or write handler. + * + * \param twi The TWI_Slave_t struct instance. + */ +void TWI_SlaveDataHandler(TWI_Slave_t *twi) +{ + if (twi->interface->SLAVE.STATUS & TWI_SLAVE_DIR_bm) { + TWI_SlaveWriteHandler(twi); + } else { + TWI_SlaveReadHandler(twi); + } +} + + +/*! \brief TWI slave read interrupt handler. + * + * Handles TWI slave read transactions and responses. + * + * \param twi The TWI_Slave_t struct instance. + */ +void TWI_SlaveReadHandler(TWI_Slave_t *twi) +{ + /* Enable stop interrupt. */ + uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; + twi->interface->SLAVE.CTRLA = currentCtrlA | TWI_SLAVE_PIEN_bm; + + /* If free space in buffer. */ + if (twi->bytesReceived < TWIS_RECEIVE_BUFFER_SIZE) { + /* Fetch data */ + uint8_t data = twi->interface->SLAVE.DATA; + twi->receivedData[twi->bytesReceived] = data; + + /* Process data. */ + twi->Process_Data(); + + twi->bytesReceived++; + + /* If application signalling need to abort (error occured), + * complete transaction and wait for next START. Otherwise + * send ACK and wait for data interrupt. + */ + if (twi->abort) { + twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; + TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED); + twi->abort = false; + } else { + twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; + } + } + /* If buffer overflow, send NACK and wait for next START. Set + * result buffer overflow. + */ + else { + twi->interface->SLAVE.CTRLB = TWI_SLAVE_ACKACT_bm | + TWI_SLAVE_CMD_COMPTRANS_gc; + TWI_SlaveTransactionFinished(twi, TWIS_RESULT_BUFFER_OVERFLOW); + } +} + + +/*! \brief TWI slave write interrupt handler. + * + * Handles TWI slave write transactions and responses. + * + * \param twi The TWI_Slave_t struct instance. + */ +void TWI_SlaveWriteHandler(TWI_Slave_t *twi) +{ + /* If NACK, slave write transaction finished. */ + if ((twi->bytesSent > 0) && (twi->interface->SLAVE.STATUS & + TWI_SLAVE_RXACK_bm)) { + + twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; + TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK); + } + /* If ACK, master expects more data. */ + else { + if (twi->bytesSent < TWIS_SEND_BUFFER_SIZE) { + uint8_t data = twi->sendData[twi->bytesSent]; + twi->interface->SLAVE.DATA = data; + twi->bytesSent++; + + /* Send data, wait for data interrupt. */ + twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; + } + /* If buffer overflow. */ + else { + twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; + TWI_SlaveTransactionFinished(twi, TWIS_RESULT_BUFFER_OVERFLOW); + } + } +} + + +/*! \brief TWI transaction finished function. + * + * Prepares module for new transaction. + * + * \param twi The TWI_Slave_t struct instance. + * \param result The result of the transaction. + */ +void TWI_SlaveTransactionFinished(TWI_Slave_t *twi, uint8_t result) +{ + twi->result = result; + twi->status = TWIS_STATUS_READY; +} -- cgit v1.2.3