aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlynxeyed-atsu <lynxeyed@xj9.so-net.ne.jp>2012-05-12 16:36:44 +0900
committerlynxeyed-atsu <lynxeyed@xj9.so-net.ne.jp>2012-05-12 16:36:44 +0900
commit035e464f9db8b689e58a4f3fe277bd9eaeedf900 (patch)
tree0b14a9deb4fbe4dc15b3777513eb8acda9adc61f
parent23dc1f51056a82884ad3185766ace4af5f5cee94 (diff)
added Wire class but master only
-rwxr-xr-xsrc/core/Wire.cpp519
-rwxr-xr-xsrc/core/Wire.h97
2 files changed, 616 insertions, 0 deletions
diff --git a/src/core/Wire.cpp b/src/core/Wire.cpp
new file mode 100755
index 0000000..04150cf
--- /dev/null
+++ b/src/core/Wire.cpp
@@ -0,0 +1,519 @@
+#include "Wire.h"
+#include <stdio.h>
+#include <string.h>
+#include <string>
+
+
+void i2c_startbit(int sda, int scl);
+void i2c_stopbit(int sda, int scl);
+void i2c_begin_transmission(int sda, int scl, unsigned char address);
+uint8_t i2c_request_from(int sda, int scl, unsigned char address, unsigned char* data, unsigned char counter);
+uint8_t i2c_recv_byte(int sda, int scl, WIRE_ACK_STATE ack);
+uint8_t i2c_read(int sda, int scl, uint8_t addr, uint8_t* data, uint8_t nbytes);
+WIRE_ACK_STATE i2c_write(int sda, int scl, uint8_t addr, uint8_t* data, uint8_t nbytes);
+WIRE_ACK_STATE i2c_send_byte(int sda, int scl, uint8_t data);
+WIRE_ACK_STATE i2c_ping(int sda, int scl,uint8_t addr);
+
+inline void WAIT(void);
+inline int SCL_IN(int scl);
+inline int SDA_IN(int sda);
+inline void SDA_REL(int sda);
+inline void SCL_REL(int scl);
+inline void SDA_PUL(int sda);
+inline void SCL_PUL(int scl);
+inline void SCL_SDA_PUL(int scl,int sda);
+
+// Initialize Class Variables //////////////////////////////////////////////////
+TwoWire::TwoWire()
+{
+ rxAddress = 0;
+ rxBuffer[BUFFER_LENGTH];
+ rxBufferIndex = 0;
+ rxBufferLength = 0;
+
+ txAddress = 0;
+ txBuffer[BUFFER_LENGTH];
+ txBufferIndex = 0;
+ txBufferLength = 0;
+
+ transmitting = 0;
+ user_onRequest = NULL;
+ user_onReceive = NULL;
+}
+
+
+void TwoWire::begin(void)
+{
+ rxBufferIndex = 0;
+ rxBufferLength = 0;
+
+ txBufferIndex = 0;
+ txBufferLength = 0;
+
+ sda = 18;
+ scl = 19; //Arduino's default TWI pins(D18,D19)
+
+ begin(sda, scl);
+}
+
+void TwoWire::begin(int sda,int scl)
+{
+ rxBufferIndex = 0;
+ rxBufferLength = 0;
+
+ txBufferIndex = 0;
+ txBufferLength = 0;
+
+ this->sda = sda;
+ this->scl = scl;
+
+ digitalWrite(sda,LOW); // 出力に設定したらLowが出力されるようにしておく
+ digitalWrite(scl,LOW);
+
+ pinMode(sda,INPUT); // 入力(Hi-Z)にしておく
+ pinMode(sda,INPUT);
+
+}
+
+// Slave
+void TwoWire::begin(uint8_t address)
+{
+// twi_setAddress(address);
+// twi_attachSlaveTxEvent(onRequestService);
+// twi_attachSlaveRxEvent(onReceiveService);
+ begin();
+}
+
+// Slave
+void TwoWire::begin(int address)
+{
+ begin((uint8_t)address);
+}
+
+uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
+{
+ // clamp to buffer length
+ if(quantity > BUFFER_LENGTH){
+ quantity = BUFFER_LENGTH;
+ }
+ // perform blocking read into buffer
+ //uint8_t read = twi_readFrom(address, rxBuffer, quantity);
+ uint8_t read = i2c_request_from(sda, scl, address, rxBuffer, quantity);
+
+ // set rx buffer iterator vars
+ rxBufferIndex = 0;
+ rxBufferLength = read;
+
+ return read;
+}
+
+uint8_t TwoWire::requestFrom(int address, int quantity)
+{
+ return 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);
+}
+
+uint8_t TwoWire::endTransmission(void)
+{
+ // transmit buffer (blocking)
+ //signed int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1);
+ i2c_begin_transmission(sda, scl, txAddress);
+ WIRE_ACK_STATE st = i2c_write(sda, scl, txAddress, txBuffer, txBufferLength);
+
+ unsigned char res = 0; //return value (0:OK, 1:BUFFER OV, 2:ADDRESS NAK, 3:DATA NAK, 4:Another error)
+ i2c_stopbit(sda, scl);
+ switch(st)
+ {
+ case ACK: res = 0; break;
+ case BUFF_OV: res = 1; break;
+ case ADDR_NAK: res = 2; break;
+ case AND_MORE: res = 4; break;
+ default: res = 4;
+ }
+ // reset tx buffer iterator vars
+ txBufferIndex = 0;
+ txBufferLength = 0;
+ // indicate that we are done transmitting
+ transmitting = 0;
+ return res;
+}
+
+// must be called in:
+// slave tx event callback
+// or after beginTransmission(address)
+void TwoWire::send(int8_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(int8_t* data)
+{
+ send((uint8_t *)data, strlen((const char*)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 int8_t
+ // for people using with int8_t 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;
+}
+
+// Preinstantiate Objects ////////////
+
+TwoWire Wire = TwoWire();
+
+//-------------------------------------------------------------------------------
+// Lowlevel
+//-------------------------------------------------------------------------------
+
+uint8_t i2c_request_from(int sda, int scl, unsigned char address, unsigned char* data, unsigned char counter)
+{
+ i2c_startbit(sda, scl);
+ i2c_ping(sda, scl, address);
+ uint8_t result_bytes = i2c_read(sda, scl, address, data, counter); //counterは受信要求バイト数
+ i2c_stopbit(sda, scl);
+ return result_bytes; //i2c->st_request_countは実際に受信できたバイト数
+}
+
+void i2c_begin_transmission(int sda, int scl, unsigned char address)
+{
+ i2c_startbit(sda, scl);
+ i2c_ping(sda, scl, address);
+}
+
+WIRE_ACK_STATE i2c_write(int sda, int scl, uint8_t addr, uint8_t* data, uint8_t nbytes)
+{
+ //uint8_t addr;
+ uint8_t* data_end = data + nbytes;
+ if(i2c_send_byte(sda, scl, (addr << 1) | 0x00) != 0)
+ {
+ //i2c->st_ack = NAK;
+ //i2c->st_nack = DATA_NAK;
+ return ADDR_NAK;
+ }
+ while(data != data_end){
+ if(i2c_send_byte(sda, scl, *data++) != ACK)
+ {
+ //i2c->st_ack = ACK;
+ return DATA_NAK;
+ }
+ }
+ return ACK;
+}
+
+//戻り値は読み込めたバイト数
+uint8_t i2c_read(int sda, int scl, uint8_t addr, uint8_t* data, uint8_t nbytes)
+{
+ //uint8_t addr = i2c->st_your_sddress;
+ uint8_t counter = 0;// = i2c->st_request_count;
+ uint8_t* data_end = data + nbytes;
+ if(i2c_send_byte(sda, scl, (addr << 1) | 0x01) != 0)
+ {
+ //NAK;
+ //ADDR_NAK
+ return counter;
+ }
+ while(data != data_end){
+ *data = i2c_recv_byte(sda, scl, (data != data_end - 1)?ACK:NAK);
+ data++;
+ counter++;
+ }
+ //i2c->st_ack = ACK;
+ //i2c->st_request_count = counter;
+ return counter;
+}
+
+void i2c_startbit(int sda, int scl)
+{
+ WAIT();
+ if(!SCL_IN(scl) || !SDA_IN(sda))
+ {
+ if(SCL_IN(scl)){
+ SCL_PUL(scl);
+ WAIT();
+ }
+ if(!SDA_IN(sda)){
+ SDA_REL(sda);
+ WAIT();
+ }
+ SCL_REL(scl);
+ WAIT();
+ }
+ SDA_PUL(sda);
+ WAIT();
+ SCL_PUL(scl);
+ WAIT();
+ /* SCL = SDA = L */
+}
+
+WIRE_ACK_STATE i2c_send_byte(int sda, int scl, uint8_t data)
+{
+ /* assume SCL = SDA = L */
+ WIRE_ACK_STATE ack;
+ volatile int i;
+ for(i = 0; i < 8; i++)
+ {
+ if(data & 0x80)
+ SDA_REL(sda);
+ else SDA_PUL(sda);
+ WAIT();
+ WAIT();
+ SCL_REL(scl);
+ WAIT();
+ WAIT();
+ if(i != 7)
+ data <<= 1;
+ SCL_PUL(scl);
+ }
+ WAIT();
+ WAIT();
+ SDA_REL(sda);
+ SCL_REL(scl);
+ WAIT();
+ /*while(SCL_IN == 0);*/ /* スレーブによるクロックの引き延ばし */
+ ack = (SDA_IN(sda)==0)? ACK:NAK;
+ WAIT();
+ WAIT();
+ SCL_SDA_PUL(sda,scl);
+ /* SCL = SDA = L */
+ return ack;
+}
+
+void i2c_stopbit(int sda, int scl)
+{
+ /* assume SCL = SDA = L */
+ WAIT();
+ SCL_REL(scl);
+ WAIT();
+ SDA_REL(sda);
+ WAIT();
+ /* SCL = SDA = H */
+}
+
+uint8_t i2c_recv_byte(int sda, int scl, WIRE_ACK_STATE ack)
+{
+
+ /* SCL = SDA = L */
+ volatile uint8_t data;
+ volatile int i;
+ SDA_REL(sda);
+ for(i = 0, data = 0; i < 8; i++){
+ WAIT();
+ WAIT();
+ SCL_REL(scl);
+ if(SDA_IN(sda))
+ data |= 0x01;
+ else data &= ~0x01;
+ WAIT();
+ WAIT();
+ if(i != 7)
+ data <<= 1;
+ SCL_PUL(scl);
+ }
+ if(ack) /* ack送信 */
+ SDA_REL(sda);
+ else
+ SDA_PUL(sda);
+ WAIT();
+ WAIT();
+ SCL_REL(scl);
+ WAIT();
+ WAIT();
+ SCL_PUL(scl);
+ SDA_PUL(sda);
+ /* SCL = SDA = L */
+ return data;
+}
+
+
+
+WIRE_ACK_STATE i2c_ping(int sda, int scl,uint8_t addr)
+{
+ WIRE_ACK_STATE ack;
+ //uint8_t addr = i2c->st_your_sddress;
+ i2c_startbit(sda, scl);
+ ack = i2c_send_byte(sda, scl, (addr << 1) | 0x00);
+ i2c_stopbit(sda, scl);
+ return ack;
+}
+
+//ピンの制御
+//Sxx_PUL = Low
+//Sxx_REL = Hi-Z
+inline void WAIT(void)
+{
+ delay(1);
+}
+
+inline int SCL_IN(int scl)
+{
+ return digitalRead(scl);
+}
+
+inline int SDA_IN(int sda)
+{
+ return digitalRead(sda);
+}
+
+inline void SDA_REL(int sda)
+{
+ pinMode(sda, INPUT); //入力=Hi-Z
+}
+
+inline void SCL_REL(int scl)
+{
+ pinMode(scl, INPUT); //入力=Hi-Z
+}
+
+inline void SDA_PUL(int sda)
+{
+ digitalWrite(sda, LOW);
+ pinMode(sda, OUTPUT); //出力=Low
+}
+
+inline void SCL_PUL(int scl)
+{
+ digitalWrite(scl, LOW);
+ pinMode(scl, OUTPUT); //出力=Low
+}
+
+inline void SCL_SDA_PUL(int scl,int sda)
+{
+ digitalWrite(sda, LOW);
+ digitalWrite(scl, LOW);
+ pinMode(scl, OUTPUT); //出力=Low
+ pinMode(sda, OUTPUT); //出力=Low
+}
+
diff --git a/src/core/Wire.h b/src/core/Wire.h
new file mode 100755
index 0000000..67c47e5
--- /dev/null
+++ b/src/core/Wire.h
@@ -0,0 +1,97 @@
+#ifndef WIRE_H_
+#define WIRE_H_
+
+/**************************************************************************//**
+ * @file Wire.h
+ * @brief Arduino-like library for MARY
+ * @version V0.50
+ * @date 4. April 2012.
+ * @author @@lynxeyed_atsu
+ * @note Copyright (c) 2011 Lynx-EyED's Klavier and Craft-works. <BR>
+ * 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: <BR>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.<BR>
+ * 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.
+ ******************************************************************************/
+#include "LPC11xx.h"
+#include <libmary.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define BUFFER_LENGTH 32
+
+/*! @enum WIRE_ACK_STATE
+ @brief I2Cでバイトデータを送った際にスレーブからの値を返す
+*/
+typedef enum {
+ ACK = 0, /*!< ACK(入力バイトは承認された) */
+ NAK, /*!< ACK(入力バイトは承認されなかった) */
+ BUFF_OV, /*!< バッファオーバーフロー */
+ ADDR_NAK, /*!< スレーブへアドレスを送信しNACKを受信した */
+ DATA_NAK, /*!< スレーブへデータを送信しNACKを受信した */
+ AND_MORE /*!< その他のエラー */
+} WIRE_ACK_STATE;
+
+class TwoWire{
+
+private:
+ uint8_t rxAddress;
+ uint8_t rxBuffer[];
+ uint8_t rxBufferIndex;
+ uint8_t rxBufferLength;
+
+ uint8_t txAddress;
+ uint8_t txBuffer[];
+ uint8_t txBufferIndex;
+ uint8_t txBufferLength;
+
+ int sda,scl;
+
+ uint8_t transmitting;
+ void (*user_onRequest)(void);
+ void (*user_onReceive)(int);
+ void onRequestService(void);
+ void onReceiveService(uint8_t*, int);
+
+
+public:
+ TwoWire();
+ void begin();
+ void begin(uint8_t);
+ void begin(int);
+ void begin(int,int);
+ void beginTransmission(uint8_t);
+ void beginTransmission(int);
+ uint8_t endTransmission(void);
+ uint8_t requestFrom(uint8_t, uint8_t);
+ uint8_t requestFrom(int, int);
+ void send(int8_t);
+ void send(uint8_t*, uint8_t);
+ void send(int8_t*);
+ void send(int);
+ uint8_t available(void);
+ uint8_t receive(void);
+ void onReceive( void (*)(int) );
+ void onRequest( void (*)(void) );
+};
+
+extern TwoWire Wire;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* WIRE_H_ */