#!/usr/bin/python3
from fcntl import ioctl
import os
import time

# return two bytes from data as an unsigned 16-bit value
def get_uint16(dat, index):
	return (dat[index] << 8) + dat[index + 1]

# return two bytes from data as a signed 16-bit value
def get_int16(dat, index):
	val = (dat[index] << 8) + dat[index + 1]
	if val > 32767:
		val = val - 65536
	return val

# refine bmp180 raw sample, ref. bmp180 datasheet
def refine_UT_UP(UT, UP, OVERSAMPLE = 3):
	# Refine temperature
	X1 = ((UT - AC6) * AC5) >> 15
	X2 = (MC << 11) / (X1 + MD)
	B5 = X1 + X2
	temperature = int(B5 + 8) >> 4

	# Refine pressure
	UP = UP >> (8 - OVERSAMPLE)
	B6  = B5 - 4000
	B62 = int(B6 * B6) >> 12
	X1  = (B2 * B62) >> 11
	X2  = int(AC2 * B6) >> 11
	X3  = X1 + X2
	B3  = (((AC1 * 4 + X3) << OVERSAMPLE) + 2) >> 2

	X1 = int(AC3 * B6) >> 13
	X2 = (B1 * B62) >> 16
	X3 = ((X1 + X2) + 2) >> 2
	B4 = (AC4 * (X3 + 32768)) >> 15
	B7 = (UP - B3) * (50000 >> OVERSAMPLE)

	P = (B7 * 2) / B4

	X1 = (int(P) >> 8) * (int(P) >> 8)
	X1 = (X1 * 3038) >> 16
	X2 = int(-7357 * P) >> 16
	pressure = int(P + ((X1 + X2 + 3791) >> 4))

	# Return temperature in degree C; pressure in mbar
	return(temperature/10.0, pressure/100.0)


# ======== gpio ===========
# gpio0 --> touch sensor power
# gpio1 <-- touch sensor output
os.system('echo in  > /sys/class/gpio/gpio1/direction')
os.system('echo out > /sys/class/gpio/gpio0/direction')
# Set gpio0 high, touch sensor power on, LED on
os.system('echo 1  > /sys/class/gpio/gpio0/value')
gpio1 = open("/sys/class/gpio/gpio1/value", "r")


#===== bmp180 i2c open and read calibration data ====
bmp180_i2c = open("/dev/i2c-1",  "r+b", buffering=0)
# bmp180 i2c slave address 0x77
I2C_SLAVE_ADDR = 0x77
# ioctl function number: force set i2c slave address
I2C_SLAVE_FORCE = 0x0706
rt = ioctl(bmp180_i2c, I2C_SLAVE_FORCE, I2C_SLAVE_ADDR)

#read 22 bytes starting from register 0xAA
rt = bmp180_i2c.write(bytes([0xaa]))
dat = bmp180_i2c.read(22)
# Convert calibration byte data to word values
AC1 = get_int16(dat, 0)
AC2 = get_int16(dat, 2)
AC3 = get_int16(dat, 4)
AC4 = get_uint16(dat, 6)
AC5 = get_uint16(dat, 8)
AC6 = get_uint16(dat, 10)
B1  = get_int16(dat, 12)
B2  = get_int16(dat, 14)
MB  = get_int16(dat, 16)
MC  = get_int16(dat, 18)
MD  = get_int16(dat, 20)

touch_state = 0

#===== Main Loop ======
while True:
	#======  touch sensor action
	gpio1.seek(0)  	# rewind for read
	if gpio1.read() == '1\n':
		touch = 1
	else:
		touch = 0

	if touch == 1 and touch_state == 0:
		# say Good on LED display
		os.system('echo \"Good\" > /tmp/led')
	elif touch == 0 and touch_state == 1:
		# default LED display
		os.system('echo \"&&\" > /tmp/led')

	touch_state = touch

	#====== BMP180 i2c
	# write 0x2E to reg. 0xF4, start sampling UT
	rt = bmp180_i2c.write(bytes([0xf4, 0x2e]))
	time.sleep(.0045)
	# read 2 bytes starting from reg. 0xF6
	rt = bmp180_i2c.write(bytes([0xf6]))
	dat = bmp180_i2c.read(2)
	UT = get_uint16(dat, 0)

	# write 0x34+(OVERSAMPLE<<6) to reg. 0xF4, start sampling UP
	rt = bmp180_i2c.write(bytes([0xf4, 0x34 + (3<<6)]))
	time.sleep(.0225)
	# read 3 bytes starting from reg. 0xF6
	rt = bmp180_i2c.write(bytes([0xf6]))
	dat = bmp180_i2c.read(3)
	UP = (dat[0]<<16) + get_uint16(dat, 1)

	temperature, pressure =  refine_UT_UP(UT, UP)

	# The pressure change per meter of sensor altitude should be approximately 0.12 mbar

	print("touch =", touch_state, "   Temp =", temperature, "C   Pressure =", pressure, "mbar")

	time.sleep(0.2)
