#!/usr/bin/python
# Usage: mpl115a2.py FILENAME DELAY HISTORY-LENGTH

import offog
import smbus
import struct
import time

class MPL115A2:
    """Read pressure from an MPL115A2 I2C barometer, which measures pressure
    from 50 to 115 kPa, with +/- 1 kPA accuracy."""

    def __init__(self, nbus):
        self.bus = smbus.SMBus(nbus)
        self.addr = 0x60

        # Read calibration coefficients.
        self.a0, self.b1, self.b2, self.c12 = self._read(0x04, ">hhhh")
        self.a0 /= 1.0 * (1 << 3)
        self.b1 /= 1.0 * (1 << 13)
        self.b2 /= 1.0 * (1 << 14)
        self.c12 /= 1.0 * (1 << 24)
        # XXX: If the above doesn't work, it was previously: self.c12 = (self.c12 >> 10) / (1.0 * (1 << 14))

    def _read(self, cmd, fmt):
        """Read and unpack a block of data from the chip."""

        size = struct.calcsize(fmt)
        data = self.bus.read_i2c_block_data(self.addr, cmd, size)
        return struct.unpack(fmt, "".join(chr(c) for c in data))

    def get(self):
        """Return pressure in kPa."""

        # Start conversion.
        self.bus.write_i2c_block_data(self.addr, 0x12, [0x00])

        # Wait for it to finish (3ms max).
        time.sleep(0.005)

        # Read results.
        rawp, rawt = self._read(0x00, ">HH")
        rawp >>= 6
        rawt >>= 6

        t = (self.c12 * rawt) + self.b1
        t = (t * rawp) + self.a0
        pcomp = t + (self.b2 * rawt)

        pressure = (pcomp * ((115.0 - 50.0) / 1023.0)) + 50.0

        # The temperature could also be returned as something like:
        # temp = ((rawt - 498.0) / -5.35) + 25.0
        # but it's not calibrated (according to the datasheet).

        return pressure

if __name__ == "__main__":
    import sys
    filename = sys.argv[1]
    delay = int(sys.argv[2])
    histlen = int(sys.argv[3])

    history = []
    mpl = MPL115A2(1)
    while True:
        pressure = mpl.get()
        history.insert(0, pressure)
        history = history[:histlen]

        with offog.atomically_updated(filename, "w") as f:
            f.write("pressure,%f\n" % (sum(history) / len(history),))
        time.sleep(delay)
