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
Wire.cpp
- Committer:
- dotnfc
- Date:
- 2016-09-13
- Revision:
- 0:db8030e71f55
File content as of revision 0:db8030e71f55:
/* * 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