Merged with Wire implementation from stm32duino/Arduino_Core_STM32
This commit is contained in:
parent
78f8a90a2d
commit
b46b7461f4
|
@ -15,7 +15,7 @@
|
|||
void setup()
|
||||
{
|
||||
Wire.begin(); // join i2c bus (address optional for master)
|
||||
Serial.begin(9600); // start serial communication at 9600bps
|
||||
Serial.begin(115200); // start serial communication at 9600bps
|
||||
}
|
||||
|
||||
int reading = 0;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
#include <Wire_slave.h>
|
||||
#include <Arduino.h>
|
||||
#include <libmaple/i2c.h>
|
||||
|
||||
#define USE_BUFFERED_EXAMPLE 1
|
||||
|
||||
|
@ -52,12 +51,8 @@ void functx(i2c_msg *msg){
|
|||
|
||||
#endif
|
||||
|
||||
// #define Serial Serial1
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while(!Serial)
|
||||
;
|
||||
Serial.println("I2C Slave example");
|
||||
|
||||
// attach the buffer
|
|
@ -0,0 +1,78 @@
|
|||
// --------------------------------------
|
||||
// i2c_scanner
|
||||
//
|
||||
// Version 1
|
||||
// This program (or code that looks like it)
|
||||
// can be found in many places.
|
||||
// For example on the Arduino.cc forum.
|
||||
// The original author is not know.
|
||||
// Version 2, Juni 2012, Using Arduino 1.0.1
|
||||
// Adapted to be as simple as possible by Arduino.cc user Krodal
|
||||
// Version 3, Feb 26 2013
|
||||
// V3 by louarnold
|
||||
// Version 4, March 3, 2013, Using Arduino 1.0.3
|
||||
// by Arduino.cc user Krodal.
|
||||
// Changes by louarnold removed.
|
||||
// Scanning addresses changed from 0...127 to 1...119,
|
||||
// according to the i2c scanner by Nick Gammon
|
||||
// http://www.gammon.com.au/forum/?id=10896
|
||||
// Version 5, March 28, 2013
|
||||
// As version 4, but address scans now to 127.
|
||||
// A sensor seems to use address 120.
|
||||
//
|
||||
// This sketch tests the standard 7-bit addresses
|
||||
// Devices with higher bit address might not be seen properly.
|
||||
//
|
||||
|
||||
#include <Wire_slave.h>
|
||||
|
||||
//use IIC2
|
||||
//TwoWire WIRE2 (2,I2C_FAST_MODE);
|
||||
//#define Wire WIRE2
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
Wire.begin();
|
||||
Serial.println("\nI2C Scanner");
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
byte error, address;
|
||||
int nDevices;
|
||||
|
||||
Serial.println("Scanning...");
|
||||
|
||||
nDevices = 0;
|
||||
for(address = 1; address < 127; address++) {
|
||||
// The i2c_scanner uses the return value of
|
||||
// the Write.endTransmisstion to see if
|
||||
// a device did acknowledge to the address.
|
||||
|
||||
Wire.beginTransmission(address);
|
||||
error = Wire.endTransmission();
|
||||
|
||||
if (error == 0) {
|
||||
Serial.print("I2C device found at address 0x");
|
||||
if (address < 16)
|
||||
Serial.print("0");
|
||||
Serial.println(address, HEX);
|
||||
|
||||
nDevices++;
|
||||
}
|
||||
else if (error == 4) {
|
||||
Serial.print("Unknown error at address 0x");
|
||||
if (address < 16)
|
||||
Serial.print("0");
|
||||
Serial.println(address, HEX);
|
||||
}
|
||||
}
|
||||
if (nDevices == 0)
|
||||
Serial.println("No I2C devices found");
|
||||
else
|
||||
Serial.println("done");
|
||||
|
||||
delay(5000); // wait 5 seconds for next scan
|
||||
}
|
|
@ -15,12 +15,12 @@
|
|||
void setup()
|
||||
{
|
||||
Wire.begin(); // join i2c bus (address optional for master)
|
||||
Serial.begin(9600); // start serial for output
|
||||
Serial.begin(115200); // start serial for output
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
Wire.requestFrom(2, 6); // request 6 bytes from slave device #2
|
||||
Wire.requestFrom(8, 6); // request 6 bytes from slave device #8
|
||||
|
||||
while(Wire.available()) // slave may send less than requested
|
||||
{
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
// 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_slave.h>
|
||||
//#define Serial Serial1
|
||||
|
||||
#define MasterWire Wire
|
||||
#define SlaveWire Wire1
|
||||
#define ENABLE_SLAVE
|
||||
#define ENABLE_MASTER
|
||||
|
||||
void receiveEvent(int howMany);
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200); // start serial for output
|
||||
|
||||
#ifdef ENABLE_MASTER
|
||||
MasterWire.begin(); // join i2c bus #1 as master
|
||||
Serial.println("Done with MasterWire.begin ");
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SLAVE
|
||||
SlaveWire.begin(4); // join i2c bus #2 as slave with address #4
|
||||
Serial.println("Done with SlaveWire.begin ");
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SLAVE
|
||||
SlaveWire.onReceive(receiveEvent); // register event
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop(){
|
||||
#ifdef ENABLE_MASTER
|
||||
static byte x = 0;
|
||||
Serial.print("Master writing ");
|
||||
Serial.println(x);
|
||||
|
||||
MasterWire.beginTransmission(4); // transmit to device #4
|
||||
MasterWire.write("x is "); // sends five bytes
|
||||
MasterWire.write(x); // sends one byte
|
||||
MasterWire.endTransmission(); // stop transmitting
|
||||
|
||||
x++;
|
||||
#endif
|
||||
delay(500);
|
||||
}
|
||||
|
||||
// function that executes whenever data is received from master
|
||||
// this function is registered as an event, see setup()
|
||||
// Note that it is not advicable to call Serial.print() from within an ISR
|
||||
void receiveEvent(int howMany){
|
||||
//Serial.print("Slave receving ");
|
||||
while(1 < SlaveWire.available()){ // loop through all but the last
|
||||
char c = SlaveWire.read(); // receive byte as a character
|
||||
Serial.print(c); // print the character
|
||||
}
|
||||
int x = SlaveWire.read(); // receive byte as an integer
|
||||
Serial.println(x); // print the integer
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// 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.
|
||||
|
||||
// The code is temporarily moved to the code.cpp.
|
||||
// This makes it possible to set breakpoints in eclipse IDE.
|
||||
// I'm sure that there is an Eclipse configuration that makes it
|
||||
// possible for it to detect .ino files as .cpp, but I'm lazy
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// 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_slave.h>
|
||||
#define Serial Serial1
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200); // start serial for output
|
||||
|
||||
Wire.begin(4); // join i2c bus with address #4
|
||||
Wire.onReceive(receiveEvent); // register event
|
||||
}
|
||||
|
||||
void loop(){
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// function that executes whenever data is received from master
|
||||
// this function is registered as an event, see setup()
|
||||
// Note that it is not advicable to call Serial.print() from within an ISR
|
||||
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
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// 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_slave.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
Wire.begin(8); // join i2c bus with address #8
|
||||
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
|
||||
}
|
|
@ -1,106 +1,523 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file TwoWire.cpp
|
||||
* @author Trystan Jones <crenn6977@gmail.com>
|
||||
* @brief Wire library, uses the hardware I2C available in the Maple to
|
||||
* interact with I2C slave devices.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Library created by crenn to use the new WireBase system and allow Arduino
|
||||
* users easy interaction with the I2C Hardware in a familiar method.
|
||||
TwoWire.cpp - TWI/I2C library for Wiring & Arduino
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
}
|
||||
|
||||
#include "Wire_slave.h"
|
||||
#include "wirish.h"
|
||||
#include <libmaple/i2c_slave.h>
|
||||
|
||||
uint8 TwoWire::process(uint8 stop) {
|
||||
int8 res = i2c_master_xfer(sel_hard, &itc_msg, 1, 0);
|
||||
if (res == I2C_ERROR_PROTOCOL) {
|
||||
if (sel_hard->error_flags & I2C_SR1_AF) { /* NACK */
|
||||
res = (sel_hard->error_flags & I2C_SR1_ADDR ? ENACKADDR :
|
||||
ENACKTRNS);
|
||||
} else if (sel_hard->error_flags & I2C_SR1_OVR) { /* Over/Underrun */
|
||||
res = EDATA;
|
||||
} else { /* Bus or Arbitration error */
|
||||
res = EOTHER;
|
||||
}
|
||||
i2c_disable(sel_hard);
|
||||
i2c_master_enable(sel_hard, (I2C_BUS_RESET | dev_flags));
|
||||
}
|
||||
return res;
|
||||
#define BUFFER_LENGTH 32
|
||||
|
||||
#define MASTER_ADDRESS 0x33
|
||||
// Constructors ////////////////////////////////////////////////////////////////
|
||||
|
||||
TwoWire::TwoWire(i2c_dev* i2cDevice) :
|
||||
sel_hard(i2cDevice),
|
||||
rxBuffer(nullptr),
|
||||
rxBufferAllocated(0),
|
||||
rxBufferIndex(0),
|
||||
rxBufferLength(0),
|
||||
txBuffer(nullptr),
|
||||
txBufferAllocated(0),
|
||||
txBufferIndex(0),
|
||||
txBufferLength(0),
|
||||
transmitting(false),
|
||||
master(true),
|
||||
dev_flags(0),
|
||||
itc_msg(),
|
||||
itc_slave_msg(),
|
||||
user_onRequest(nullptr),
|
||||
user_onReceive(nullptr) {
|
||||
}
|
||||
|
||||
uint8 TwoWire::process(){
|
||||
return process(true);
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
void TwoWire::begin(void) {
|
||||
begin(MASTER_ADDRESS);
|
||||
}
|
||||
|
||||
// TODO: Add in Error Handling if devsel is out of range for other Maples
|
||||
TwoWire::TwoWire(uint8 dev_sel, uint8 flags) {
|
||||
if (dev_sel == 1) {
|
||||
sel_hard = I2C1;
|
||||
} else if (dev_sel == 2) {
|
||||
sel_hard = I2C2;
|
||||
} else {
|
||||
ASSERT(1);
|
||||
}
|
||||
dev_flags = flags;
|
||||
}
|
||||
void TwoWire::begin(uint8_t address){
|
||||
|
||||
TwoWire::~TwoWire() {
|
||||
i2c_disable(sel_hard);
|
||||
sel_hard = 0;
|
||||
}
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = 0;
|
||||
allocateRxBuffer(BUFFER_LENGTH);
|
||||
|
||||
void TwoWire::begin(uint8 self_addr) {
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
allocateTxBuffer(BUFFER_LENGTH);
|
||||
|
||||
transmitting = 0;
|
||||
|
||||
master = (address == MASTER_ADDRESS);
|
||||
|
||||
// Set default speed to 100KHz
|
||||
if (master) {
|
||||
dev_flags = 0;
|
||||
i2c_master_enable(sel_hard, dev_flags);
|
||||
} else {
|
||||
// TODO: I2C_SLAVE_DUAL_ADDRESS ?
|
||||
dev_flags = I2C_SLAVE_GENERAL_CALL | I2C_SLAVE_USE_RX_BUFFER |
|
||||
I2C_SLAVE_USE_TX_BUFFER;
|
||||
|
||||
itc_slave_msg.addr = address;
|
||||
itc_slave_msg.flags = 0;
|
||||
itc_slave_msg.data = rxBuffer;
|
||||
itc_slave_msg.length = 0;
|
||||
itc_slave_msg.flags = 0;
|
||||
|
||||
// TODO why does enable only work before setting IRS and address?
|
||||
i2c_slave_enable(sel_hard, dev_flags);
|
||||
|
||||
if (sel_hard==I2C1){
|
||||
// attach receive handler
|
||||
i2c_slave_attach_recv_handler(sel_hard, &itc_slave_msg, onReceiveService1);
|
||||
// attach transmit handler
|
||||
i2c_slave_attach_transmit_handler(sel_hard, &itc_slave_msg, onRequestService1);
|
||||
}
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
else if (sel_hard==I2C2){
|
||||
// attach receive handler
|
||||
i2c_slave_attach_recv_handler(sel_hard, &itc_slave_msg, onReceiveService2);
|
||||
// attach transmit handler
|
||||
i2c_slave_attach_transmit_handler(sel_hard, &itc_slave_msg, onRequestService2);
|
||||
}
|
||||
#endif
|
||||
|
||||
i2c_slave_set_own_address(sel_hard, address);
|
||||
}
|
||||
}
|
||||
|
||||
void TwoWire::end() {
|
||||
void TwoWire::begin(int address) {
|
||||
begin((uint8_t) address);
|
||||
}
|
||||
|
||||
void TwoWire::end(void) {
|
||||
free(txBuffer);
|
||||
txBuffer = nullptr;
|
||||
txBufferAllocated = 0;
|
||||
free(rxBuffer);
|
||||
rxBuffer = nullptr;
|
||||
rxBufferAllocated = 0;
|
||||
i2c_peripheral_disable(sel_hard);
|
||||
i2c_master_release_bus(sel_hard); // TODO is this required?
|
||||
}
|
||||
|
||||
void TwoWire::setClock(uint32_t frequencyHz) {
|
||||
switch (frequencyHz) {
|
||||
case 400000:
|
||||
dev_flags |= I2C_FAST_MODE; // set FAST_MODE bit
|
||||
break;
|
||||
case 100000:
|
||||
default:
|
||||
dev_flags &= ~I2C_FAST_MODE; // clear FAST_MODE bit
|
||||
break;
|
||||
}
|
||||
if (sel_hard->regs->CR1 & I2C_CR1_PE){
|
||||
i2c_disable(sel_hard);
|
||||
sel_hard = 0;
|
||||
i2c_master_enable(sel_hard, dev_flags);
|
||||
}
|
||||
}
|
||||
|
||||
void TwoWire::setClock(uint32_t frequencyHz)
|
||||
{
|
||||
switch(frequencyHz)
|
||||
{
|
||||
case 400000:
|
||||
dev_flags |= I2C_FAST_MODE;// set FAST_MODE bit
|
||||
break;
|
||||
case 100000:
|
||||
default:
|
||||
dev_flags &= ~I2C_FAST_MODE;// clear FAST_MODE bit
|
||||
break;
|
||||
}
|
||||
if (sel_hard->regs->CR1 & I2C_CR1_PE){
|
||||
i2c_disable(sel_hard);
|
||||
i2c_master_enable(sel_hard, dev_flags);
|
||||
}
|
||||
uint8 TwoWire::process(bool stop) {
|
||||
int8 res = i2c_master_xfer(sel_hard, &itc_msg, 1, 0);
|
||||
|
||||
if (res == I2C_ERROR_PROTOCOL) {
|
||||
if (sel_hard->error_flags & I2C_SR1_AF) { /* NACK */
|
||||
res = (sel_hard->error_flags & I2C_SR1_ADDR ? ENACKADDR : ENACKTRNS);
|
||||
} else if (sel_hard->error_flags & I2C_SR1_OVR) { /* Over/Underrun */
|
||||
res = EDATA;
|
||||
} else { /* Bus or Arbitration error */
|
||||
res = EOTHER;
|
||||
}
|
||||
i2c_disable(sel_hard);
|
||||
i2c_master_enable(sel_hard, (I2C_BUS_RESET | dev_flags));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
TwoWire Wire(1);
|
||||
//TODO: Add the ability to queue messages (adding a boolean to end of function
|
||||
// call, allows for the Arduino style to stay while also giving the flexibility
|
||||
// to bulk send
|
||||
uint8 TwoWire::requestFrom(uint8_t address, uint8_t num_bytes,
|
||||
uint32_t iaddress, uint8_t isize, uint8_t sendStop) {
|
||||
|
||||
ASSERT(master);
|
||||
|
||||
allocateRxBuffer(num_bytes);
|
||||
// error if no memory block available to allocate the buffer
|
||||
if (rxBuffer == nullptr) {
|
||||
return EDATA;
|
||||
}
|
||||
|
||||
// reset tx buffer iterator vars
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = 0;
|
||||
|
||||
if (num_bytes > BUFFER_LENGTH) {
|
||||
num_bytes = BUFFER_LENGTH;
|
||||
}
|
||||
|
||||
itc_msg.addr = address;
|
||||
itc_msg.flags = I2C_MSG_READ;
|
||||
itc_msg.length = num_bytes;
|
||||
itc_msg.data = &rxBuffer[rxBufferIndex];
|
||||
process(sendStop); // TODO deal with to the return value
|
||||
|
||||
// TODO handle iaddress & isize
|
||||
rxBufferLength += itc_msg.xferred;
|
||||
itc_msg.flags = 0;
|
||||
|
||||
return rxBufferLength;
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity,
|
||||
uint8_t sendStop) {
|
||||
// TODO shouldn't this set flag |= I2C_MSG_10BIT_ADDR ???
|
||||
return requestFrom((uint8_t) address, (uint8_t) quantity, (uint32_t) 0,
|
||||
(uint8_t) 0, sendStop);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) {
|
||||
return requestFrom((uint8_t) address, (uint8_t) quantity, (uint32_t) 0,
|
||||
(uint8_t) 0, (uint8_t) true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int quantity) {
|
||||
return requestFrom((uint8_t) address, (uint8_t) quantity, (uint32_t) 0,
|
||||
(uint8_t) 0, (uint8_t) true);
|
||||
}
|
||||
|
||||
uint8_t TwoWire::requestFrom(int address, int quantity,
|
||||
int sendStop) {
|
||||
return requestFrom((uint8_t) address, (uint8_t) quantity, (uint32_t) 0,
|
||||
(uint8_t) 0, (bool) sendStop);
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(uint8_t address) {
|
||||
|
||||
// indicate that we are transmitting
|
||||
transmitting = 1;
|
||||
|
||||
// reset tx buffer iterator vars
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
|
||||
itc_msg.addr = address;
|
||||
itc_msg.data = &txBuffer[txBufferIndex];
|
||||
itc_msg.length = 0;
|
||||
itc_msg.flags = 0;
|
||||
|
||||
}
|
||||
|
||||
void TwoWire::beginTransmission(int address) {
|
||||
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) {
|
||||
//UNUSED(sendStop);
|
||||
int8_t ret = 4;
|
||||
|
||||
if (master == true) {
|
||||
|
||||
itc_msg.data = txBuffer;
|
||||
itc_msg.length = txBufferLength;
|
||||
itc_msg.flags = 0;
|
||||
ret = process(sendStop); // Changed so that the return value from process is returned by this function see also the return line below
|
||||
txBufferIndex = 0;
|
||||
|
||||
// reset Tx buffer
|
||||
resetTxBuffer(); // TODO why? isn't this just unesssesary?
|
||||
|
||||
// reset tx buffer iterator vars
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
|
||||
// indicate that we are done transmitting
|
||||
transmitting = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This provides backwards compatibility with the original
|
||||
// definition, and expected behaviour, of endTransmission
|
||||
//
|
||||
|
||||
uint8_t TwoWire::endTransmission(void) {
|
||||
return endTransmission(true);
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave tx event callback
|
||||
// or after beginTransmission(address)
|
||||
size_t TwoWire::write(uint8_t data) {
|
||||
if (!transmitting && master) {
|
||||
return 0;
|
||||
} else {
|
||||
// in master transmitter mode or slave tx event callback
|
||||
allocateTxBuffer(txBufferLength + 1);
|
||||
// error if no memory block available to allocate the buffer
|
||||
if (txBuffer == nullptr) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
// put byte in tx buffer
|
||||
txBuffer[txBufferIndex] = data;
|
||||
++txBufferIndex;
|
||||
// update amount in buffer
|
||||
txBufferLength = txBufferIndex;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function must be called in slave Tx event callback or after
|
||||
* beginTransmission() and before endTransmission().
|
||||
* @param pdata: pointer to the buffer data
|
||||
* @param quantity: number of bytes to write
|
||||
* @retval number of bytes ready to write.
|
||||
*/
|
||||
size_t TwoWire::write(const uint8_t *data, size_t quantity) {
|
||||
if (!transmitting && master) {
|
||||
return 0;
|
||||
} else {
|
||||
// in master transmitter mode or slave Tx event callback
|
||||
allocateTxBuffer(txBufferLength + quantity);
|
||||
// error if no memory block available to allocate the buffer
|
||||
if (txBuffer == nullptr) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
// put bytes in tx buffer
|
||||
memcpy(&(txBuffer[txBufferIndex]), data, quantity);
|
||||
txBufferIndex = txBufferIndex + quantity;
|
||||
// update amount in buffer
|
||||
txBufferLength = txBufferIndex;
|
||||
return quantity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave rx event callback
|
||||
// or after requestFrom(address, numBytes)
|
||||
int TwoWire::available(void) {
|
||||
return rxBufferLength - rxBufferIndex;
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave rx event callback
|
||||
// or after requestFrom(address, numBytes)
|
||||
int TwoWire::read(void) {
|
||||
int value = -1;
|
||||
|
||||
// get each successive byte on each call
|
||||
if (rxBufferIndex < rxBufferLength) {
|
||||
value = rxBuffer[rxBufferIndex];
|
||||
++rxBufferIndex;
|
||||
|
||||
/* Commented as not I think it is not useful
|
||||
* but kept to show that it is possible to
|
||||
* reset rx buffer when no more data available */
|
||||
/*if(rxBufferIndex == rxBufferLength) {
|
||||
resetRxBuffer();
|
||||
}*/
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// must be called in:
|
||||
// slave rx event callback
|
||||
// or after requestFrom(address, numBytes)
|
||||
int TwoWire::peek(void) {
|
||||
int value = -1;
|
||||
|
||||
if (rxBufferIndex < rxBufferLength) {
|
||||
value = rxBuffer[rxBufferIndex];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void TwoWire::flush(void) {
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = 0;
|
||||
resetRxBuffer();
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
resetTxBuffer();
|
||||
}
|
||||
|
||||
// behind the scenes function that is called when data is received
|
||||
void __attribute__((always_inline)) TwoWire::onReceiveService(i2c_msg* msg) {
|
||||
// don't bother if user hasn't registered a callback
|
||||
if (!user_onReceive) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't bother if rx buffer is in use by a master requestFrom() op
|
||||
// i know this drops data, but it allows for slight stupidity
|
||||
// meaning, they may not have read all the master requestFrom() data yet
|
||||
if (rxBufferIndex < rxBufferLength) {
|
||||
return;
|
||||
}
|
||||
// copy twi rx buffer into local read buffer
|
||||
// this enables new reads to happen in parallel
|
||||
//
|
||||
// TODO: Something is strange here, isn't msg->data==rxBuffer? nope, itsnot
|
||||
//
|
||||
memcpy(rxBuffer, msg->data, msg->length);
|
||||
// set rx iterator vars
|
||||
rxBufferIndex = 0;
|
||||
rxBufferLength = msg->length;
|
||||
// alert user program
|
||||
user_onReceive(msg->length);
|
||||
}
|
||||
|
||||
// behind the scenes function that is called when data is requested
|
||||
void __attribute__((always_inline)) TwoWire::onRequestService(i2c_msg* msg) {
|
||||
// don't bother if user hasn't registered a callback
|
||||
if (!user_onRequest) {
|
||||
return;
|
||||
}
|
||||
|
||||
// reset tx buffer iterator vars
|
||||
// !!! this will kill any pending pre-master sendTo() activity
|
||||
txBufferIndex = 0;
|
||||
txBufferLength = 0;
|
||||
// alert user program
|
||||
user_onRequest();
|
||||
|
||||
// update i2c_msg
|
||||
msg->data = txBuffer;
|
||||
msg->length = txBufferLength;
|
||||
msg->xferred = 0;
|
||||
}
|
||||
|
||||
// sets function called on slave write
|
||||
void TwoWire::onReceive(void (*function)(int)) {
|
||||
user_onReceive = function;
|
||||
}
|
||||
|
||||
// sets function called on slave read
|
||||
void TwoWire::onRequest(void (*function)(void)) {
|
||||
user_onRequest = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate the Rx/Tx buffer to the requested length if needed
|
||||
* @note Minimum allocated size is BUFFER_LENGTH)
|
||||
* @param length: number of bytes to allocate
|
||||
*/
|
||||
inline void TwoWire::allocateRxBuffer(size_t length) {
|
||||
// By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
|
||||
if (length < BUFFER_LENGTH) {
|
||||
length = BUFFER_LENGTH;
|
||||
}
|
||||
if (rxBufferAllocated < length) {
|
||||
rxBuffer = (uint8_t *) realloc(rxBuffer, length * sizeof(uint8_t));
|
||||
rxBufferAllocated = (rxBuffer != nullptr) ? length : 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void TwoWire::allocateTxBuffer(size_t length) {
|
||||
// By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
|
||||
if (length < BUFFER_LENGTH) {
|
||||
length = BUFFER_LENGTH;
|
||||
}
|
||||
if (txBufferAllocated < length) {
|
||||
txBuffer = (uint8_t *) realloc(txBuffer, length * sizeof(uint8_t));
|
||||
txBufferAllocated = (txBuffer != nullptr) ? length : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset Rx/Tx buffer content to 0
|
||||
*/
|
||||
inline void TwoWire::resetRxBuffer(void) {
|
||||
if (rxBuffer != nullptr)
|
||||
memset(rxBuffer, 0, rxBufferAllocated);
|
||||
}
|
||||
|
||||
inline void TwoWire::resetTxBuffer(void) {
|
||||
if (txBuffer != nullptr)
|
||||
memset(txBuffer, 0, txBufferAllocated);
|
||||
}
|
||||
|
||||
|
||||
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||
TwoWire& Wire = TwoWire::getInstance(); //SCL:D14 SDA:D15
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
TwoWire& Wire1 = TwoWire::getInstance1(); //SCL: D1 SDA: D0
|
||||
#endif
|
||||
|
||||
// Static methods //////////////////////////////////////////////////////////////
|
||||
|
||||
TwoWire& TwoWire::getInstance(){
|
||||
static TwoWire instance(I2C1);
|
||||
return instance;
|
||||
}
|
||||
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
TwoWire& TwoWire::getInstance1(){
|
||||
static TwoWire instance(I2C2);
|
||||
return instance;
|
||||
}
|
||||
#endif
|
||||
|
||||
// onRequestServiceX and onReceiveServiceX can't be inline since they
|
||||
// are exclusively called via a function pointer
|
||||
void TwoWire::onRequestService1(i2c_msg* msg) {
|
||||
Wire.onRequestService(msg);
|
||||
}
|
||||
|
||||
void TwoWire::onReceiveService1(i2c_msg* msg) {
|
||||
Wire.onReceiveService(msg);
|
||||
}
|
||||
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
void TwoWire::onRequestService2(i2c_msg* msg) {
|
||||
Wire1.onRequestService(msg);
|
||||
}
|
||||
void TwoWire::onReceiveService2(i2c_msg* msg) {
|
||||
Wire1.onReceiveService(msg);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,78 +1,149 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file Wire.h
|
||||
* @author Trystan Jones <crenn6977@gmail.com>
|
||||
* @brief Wire library, uses the hardware I2C available in the Maple to
|
||||
* interact with I2C slave devices.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Library created by crenn to use the new WireBase system and allow Arduino
|
||||
* users easy interaction with the I2C Hardware in a familiar method.
|
||||
TwoWire.h - TWI/I2C library for Arduino & Wiring
|
||||
Copyright (c) 2006 Nicholas Zambetti. All right 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
|
||||
|
||||
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
|
||||
*/
|
||||
|
||||
#ifndef _TWOWIRE_H_
|
||||
#define _TWOWIRE_H_
|
||||
#ifndef TwoWire_h
|
||||
#define TwoWire_h
|
||||
|
||||
#include "utility/WireBase_slave.h"
|
||||
#include "wirish.h"
|
||||
#include <inttypes.h>
|
||||
#include "Stream.h"
|
||||
#include "Arduino.h"
|
||||
#include <libmaple/i2c_slave.h>
|
||||
|
||||
class TwoWire : public WireBase {
|
||||
|
||||
// WIRE_HAS_END means Wire has end()
|
||||
#ifndef WIRE_HAS_END
|
||||
#define WIRE_HAS_END 1
|
||||
#endif
|
||||
|
||||
#ifndef WIRE_INTERFACES_COUNT
|
||||
#define WIRE_INTERFACES_COUNT 2
|
||||
#endif
|
||||
|
||||
/* return codes from endTransmission() */
|
||||
typedef enum EndTranmissionCodes {
|
||||
SUCCESS = 0, /* transmission was successful */
|
||||
EDATA = 1, /* too much data */
|
||||
ENACKADDR = 2, /* received nack on transmit of address */
|
||||
ENACKTRNS = 3, /* received nack on transmit of data */
|
||||
EOTHER = 4, /* other error */
|
||||
} EndTranmissionCodes;
|
||||
|
||||
class TwoWire: public Stream {
|
||||
private:
|
||||
i2c_dev* sel_hard;
|
||||
uint8 dev_flags;
|
||||
protected:
|
||||
/*
|
||||
* Processes the incoming I2C message defined by WireBase to the
|
||||
* hardware. If an error occured, restart the I2C device.
|
||||
*/
|
||||
uint8 process(uint8);
|
||||
uint8 process();
|
||||
i2c_dev* sel_hard;
|
||||
|
||||
uint8_t *rxBuffer; // lazy allocation
|
||||
uint8_t rxBufferAllocated;
|
||||
uint8_t rxBufferIndex;
|
||||
uint8_t rxBufferLength;
|
||||
|
||||
uint8_t *txBuffer; // lazy allocation
|
||||
uint8_t txBufferAllocated;
|
||||
uint8_t txBufferIndex;
|
||||
uint8_t txBufferLength;
|
||||
|
||||
uint8_t transmitting;
|
||||
|
||||
bool master;
|
||||
|
||||
uint8 dev_flags;
|
||||
i2c_msg itc_msg;
|
||||
i2c_msg itc_slave_msg;
|
||||
|
||||
void (*user_onRequest)(void);
|
||||
void (*user_onReceive)(int);
|
||||
|
||||
void allocateRxBuffer(size_t length);
|
||||
void allocateTxBuffer(size_t length);
|
||||
|
||||
void resetRxBuffer(void);
|
||||
void resetTxBuffer(void);
|
||||
uint8 process(bool stop = true); // wrapper for i2c_master_xfer
|
||||
|
||||
inline void __attribute__((always_inline)) onReceiveService(i2c_msg* msg);
|
||||
inline void __attribute__((always_inline)) onRequestService(i2c_msg* msg);
|
||||
|
||||
static void onRequestService1(i2c_msg*);
|
||||
static void onReceiveService1(i2c_msg*);
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
static void onRequestService2(i2c_msg*);
|
||||
static void onReceiveService2(i2c_msg*);
|
||||
#endif
|
||||
|
||||
TwoWire(i2c_dev* i2cDevice);
|
||||
TwoWire() = delete;
|
||||
TwoWire(const TwoWire&) = delete;
|
||||
TwoWire& operator=(const TwoWire&) = delete;
|
||||
TwoWire(TwoWire&&) = delete;
|
||||
TwoWire& operator=(TwoWire&&) = delete;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Check if devsel is within range and enable selected I2C interface with
|
||||
* passed flags
|
||||
*/
|
||||
TwoWire(uint8, uint8 = 0);
|
||||
static TwoWire& getInstance();
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
static TwoWire& getInstance1();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Shuts down (disables) the hardware I2C
|
||||
*/
|
||||
void end();
|
||||
void begin();
|
||||
void begin(uint8_t);
|
||||
void begin(int);
|
||||
void end();
|
||||
void setClock(uint32_t);
|
||||
void beginTransmission(uint8_t);
|
||||
void beginTransmission(int);
|
||||
uint8_t endTransmission(void);
|
||||
uint8_t endTransmission(uint8_t);
|
||||
|
||||
void setClock(uint32_t frequencyHz);
|
||||
/*
|
||||
* Disables the I2C device and remove the device address.
|
||||
*/
|
||||
~TwoWire();
|
||||
uint8_t requestFrom(uint8_t, uint8_t);
|
||||
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
|
||||
uint8_t requestFrom(uint8_t, uint8_t, uint32_t, uint8_t, uint8_t);
|
||||
uint8_t requestFrom(int, int);
|
||||
uint8_t requestFrom(int, int, int);
|
||||
|
||||
void begin(uint8 = 0x00);
|
||||
virtual size_t write(uint8_t);
|
||||
virtual size_t write(const uint8_t *, size_t);
|
||||
virtual int available(void);
|
||||
virtual int read(void);
|
||||
virtual int peek(void);
|
||||
virtual void flush(void);
|
||||
void onReceive(void (*)(int));
|
||||
void onRequest(void (*)(void));
|
||||
|
||||
inline size_t write(unsigned long n) {
|
||||
return write((uint8_t) n);
|
||||
}
|
||||
inline size_t write(long n) {
|
||||
return write((uint8_t) n);
|
||||
}
|
||||
inline size_t write(unsigned int n) {
|
||||
return write((uint8_t) n);
|
||||
}
|
||||
inline size_t write(int n) {
|
||||
return write((uint8_t) n);
|
||||
}
|
||||
using Print::write;
|
||||
};
|
||||
extern TwoWire Wire;
|
||||
#endif // _TWOWIRE_H_
|
||||
|
||||
extern TwoWire& Wire;
|
||||
#if WIRE_INTERFACES_COUNT > 1
|
||||
extern TwoWire& Wire1;
|
||||
#endif
|
||||
|
||||
#endif // TwoWire_h
|
||||
|
|
Binary file not shown.
|
@ -158,6 +158,7 @@ void i2c_bus_reset(const i2c_dev *dev) {
|
|||
* @param dev Device to initialize.
|
||||
*/
|
||||
void i2c_init(i2c_dev *dev) {
|
||||
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
_i2c_irq_priority_fixup(dev);
|
||||
|
@ -197,8 +198,10 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) {
|
|||
i2c_init(dev);
|
||||
i2c_config_gpios(dev);
|
||||
|
||||
/* Configure clock and rise time */
|
||||
set_ccr_trise(dev, flags);
|
||||
/* Configure clock and rise time, but only if in master mode */
|
||||
if (!(flags & (I2C_SLAVE_DUAL_ADDRESS|I2C_SLAVE_GENERAL_CALL))) {
|
||||
set_ccr_trise(dev, flags);
|
||||
}
|
||||
|
||||
/* Enable event and buffer interrupts */
|
||||
nvic_irq_enable(dev->ev_nvic_line);
|
||||
|
@ -245,8 +248,9 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) {
|
|||
* Callback will be called before tx
|
||||
*/
|
||||
void i2c_slave_enable(i2c_dev *dev, uint32 flags) {
|
||||
// TODO: Figure out why i2c_disable(I2C2) causes a crash when I2C1 is enabled
|
||||
i2c_disable(dev);
|
||||
i2c_master_enable(dev, dev->config_flags | flags);
|
||||
i2c_master_enable(dev, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -329,7 +333,8 @@ static inline int32 wait_for_state_change(i2c_dev *dev,
|
|||
*/
|
||||
|
||||
/*
|
||||
* IRQ handler for I2C master. Handles transmission/reception.
|
||||
* IRQ handler for I2C master and slave.
|
||||
* Handles transmission/reception.
|
||||
*/
|
||||
void _i2c_irq_handler(i2c_dev *dev) {
|
||||
/* WTFs:
|
||||
|
@ -676,7 +681,7 @@ void _i2c_irq_error_handler(i2c_dev *dev) {
|
|||
I2C_SR1_OVR);
|
||||
|
||||
/* Are we in slave mode? */
|
||||
if ((dev->regs->SR2 & I2C_SR2_MSL) != I2C_SR2_MSL) {
|
||||
if (dev->config_flags & (I2C_SLAVE_DUAL_ADDRESS|I2C_SLAVE_GENERAL_CALL)) {
|
||||
/* Check to see if the master device did a NAK on the last bit
|
||||
* This is perfectly valid for a master to do this on the bus.
|
||||
* We ignore this. Any further error processing takes us into dead
|
||||
|
|
|
@ -1,145 +0,0 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file WireBase.cpp
|
||||
* @author Trystan Jones <crenn6977@gmail.com>
|
||||
* @brief Wire library, following the majority of the interface from Arduino.
|
||||
* Provides a 'standard' interface to I2C (two-wire) communication for
|
||||
* derived classes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Library created by crenn to allow a system which would provide users the
|
||||
* 'standardised' Arduino method for interfacing with I2C devices regardless of
|
||||
* whether it is I2C hardware or emulating software.
|
||||
*/
|
||||
|
||||
#include "WireBase_slave.h"
|
||||
#include "wirish.h"
|
||||
|
||||
void WireBase::begin(uint8 self_addr) {
|
||||
tx_buf_idx = 0;
|
||||
tx_buf_overflow = false;
|
||||
rx_buf_idx = 0;
|
||||
rx_buf_len = 0;
|
||||
}
|
||||
|
||||
void WireBase::beginTransmission(uint8 slave_address) {
|
||||
itc_msg.addr = slave_address;
|
||||
itc_msg.data = &tx_buf[tx_buf_idx];
|
||||
itc_msg.length = 0;
|
||||
itc_msg.flags = 0;
|
||||
}
|
||||
|
||||
void WireBase::beginTransmission(int slave_address) {
|
||||
beginTransmission((uint8)slave_address);
|
||||
}
|
||||
|
||||
uint8 WireBase::endTransmission(bool stop) {
|
||||
uint8 retVal;
|
||||
if (tx_buf_overflow) {
|
||||
return EDATA;
|
||||
}
|
||||
retVal = process(stop);// Changed so that the return value from process is returned by this function see also the return line below
|
||||
tx_buf_idx = 0;
|
||||
tx_buf_overflow = false;
|
||||
return retVal;//SUCCESS;
|
||||
}
|
||||
|
||||
uint8 WireBase::endTransmission(){
|
||||
endTransmission(true);
|
||||
}
|
||||
|
||||
//TODO: Add the ability to queue messages (adding a boolean to end of function
|
||||
// call, allows for the Arduino style to stay while also giving the flexibility
|
||||
// to bulk send
|
||||
uint8 WireBase::requestFrom(uint8 address, int num_bytes) {
|
||||
if (num_bytes > BUFFER_LENGTH) {
|
||||
num_bytes = BUFFER_LENGTH;
|
||||
}
|
||||
itc_msg.addr = address;
|
||||
itc_msg.flags = I2C_MSG_READ;
|
||||
itc_msg.length = num_bytes;
|
||||
itc_msg.data = &rx_buf[rx_buf_idx];
|
||||
process();
|
||||
rx_buf_len += itc_msg.xferred;
|
||||
itc_msg.flags = 0;
|
||||
return rx_buf_len;
|
||||
}
|
||||
|
||||
uint8 WireBase::requestFrom(int address, int numBytes) {
|
||||
return WireBase::requestFrom((uint8)address, numBytes);
|
||||
}
|
||||
|
||||
void WireBase::write(uint8 value) {
|
||||
if (tx_buf_idx == BUFFER_LENGTH) {
|
||||
tx_buf_overflow = true;
|
||||
return;
|
||||
}
|
||||
tx_buf[tx_buf_idx++] = value;
|
||||
itc_msg.length++;
|
||||
}
|
||||
|
||||
void WireBase::write(uint8* buf, int len) {
|
||||
for (uint8 i = 0; i < len; i++) {
|
||||
write(buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void WireBase::write(int value) {
|
||||
write((uint8)value);
|
||||
}
|
||||
|
||||
void WireBase::write(int* buf, int len) {
|
||||
write((uint8*)buf, (uint8)len);
|
||||
}
|
||||
|
||||
void WireBase::write(char* buf) {
|
||||
uint8 *ptr = (uint8*)buf;
|
||||
while (*ptr) {
|
||||
write(*ptr);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 WireBase::available() {
|
||||
return rx_buf_len - rx_buf_idx;
|
||||
}
|
||||
|
||||
uint8 WireBase::read() {
|
||||
if (rx_buf_idx == rx_buf_len) {
|
||||
rx_buf_idx = 0;
|
||||
rx_buf_len = 0;
|
||||
return 0;
|
||||
} else if (rx_buf_idx == (rx_buf_len-1)) {
|
||||
uint8 temp = rx_buf[rx_buf_idx];
|
||||
rx_buf_idx = 0;
|
||||
rx_buf_len = 0;
|
||||
return temp;
|
||||
}
|
||||
return rx_buf[rx_buf_idx++];
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file WireBase.h
|
||||
* @author Trystan Jones <crenn6977@gmail.com>
|
||||
* @brief Wire library, following the majority of the interface from Arduino.
|
||||
* Provides a 'standard' interface to I2C (two-wire) communication for
|
||||
* derived classes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Library created by crenn to allow a system which would provide users the
|
||||
* 'standardised' Arduino method for interfacing with I2C devices regardless of
|
||||
* whether it is I2C hardware or emulating software.
|
||||
*/
|
||||
|
||||
#ifndef _WIREBASE_H_
|
||||
#define _WIREBASE_H_
|
||||
|
||||
#include "wirish.h"
|
||||
#include <libmaple/i2c_slave.h>
|
||||
|
||||
#define BUFFER_LENGTH 32
|
||||
|
||||
/* return codes from endTransmission() */
|
||||
#define SUCCESS 0 /* transmission was successful */
|
||||
#define EDATA 1 /* too much data */
|
||||
#define ENACKADDR 2 /* received nack on transmit of address */
|
||||
#define ENACKTRNS 3 /* received nack on transmit of data */
|
||||
#define EOTHER 4 /* other error */
|
||||
|
||||
class WireBase { // Abstraction is awesome!
|
||||
protected:
|
||||
i2c_msg itc_msg;
|
||||
uint8 rx_buf[BUFFER_LENGTH]; /* receive buffer */
|
||||
uint8 rx_buf_idx; /* first unread idx in rx_buf */
|
||||
uint8 rx_buf_len; /* number of bytes read */
|
||||
|
||||
uint8 tx_buf[BUFFER_LENGTH]; /* transmit buffer */
|
||||
uint8 tx_buf_idx; // next idx available in tx_buf, -1 overflow
|
||||
boolean tx_buf_overflow;
|
||||
|
||||
// Force derived classes to define process function
|
||||
virtual uint8 process(uint8) = 0;
|
||||
virtual uint8 process() = 0;
|
||||
public:
|
||||
WireBase() {}
|
||||
~WireBase() {}
|
||||
|
||||
/*
|
||||
* Initialises the class interface
|
||||
*/
|
||||
// Allow derived classes to overwrite begin function
|
||||
virtual void begin(uint8 = 0x00);
|
||||
|
||||
/*
|
||||
* Sets up the transmission message to be processed
|
||||
*/
|
||||
void beginTransmission(uint8);
|
||||
|
||||
/*
|
||||
* Allow only 8 bit addresses to be used
|
||||
*/
|
||||
void beginTransmission(int);
|
||||
|
||||
/*
|
||||
* Call the process function to process the message if the TX
|
||||
* buffer has not overflowed.
|
||||
*/
|
||||
uint8 endTransmission(bool);
|
||||
uint8 endTransmission(void);
|
||||
|
||||
/*
|
||||
* Request bytes from a slave device and process the request,
|
||||
* storing into the receiving buffer.
|
||||
*/
|
||||
uint8 requestFrom(uint8, int);
|
||||
|
||||
/*
|
||||
* Allow only 8 bit addresses to be used when requesting bytes
|
||||
*/
|
||||
uint8 requestFrom(int, int);
|
||||
|
||||
/*
|
||||
* Stack up bytes to be sent when transmitting
|
||||
*/
|
||||
void write(uint8);
|
||||
|
||||
/*
|
||||
* Stack up bytes from the array to be sent when transmitting
|
||||
*/
|
||||
void write(uint8*, int);
|
||||
|
||||
/*
|
||||
* Ensure that a sending data will only be 8-bit bytes
|
||||
*/
|
||||
void write(int);
|
||||
|
||||
/*
|
||||
* Ensure that an array sending data will only be 8-bit bytes
|
||||
*/
|
||||
void write(int*, int);
|
||||
|
||||
/*
|
||||
* Stack up bytes from a string to be sent when transmitting
|
||||
*/
|
||||
void write(char*);
|
||||
|
||||
/*
|
||||
* Return the amount of bytes that is currently in the receiving buffer
|
||||
*/
|
||||
uint8 available();
|
||||
|
||||
/*
|
||||
* Return the value of byte in the receiving buffer that is currently being
|
||||
* pointed to
|
||||
*/
|
||||
uint8 read();
|
||||
};
|
||||
|
||||
#endif // _WIREBASE_H_
|
Loading…
Reference in New Issue