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