///
/// @file hih6130.c
/// @authors k. Headley
/// @date 01 apr 2014
/// 
/// HIH6130 SPI RH/Temp
/// Reads relative humitidy and temp from Gateway GF/env sensor cape
///
/// raw bits: S1,S0,C13,C12...C0,T13,T12,...T0,X,X
/// raw_bytes[0]:S[1:0]C[13:8]
/// raw_bytes[1]:C[7:0]
/// raw_bytes[2]:T[13:6]
/// raw_bytes[3]:T[5:0]X[1:0]

/////////////////////////
// Terms of use 
/////////////////////////
/*
 Copyright Information
 
 xFOCE - software for ocean acidification experiments
 Copyright 2002-2013 MBARI
 Monterey Bay Aquarium Research Institute, all rights reserved.
 
 Terms of Use
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version. You can access the GPLv3 license at
 http://www.gnu.org/licenses/gpl-3.0.html
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details 
 (http://www.gnu.org/licenses/gpl-3.0.html)
 
 MBARI provides the documentation and software code "as is", with no warranty,
 express or implied, as to the software, title, non-infringement of third party 
 rights, merchantability, or fitness for any particular purpose, the accuracy of
 the code, or the performance or results which you may obtain from its use. You 
 assume the entire risk associated with use of the code, and you agree to be 
 responsible for the entire cost of repair or servicing of the program with 
 which you are using the code.
 
 In no event shall MBARI be liable for any damages, whether general, special,
 incidental or consequential damages, arising out of your use of the software, 
 including, but not limited to, the loss or corruption of your data or damages 
 of any kind resulting from use of the software, any prohibited use, or your 
 inability to use the software. You agree to defend, indemnify and hold harmless
 MBARI and its officers, directors, and employees against any claim, loss, 
 liability or expense, including attorneys' fees, resulting from loss of or 
 damage to property or the injury to or death of any person arising out of the 
 use of the software.
 
 The MBARI software is provided without obligation on the part of the 
 Monterey Bay Aquarium Research Institute to assist in its use, correction, 
 modification, or enhancement.
 
 MBARI assumes no responsibility or liability for any third party and/or 
 commercial software required for the database or applications. Licensee agrees 
 to obtain and maintain valid licenses for any additional third party software 
 required.
 */

/////////////////////////
// Headers 
/////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#include "hih6130-dev.h"
#include "xf-debug.h"

/////////////////////////
// Macros
/////////////////////////
#define HIH_STATUS_BYTES 64
#define HIH_FS_COUNTS ((uint16_t)((1<<14)-2))
/////////////////////////
// Declarations 
/////////////////////////


/////////////////////////
// Imports
/////////////////////////

/////////////////////////
// Module Global Variables
/////////////////////////


/////////////////////////
// Function Definitions
/////////////////////////

/////////////////////////
// Utility
/////////////////////////

double hih6130_temp(byte *raw_bytes){
    // raw_bytes[2]:T[13:6]
    // raw_bytes[3]:T[5:0]X[1:0]
    
    // parse temp counts
    uint16_t temp_counts  = ((raw_bytes[2]&0xFF)<<6)|(((raw_bytes[3]&0xFC)>>2)&0x3F);
    // calculate temp (deg C)
    double temp=(double)(165.0*((double)temp_counts/HIH_FS_COUNTS)-40.0);
    
//    fprintf(stderr,"raw[%02X%02X%02X%02X]: tcounts[%04X] HIH_FS_COUNTS[%04X] T[%lf]\n",
//            raw_bytes[0],raw_bytes[1],raw_bytes[2],raw_bytes[3],
//            temp_counts,HIH_FS_COUNTS,temp);
  
    // return Temp (deg C)
    return temp;
}
double hih6130_rh(byte *raw_bytes){
    // raw_bytes[0]:S[1:0]C[13:8]
    // raw_bytes[1]:C[7:0]

	// parse rh counts
    uint16_t rh_counts  = ((raw_bytes[0]&0x3F)<<8)|((raw_bytes[1]&0xFF));//(data_bytes&0x3FFF0000)>>16;
    // calculte RH (%)
    double rh=(double)(100.0*rh_counts/HIH_FS_COUNTS);

//    fprintf(stderr,"raw[%02X%02X%02X%02X]: rhcounts[%04X] HIH_FS_COUNTS[%04X] RH[%lf]\n",
//            raw_bytes[0],raw_bytes[1],raw_bytes[2],raw_bytes[3],
//            rh_counts,HIH_FS_COUNTS,rh);
	
	// return RH (%)
	return rh;
}
byte hih6130_status(byte *raw_bytes){
    // raw_bytes[0]:S[1:0]C[13:8]
	// parse status bits
    byte stat_counts  = ((raw_bytes[0]&0xC0)>>6);
    // returned byte
    byte status  = stat_counts+'0';

//    fprintf(stderr,"raw[%02X%02X%02X%02X]: statraw[%02X] stat[%c]\n",
//            raw_bytes[0],raw_bytes[1],raw_bytes[2],raw_bytes[3],
//            stat_counts,status);

    // return '0','1','2','3'
    return status;
}

char *
hih6130_raw2str(byte *raw_bytes)
{
		
	// output temp
	double temp = hih6130_temp(raw_bytes);
	
	// parse fault bit
	byte status = hih6130_status(raw_bytes);
	
	// internal temp
	double rh   = hih6130_rh(raw_bytes);

    // string buf
	char str[HIH_STATUS_BYTES]={0};
	
	// raw, temp (deg C), rh (%), status
	snprintf(str,HIH_STATUS_BYTES,"%02X%02X%02X%02X,%.4lf,%.4lf,%c",
            raw_bytes[0],raw_bytes[1],raw_bytes[2],raw_bytes[3],
            temp,rh,status);
	
	return strdup(str);
}

/////////////////////////
// Protocol API
/////////////////////////
/// @fn static int hih6130_read(spi_port_t *io_port, byte *temp)
/// @brief device returns 4 data bytes:
/// D[30:31]: Status
/// D[24:29]: upper 6 bits of RH data
/// D[16:23]: lower 8 bits of RH data
/// D[08:15]: corrected temp data
/// D[02:07]: remaining bits of temp for full 14-bit res
/// D[00:01]: don't care

/// @param[in] io_port description
/// @param[in] temp description
/// @return tbd
int
hih6130_read(spi_port_t *io_port, byte *temp)
{
	int stat=-1;
	if (io_port && temp) {
		byte tx_data[4]={0};
		byte rx_data[4]={0};
        // initiate measurement by
        // reading 8 or more bits, and discarding data
        stat = spi_wr(io_port, tx_data, rx_data, 1);
        
        // data cycle is ~37 msec
        // wait and check status until 00 (or retries, typically 1)
        memset(rx_data,0,4);
        bool check_stat=FALSE;
        int retries=10;
        while (!check_stat && retries--) {
          // read cycle takes ~36.65 msec
            delay_msec(40L);
            //read data until status bits indicate
            // valid data (00)
            stat = spi_wr(io_port, tx_data, rx_data, 4 );
            if ( (rx_data[0]&0xC0) == 0) {
                //fprintf(stderr,"%s:%d - valid data! cycles[%d]\n",__FUNCTION__,__LINE__,(10-retries));
                stat=0;
                break;
            }
            memset(rx_data,0,4);
        }
        // transfer bytes to return value
		memcpy(temp,rx_data,4);
	}
	return stat;
	
}

/////////////////////////
// Application Logic API
/////////////////////////



