Friday, September 26, 2008

final results


On the picture you can see my test equipment for the FTDI. Three parts are involved:

1. Asus EEE PC as platform
2. FTDI interface board ( small one)
3. I2C I/O board ( big one )

The final test I did was based on the fact that I simulated the real domotic logic as close as possible to the final program logical blocks. I also included the fact of worse case timings. The best way to explain this is by showing you the piece of test code I wrote:

void TestWorstCaseTiming(void)

{
 UCHAR in [5]; //I2C InBuf
 UCHAR out [5]; //I2C OutBuf
 UCHAR ad [1]; //Int

 //*********INIT BLOCK
 status = FTDI_I2C_STARTUP( _400KHZ );
 //*********PREPARE IN AND INVERT
 status = FTDI_I2C_PCA_READN_ALL( PCA9698_INPUT_READ , in );
 BitSetExtended<40> InSet(in);// start with real values
 InSet.flip();// invert push = 1
 //*********PREPARE OUT ALL TO ZERO
 BitSetExtended<40> OutSet(CmdOut);
 //OutSet.none();
 OutSet.ToByteBuf(CmdOut);
 status = FTDI_I2C_PCA_WRITE_ALL( PCA9698_OUTPUT_WRITE , CmdOut );//16ms
 //*********MAIN LOOP
 while (1)
 {
  //*********POLL LOOP
  status = FTDI_2XX_READN_ADBUS(ad);
  while ( (ad[0] & INT_MASK_FLAG) != 0 )
  {
  //overwrite time to have total chain time at the end
  GetSystemTime(&begin);
  status = FTDI_2XX_READN_ADBUS(ad);//2ms
  }
  //*********DOMOTICS LOGIC READ
  status = FTDI_I2C_PCA_READN_ALL( PCA9698_INPUT_READ , in );//22ms
  //*********DOMOTICS LOGIC COMPARE AND MODIFY
  BitSetExtended<40> InNew(in);
  InNew.flip();
  for ( int input = 0 ; input <>
  {
  if ( (InSet[input] != InNew[input]) && (InNew.test(input)) )
  {
  OutSet.flip(input);
  }
  }
  //*********DOMOTICS LOGIC UPDATE LAST IN
  InSet = InNew;
  //*********DOMOTICS LOGIC PREPARE AND OUT
  OutSet.ToByteBuf(CmdOut);
  status = FTDI_I2C_PCA_WRITE_ALL( PCA9698_OUTPUT_WRITE , CmdOut );//16ms
  status = FTDI_I2C_DAC_SET(0,0);//10ms
  //*********CHECK TIME
  //Sleep(30); simulate cpu charge
  GetSystemTime(&end);
  printf ("cpu time : %d ms\n",end.wMilliseconds-begin.wMilliseconds);
  // should be ca 50ms + Xms logic
 }
}


The program flow is very simple. I poll on interrupt flag change in the inner while loop. As soon this becomes signals I leave the loop to read in the values of the PCA-IN. I check upon which bits are changed and also if this bit equal to 1. Due to the fact I use the inputs as button device I'm not interested if this bit is zero because this indicates the released state. I'm only act upon state pushed here. I invert the PCA-OUT accordingly to have a toggle behaviour on the leds. I didn't use a complex mapping for the in and out simply in-bit[0] relates to out-bit[0] etc for all 40 of them. Finally I write the new output state to the I/O board. I also added the DAC write just for timing simulating purposes but has no further meaning in this test. As you can see in the code I use the BitSetExtended<40> InNew(in) class. This one I wrote to ease the work with atomic bits. It's an extended (derived) STD class of BitSet:

template class BitSetExtended : public bitset<_n>
{
 typedef __int64 _Ty;
 public:
  BitSetExtended ( );
  BitSetExtended ( __int64 ll );
  BitSetExtended ( PUCHAR pC );
  void ToByteBuf ( PUCHAR pC);
 private:
  enum { _Nb = CHAR_BIT * sizeof (_Ty),_Nw = _N == 0 ? 0 : (_N - 1) / _Nb };
  void _Treat64( __int64 _X);
  void _Tidy(_Ty _X = 0);
  void _Trim( void );
  _Ty _A[_Nw + 1];

};

My estimated 50ms total time was quite correctly. I tried pretty much with a real button switch connected on several inputs to check if the program was fast enough to trigger all interrupt coming from the PCA-IN. And it worked very well I must say ! I can in some unreal conditions trigger an error but this really testing as a fool and can not be compared to the usual real life application. I inserted a sleep line in the code to simulate higher domotic logic execution time. I went even to 30ms and my system continued working stable. I need this test to be sure that with the final code ,which will be much more than what I have now, the program will not suffer any timing site effects.

Conclusion:

I find this a very good result even with quit slow communication of the FTDI USB device. In this test I wrote the code chained one block after the other. I didn't use any optimizations on the code flow and avoided working with multiple threads. I can think of a couple changes in terms of logic and threading which can optimize the program a little bit eg seperate the poll code into one thread using events and syncronizations on the FTDI object. Perhaps writing the read-in bits to a queue system and trait the changes in an other thread. I will look into this possibilties soon and report in my blog as usually do. But I must say I'm one step closer to my decision for taking this approach as my future domotic server.

No comments: