Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Master #46

Open
wants to merge 8 commits into
base: rollback
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 7 additions & 17 deletions TinyWireS/TinyWireS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,18 @@ void USI_TWI_S::onRequest( void (*function)(void) )
usi_onRequestPtr = function;
}

// This routine is no longer used now that the usiTwiSlave is completely
// interrupt driven. The function is maintained here so that programs
// written for the pre-interrupt driven version will still compile and function.
void TinyWireS_stop_check()
{
if (!usi_onReceiverPtr)
{
// no onReceive callback, nothing to do...
return;
}
if (!(USISR & ( 1 << USIPF )))
{
// Stop not detected
return;
}
uint8_t amount = usiTwiAmountDataInReceiveBuffer();
if (amount == 0)
{
// no data in buffer
return;
}
usi_onReceiverPtr(amount);
// empty functions
}

// Implement a delay loop that checks for the stop bit (basically direct copy of the stock arduino implementation from wiring.c)
// I don't think this function is necessary now that the
// usiTwiSlave is completely interrupt driven. I'm not sure, and the function is
// behaviorally harmless because TinyWireS_stop_check() is empty, so I'm leaving it alone.
void tws_delay(unsigned long ms)
{
uint16_t start = (uint16_t)micros();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,22 @@

#define I2C_SLAVE_ADDR 0x26 // i2c slave address (38, 0x26)

#define SLAVE_RESET_PIN 2
#if defined(ESP8266)
// pins that work for Monkey Board ESP8266 12-E
// SCL=5, SDA=4
#define SLAVE_RESET_PIN 2
#define ALL_OK_LED_PIN 16
#define OK_LED_PIN 14
#define ERROR_LED_PIN 13
#else
// pins that work for Micro Pro, Uno, Mega 2560
// reference documentation for SCL and SDA pin locations
// Uno SDA=D18, SCL=D19
#define SLAVE_RESET_PIN 6
#define ALL_OK_LED_PIN 9
#define OK_LED_PIN 7
#define ERROR_LED_PIN 8
#endif

uint16_t count = 0; // total number of passes so far
uint16_t error_count = 0; // total errors encountered so far
Expand All @@ -39,22 +54,32 @@ char c_buf[64]; // for creating messages
void setup()
{
// set pin modes
pinMode(SLAVE_RESET_PIN,OUTPUT);
pinMode(SLAVE_RESET_PIN,OUTPUT); // active low reset to slave device
pinMode(OK_LED_PIN,OUTPUT); // indicates last transaction matched
pinMode(ALL_OK_LED_PIN,OUTPUT); // indicates all transactions so far have matched
pinMode(ERROR_LED_PIN,OUTPUT); // indicates last transaction mismatched

// init the serial port
Serial.begin(115200);
Serial.begin(9600);

// print some useful pinnout info for the Arduino
//Serial.println(String("SCL:")+String(SCL)+String(", SDA:")+String(SDA));
//Serial.println(String("MOSI:")+String(MOSI)+String(", SCK:")+String(SCK));

// init the Wire object (for I2C)
Wire.begin();

// init the i2c clock
// default is 100kHz if not changed
// Wire.setClock(400000L); // 400kHz

// reset the slave
digitalWrite(SLAVE_RESET_PIN, LOW);
delay(10);
digitalWrite(SLAVE_RESET_PIN, HIGH);

// set the all okay pin high
digitalWrite(ALL_OK_LED_PIN, HIGH);

// wait for slave to finish any init sequence
delay(2000);
Expand All @@ -74,11 +99,11 @@ void loop()
count++;

// compute random number of bytes for this pass
rand_byte_count = random(12) + 1;
rand_byte_count = random(16) + 1;

// force the first three requests to be small so that the tx buffer doesn't overflow
// instantly and the user can see at least one successful transaction and some
// mismtaches before the usiTwiSlave.c library hangs on the line "while ( tmphead == txTail );".
// mismtaches before the usiTwiSlave.c library hangs on the line "while ( !txCount );".
if (count <= 3) rand_byte_count = 2;

// generate, save, and send N random byte values
Expand All @@ -87,8 +112,12 @@ void loop()
Wire.write(out_rand[i] = random(256));
Wire.endTransmission();

//delay (10); // optional delay if required by slave (like sample ADC)

// delay 20 milliseconds to accomodate slave onReceive() callback
// function. The actual time that slave takes is application dependent, but
// just storing the master's transmitted data does not take
// anywhere near 20ms.
delay(20);

// read N bytes from slave
req_rtn = Wire.requestFrom(I2C_SLAVE_ADDR, (int)rand_byte_count); // Request N bytes from slave
for (i = 0; i < req_rtn; i++)
Expand All @@ -101,9 +130,22 @@ void loop()

// increment the error counter if the number of byte variables don't match or
// if the data itself doesn't match
if (mismatch || (rand_byte_count != req_rtn)) error_count++;
if (mismatch || (rand_byte_count != req_rtn))
{
error_count++;
digitalWrite(ERROR_LED_PIN, HIGH);
digitalWrite(OK_LED_PIN, LOW);
// If there's ever an error, reset the ALL_OK_LED
// and it is not set again until the master resets.
digitalWrite(ALL_OK_LED_PIN, LOW);
}
else
{
digitalWrite(ERROR_LED_PIN, LOW);
digitalWrite(OK_LED_PIN, HIGH);
}

// The rest of the program just displays the results
// The rest of the program just displays the results to the serial port

// display total requests so far and error count so far
snprintf(c_buf, sizeof(c_buf), "req: %3d,err: %3d", count, error_count);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,42 @@
// Please see credits and usage for usiTwiSlave and TinyWireS in the .h files of
// those libraries.

#include <avr/sleep.h>
#include <avr/wdt.h>
#include "TinyWireS.h" // wrapper class for I2C slave routines

#define I2C_SLAVE_ADDR 0x26 // i2c slave address (38, 0x26)

// turns on code that makes the Tiny85 sleep between transactions
// This is optional. The Tiny85 current drops from
// about 2mA to about 20uA when the CPU is put into
// PowerDown sleep mode.
#define USE_CPU_SLEEP

// global buffer to store data sent from the master.
uint8_t master_data[16];
// global variable to number of bytes sent from the master.
uint8_t master_bytes;

// Gets called when the ATtiny receives an i2c write slave request
// This routine runs from the usiTwiSlave interrupt service routine (ISR)
// so interrupts are disabled while it runs.
void receiveEvent(uint8_t num_bytes)
{
uint8_t i;

// save the number of bytes sent from the master
master_bytes = num_bytes;

// store the data from the master into the data buffer
for (i = 0; i < master_bytes; i++)
master_data[i] = TinyWireS.receive();

}

// Gets called when the ATtiny receives an i2c read slave request
// This routine runs from the usiTwiSlave interrupt service routine (ISR)
// so interrupts are disabled while it runs.
void requestEvent()
{
uint8_t i;
Expand All @@ -61,20 +73,20 @@ void requestEvent()
TinyWireS.send(master_data[i]);

// corrupt the byte values in the data buffer
// so that subsequent call won't match
// so that any subsequent call won't match
for (i = 0; i < master_bytes; i++)
master_data[i] += 0x5a;

// corrupt length of the request, but dont' make it zero
// corrupt length of the request, but don't make it zero

// if the usiTwiSlave.c is working fine, then this number is completely irrelevant
// because the requestEvent() callback will not be called again until
// after the next receiveEvent() callback, so the master_data and
// master_bytes variables will be set by that call.
// master_bytes variables will be overwritten by that call.

// If the usiTwiSlave.c has the issue of calling the requestFrom() callback
// for each byte sent, the buffer will accumulate by this amount *for each byte
// in the original request*.
// in the original request*. (This problem is fixed in the recent version.)
//
// Making it zero will obscure the 1-byte send issue in the usiTwiSlave.c
// that is being tested.
Expand All @@ -86,6 +98,8 @@ void requestEvent()

void setup()
{
//pinMode(1,OUTPUT); // This pin can be used for rudimentary debug

// initialize the TinyWireS and usiTwiSlave libraries
TinyWireS.begin(I2C_SLAVE_ADDR); // init I2C Slave mode

Expand All @@ -94,11 +108,36 @@ void setup()

// register the onRequest() callback function
TinyWireS.onRequest(requestEvent);

// disable the watchdog timer so that it doesn't
// cause power-up, code is from datasheet
// Clear WDRF in MCUSR – MCU Status Register
// MCUSR provides information on which reset source caused an MCU Reset.
MCUSR = 0x00;
// WDTCR - Watchdog Timer Control Register
// Write logical one to WDCE and WDE (must be done before disabling)
WDTCR |= ( _BV(WDCE) | _BV(WDE) );
// Turn off WDT
WDTCR = 0x00;

#ifdef USE_CPU_SLEEP
// enable power down sleep mode
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode
sleep_enable();
#endif

sei(); // enable interrupts

}

void loop()
{
// This needs to be here
TinyWireS_stop_check();
// otherwise empty loop

#ifdef USE_CPU_SLEEP
// optionally put the CPU to sleep. It will be woken by a USI interrupt
// when it sees a "start condition" on the I2C bus. Everything interesting
// happens in the usiTwiSlave ISR.
sleep_cpu();
#endif

}
Loading