*/
/**
- * Take an instantaneous reading of the wind vane position, in degrees.
+ * Take an instantaneous reading of the wind vane position as a 10 bit unsigned
+ * value.
*
* @author R. Steve McKown <smckown@gmail.com>
*/
provides interface Read<uint16_t>;
}
implementation {
- components WindVaneReadP;
+ enum { SAMPLES_PER_READ = 4, };
+
+ components new WindVaneReadP(SAMPLES_PER_READ);
Read = WindVaneReadP;
- components new MultiSampleC(uint16_t, 4);
- WindVaneReadP.Count -> MultiSampleC;
- WindVaneReadP.SubRead -> MultiSampleC;
+ components new MultiSampleC(SAMPLES_PER_READ);
+ WindVaneReadP.ReadRef -> MultiSampleC;
components WindVaneAdcP;
MultiSampleC.AdcConfigure -> WindVaneAdcP;
WindVaneReadP.WPower -> HalWindVaneC.WPower;
WindVaneReadP.WDead -> HalWindVaneC.WDead;
+ components new AverageAngleC(SAMPLES_PER_READ);
+ WindVaneReadP.Average -> AverageAngleC;
+
components new StateC();
WindVaneReadP.State -> StateC;
}
*/
/**
- * Take an instantaneous reading of the wind vane position.
+ * Take an instantaneous reading of the wind vane position as a 10 bit unsigned
+ * value.
*
* @author R. Steve McKown <smckown@gmail.com>
*/
-module WindVaneReadP @safe()
+generic module WindVaneReadP(uint16_t count) @safe()
{
provides interface Read<uint16_t>;
uses {
- interface Get<uint16_t> as Count;
- interface Read<uint16_t> as SubRead;
+ interface ReadRef<uint16_t>;
interface GeneralIO as WPower;
interface GeneralIO as WDead;
+ interface Average<uint16_t>;
interface State;
}
}
* within the dead zone, of course, but would be even if we did implement
* the extra logic.
*/
- DEAD_BEGIN = 6000, /* 4 12-bit ADC readings; about 120 degrees */
- DEAD_END = 10000, /* About 220 degrees */
+ DEAD_BEGIN = 1500, /* 10-bit degree value; about 120 degrees */
+ DEAD_END = 2500, /* About 220 degrees */
DEAD_THRESH = 14472, /* > when checking means in dead zone */
};
- char m_msg[80];
+ uint16_t m_value;
+ uint16_t m_samples[count];
command error_t Read.read()
{
return EBUSY;
call WPower.set();
- if (call SubRead.read() == SUCCESS) {
+ if (call ReadRef.read(m_samples) == SUCCESS) {
call State.forceState(S_READ);
return SUCCESS;
} else {
call WDead.makeInput();
call WPower.clr();
- /* Value is the sum of multiple 12-bit ADC acquisitions, per the attached
- * MultiSampleC component. Convert the value to degrees. Note, the values
- * 360 and 0 (zero) represent the same angular position. We don't do a
- * modulus operation here because we fully expect the client will do
- * additional processing that will likely involve a modulus function anyway.
- */
- value = (uint16_t)(((uint32_t)(value / call Count.get()) * 360 + 2047) /
- 4096);
-
call State.toIdle();
signal Read.readDone(error, value);
}
- event void SubRead.readDone(error_t error, uint16_t result)
- {
- static uint16_t m_value;
+ void averageAngle();
- if (error != SUCCESS) {
+ event void ReadRef.readDone(error_t error, uint16_t* result)
+ {
+ if (error != SUCCESS)
signalReadDone(error, 0);
- return;
- }
+ else
+ averageAngle();
+ }
+ void averageAngle()
+ {
+ unsigned i;
+
+ /* Submit a full set of values to be averaged, which will cause
+ * Average.average() to be signalled.
+ */
+ call Average.reset();
+ for (i = 0; i < count; i++)
+ call Average.submit(m_samples[i]);
+ }
+
+ event void Average.average(uint16_t result)
+ {
switch (call State.getState()) {
case S_READ:
if (result < DEAD_BEGIN || result > DEAD_END)
else {
m_value = result;
call WDead.makeOutput();
- if (call SubRead.read() == SUCCESS)
+ if (call ReadRef.read(m_samples) == SUCCESS)
call State.forceState(S_CHECK);
else
signalReadDone(FAIL, 0);