aboutsummaryrefslogtreecommitdiff
path: root/src/core/Wire.cpp
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 /src/core/Wire.cpp
parent23dc1f51056a82884ad3185766ace4af5f5cee94 (diff)
added Wire class but master only
Diffstat (limited to 'src/core/Wire.cpp')
-rwxr-xr-xsrc/core/Wire.cpp519
1 files changed, 519 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
+}
+