///
/// @file sht3x.h
/// @authors k. headley
/// @date 05 dec 2019

/// Sensirion SHT3X I2C RH/Temp sensor driver

/// @sa doxygen-examples.c for more examples of Doxygen markup


/////////////////////////
// Terms of use
/////////////////////////
/*
 Copyright Information
  
 Copyright 2002-2019 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.
 */

// Always do this
#ifndef SHT3X_H
#define SHT3X_H

/////////////////////////
// Includes 
/////////////////////////
#ifdef WITH_PIC24F_CURIOSITY
#include "bbcommon.h"
#endif // WITH_PIC24F_CURIOSITY
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>

#include "i2cp.h"
// include for debug output macros
#include "cwg-shared.h"
#include "ioserial.h"

/////////////////////////
// Macros
/////////////////////////

///@def SHT3X_I2C_HND
///@brief select I2C bus handle from i2cp module
#define SHT3X_I2C_HND I2CP_HND_MMC1

#define SHT3X_TEMP_C(s) (-45.0 + 175.0*s/65535)
#define SHT3X_TEMP_F(s) (-49.0 + 315.0*s/65535)
#define SHT3X_RH_PCT(s) (100.0*s/65535)
#define SHT3X_CRC_POLY 0x31
#define SHT3X_CRC_INIT 0xFF
#define SHT3X_SREG_BYTES 3
#define SHT3X_HRESET_PORT_A SHT3X_PORT_INVALID //PORTB
#define SHT3X_HRESET_PORT_B SHT3X_PORT_INVALID //PORTB
#define SHT3X_HRESET_BIT_A  6
#define SHT3X_HRESET_BIT_B  1
#define SHT3X_BIT_VALID(b) (b>=0 && b<16 ? true : false)
#define SHT3X_HRESET_DELAY_MSEC() __delay_us((unsigned long)10UL)

/////////////////////////
// Type Definitions
/////////////////////////

typedef enum{
    SHT3X_HND_INVALID = -1,
    SHT3X_PRI = 0,
    SHT3X_HND_COUNT
}sht3x_hnd_t;

typedef enum{
    CMD_ADDR_A = 0x44,
    CMD_ADDR_B = 0x45,
    CMD_SS_CSRH = 0x2C06,
    CMD_SS_CSRM = 0x2C0D,
    CMD_SS_CSRL = 0x2C10,
    CMD_SS_NCSRH = 0x2400,
    CMD_SS_NCSRM = 0x240B,
    CMD_SS_NCSRL = 0x2416,
    CMD_SRST = 0x30A2,
    CMD_GRST = 0x0006,
    CMD_RD_SREG = 0xF32D,
    CMD_CLR_SREG = 0x3041,
    CMD_ART = 0x2B32,
    CMD_BREAK = 0x3093,
    CMD_HEATER_EN = 0x306D,
    CMD_HEATER_DI = 0x3066,
    CMD_INVALID = 0xFF,
}sht3x_command_t;

typedef enum{
    MODE_MEAS=0x001,
    MODE_ADDR=0x002,
    MODE_CS=0x004,
    MODE_TMP=0x080,
    MODE_RPT=0x030,
    MODE_INVALID=0xFFFF
}sht3x_mode_t;

#define ADDR_GEN_CALL 0
#define MODE_MEAS_SS 0x000
#define MODE_MEAS_PER 0x001
#define MODE_ADDR_A 0x000
#define MODE_ADDR_B 0x002
#define MODE_CS_DIS 0x000
#define MODE_CS_EN 0x004
#define MODE_TMP_C 0x000
#define MODE_TMP_F 0x080
#define MODE_RPT_L 0x010
#define MODE_RPT_M 0x020
#define MODE_RPT_H 0x030

#define SHT3X_MODE_SS(p) ( (NULL != p) && ((p->mode & MODE_MEAS)==0) ? true : false)
#define SHT3X_MODE_PER(p) ( (NULL != p) && ((p->mode & MODE_MEAS)!=0) ? true : false)
#define SHT3X_MODE_CS_EN(p) ( (NULL != p) && ((p->mode & MODE_CS)!=0) ? true : false)
#define SHT3X_MODE_ADDR_A(p) ( (NULL != p) && ((p->mode & MODE_ADDR)==0) ? true : false)
#define SHT3X_MODE_ADDR_B(p) ( (NULL != p) && ((p->mode & MODE_ADDR)!=0) ? true : false)
#define SHT3X_MODE_RPT_L(p) ( (NULL != p) && ((p->mode & MODE_RPT)==MODE_MEAS_RPT_L) ? true : false)
#define SHT3X_MODE_RPT_M(p) ( (NULL != p) && ((p->mode & MODE_RPT)==MODE_MEAS_RPT_M) ? true : false)
#define SHT3X_MODE_RPT_H(p) ( (NULL != p) && ((p->mode & MODE_RPT)==MODE_MEAS_RPT_H) ? true : false)
#define SHT3X_MODE_TMP_C(p) ( (NULL != p) && ((p->mode & MODE_TMP)==MODE_MEAS_TMP_C) ? true : false)
#define SHT3X_MODE_TMP_F(p) ( (NULL != p) && ((p->mode & MODE_TMP)==MODE_MEAS_TMP_F) ? true : false)

