+++ /dev/null
-/*
- * Copyright (c) 2008, Titanium Mirror, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * - Neither the name of Titanium Mirror, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * Take an instantaneous reading of the wind vane position as a 10 bit unsigned
- * value. In this case, the instantaneous reading is 4 very fast 12-bit samples
- * plus the possibility of an additional four to deal with the dead band.
- *
- * @author R. Steve McKown <smckown@gmail.com>
- */
-
-generic module WindVaneReadP(uint16_t count) @safe()
-{
- provides interface Read<uint16_t>;
- uses {
- interface ReadRef<uint16_t>;
- interface GeneralIO as WPower;
- interface GeneralIO as WDead;
- interface State;
- }
-}
-implementation
-{
- enum {
- S_IDLE = 0,
- S_READ,
- S_CHECK,
- S_OUTPUT,
-
- /* The wind vane has a dead zone where it returns an ADC value that also
- * represents another angular location. Therefore, we implement special
- * dead zone checking over a certain range of return values from the
- * wind vane, with hardware assistance (WDead).
- *
- * Note: the wind vane's dead zone is probably 5-10 degrees. We would be
- * more accurate if we took the ADC range over 350 or 355 degrees, then
- * added 1/2 of the dead zone as an offset. However, without this logic,
- * the wind vane appears more than accurate enough. It is less accurate
- * within the dead zone, of course, but would be even if we did implement
- * the extra logic.
- */
- DEAD_BEGIN = 1500 * count, /* About 132 degrees */
- DEAD_END = 2500 * count, /* About 220 degrees */
- DEAD_THRESH = 3618 * count, /* > when checking means in dead zone */
-
- /* If we assume the greatest angular velocity of the wind vane is 4 full
- * rotations in a second, then in the 460us it takes to read the vane 4
- * times, it could move over 6 degrees. This means that the vane could
- * cross into, out of, or over the dead band, causing readings that can
- * not be averaged. If we see a delta from min reading to max reading
- * suggesting a large enough deflection, we can assume the reading is
- * invalid.
- */
- MAX_DEFLECT = 1024, /* 90 degrees */
- };
-
- uint16_t m_value;
- uint16_t m_samples[count];
-
- command error_t Read.read()
- {
- if (!(call State.isIdle()))
- return EBUSY;
-
- call WPower.set();
- if (call ReadRef.read(m_samples) == SUCCESS) {
- call State.forceState(S_READ);
- return SUCCESS;
- } else {
- call WPower.clr();
- return FAIL;
- }
- }
-
- void signalReadDone(error_t error, uint16_t value)
- {
- call WDead.makeInput();
- call WPower.clr();
-
- call State.toIdle();
- /* Read has returned a value that is count * 12-bit ADC values. Convert
- * this to a 10-bit value, with rounding.
- */
- value = (value + (count / 2)) / count / 4;
- signal Read.readDone(error, value);
- }
-
- bool badReading(uint16_t* result)
- {
- unsigned i;
- uint16_t min = result[0];
- uint16_t max = result[0];
-
- for (i = 1; i < count; i++) {
- if (result[i] < min)
- min = result[i];
- if (result[i] > max)
- max = result[i];
- }
- return (max - min) > MAX_DEFLECT;
- }
-
- event void ReadRef.readDone(error_t error, uint16_t* result)
- {
- if (error != SUCCESS || badReading(result))
- signalReadDone(error, 0);
- else {
- unsigned i;
- uint16_t value = result[0];
-
- for (i = 1; i < count; i++)
- value += result[i];
-
- switch (call State.getState()) {
- case S_READ:
- if (value < DEAD_BEGIN || value > DEAD_END)
- signalReadDone(SUCCESS, value);
- else {
- m_value = value;
- call WDead.makeOutput();
- if (call ReadRef.read(m_samples) == SUCCESS)
- call State.forceState(S_CHECK);
- else
- signalReadDone(FAIL, 0);
- }
- break;
- case S_CHECK:
- signalReadDone(SUCCESS, (value > DEAD_THRESH) ? 0 : m_value);
- break;
- }
- }
- }
-}