277 lines
6.4 KiB
C++
277 lines
6.4 KiB
C++
/*
|
|
* Modified for Waspmote by A. Bielsa, 2009
|
|
*
|
|
* Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
|
*
|
|
* This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
extern "C" {
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
#include "twi.h"
|
|
}
|
|
|
|
//#include "Wire.h"
|
|
|
|
#ifndef __WPROGRAM_H__
|
|
#include "WaspClasses.h"
|
|
#endif
|
|
|
|
// Initialize Class Variables //////////////////////////////////////////////////
|
|
|
|
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH] = {0};
|
|
uint8_t TwoWire::rxBufferIndex = 0;
|
|
uint8_t TwoWire::rxBufferLength = 0;
|
|
|
|
uint8_t TwoWire::txAddress = 0;
|
|
uint8_t TwoWire::txBuffer[BUFFER_LENGTH] = {0};
|
|
uint8_t TwoWire::txBufferIndex = 0;
|
|
uint8_t TwoWire::txBufferLength = 0;
|
|
|
|
uint8_t TwoWire::transmitting = 0;
|
|
void (*TwoWire::user_onRequest)(void);
|
|
void (*TwoWire::user_onReceive)(int);
|
|
|
|
// Constructors ////////////////////////////////////////////////////////////////
|
|
|
|
TwoWire::TwoWire()
|
|
{
|
|
}
|
|
|
|
// Public Methods //////////////////////////////////////////////////////////////
|
|
|
|
void TwoWire::begin(void)
|
|
{
|
|
int i=0;
|
|
// init buffer for reads
|
|
for(i=0;i<BUFFER_LENGTH;i++) rxBuffer[BUFFER_LENGTH]=0;
|
|
rxBufferIndex = 0;
|
|
rxBufferLength = 0;
|
|
|
|
// init buffer for writes
|
|
for(i=0;i<BUFFER_LENGTH;i++) txBuffer[BUFFER_LENGTH]=0;
|
|
txBufferIndex = 0;
|
|
txBufferLength = 0;
|
|
|
|
twi_init();
|
|
|
|
I2C_ON = 1;
|
|
}
|
|
|
|
void TwoWire::begin(uint8_t address)
|
|
{
|
|
twi_setAddress(address);
|
|
twi_attachSlaveTxEvent(onRequestService);
|
|
twi_attachSlaveRxEvent(onReceiveService);
|
|
begin();
|
|
}
|
|
|
|
void TwoWire::begin(int address)
|
|
{
|
|
begin((uint8_t)address);
|
|
}
|
|
|
|
void TwoWire::requestFrom(uint8_t address, uint8_t quantity)
|
|
{
|
|
// clamp to buffer length
|
|
if(quantity > BUFFER_LENGTH){
|
|
quantity = BUFFER_LENGTH;
|
|
}
|
|
// perform blocking read into buffer
|
|
twi_readFrom(address, rxBuffer, quantity);
|
|
// set rx buffer iterator vars
|
|
rxBufferIndex = 0;
|
|
rxBufferLength = quantity;
|
|
}
|
|
|
|
void TwoWire::requestFrom(int address, int quantity)
|
|
{
|
|
requestFrom((uint8_t)address, (uint8_t)quantity);
|
|
}
|
|
|
|
void TwoWire::beginTransmission(uint8_t address)
|
|
{
|
|
// indicate that we are transmitting
|
|
transmitting = 1;
|
|
// set address of targeted slave
|
|
txAddress = address;
|
|
// reset tx buffer iterator vars
|
|
txBufferIndex = 0;
|
|
txBufferLength = 0;
|
|
}
|
|
|
|
void TwoWire::beginTransmission(int address)
|
|
{
|
|
beginTransmission((uint8_t)address);
|
|
}
|
|
|
|
void TwoWire::endTransmission(void)
|
|
{
|
|
// transmit buffer (blocking)
|
|
twi_writeTo(txAddress, txBuffer, txBufferLength, 1);
|
|
// reset tx buffer iterator vars
|
|
txBufferIndex = 0;
|
|
txBufferLength = 0;
|
|
// indicate that we are done transmitting
|
|
transmitting = 0;
|
|
}
|
|
|
|
// must be called in:
|
|
// slave tx event callback
|
|
// or after beginTransmission(address)
|
|
void TwoWire::send(uint8_t data)
|
|
{
|
|
if(transmitting){
|
|
// in master transmitter mode
|
|
// don't bother if buffer is full
|
|
if(txBufferLength >= BUFFER_LENGTH){
|
|
return;
|
|
}
|
|
// put byte in tx buffer
|
|
txBuffer[txBufferIndex] = data;
|
|
++txBufferIndex;
|
|
// update amount in buffer
|
|
txBufferLength = txBufferIndex;
|
|
}else{
|
|
// in slave send mode
|
|
// reply to master
|
|
twi_transmit(&data, 1);
|
|
}
|
|
}
|
|
|
|
// must be called in:
|
|
// slave tx event callback
|
|
// or after beginTransmission(address)
|
|
void TwoWire::send(uint8_t* data, uint8_t quantity)
|
|
{
|
|
if(transmitting){
|
|
// in master transmitter mode
|
|
for(uint8_t i = 0; i < quantity; ++i){
|
|
send(data[i]);
|
|
}
|
|
}else{
|
|
// in slave send mode
|
|
// reply to master
|
|
twi_transmit(data, quantity);
|
|
}
|
|
}
|
|
|
|
// must be called in:
|
|
// slave tx event callback
|
|
// or after beginTransmission(address)
|
|
void TwoWire::send(char* data)
|
|
{
|
|
send((uint8_t*)data, strlen(data));
|
|
}
|
|
|
|
// must be called in:
|
|
// slave tx event callback
|
|
// or after beginTransmission(address)
|
|
void TwoWire::send(int data)
|
|
{
|
|
send((uint8_t)data);
|
|
}
|
|
|
|
// must be called in:
|
|
// slave rx event callback
|
|
// or after requestFrom(address, numBytes)
|
|
uint8_t TwoWire::available(void)
|
|
{
|
|
return rxBufferLength - rxBufferIndex;
|
|
}
|
|
|
|
// must be called in:
|
|
// slave rx event callback
|
|
// or after requestFrom(address, numBytes)
|
|
uint8_t TwoWire::receive(void)
|
|
{
|
|
// default to returning null char
|
|
// for people using with char strings
|
|
uint8_t value = '\0';
|
|
|
|
// get each successive byte on each call
|
|
if(rxBufferIndex < rxBufferLength){
|
|
value = rxBuffer[rxBufferIndex];
|
|
++rxBufferIndex;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
// behind the scenes function that is called when data is received
|
|
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
|
|
{
|
|
// 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
|
|
for(uint8_t i = 0; i < numBytes; ++i){
|
|
rxBuffer[i] = inBytes[i];
|
|
}
|
|
// set rx iterator vars
|
|
rxBufferIndex = 0;
|
|
rxBufferLength = numBytes;
|
|
// alert user program
|
|
user_onReceive(numBytes);
|
|
}
|
|
|
|
// behind the scenes function that is called when data is requested
|
|
void TwoWire::onRequestService(void)
|
|
{
|
|
// 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();
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
void TwoWire::close()
|
|
{
|
|
twi_close();
|
|
I2C_ON = 0;
|
|
}
|
|
|
|
|
|
// Preinstantiate Objects //////////////////////////////////////////////////////
|
|
|
|
TwoWire Wire = TwoWire();
|
|
|