#!/usr/bin/env python

# sudo apt-get install python-pandas
# sudo apt-get install python-numpy

import time
import os
import pygame
import pandas as pd
import numpy as np
import random
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
DEBUG = 1
v_in = 4.9

# define global variables
trial0LB=0.0
trial3LB=0.0
trial10LB=0.0

linSlope=0.0
linIntercept=0.0

# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
        if ((adcnum > 7) or (adcnum < 0)):
                return -1
        GPIO.output(cspin, True)

        GPIO.output(clockpin, False)  # start clock low
        GPIO.output(cspin, False)     # bring CS low

        commandout = adcnum
        commandout |= 0x18  # start bit + single-ended bit
        commandout <<= 3    # we only need to send 5 bits here
        for i in range(5):
                if (commandout & 0x80):
                        GPIO.output(mosipin, True)
                else:
                        GPIO.output(mosipin, False)
                commandout <<= 1
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)

        adcout = 0
        # read in one empty bit, one null bit and 10 ADC bits
        for i in range(12):
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)
                adcout <<= 1
                if (GPIO.input(misopin)):
                        adcout |= 0x1

        GPIO.output(cspin, True)
        
        adcout >>= 1       # first bit is 'null' so drop it
        return adcout

# change these as desired - they're the pins connected from the
# SPI port on the ADC to the Cobbler
SPICLK = 18
SPIMISO = 23
SPIMOSI = 24
SPICS = 25  

# set up the SPI interface pins
GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)

# LM358P coutput connected to adc #0
cell_1 = 1;

# Lb to Voltage. 
def LbToV():
        # read the analog pin
        analog_out_1 = readadc(cell_1, SPICLK, SPIMOSI, SPIMISO, SPICS)

        # convert output from a number to a voltage
        v = analog_out_1*(v_in/1023)
        return v

# to calibrate, place weight in the center of scale
def avgVolts():
        volts = 0.0
        counts = 51.0
        total = counts 

        # find average of 10 trials at 0, 3, and 10 lb
        while counts > 1.0:
                reading = LbToV()
                volts = volts +reading
                counts = counts -1.0
        avg_volts = volts/total
        return avg_volts

def calibration():
        global trial0LB
        global trial3LB
        global trial10LB
        
        # uses math you learned in 7th grade to convert two (x,y)
        # coordinates into a linear function
        ready0=raw_input('ready for the zero lb calibration? y/n ')
        if ready0=='y':
                t0 = avgVolts()
                # round to 3rd decimal place
                trial0LB = float("{0:3f}".format(t0))
                #print trial0LB

        ready3=raw_input('ready for the three lb calibration? y/n ')                
        if ready3=='y':
                t3= avgVolts()
                trial3LB = float("{0:3f}".format(t3))
                #print trial3LB

        ready10=raw_input('ready for the ten lb calibration? y/n ')                
        if ready10=='y':
                t10= avgVolts()
                trial10LB = float("{0:3f}".format(t10))
                #print trial10LB

# calculates slope and y-intercept for linear function whose x values are volts
# and y values are pounds
def makeLinFunc():
        global linSlope
        global linIntercept
        x=[trial0LB,trial3LB,trial10LB]
        print "trials: ", x
        y=[0,3,10]
        regression = np.polyfit(x,y,1)
        print "regression vars: ", regression
        linSlope = regression[0]
        linIntercept = regression[1]
        print linSlope
        print linIntercept
        
##########################################
# CALLIBRATION PROCEDURE
# uncomment to calibration before running
calibration()
#print "trial10= ", trial10LB
#makeLinFunc()
##########################################
        
# insert linSlope and linIntercept into the equation here! 
# LB = -277.75887*V + 622.59543
def calcWeight(v):
        yourWeight = -277.758877332*v+622.595429593
        return yourWeight

while True:
        # get the user's goal weight. Type in weight and press 'Enter'
        # goal_weight=raw_input('what is your goal weight?')
        goal_weight=raw_input()
    
        # do this after calibration
        v = avgVolts()
        #print "volts from weight on scale ", v
        real_weight = calcWeight(v)
        #print "real weight ", real_weight

        # dummy weight for testings
        # real_weight = 112

        # initialize mp3 player
        pygame.init()

        # make lists of compliments and criticisms
        # 8 compliments and 14 criticisms

        # if overweight
        if real_weight > (int(goal_weight)+5):
            # randomly choose a criticism
            rand = random.randrange(0,14)+1
            comment = 'mean'+str(rand)+'.mp3'
            print comment

            # play a criticism
            pygame.mixer.music.load('/home/pi/Desktop/comments/'+comment)
            pygame.mixer.music.play()
            time.sleep(5)
        # if underweight
        else:
            # randomly choose a criticism
            rand = random.randrange(0,8)+1
            comment = 'nice'+str(rand)+'.mp3'
            print comment

            # play a compliment
            pygame.mixer.music.load('/home/pi/Desktop/comments/'+comment)
            pygame.mixer.music.set_volume(1.0)
            pygame.mixer.music.play()
            time.sleep(5)
     

