Created
April 10, 2015 15:42
-
-
Save analog-io/a95520fee652e7e6fb56 to your computer and use it in GitHub Desktop.
SoftwareI2C for MSP430 Energia
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SoftwareWire.cpp | |
// Library C++ code | |
// ---------------------------------- | |
// Developed with embedXcode | |
// http://embedXcode.weebly.com | |
// | |
// Project embed1 | |
// | |
// Created by Rei VILO, mars 29, 2013 09:59 | |
// http://embedXcode.weebly.com | |
// | |
// | |
// Copyright © Rei VILO, 2013-2014 | |
// License CC = BY NC SA | |
// | |
// See I2C_SoftwareLibrary.h and ReadMe.txt for references | |
// | |
#include "I2C_SoftwareLibrary.h" | |
/// | |
/// @brief Delay values for software I2C | |
/// | |
const uint8_t DELAY_LONG = 32; | |
const uint8_t DELAY_FULL = 8; | |
const uint8_t DELAY_HALF = 4; | |
const uint8_t DELAY_PART = 2; | |
#define I2C_READ 1 | |
#define I2C_WRITE 0 | |
#define TICKS_PER_MS (F_CPU / 1000) | |
#define TICKS_PER_US (TICKS_PER_MS / 1000) | |
void delayI2Cms(uint16_t delay) | |
{ | |
while (delay--) __delay_cycles(TICKS_PER_MS); | |
} | |
void delayI2Cus(uint16_t delay) | |
{ | |
while (delay--) __delay_cycles(TICKS_PER_US); | |
} | |
uint8_t SoftwareWire::rxBuffer[BUFFER_LENGTH]; | |
uint8_t SoftwareWire::rxBufferIndex = 0; | |
uint8_t SoftwareWire::rxBufferLength = 0; | |
uint8_t SoftwareWire::txAddress = 0; | |
uint8_t SoftwareWire::txBuffer[BUFFER_LENGTH]; | |
uint8_t SoftwareWire::txBufferIndex = 0; | |
uint8_t SoftwareWire::txBufferLength = 0; | |
uint8_t SoftwareWire::transmitting = 0; | |
SoftwareWire::SoftwareWire(uint8_t pinSDA, uint8_t pinSCL) { | |
_pinSDA = pinSDA; | |
_pinSCL = pinSCL; | |
} | |
void SoftwareWire::begin() { | |
pinMode(_pinSDA, OUTPUT); | |
digitalWrite(_pinSDA, HIGH); | |
pinMode(_pinSCL, OUTPUT); | |
digitalWrite(_pinSCL, HIGH); | |
rxBufferIndex = 0; | |
rxBufferLength = 0; | |
txBufferIndex = 0; | |
txBufferLength = 0; | |
} | |
void SoftwareWire::beginTransmission(uint8_t address) | |
{ | |
transmitting = 1; | |
txAddress = address; | |
txBufferIndex = 0; | |
txBufferLength = 0; | |
} | |
uint8_t SoftwareWire::endTransmission(uint8_t sendStop) | |
{ | |
uint8_t result = 0; | |
startI2C(txAddress, I2C_WRITE); | |
result += writeI2C(txBuffer, txBufferLength); | |
if (sendStop) stopI2C(); | |
else stallI2C(); | |
txBufferIndex = 0; | |
txBufferLength = 0; | |
transmitting = 0; | |
return result; | |
} | |
uint8_t SoftwareWire::endTransmission(void) | |
{ | |
return endTransmission(true); | |
} | |
uint8_t SoftwareWire::requestFrom(uint8_t address, uint8_t length) | |
{ | |
bool first = true; | |
if (length > BUFFER_LENGTH) length = BUFFER_LENGTH; | |
startI2C(address, I2C_READ); | |
pinMode(_pinSCL, INPUT); | |
pinMode(_pinSDA, INPUT); | |
delayI2Cus(DELAY_FULL); | |
while (digitalRead(_pinSCL)==LOW); | |
if (length > 1) { | |
for (uint8_t i=0; i<length-1; i++) { | |
rxBuffer[i] = readI2C(false,first); | |
first = false; | |
} | |
} | |
rxBuffer[length-1] = readI2C(true,first); | |
stopI2C(); | |
rxBufferIndex = 0; | |
rxBufferLength = length; | |
return length; | |
} | |
size_t SoftwareWire::write(uint8_t data) | |
{ | |
if (transmitting){ | |
if (txBufferLength >= BUFFER_LENGTH) { | |
return 0; | |
} | |
txBuffer[txBufferIndex] = data; | |
++txBufferIndex; | |
txBufferLength = txBufferIndex; | |
} else { | |
writeI2C(data); | |
} | |
return 1; | |
} | |
size_t SoftwareWire::write(const uint8_t *data, size_t length) | |
{ | |
if (transmitting) { | |
for (size_t i = 0; i < length; ++i) write(data[i]); | |
} else { | |
for (size_t i = 0; i < length; ++i) writeI2C(data[i]); | |
} | |
return length; | |
} | |
int SoftwareWire::available(void) | |
{ | |
return rxBufferLength - rxBufferIndex; | |
} | |
int SoftwareWire::read(void) | |
{ | |
int value = -1; | |
if(rxBufferIndex < rxBufferLength){ | |
value = rxBuffer[rxBufferIndex]; | |
++rxBufferIndex; | |
} | |
return value; | |
} | |
int SoftwareWire::peek(void) | |
{ | |
int value = -1; | |
if (rxBufferIndex < rxBufferLength) value = rxBuffer[rxBufferIndex]; | |
return value; | |
} | |
void SoftwareWire::flush(void) | |
{ | |
; | |
} | |
uint8_t SoftwareWire::readI2C(uint8_t last, bool first) { | |
uint8_t data = 0; | |
digitalWrite(_pinSDA, LOW); | |
if (!first) | |
{ | |
delayI2Cus(DELAY_LONG); | |
pinMode(_pinSDA, INPUT); | |
delayI2Cus(DELAY_HALF); | |
} | |
for (uint8_t i = 0; i < 8; i++) { | |
if (first && i==0) { | |
data <<= 1; | |
if (digitalRead(_pinSDA)) data |= 1; | |
digitalWrite(_pinSCL, LOW); | |
pinMode(_pinSCL, OUTPUT); | |
delayI2Cus(DELAY_HALF); | |
} | |
else | |
{ | |
data <<= 1; | |
digitalWrite(_pinSCL, HIGH); | |
delayI2Cus(DELAY_PART); | |
if (digitalRead(_pinSDA)) data |= 1; | |
delayI2Cus(DELAY_PART); | |
digitalWrite(_pinSCL, LOW); | |
delayI2Cus(DELAY_HALF); | |
} | |
} | |
pinMode(_pinSDA, OUTPUT); | |
digitalWrite(_pinSDA, last); | |
digitalWrite(_pinSCL, HIGH); | |
delayI2Cus(DELAY_HALF); | |
digitalWrite(_pinSCL, LOW); | |
digitalWrite(_pinSDA, LOW); | |
delayI2Cus(DELAY_LONG); | |
return data; | |
} | |
uint8_t SoftwareWire::readI2C(uint8_t* data, uint8_t length) | |
{ | |
if (length > 1) { | |
while (--length) *data++= readI2C(false); | |
} | |
*data = readI2C(true); | |
} | |
bool SoftwareWire::restartI2C(uint8_t address, uint8_t RW) { | |
digitalWrite(_pinSDA, HIGH); | |
digitalWrite(_pinSCL, HIGH); | |
delayI2Cus(DELAY_FULL); | |
return startI2C(address, RW); | |
} | |
bool SoftwareWire::startI2C(uint8_t address, uint8_t RW) { | |
pinMode(_pinSDA, OUTPUT); | |
digitalWrite(_pinSDA, LOW); | |
digitalWrite(_pinSCL, LOW); | |
delayI2Cus(DELAY_FULL); | |
return writeI2C((address << 1) + RW); | |
} | |
void SoftwareWire::stopI2C(void) { | |
pinMode(_pinSDA, OUTPUT); | |
digitalWrite(_pinSDA, LOW); | |
delayI2Cus(DELAY_FULL); | |
digitalWrite(_pinSCL, HIGH); | |
delayI2Cus(DELAY_FULL); | |
digitalWrite(_pinSDA, HIGH); | |
delayI2Cus(DELAY_FULL); | |
} | |
void SoftwareWire::stallI2C(void) { | |
digitalWrite(_pinSDA, HIGH); | |
pinMode(_pinSDA, OUTPUT); | |
digitalWrite(_pinSCL, HIGH); | |
delayI2Cus(DELAY_FULL); | |
digitalWrite(_pinSDA, LOW); | |
delayI2Cus(DELAY_FULL); | |
} | |
bool SoftwareWire::writeI2C(uint8_t data) { | |
pinMode(_pinSDA, OUTPUT); | |
for (uint8_t i=0; i < 8; ++i ){ | |
if (data & 0x80) digitalWrite(_pinSDA, HIGH); | |
else digitalWrite(_pinSDA, LOW); | |
digitalWrite(_pinSCL, HIGH); | |
data <<= 1; | |
delayI2Cus(DELAY_HALF); | |
digitalWrite(_pinSCL, LOW); | |
delayI2Cus(DELAY_HALF); | |
} | |
pinMode(_pinSDA, INPUT); | |
digitalWrite(_pinSCL, HIGH); | |
uint8_t result = !digitalRead(_pinSDA); | |
if (result) digitalWrite(_pinSDA, LOW); | |
delayI2Cus(DELAY_HALF); | |
digitalWrite(_pinSCL, LOW); | |
delayI2Cus(DELAY_FULL); | |
return result; | |
} | |
bool SoftwareWire::writeI2C(uint8_t* data, size_t length) | |
{ | |
uint8_t result; | |
for (uint8_t i=0; i < length; i++) result = writeI2C(data[i]); | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// | |
/// @mainpage I2C_Software | |
/// | |
/// @details Software I2C for MSP430 | |
/// @n | |
/// @n @b Contribute! | |
/// @n Help me for my developments: http://embeddedcomputing.weebly.com/contact | |
/// | |
/// @n @a Developed with [embedXcode](http://embedXcode.weebly.com) | |
/// | |
/// @author Rei VILO | |
/// @author http://embedXcode.weebly.com | |
/// @date Feb 10, 2014 | |
/// @version 104 | |
/// | |
/// @copyright (c) Rei VILO, 2013-2014 | |
/// @copyright CC = BY NC SA | |
/// | |
/// @see | |
/// * ReadMe.txt for references | |
/// * TwoWire.h - TWI/I2C library for Arduino & Wiring | |
/// @n Copyright (c) 2006 Nicholas Zambetti. All right reserved. | |
/// * Arduino core files for MSP430 | |
/// @n Copyright (c) 2012 Robert Wessels. All right reserved. | |
#ifndef I2C_MASTER_H | |
#define I2C_MASTER_H | |
#include "Energia.h" | |
#define BUFFER_LENGTH 16 | |
class SoftwareWire { | |
public: | |
SoftwareWire(uint8_t pinSDA, uint8_t pinSCL); | |
void begin(); | |
void beginTransmission(uint8_t address); | |
uint8_t endTransmission(void); | |
uint8_t endTransmission(uint8_t sendStop); | |
virtual size_t write(uint8_t data); | |
virtual size_t write(const uint8_t *data , size_t length); | |
uint8_t requestFrom(uint8_t address, uint8_t length); | |
virtual int available(void); | |
virtual int read(void); | |
virtual int peek(void); | |
virtual void flush(void); | |
private: | |
uint8_t readI2C(uint8_t last=false, bool first=false); | |
uint8_t readI2C(uint8_t* data, uint8_t length); | |
bool restartI2C(uint8_t address, uint8_t RW); | |
bool startI2C(uint8_t address, uint8_t RW); | |
void stopI2C(); | |
void stallI2C(); | |
bool writeI2C(uint8_t data); | |
bool writeI2C(uint8_t* data, size_t length); | |
uint8_t _pinSDA, _pinSCL; | |
static uint8_t txAddress; | |
static uint8_t rxBuffer[]; | |
static uint8_t rxBufferIndex; | |
static uint8_t rxBufferLength; | |
static uint8_t txBuffer[]; | |
static uint8_t txBufferIndex; | |
static uint8_t txBufferLength; | |
static uint8_t transmitting; | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment