Constructor hanging at Wire.endTransmission()

I am attempting to write yet another class object for the DS1307.
I want to have a constructor that will accept the compile date and time constants as parameters. The constructor will parse the strings into time elements. It will then read previous time elements from the 56 bytes of ram also on the DS1307. If the times are different then the clock is reset to the compile time.
The works under the assumption that a sketch is compiled just before it is uploaded. And the sketch executes as soon as it is uploaded. Therefore, the clock will be reset to the clock time of the computer (allowing for the fact that there are some seconds between the time the sketch is compiled and when it executes).

My problem occurs at the point where I am reading the old values from the RAM. The sketch hangs at the endTransmission() call. My code looks like:

//  DS1307(__DATE__, __TIME__);
DS1307::DS1307(const char* date, const char* time)
{
...
  Wire.begin();
...
  Wire.beginTransmission(DS1307_CTRL_ID);
  Wire.write(60);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_CTRL_ID, 4);
  while (Wire.available()) {
      OldValBuf[i++] = Wire.read();
  }
...
}

I have done some poking around in the twi.c and found:

while(TWI_READY != twi_state){
    continue;

but I don't know what it takes to get the twi in a ready state other than "twi_init()" and that is called from "Begin"

I suspect that the DS1307 constructor is being called before the Wire constructor. Since the Wire object isn't valid yet the Wire.begin() may be failing.

Rather than creating the object with date and time you might want to create the object empty and set the data and time at run time.

I call the "begin" method in the DS1307 constructor. I would not think that it would be possible to call a method before it was constructed.

Since Wire.begin() returns a void it does not report it's success.

  rxBufferIndex = 0;   rxBufferLength = 0;
  txBufferIndex = 0;  txBufferLength = 0;
  twi_init();

Rather than creating the object with date and time you might want to create the object empty and set the data and time at run time.

I may have to but I won't "want" to.

I'd not do anything in the constructor except initialise the object's memory state - top level constructors get called early.

So by all means pass in the time parameters in the constructor but don't use them till begin() is called.

The DS1307 class has no member variable/properties. All the methods are 'static' so there is almost no reason to instantiate an object if I can not set the date in the constructor. There is no "Begin" for the DS1307 class and the I call the Wire.begin with I was getting the hang.

Exactly, I'm suggesting you pass the information to the constructor, but don't do anything on the bus till calling a method Begin() - ie write a Begin() and move the code to it. Then you get control of when things happen.

Or you can leave the constructor empty and define a function init() where you set the time and date.
In C++, the role of the constructor is to initialize the object memory.

RandallR:
My code looks like:

//  DS1307(__DATE__, __TIME__);

DS1307::DS1307(const char* date, const char* time)
{
...
 Wire.begin();
...
 Wire.beginTransmission(DS1307_CTRL_ID);
 Wire.write(60);
 Wire.endTransmission();

Wire.requestFrom(DS1307_CTRL_ID, 4);
 while (Wire.available()) {
     OldValBuf[i++] = Wire.read();
 }
...
}

This is too much to be doing in a constructor IMHO. Especially one which is for an object created statically.

Remember, after your constructor is called main is executed (since that is a function). The first thing main does is call init. The first thing init does is:

	sei();

So, first problem. Interrupts are not enabled. And endTransmission uses interrupts.

If you create your object dynamically there shouldn't be a big problem. That is:

DS1307 * foo = new DS1307 (__DATE__, __TIME__);

(edit)

Preferably separating the two actions. eg.

DS1307 * foo;  // declare it
void setup ()
  {
  foo = new DS1307 (__DATE__, __TIME__);  // create an instance
...
  }

But if you are going to do that you may as well just use the "foo.begin ()" idea.

OK, well its not my preferred solution but for a work around I did this.
I created a function to parse the data and time to give me a time object.

time_t CompileTime(const char* datetime);

I then create a macro to invoke the function

#define COMPILE_TIME   CompileTime(__DATE__ __TIME__)

I then use the macro in my code in the "setup()"

void setup () {
  time_t t = COMPILE_TIME;
  setTime(t);
...

Its not perfect, but it will work.

I presume you are going to have some test there, that you don't do that every time the chip is reset. Otherwise the clock won't be very useful.

Of course. I use this stripped down code just to set them time when I don't have a RTC and just need a reasonable time. Usually I am compiling and testing so much that the time is usually quite close.
When I have the DS1307 attached, I convert the time into 4 bytes and check them against the last 4 bytes in the clock's RAM (60-63). If they are different, I update the clock and store the bytes into the RAM. If they are the same, I use the clock's time.