#define SHT3X_MODE_MEAS(p) ( (NULL != p) ? (p->mode & MODE_MEAS) : MODE_INVALID)
#define SHT3X_MODE_ADDR(p) ( (NULL != p) ? (p->mode & MODE_ADDR) : MODE_INVALID)
#define SHT3X_MODE_CS(p) ( (NULL != p) ? (p->mode & MODE_CS) : MODE_INVALID)
#define SHT3X_MODE_TMP(p) ( (NULL != p) ? (p->mode & MODE_ADDR) : MODE_INVALID)
#define SHT3X_MODE_RPT(p) ( (NULL != p) ? (p->mode & MODE_RPT) : MODE_INVALID)
#define SHT3X_REG(w) (byte)((w & 0x00FF))
#define SHT3X_DATA(w) (byte)((w & 0xFF00) >> 8)
#define SHT3X_LSB(w) (byte)((w & 0x00FF))
#define SHT3X_MSB(w) (byte)((w & 0xFF00) >> 8)

#define SHT3X_ADDR(self) (i2c_addr_t)(SHT3X_MODE_ADDR_A(self) ? CMD_ADDR_A : CMD_ADDR_B)

#define SHT3X_PRI_MODE_DFL (MODE_MEAS_SS|MODE_ADDR_A|MODE_CS_DIS|MODE_TMP_C|MODE_RPT_H)

/// @def SHT3X__HRANGE_VALID
/// @brief return true if handle is valid index
/// @param hnd handle to test
#define SHT3X_HRANGE_VALID(hnd) ( ((hnd>=0) && (hnd<SHT3X_HND_COUNT)) ? true : false)

typedef enum{
    SREG_ALRT =  0x8000,
    SREG_RES14 = 0x4000,
    SREG_HEAT =  0x2000,
    SREG_RES12 = 0x1000,
    SREG_RH_TRKALRT = 0x0800,
    SREG_T_TRKALRT = 0x0400,
    SREG_RES95 = 0x03E0,
    SREG_SYS_RST = 0x0010,
    SREG_RES32 = 0x000C,
    SREG_CMD = 0x0002,
    SREG_WCHK = 0x0001
}sht3x_sreg_bits_t;

#pragma pack(push,1)
///@typedef struct sht3x_ssmeas_s sht3x_ssmeas_t
///@brief SHT3X measurement
typedef struct sht3x_ssmeas_s{
    /// @var sht3x_ssmeas_s::temp
    /// @brief temperature
    uint16_t temp;
    /// @var sht3x_ssmeas_s::rh
    /// @brief relative humidity
    uint16_t rh;
    /// @var sht3x_ssmeas_s::crc
    /// @brief 16-bit checksum
    byte crc[2];
}sht3x_ssmeas_t;
#pragma pack(pop)

///@typedef struct sht3x_s sht3x_t
///@brief SHT3X sensor instance
typedef struct sht3x_s{
    /// @var sht3x_s::bus
    /// @brief i2c bus handle
    i2cp_hnd_t bus;
    /// @var sht3x_s::mode
    /// @brief sensor mode
    sht3x_mode_t mode;
    /// @var sht3x_s::measurement
    /// @brief sensor measurement
    sht3x_ssmeas_t meas;
}sht3x_t;


/////////////////////////
// Exports
/////////////////////////

#ifdef __cplusplus
extern "C" {
#endif
extern uint16_t SHT3X_PORT_INVALID;

void sht3x_init(sht3x_hnd_t hnd);
byte sht3x_crc8(byte *data, uint32_t len);
int sht3x_power(sht3x_hnd_t hnd, bool state);
int sht3x_hreset(sht3x_hnd_t hnd);
int sht3x_heater(sht3x_hnd_t hnd, bool state);
int sht3x_art_en(sht3x_hnd_t hnd);
int sht3x_break(sht3x_hnd_t hnd);
int sht3x_per_start(sht3x_hnd_t hnd);
int sht3x_per_read(sht3x_hnd_t hnd);
int sht3x_clr_sreg(sht3x_hnd_t hnd);

int sht3x_sreset(sht3x_hnd_t hnd);
int sht3x_gcall(sht3x_hnd_t hnd);
int sht3x_ss_read(sht3x_hnd_t hnd, int32_t retries);
int sht3x_sreg(sht3x_hnd_t hnd, byte *dest, size_t len);

#ifdef __cplusplus
}
#endif

#endif // THIS_FILE
