PN532 Driver library This library provides an abstract API to drive the pn532 nfc chip, with I2C/HSU/SPI interface. Its based on the Seeed Studio's Arduino version.
Dependents: PN532_ReadUid Nfctest2
Diff: Wire.cpp
- Revision:
- 0:db8030e71f55
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Wire.cpp Tue Sep 13 06:01:19 2016 +0000 @@ -0,0 +1,391 @@ +/* + * TwoWire.h + * Copyright (c) 2011 Cristian Maglie <c.maglie@bug.st>. + * All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +extern "C" { +#include <string.h> +} + +#include "Wire.h" + + + +#define EVENT_TIMEOUT 100 + + +TwoWire::TwoWire(I2C_TypeDef *_twi) : + twi(_twi), rxBufferIndex(0), rxBufferLength(0), txAddress(0), + txBufferLength(0), srvBufferIndex(0), srvBufferLength(0), status( + UNINITIALIZED){ + // Empty +} + +void TwoWire::begin(void) { + if (onBeginCallback) + onBeginCallback(); + + if (twi==I2C1) + { + RCC_I2CCLKConfig(RCC_I2C1CLK_HSI); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); + + pinMode(SDA, ALTERNATE); + pinMode(SCL, ALTERNATE); + } + else if (twi == I2C2) + { + RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); + + pinMode(SDA1, ALTERNATE); + pinMode(SCL1, ALTERNATE); + } + + + I2C_DeInit(twi); + + I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; + I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable; + I2C_InitStructure.I2C_DigitalFilter = 0x00; + if (status == UNINITIALIZED) + { + I2C_InitStructure.I2C_OwnAddress1 = 0x00; + status = MASTER_IDLE; + } + I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; + I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; + I2C_InitStructure.I2C_Timing = 0x00E0D3FF; + I2C_Init(twi, &I2C_InitStructure); + + I2C_Cmd(twi, ENABLE); + + +} + +void TwoWire::begin(uint8_t address) { + if (onBeginCallback) + onBeginCallback(); + status = SLAVE_IDLE; + if (twi==I2C1) + { + RCC_I2CCLKConfig(RCC_I2C1CLK_HSI); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); + + pinMode(SDA, ALTERNATE); + pinMode(SCL, ALTERNATE); + } + + + I2C_DeInit(twi); + + I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; + I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable; + I2C_InitStructure.I2C_DigitalFilter = 0x00; + I2C_InitStructure.I2C_OwnAddress1 = address; + I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; + I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; + I2C_InitStructure.I2C_Timing = 0x00E0D3FF; + I2C_Init(twi, &I2C_InitStructure); + + NVIC_SetPriority(I2C1_IRQn, 0); + NVIC_EnableIRQ(I2C1_IRQn); + I2C_Cmd(twi, ENABLE); + I2C_ITConfig(twi, I2C_IT_ADDRI, ENABLE); +} + +void TwoWire::begin(int address) { + address <<= 1; + begin((uint8_t) address); +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) { + address <<= 1; + if (quantity > BUFFER_LENGTH) + quantity = BUFFER_LENGTH; + uint32_t _millis; + + _millis = millis(); + while(I2C_GetFlagStatus(twi, I2C_FLAG_BUSY) != RESET) + { + if(EVENT_TIMEOUT < (millis() - _millis)) return 0; + } + + I2C_TransferHandling(twi, address, quantity, I2C_AutoEnd_Mode, I2C_Generate_Start_Read); + + + uint8_t *pBuffer = rxBuffer; + uint8_t numByteToRead = quantity; + uint8_t bytesRead = 0; + /* While there is data to be read */ + while(numByteToRead) + { + _millis = millis(); + while(I2C_GetFlagStatus(twi, I2C_FLAG_RXNE) == RESET) + { + if(EVENT_TIMEOUT < (millis() - _millis)) return 0; + } + /* Read a byte from the Slave */ + *pBuffer = I2C_ReceiveData(twi); + + bytesRead++; + + /* Point to the next location where the byte read will be saved */ + pBuffer++; + + /* Decrement the read bytes counter */ + numByteToRead--; + } + _millis = millis(); + while(I2C_GetFlagStatus(twi, I2C_FLAG_STOPF) == RESET) + { + if(EVENT_TIMEOUT < (millis() - _millis)) return 0; + } + // set rx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = bytesRead; + + return bytesRead; +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) { + return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity) { + return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) { + return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) sendStop); +} + +void TwoWire::beginTransmission(uint8_t address) { + status = MASTER_SEND; + + // save address of target and empty buffer + txAddress = address; + txBufferLength = 0; +} + +void TwoWire::beginTransmission(int address) { + address <<= 1; + beginTransmission((uint8_t) address); +} + +// +// Originally, 'endTransmission' was an f(void) function. +// It has been modified to take one parameter indicating +// whether or not a STOP should be performed on the bus. +// Calling endTransmission(false) allows a sketch to +// perform a repeated start. +// +// WARNING: Nothing in the library keeps track of whether +// the bus tenure has been properly ended with a STOP. It +// is very possible to leave the bus in a hung state if +// no call to endTransmission(true) is made. Some I2C +// devices will behave oddly if they do not see a STOP. +// +uint8_t TwoWire::endTransmission(uint8_t sendStop) { + uint32_t _millis; + + _millis = millis(); + while(I2C_GetFlagStatus(twi, I2C_FLAG_BUSY) != RESET) + { + if(EVENT_TIMEOUT < (millis() - _millis)) return 0; + } + if (sendStop == true) + { + I2C_TransferHandling(twi, txAddress, txBufferLength, I2C_AutoEnd_Mode, I2C_Generate_Start_Write); + } + else + { + I2C_TransferHandling(twi, txAddress, txBufferLength, I2C_SoftEnd_Mode, I2C_Generate_Start_Write); + } + uint8_t *pBuffer = txBuffer; + uint8_t NumByteToWrite = txBufferLength; + /* While there is data to be read */ + while(NumByteToWrite--) + { + _millis = millis(); + while(I2C_GetFlagStatus(twi, I2C_FLAG_TXIS) == RESET) + { + if(EVENT_TIMEOUT < (millis() - _millis)) return 0; + } + /* Send the current byte to slave */ + I2C_SendData(twi, *pBuffer++); + } + _millis = millis(); + if (sendStop == true) + { + while(I2C_GetFlagStatus(twi, I2C_FLAG_STOPF) == RESET) + { + if(EVENT_TIMEOUT < (millis() - _millis)) return 0; + } + } + else + { + while(I2C_GetFlagStatus(twi, I2C_FLAG_STOPF) == RESET) + { + if(EVENT_TIMEOUT < (millis() - _millis)) return 0; + } + } + // reset tx buffer iterator vars + txBufferLength = 0; + + status = MASTER_IDLE; + return 0; +} + +// This provides backwards compatibility with the original +// definition, and expected behaviour, of endTransmission +// +uint8_t TwoWire::endTransmission(void) +{ + return endTransmission(true); +} + +size_t TwoWire::write(uint8_t data) { + if (status == MASTER_SEND) { + if (txBufferLength >= BUFFER_LENGTH) + return 0; + txBuffer[txBufferLength++] = data; + return 1; + } else { + if (srvBufferLength >= BUFFER_LENGTH) + return 0; + srvBuffer[srvBufferLength++] = data; + return 1; + } +} + +size_t TwoWire::write(const uint8_t *data, size_t quantity) { + if (status == MASTER_SEND) { + for (size_t i = 0; i < quantity; ++i) { + if (txBufferLength >= BUFFER_LENGTH) + return i; + txBuffer[txBufferLength++] = data[i]; + } + } else { + for (size_t i = 0; i < quantity; ++i) { + if (srvBufferLength >= BUFFER_LENGTH) + return i; + srvBuffer[srvBufferLength++] = data[i]; + } + } + return quantity; +} + +int TwoWire::available(void) { + return rxBufferLength - rxBufferIndex; +} + +int TwoWire::read(void) { + if (rxBufferIndex < rxBufferLength) + return rxBuffer[rxBufferIndex++]; + return -1; +} + +int TwoWire::peek(void) { + if (rxBufferIndex < rxBufferLength) + return rxBuffer[rxBufferIndex]; + return -1; +} + +void TwoWire::flush(void) { + // Do nothing, use endTransmission(..) to force + // data transfer. +} + +void TwoWire::onReceive(void(*function)(int)) { + onReceiveCallback = function; +} + +void TwoWire::onRequest(void(*function)(void)) { + onRequestCallback = function; +} + +void TwoWire::onService(void) +{ + if (I2C_GetITStatus(twi, I2C_IT_ADDR) == SET) + { + I2C_ITConfig(twi, I2C_IT_RXI | I2C_IT_TXI | I2C_IT_STOPI, ENABLE); + srvBufferLength = 0; + srvBufferIndex = 0; + if (twi->ISR & (1 << 16)) { + status = SLAVE_SEND; + if (onRequestCallback) + onRequestCallback(); + } else { + status = SLAVE_RECV; + } + + I2C_ClearITPendingBit(twi, I2C_IT_ADDR); + } + if (I2C_GetITStatus(twi, I2C_IT_TXIS) == SET) + { + uint8_t c = 'x'; + if (srvBufferIndex < srvBufferLength) + c = srvBuffer[srvBufferIndex++]; + I2C_SendData(twi, c); + } + if (I2C_GetITStatus(twi, I2C_IT_RXNE) == SET) + { + if (srvBufferLength < BUFFER_LENGTH) + srvBuffer[srvBufferLength++] = I2C_ReceiveData(twi); + } + if (I2C_GetITStatus(twi, I2C_IT_STOPF) == SET) + { + if (status == SLAVE_RECV && onReceiveCallback) { + // Copy data into rxBuffer + // (allows to receive another packet while the + // user program reads actual data) + for (uint8_t i = 0; i < srvBufferLength; ++i) + rxBuffer[i] = srvBuffer[i]; + rxBufferIndex = 0; + rxBufferLength = srvBufferLength; + // Alert calling program + onReceiveCallback( rxBufferLength); + } + I2C_ITConfig(twi, I2C_IT_ADDRI, ENABLE); + I2C_ITConfig(twi, I2C_IT_RXI | I2C_IT_TXI | I2C_IT_STOPI, DISABLE); + I2C_ClearITPendingBit(twi, I2C_IT_STOPF); + } +} + + + + +TwoWire Wire = TwoWire(I2C1); +TwoWire Wire1 = TwoWire(I2C2); + +#ifdef __cplusplus +extern "C" { +#endif +void WIRE_ISR_HANDLER(void) { + Wire.onService(); +} + +void WIRE1_ISR_HANDLER(void) { + Wire1.onService(); +} +#ifdef __cplusplus +} +#endif + + +