provides interface ReadRef<wind_vane_t>;
uses {
interface Tick as Second;
- interface AsyncGet<uint8_t> as Vane;
+ interface Read<uint16_t> as Vane;
}
}
implementation {
-#define COMPASS_COUNT 32
+ enum {
+ /* Compass count should ideally be a power of 2, or at least even */
+ COMPASS_COUNT = 36,
+ ADC_PER_HEADING = (4096 + COMPASS_COUNT - 1) / COMPASS_COUNT,
+ ADC_OFFSET = (ADC_PER_HEADING + 1) / 2,
+ ADC_BITMASK = 0x0fff,
+ };
wind_vane_t* m_data;
/* compass[0] = North, 0 degrees,
/*** Method implementations ***/
+ task void startRead()
+ {
+ call Vane.read();
+ }
async event void Second.fired()
{
- const static uint8_t lookup[] = {
- 0x01, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08, 0x18,
- 0x10, 0x30, 0x20, 0x60, 0x40, 0xc0, 0x80, 0x81
- };
- uint8_t wind;
- uint8_t i = 0;
-
- wind = call Vane.get();
- for (i = 0; i < sizeof(lookup); i++) {
- if (lookup[i] == wind) {
- compass[i]++;
- return;
- }
+ post startRead();
+ }
+
+ event void Vane.readDone(error_t error, uint16_t value)
+ {
+ if (error == SUCCESS) {
+ /* Convert the adc value (0...4095) to a compass heading
+ * (0...COMPASS_COUNT - 1).
+ */
+ value = (value + ADC_OFFSET) / ADC_PER_HEADING;
+ while (value >= COMPASS_COUNT)
+ value -= COMPASS_COUNT;
+ compass[value]++;
}
}
/* m_data's left, avg and right fields are currently represented in
* compass positions. We must now convert those fields into units of
- * angular degrees.
+ * angular degrees. The order of calculations is to maximize precision
+ * using integer arithmetic. Note that using a 16-bit unsigned field
+ * for calculations, the largest value of COMPASS_COUNT is 37.
*/
- m_data->left = 1800U / COMPASS_COUNT * m_data->left / 10;
- m_data->right = 1800U / COMPASS_COUNT * m_data->right / 10;
+ m_data->left = 1800U * m_data->left / COMPASS_COUNT / 10;
+ m_data->right = 1800U * m_data->right / COMPASS_COUNT / 10;
}
m_data = 0;