' _HTU21DLib.bas
'===============================================================================
' LIBRARY: HTU21D Temperature and Humidity Sensor
' Interface: I2C
' Mode: No Hold Master and Hold Master
' Target: PIC18F46K22 - PIC18 Basic Oshonsoft
' Date: 2026/05/03
'===============================================================================
'
' Description:
' This library controls the HTU21D temperature and humidity sensor using
' the I2C bus in No Hold Master mode and Hold Master mode.
'
' No Hold Master:
' In No Hold Master mode, the master sends a measurement command and then
' releases the I2C bus. The sensor performs the internal conversion without
' holding the SCL line low. After the required conversion time, the master
' starts a new read operation to obtain the measurement data.
'
'
' Hold Master:
' This is an operating mode of the slave device.
' After the master sends a measurement command and starts
' a read operation, the slave may hold the I2C clock line
' (SCL) low. This temporarily blocks the I2C bus while the
' slave completes its internal measurement.
' Once the conversion is finished, the slave releases the
' clock line and the master can continue reading the data.
' This mechanism is known as clock stretching.
'
'
' Notes:
' - Temperature command: 0xF3
' - Humidity command   : 0xF5
' - Temperature command: 0xE3 ' HTU21D MODE: HOLD MASTER
' - Humidity command   : 0xE5 ' HTU21D MODE: HOLD MASTER
' - Sensor I2C address : 0x40
' - 8-bit write address: 0x80
' - 8-bit read address : 0x81
'
'===============================================================================

'-------------------------------------------------------------------------------
' PUBLIC ROUTINES
'-------------------------------------------------------------------------------
' Function HTU21D_Init() As Byte
' Proc HTU21D_Reset()
' Function HTU21D_RequestMeasurement(cmd as byte) As Byte
' Function HTU21D_ReadRaw(cmd As Byte) As Word
' Function HTU21D_ReadTemp() As Single
' Function HTU21D_ReadHum() As Single
'-------------------------------------------------------------------------------

'-------------------------------------------------------------------------------
' ADDRESS AND COMMANDS
'-------------------------------------------------------------------------------
Const HTU21D_W           = 0x80	' 0x40 << 1 + 0: Write address
Const HTU21D_R           = 0x81	' 0x40 << 1 + 1: Read address

Const HTU21D_CMD_TEMP    = 0xF3	' Trigger temperature measurement, No Hold Master
Const HTU21D_CMD_HUM     = 0xF5	' Trigger humidity measurement,    No Hold Master
Const HTU21D_CMD_TEMP_HM = 0xE3	' Trigger temperature measurement, Hold Master
Const HTU21D_CMD_HUM_HM  = 0xE5	' Trigger humidity measurement,    Hold Master
Const HTU21D_CMD_RESET   = 0xFE	' Soft reset command

'-------------------------------------------------------------------------------
' SENSOR INITIALIZATION
'-------------------------------------------------------------------------------
Function HTU21D_Init() As Byte

    WaitMs 20
    Call HTU21D_Reset()
    WaitMs 20

End Function

'-------------------------------------------------------------------------------
' SENSOR SOFT RESET
'-------------------------------------------------------------------------------
Proc HTU21D_Reset()

    START_I2C()
    WRITE_I2C(HTU21D_W)
    WRITE_I2C(HTU21D_CMD_RESET)
    STOP_I2C()

End Proc

'-------------------------------------------------------------------------------
' TRIGGER MEASUREMENT
'
' Description:
' Sends a measurement command to the HTU21D.
'
' In No Hold Master mode, the sensor starts the internal conversion and releases
' the I2C bus. The master must wait the required conversion time, or use ACK
' polling, before reading the result.
'-------------------------------------------------------------------------------
Function HTU21D_RequestMeasurement(cmd As Byte) As Byte

    START_I2C()
    WRITE_I2C(HTU21D_W)
    WRITE_I2C(cmd)
    STOP_I2C()

    ReturnValue 0

End Function

'-------------------------------------------------------------------------------
' READ RAW MEASUREMENT VALUE
'
' Description:
' Sends the selected measurement command.
' Then reads the raw 16-bit value returned by the sensor.
'
' Arguments:
' - cmd      : measurement command
'
' Notes:
' The HTU21D returns two data bytes. The two least significant bits are status
' bits and must be cleared before applying the conversion formula.
'-------------------------------------------------------------------------------
Function HTU21D_ReadRaw(cmd As Byte) As Word ', delay_ms As Byte) As Word

    Dim rawValue As Word
    Dim msb As Byte
    Dim lsb As Byte

	' Hold Master Mode
	If cmd = HTU21D_CMD_TEMP_HM Or cmd = HTU21D_CMD_HUM_HM Then
		START_I2C()
		WRITE_I2C(HTU21D_W)
		WRITE_I2C(cmd)
    Endif

    START_I2C()
    WRITE_I2C(HTU21D_R)
    msb = READ_I2C(ACK)
    lsb = READ_I2C(NACK)
    STOP_I2C()

    rawValue = msb
    rawValue = rawValue << 8
    rawValue = rawValue + lsb

    ' Clear the two status bits before applying the formula
    rawValue = rawValue And 0xFFFC

    ReturnValue rawValue

End Function

'-------------------------------------------------------------------------------
' READ TEMPERATURE
'
' Description:
' Reads the temperature and converts the raw value to degrees Celsius.
'
' Formula:
' T = -46.85 + 175.72 * rawValue / 65536
'-------------------------------------------------------------------------------
Function HTU21D_ReadTemp(cmd As Word) As Single

    Dim rawValue As Word

    rawValue = HTU21D_ReadRaw(cmd)

    ReturnValue -46.85 + (175.72 * rawValue / 65536.0)

End Function

'-------------------------------------------------------------------------------
' READ HUMIDITY
'
' Description:
' Reads the relative humidity and converts the raw value to %RH.
'
' Formula:
' RH = -6 + 125 * rawValue / 65536
'
' The result is limited to the physical range 0...100 %RH.
'-------------------------------------------------------------------------------
Function HTU21D_ReadHum(cmd As Word) As Single

    Dim rawValue As Word
    Dim rh As Single

    rawValue = HTU21D_ReadRaw(cmd)

    rh = -6.0 + (125.0 * rawValue / 65536.0)

    If rh < 0 Then
        rh = 0
    Endif

    If rh > 100 Then
        rh = 100
    Endif

    ReturnValue rh

End Function