This seems like it should be simple, but of course it's not...

I have a T1 module with the usual standard control functions,
implementing the SplitControl interface -- although it doesn't
seem to matter, I tried StdControl too.

For some reason I cannot put calls to other module interfaces
in the *Control.start() function. I get this error:

  In component `cryoSensorM':
  cryoSensorM.nc: In function `SplitControl.start':
  cryoSensorM.nc:126: I2CPacketControl.start not connected
  cryoSensorM.nc:129: I2CPacket.writePacket not connected

(The same thing happens with Timer.start() so it's not just
the I2C stuff. And there seem to be plenty of examples of
doing this in other modules that I don't need to use...)

If I move the offending code to any other function, e.g.,
init() or stop() I get no complaints and a no-error compile.
And all other calls to the I2CPacket module in the file
seem to pass muster just fine. If I move the code to a
sub-function, or a sub-task, I still get the complaint,
so somehow it knows what I want to do and refuses to comply.
Moving the whole start() function around doesn't matter either.

I'm using Moteworks, which is some mystery late version of TOS1.x,
and compiling for the iris platform with the "route.hp" option
that does some magic in their MULTIHOP XMESH compile system.

I've attached the config and code files for this module, but not
the entire program. If you really want to try compiling the whole
thing I'll gladly send you everything. Look for `SplitControl.start'
to see where I've marked the lines that cause the trouble.

thx
MS
/* cryoSensorM.nc -- Implementation of Cryopoint sensor and ADC circuit
 *                                       using ST18 I2C->SPI and AD7793 chips.
 *                                      Presents a standard TOS ADC interface 
for sampling.
 *
 * Authors:             M.Schippling, based on Crosbow mts400/cryoSensorM.nc
 *                                      version 0.1  07/16/09
includes cryosensor;
includes cryopointMsg;
 */

module cryoSensorM
{
  provides
  {
    interface ADC[uint8_t id];
    interface SplitControl;
        /**
        command void setCalibParams( unsigned int settle,
                                                                 unsigned int 
p1,
                                                                 unsigned int 
p2,
                                                                 unsigned int 
p3,
                                                                 unsigned int 
p4 );
  **/
  }
  uses
  {
    interface StdControl as I2CPacketControl;
    interface I2CPacket;
        interface StdControl as TimerControl;
    interface Timer;
  }
}
implementation
{
#include "cryosensor.h"
#include "cryopointMsg.h"

//#include "SODebug.h"
//#define DBG_USR2  0  

  // time to wait for conversion complete
  //  ...swag for now...
  #define CONVERT_TIME  250
  // number of chars to read from conversion buffer
  #define READ_BUFSIZE  5

  // the Don't Set value for calib parameters
  #define NOTSET        0xffff

  // default calibration parameters
  #define CR_DEF_SETTLE 10;
  #define CR_DEF_CP1 1;
  #define CR_DEF_CP2 1;
  #define CR_DEF_CP3 1;
  #define CR_DEF_CP4 1;

  // various I2C packets to be sent:
  char pk_I2CCONF[] =                   // ST18 I2C config
        { ST18_I2CFCON, ST18_I2CCONF };
  char pk_ADWRCONF[] =                  // ADC config
        { ST18_I2CFSSD, AD_WRCONF, AD_CONF_B1, AD_CONF_B2_C1 };
  char pk_ADIO[] =                              // ADC IO config
        { ST18_I2CFSSD, AD_IO_B1 };
  char pk_ADCMODE[] =                   // ADC mode and conversion start
    { ST18_I2CFSSD, AD_WRMODE, AD_MODE_SINGLE, AD_MODE_CF };
  char pk_SPIREAD[] =                   // ADC data read command
    { ST18_I2CFSSD, AD_RDDATA, 0xFF, 0xFF, 0xFF, 0xFF };

  // system state indicators
  enum {INIT = 0,                       // hasn't been initialized
                IDLE,                           // initialized, waiting for 
start
                START_SYS,                      // starting
                CONF_ADC,                       // config the ADC chip
                WRITE_ADCIO,            // write IO to ADC
                CALIB_ADC,                      // do ADC calibration
                POWER_ON,                       // powered up and configured
                READY,                          // ready to start conversion
        START_CONV,                     // doing a conversion
        DOING_CONV,                     // doing a conversion
        GET_BUF,                        // setup to get conversion data buffer
        READ_DATA,                      // start reading conversion data back
                PARSE_DATA,                     // parse read data
                STOP_SYS                        // stopping
                };

  unsigned char state = INIT;
  unsigned int settleTime = CR_DEF_SETTLE;
  unsigned int calParam1 = CR_DEF_CP1;
  unsigned int calParam2 = CR_DEF_CP2;
  unsigned int calParam3 = CR_DEF_CP3;
  unsigned int calParam4 = CR_DEF_CP4;


  /***********************************************************************
   * SplitControl interface
   *  Like StdControl but has callbacks to indiate each function complete.
   *  This is only significant for start() which needs a timeout.
   ***********************************************************************/

  /** Init: 
   * - Crank up the subsystems and initialize variables.
   *    May be called multiple times...
   **/
  command result_t SplitControl.init()
  {
        // if we've been here, don't do it
        if( state != INIT )
                return SUCCESS;

//      SODbg(DBG_USR2, "cryoSensor:init \n"); 

    call TimerControl.init(); // Explicitly initialize the TOS Timer ???
    call I2CPacketControl.init();

        // setup our control pins
        TOSH_MAKE_IRIS_sInt_INPUT();            // ST18 interrupt pin
        TOSH_MAKE_IRIS_spiReset_OUTPUT();       // ST18 reset pin
        TOSH_SET_IRIS_spiReset_PIN();           // leave it on, active low
        TOSH_MAKE_IRIS_AnPwrOn_OUTPUT();        // power control
        TOSH_CLR_IRIS_AnPwrOn_PIN();            // shut it off, active high

    atomic state = IDLE;

    signal SplitControl.initDone();       //don't really need this....

        return SUCCESS;;
  }

  /** Start: 
   * - turn power on,
   * - initialize components
   * - wait for sensor settle time
   * - signals startDone() when settling time is over
   **/
  command result_t SplitControl.start()
  {
//      SODbg(DBG_USR2, "cryoSensor:start \n"); 
        // if we've been here, don't do it
        if( state != IDLE )
                if( state == READY )    // already did the start()
                        return SUCCESS;
                else
                        return FAIL;            // summit fubarked

        // startup system
        atomic state = START_SYS;                       // starting

        // Turn on sensor power system
        TOSH_SET_IRIS_AnPwrOn_PIN();            // active high
        TOSH_uwait(10);

        // Init ST18 I2C->SPI convertor
        //  toggle ST18 reset
        TOSH_CLR_IRIS_spiReset_PIN();           // active low
        TOSH_uwait(5);
        TOSH_SET_IRIS_spiReset_PIN();           // leave it on
        TOSH_uwait(10);

  //task void fuckme()
  {
    call I2CPacketControl.start();

        //  write ST18 I2C/SPI CONFIG packet:
        call I2CPacket.writePacket( sizeof(pk_I2CCONF),
                                                                pk_I2CCONF,
                                                                I2CP_I2CFLAGS );
        // writePacketDone will call subsequent functions
  }

    return SUCCESS;
  }

  /** start system state functions, in order of execution
   **  executed from PacketDone or Timer.fired() **/

  // configure the ADC
  void conf_adc()
  {
        atomic state = CONF_ADC;

        // write ADCSPI config packet:
        //      selects channel 1 with defined bias and gain
        call I2CPacket.writePacket( sizeof(pk_ADWRCONF),
                                                                pk_ADWRCONF,
                                                                I2CP_I2CFLAGS );
  }

  // write ADCIO packet
  void write_adcio()
  {
        atomic state = WRITE_ADCIO;

        //      sets excitation current and source config
        call I2CPacket.writePacket( sizeof(pk_ADIO),
                                                                pk_ADIO,
                                                                I2CP_I2CFLAGS );
  }

  // Calibrate ADC
  void calib_adc()
  {
        atomic state = CALIB_ADC;

        //  TBD
        // dummy: fire back to writePacketDone
        signal I2CPacket.writePacketDone( SUCCESS );
  }

  // powered up, do settle time
  void power_on()
  {
        atomic state = POWER_ON;                // powered up and configured

        // wait for settling time
        call Timer.start( TIMER_ONE_SHOT, settleTime );
        // timer.fired will go to READY state and signal startDone()
  }


  /** Stop: 
   * - turn power off
   **/
  command result_t SplitControl.stop()
  {
//         SODbg(DBG_USR2, "cryoSensor:stop \n"); 

        atomic state = STOP_SYS;

        // stop our sub-components
    call I2CPacketControl.stop();
    call Timer.stop();

    // turn the sensor system off
        TOSH_CLR_IRIS_AnPwrOn_PIN();            // shut off power, active high

        // back to IDLE...only to start() again someday
        atomic state = IDLE;

    signal SplitControl.stopDone();       //don't really need this....

    return SUCCESS;
  }

#if 0
  /** Notify user components that this component has been initialized
   *  NOP, but User needs to implement dummy function...
   **/
  default event result_t SplitControl.initDone()
  {
        return SUCCESS;
  }

  /** Notify components that the component has been stopped. 
   *  NOP, but User needs to implement dummy function...
   **/
  default event result_t SplitControl.stopDone()
  {
        return SUCCESS;
  }

  /** Notify components that the component has been started and
   *  is ready to receive other commands, e.g. getData()...
   *  User should implement appropriate behavior
   */
  default event result_t SplitControl.startDone()
  {
        return SUCCESS;
  }
#endif

  /************************************************************************
   * Set the calibration parameters.
   ***********************************************************************/
 // command
  void setCalibParams( unsigned int st,
                                                                 unsigned int 
p1,
                                                                 unsigned int 
p2,
                                                                 unsigned int 
p3,
                                                                 unsigned int 
p4 )
  {
        if( st != NOTSET )
                settleTime = st;

        if( p1 != NOTSET )
                calParam1 = p1;

        if( p2 != NOTSET )
                calParam2 = p2;

        if( p3 != NOTSET )
                calParam3 = p3;

        if( p4 != NOTSET )
                calParam4 = p4;

        return;
  }

  /************************************************************************
   * Use the calibration parameters to convert and return received buffer.
   *  Note: evntually need 32 bit data...
   ***********************************************************************/
  ADC_datatype convertData( char length, char *data )
  {
        return (ADC_datatype) *data;
  }


  /************************************************************************
   * ADC interface
   ***********************************************************************/

  /** continious data not supported
   **/
  async command result_t ADC.getContinuousData[uint8_t id]()
  {
    return FAIL;
  }

  /** Start a single sample cycle.
   **  Signals dataReady() when complete
    *  Ignore the id (set to 1) for now...
        *    could use it to select channels but that gets set in start() now.
        *  Does conversion in multiple phases, Timer.fired() does the 
signalling.
        *  Must be in READY state when entering or FAIL is returned.
   **/
  async command result_t ADC.getData[uint8_t id]()
  {
//    SODbg(DBG_USR2, "cryoSensor:getData \n"); 
        // if we're not ready, don't do it
        if( state != READY )
                return FAIL;            // summit fubarked

        atomic state = START_CONV;

        // Send Single Conversion start command
        //  write ADCMODE packet:
        //   selects clock rate and starts single conversion
        call I2CPacket.writePacket( sizeof(pk_ADCMODE),
                                                                pk_ADCMODE,
                                                                I2CP_I2CFLAGS );
        // writePacketDone will call subsequent functions

        return SUCCESS;
  }

  /** getData system state functions, in order of execution
   **  executed from PacketDone or Timer.fired() **/

  // doing a conversion
  void doing_conv()
  {
        atomic state = DOING_CONV;

        // Wait for conversion time ~100ms (I think)
        call Timer.start( TIMER_ONE_SHOT, CONVERT_TIME );
        // Timer.fired will call subsequent functions
  }

  // initiate the data read
  void get_buf()
  {
        atomic state = GET_BUF;

        // get data from the ADC
        //  write SPIREAD packet with 4 dummy bytes (per ST18 example):
        call I2CPacket.writePacket( sizeof(pk_SPIREAD),
                                                                pk_SPIREAD,
                                                                I2CP_I2CFLAGS );
  }

  // read the conversion data buffer
  void read_data()
  {
        atomic state = READ_DATA;

        // read data from SPIbuffer -- 5 bytes read back from above
        call I2CPacket.readPacket( READ_BUFSIZE,
                                                                I2CP_I2CFLAGS );
        // readPacketDone will call subsequent function
  }

  // parse and calibrate data from given buffer
  void parse_data( char length, char *data )
  {
        ADC_datatype data_adc;  // converted result data

        atomic state = PARSE_DATA;

        data_adc = convertData( length, data );

        // ready for another conversion
        atomic state = READY;

        // tell us about it
        signal ADC.dataReady[1](data_adc);

        return;
  }


#if 0
  /** Signaled when data is available.
   ** User should implement this function to get results.
   **  Note: eventually need to get 24bits of data somehow...
   **/
  default async event result_t ADC.dataReady[uint8_t id](ADC_datatype data)
  {
    return SUCCESS;
  }
#endif


  /************************************************************************
   * I2C packet callbacks
   *  Implement state machine to setup and read data from ADC on SPI bus.
   ***********************************************************************/

  /** Done writing an I2C packet, do various subsequent operations
   **/
  event result_t I2CPacket.writePacketDone(bool result)
  {
        // Note: should check result == FAIL...but WTF...

        switch( state )
        {
                // the start() states
                case START_SYS:                 // done starting
                  conf_adc();
                break;

                case CONF_ADC:                  // done config the ADC chip
                  write_adcio();
                break;

                case WRITE_ADCIO:               // done write IO to ADC
                  calib_adc();
                break;

                case CALIB_ADC:                 // done ADC calibration
                  power_on();   // calls Timer.start for Timer.fired is next...
                break;

                // the getData() states
        case START_CONV:                // done starting a conversion
                  doing_conv(); // calls Timer.start for Timer.fired is next...
                break;

        case GET_BUF:                   // done setup to get conversion data 
buffer
                  read_data();  // calls readPacket, so readPacketDone is 
next...
                break;

                default:
                        return FAIL;
        }

        return SUCCESS;
  }

  /** Done reading an I2C packet, do various subsequent operations
   **/
  event result_t I2CPacket.readPacketDone( char length, char* data )
  {
        switch( state )
        {
        case READ_DATA:                 // done reading conversion data back
                  parse_data( length, data );   // signals dataReady
                break;

                default:
                        return FAIL;
        }

    return SUCCESS;
  }

  /************************************************************************
   * Timer fired, do various subsequent operations
   ***********************************************************************/
  event result_t Timer.fired()
  {
       switch( state )
           {
                case POWER_ON:                  // finished start() settling 
time
                   atomic state = READY;
                   signal SplitControl.startDone();
                break;

        case DOING_CONV:                // done doing getData() conversion
                  get_buf();
                break;

                default:
                        return FAIL;
                }

       return SUCCESS;
  }

} // end'o'cryoSensorM

/* cryoSensor.nc -- Configurationm file for Cryopoint sensor and ADC circuit
 *                                       using ST18 I2C->SPI and AD7793 chips.
 *                                      Presents a standard TOS ADC interface 
for sampling.
 *
 * Authors:             M.Schippling, based on Crosbow mts400/TaosPhoto.nc
 *                                      version 0.1  07/16/09
 */

includes cryosensor;

configuration cryoSensor
{
  provides
  {
    interface ADC[uint8_t id];
    interface SplitControl;
        /**
        command void setCalibParams( unsigned int settle,
                                                                 unsigned int 
p1,
                                                                 unsigned int 
p2,
                                                                 unsigned int 
p3,
                                                                 unsigned int 
p4 );
  **/
  }
}
implementation
{
  components cryoSensorM, I2CPacketC, TimerC;

  SplitControl = cryoSensorM;
  ADC = cryoSensorM;

  cryoSensorM.I2CPacketControl -> I2CPacketC.StdControl;
  cryoSensorM.I2CPacket -> I2CPacketC.I2CPacket[ST18_I2CSLAVE];

  // Explicitly initialise Timer Module
  cryoSensorM.TimerControl -> TimerC.StdControl;
  cryoSensorM.Timer -> TimerC.Timer[unique("Timer")];
}
_______________________________________________
Tinyos-help mailing list
[email protected]
https://www.millennium.berkeley.edu/cgi-bin/mailman/listinfo/tinyos-help

Reply via email to