Commit f83b6edb authored by Sandeep Mistry's avatar Sandeep Mistry

Functional Wire

parent 9a7fa4f8
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
#define NRF_TWIS_H__ #define NRF_TWIS_H__
#include "nrf.h" #include "nrf.h"
#ifndef ARDUINO
#include "nrf_drv_config.h" #include "nrf_drv_config.h"
#endif
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
......
/*
* TWI/I2C library for Arduino Zero
* Copyright (c) 2015 Arduino LLC. 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 "nrf_gpio.h"
#include <Arduino.h>
#include <wiring_private.h>
#include "Wire.h"
TwoWire::TwoWire(NRF_TWIM_Type * p_twim, NRF_TWIS_Type * p_twis, IRQn_Type IRQn, uint8_t pinSDA, uint8_t pinSCL)
{
this->_p_twim = p_twim;
this->_p_twis = p_twis;
this->_IRQn = IRQn;
this->_uc_pinSDA=pinSDA;
this->_uc_pinSCL=pinSCL;
transmissionBegun = false;
}
void TwoWire::begin(void) {
//Master Mode
master = true;
nrf_gpio_cfg(_uc_pinSCL, NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_NOSENSE);
nrf_gpio_cfg(_uc_pinSDA, NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_NOSENSE);
nrf_twim_frequency_set(_p_twim, NRF_TWIM_FREQ_100K);
nrf_twim_enable(_p_twim);
nrf_twim_pins_set(_p_twim, _uc_pinSCL, _uc_pinSDA);
NVIC_ClearPendingIRQ(_IRQn);
NVIC_SetPriority(_IRQn, 2);
NVIC_EnableIRQ(_IRQn);
}
void TwoWire::begin(uint8_t address) {
//Slave mode
master = false;
nrf_gpio_cfg(_uc_pinSCL, NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_NOSENSE);
nrf_gpio_cfg(_uc_pinSDA, NRF_GPIO_PIN_DIR_INPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_NOSENSE);
nrf_twis_address_set(_p_twis, 0, address);
nrf_twis_config_address_set(_p_twis, NRF_TWIS_CONFIG_ADDRESS0_MASK);
nrf_twis_pins_set(_p_twis, _uc_pinSCL, _uc_pinSDA);
nrf_twis_orc_set(_p_twis, 0xff);
nrf_twis_int_enable(_p_twis, NRF_TWIS_INT_STOPPED_MASK | NRF_TWIS_INT_ERROR_MASK | NRF_TWIS_INT_WRITE_MASK | NRF_TWIS_INT_READ_MASK);
NVIC_ClearPendingIRQ(_IRQn);
NVIC_SetPriority(_IRQn, 2);
NVIC_EnableIRQ(_IRQn);
nrf_twis_enable(_p_twis);
}
void TwoWire::setClock(uint32_t baudrate) {
if (master) {
nrf_twim_disable(_p_twim);
nrf_twim_frequency_t frequency;
if (baudrate <= 100000)
{
frequency = NRF_TWIM_FREQ_100K;
}
else if (baudrate <= 250000)
{
frequency = NRF_TWIM_FREQ_250K;
}
else
{
frequency = NRF_TWIM_FREQ_400K;
}
nrf_twim_frequency_set(_p_twim, frequency);
nrf_twim_enable(_p_twim);
}
}
void TwoWire::end() {
if (master)
{
nrf_twim_disable(_p_twim);
}
else
{
nrf_twis_disable(_p_twis);
}
}
uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
{
if(quantity == 0)
{
return 0;
}
size_t byteRead = 0;
rxBuffer.clear();
nrf_twim_address_set(_p_twim, address);
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_RESUME);
nrf_twim_rx_buffer_set(_p_twim, rxBuffer._aucBuffer, quantity);
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_STARTRX);
while(!nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_RXSTARTED) && !nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_ERROR));
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_RXSTARTED);
while(!nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_LASTRX) && !nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_ERROR));
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_LASTRX);
if (stopBit || nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_ERROR))
{
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_STOP);
while(!nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_STOPPED));
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_STOPPED);
}
else
{
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_SUSPEND);
while(!nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_SUSPENDED));
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_SUSPENDED);
}
if (nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_ERROR))
{
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_ERROR);
}
byteRead = rxBuffer._iHead = nrf_twim_rxd_amount_get(_p_twim);
return byteRead;
}
uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity)
{
return requestFrom(address, quantity, true);
}
void TwoWire::beginTransmission(uint8_t address) {
// save address of target and clear buffer
txAddress = address;
txBuffer.clear();
transmissionBegun = true;
}
// Errors:
// 0 : Success
// 1 : Data too long
// 2 : NACK on transmit of address
// 3 : NACK on transmit of data
// 4 : Other error
uint8_t TwoWire::endTransmission(bool stopBit)
{
transmissionBegun = false ;
// Start I2C transmission
nrf_twim_address_set(_p_twim, txAddress);
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_RESUME);
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_STARTTX);
nrf_twim_tx_buffer_set(_p_twim, txBuffer._aucBuffer, txBuffer.available());
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_STARTTX);
while(!nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_TXSTARTED) && !nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_ERROR));
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_TXSTARTED);
while(!nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_LASTTX) && !nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_ERROR));
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_LASTTX);
if (stopBit || nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_ERROR))
{
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_STOP);
while(!nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_STOPPED));
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_STOPPED);
}
else
{
nrf_twim_task_trigger(_p_twim, NRF_TWIM_TASK_SUSPEND);
while(!nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_SUSPENDED));
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_SUSPENDED);
}
if (nrf_twim_event_check(_p_twim, NRF_TWIM_EVENT_ERROR))
{
nrf_twim_event_clear(_p_twim, NRF_TWIM_EVENT_ERROR);
uint32_t error = nrf_twim_errorsrc_get_and_clear(_p_twim);
if (error == NRF_TWIM_ERROR_ADDRESS_NACK)
{
return 2;
}
else if (error == NRF_TWIM_ERROR_DATA_NACK)
{
return 3;
}
else
{
return 4;
}
}
return 0;
}
uint8_t TwoWire::endTransmission()
{
return endTransmission(true);
}
size_t TwoWire::write(uint8_t ucData)
{
// No writing, without begun transmission or a full buffer
if ( !transmissionBegun || txBuffer.isFull() )
{
return 0 ;
}
txBuffer.store_char( ucData ) ;
return 1 ;
}
size_t TwoWire::write(const uint8_t *data, size_t quantity)
{
//Try to store all data
for(size_t i = 0; i < quantity; ++i)
{
//Return the number of data stored, when the buffer is full (if write return 0)
if(!write(data[i]))
return i;
}
//All data stored
return quantity;
}
int TwoWire::available(void)
{
return rxBuffer.available();
}
int TwoWire::read(void)
{
return rxBuffer.read_char();
}
int TwoWire::peek(void)
{
return rxBuffer.peek();
}
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 (nrf_twis_event_get_and_clear(_p_twis, NRF_TWIS_EVENT_WRITE))
{
receiving = true;
nrf_twis_rx_prepare(_p_twis, rxBuffer._aucBuffer, sizeof(rxBuffer._aucBuffer));
}
if (nrf_twis_event_get_and_clear(_p_twis, NRF_TWIS_EVENT_READ))
{
receiving = false;
transmissionBegun = true;
txBuffer.clear();
if (onRequestCallback)
{
onRequestCallback();
}
transmissionBegun = false;
nrf_twis_tx_prepare(_p_twis, txBuffer._aucBuffer, txBuffer.available());
}
if (nrf_twis_event_get_and_clear(_p_twis, NRF_TWIS_EVENT_STOPPED))
{
if (receiving)
{
int rxAmount = nrf_twis_rx_amount_get(_p_twis);
rxBuffer._iHead = rxAmount;
if (onReceiveCallback)
{
onReceiveCallback(rxAmount);
}
}
}
if (nrf_twis_event_get_and_clear(_p_twis, NRF_TWIS_EVENT_ERROR))
{
nrf_twis_error_source_get_and_clear(_p_twis);
nrf_twis_task_trigger(_p_twis, NRF_TWIS_TASK_STOP);
}
}
TwoWire Wire(NRF_TWIM0, NRF_TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 26, 27);
extern "C"
{
void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void)
{
Wire.onService();
}
}
/*
* TWI/I2C library for Arduino Zero
* Copyright (c) 2015 Arduino LLC. 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
*/
#ifndef TwoWire_h
#define TwoWire_h
#include "nrf_twi.h"
#include "nrf_twim.h"
#include "nrf_twis.h"
#include "Stream.h"
#include "variant.h"
#include "RingBuffer.h"
#define BUFFER_LENGTH 32
// WIRE_HAS_END means Wire has end()
#define WIRE_HAS_END 1
class TwoWire : public Stream
{
public:
TwoWire(NRF_TWIM_Type * p_twim, NRF_TWIS_Type * p_twis, IRQn_Type IRQn, uint8_t pinSDA, uint8_t pinSCL);
void begin();
void begin(uint8_t);
void end();
void setClock(uint32_t);
void beginTransmission(uint8_t);
uint8_t endTransmission(bool stopBit);
uint8_t endTransmission(void);
uint8_t requestFrom(uint8_t address, size_t quantity, bool stopBit);
uint8_t requestFrom(uint8_t address, size_t quantity);
size_t write(uint8_t data);
size_t write(const uint8_t * data, size_t quantity);
virtual int available(void);
virtual int read(void);
virtual int peek(void);
virtual void flush(void);
void onReceive(void(*)(int));
void onRequest(void(*)(void));
using Print::write;
void onService(void);
private:
NRF_TWIM_Type * _p_twim;
NRF_TWIS_Type * _p_twis;
IRQn_Type _IRQn;
uint8_t _uc_pinSDA;
uint8_t _uc_pinSCL;
bool master;
bool receiving;
bool transmissionBegun;
// RX Buffer
RingBuffer rxBuffer;
//TX buffer
RingBuffer txBuffer;
uint8_t txAddress;
// Callback user functions
void (*onRequestCallback)(void);
void (*onReceiveCallback)(int);
// TWI clock frequency
static const uint32_t TWI_CLOCK = 100000;
};
extern TwoWire Wire;
#endif
// I2C SRF10 or SRF08 Devantech Ultrasonic Ranger Finder
// by Nicholas Zambetti <http://www.zambetti.com>
// and James Tichenor <http://www.jamestichenor.net>
// Demonstrates use of the Wire library reading data from the
// Devantech Utrasonic Rangers SFR08 and SFR10
// Created 29 April 2006
// This example code is in the public domain.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial communication at 9600bps
}
int reading = 0;
void loop()
{
// step 1: instruct sensor to read echoes
Wire.beginTransmission(112); // transmit to device #112 (0x70)
// the address specified in the datasheet is 224 (0xE0)
// but i2c adressing uses the high 7 bits so it's 112
Wire.write(byte(0x00)); // sets register pointer to the command register (0x00)
Wire.write(byte(0x50)); // command sensor to measure in "inches" (0x50)
// use 0x51 for centimeters
// use 0x52 for ping microseconds
Wire.endTransmission(); // stop transmitting
// step 2: wait for readings to happen
delay(70); // datasheet suggests at least 65 milliseconds
// step 3: instruct sensor to return a particular echo reading
Wire.beginTransmission(112); // transmit to device #112
Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02)
Wire.endTransmission(); // stop transmitting
// step 4: request reading from sensor
Wire.requestFrom(112, 2); // request 2 bytes from slave device #112
// step 5: receive reading from sensor
if(2 <= Wire.available()) // if two bytes were received
{
reading = Wire.read(); // receive high byte (overwrites previous reading)
reading = reading << 8; // shift high byte to be high 8 bits
reading |= Wire.read(); // receive low byte as lower 8 bits
Serial.println(reading); // print the reading
}
delay(250); // wait a bit since people have to read the output :)
}
/*
// The following code changes the address of a Devantech Ultrasonic Range Finder (SRF10 or SRF08)
// usage: changeAddress(0x70, 0xE6);
void changeAddress(byte oldAddress, byte newAddress)
{
Wire.beginTransmission(oldAddress);
Wire.write(byte(0x00));
Wire.write(byte(0xA0));
Wire.endTransmission();
Wire.beginTransmission(oldAddress);
Wire.write(byte(0x00));
Wire.write(byte(0xAA));
Wire.endTransmission();
Wire.beginTransmission(oldAddress);
Wire.write(byte(0x00));
Wire.write(byte(0xA5));
Wire.endTransmission();
Wire.beginTransmission(oldAddress);
Wire.write(byte(0x00));
Wire.write(newAddress);
Wire.endTransmission();
}
*/
// I2C Digital Potentiometer
// by Nicholas Zambetti <http://www.zambetti.com>
// and Shawn Bonkowski <http://people.interaction-ivrea.it/s.bonkowski/>
// Demonstrates use of the Wire library
// Controls AD5171 digital potentiometer via I2C/TWI
// Created 31 March 2006
// This example code is in the public domain.
// This example code is in the public domain.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
}
byte val = 0;
void loop()
{
Wire.beginTransmission(44); // transmit to device #44 (0x2c)
// device address is specified in datasheet
Wire.write(byte(0x00)); // sends instruction byte
Wire.write(val); // sends potentiometer value byte
Wire.endTransmission(); // stop transmitting
val++; // increment value
if(val == 64) // if reached 64th position (max)
{
val = 0; // start over from lowest value
}
delay(500);
}
// Wire Master Reader
// by Nicholas Zambetti <http://www.zambetti.com>
// Demonstrates use of the Wire library
// Reads data from an I2C/TWI slave device
// Refer to the "Wire Slave Sender" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop()
{
Wire.requestFrom(2, 6); // request 6 bytes from slave device #2
while(Wire.available()) // slave may send less than requested
{
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(500);
}
// Wire Master Writer
// by Nicholas Zambetti <http://www.zambetti.com>
// Demonstrates use of the Wire library
// Writes data to an I2C/TWI slave device
// Refer to the "Wire Slave Receiver" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
}
byte x = 0;
void loop()
{
Wire.beginTransmission(4); // transmit to device #4
Wire.write("x is "); // sends five bytes
Wire.write(x); // sends one byte
Wire.endTransmission(); // stop transmitting
x++;
delay(500);
}
// Wire Slave Receiver
// by Nicholas Zambetti <http://www.zambetti.com>
// Demonstrates use of the Wire library
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
void setup()
{
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
}
void loop()
{
delay(100);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
while(1 < Wire.available()) // loop through all but the last
{
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}
// Wire Slave Sender
// by Nicholas Zambetti <http://www.zambetti.com>
// Demonstrates use of the Wire library
// Sends data as an I2C/TWI slave device
// Refer to the "Wire Master Reader" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
void setup()
{
Wire.begin(2); // join i2c bus with address #2
Wire.onRequest(requestEvent); // register event
}
void loop()
{
delay(100);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
Wire.write("hello "); // respond with message of 6 bytes
// as expected by master
}
#######################################
# Syntax Coloring Map For Wire
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
beginTransmission KEYWORD2
endTransmission KEYWORD2
requestFrom KEYWORD2
onReceive KEYWORD2
onRequest KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
Wire KEYWORD2
Wire1 KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
name=Wire
version=1.0
author=
maintainer=
sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. Specific implementation for nRF52.
paragraph=
category=Communication
url=http://www.arduino.cc/en/Reference/Wire
architectures=nRF52
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment