#!/usr/bin/env python3
##  erstellt mit ChatGPT
import time
import argparse
from datetime import datetime
from smbus2 import SMBus

# ----------------------------
# Konstanten
# ----------------------------
FS_VOLT = 4.096          # Gain=1 Bereich
DIV_K = 10.0 / (15.0 + 10.0)   # Spannungsteiler 15k/10k = 0.4

T_MIN = -30.0
T_MAX = 70.0

ADS1115_POINTER_CONVERT = 0x00
ADS1115_POINTER_CONFIG  = 0x01

GAIN_CONFIG = {
    2/3: 0x0000,
    1:   0x0200,
    2:   0x0400,
    4:   0x0600,
    8:   0x0800,
    16:  0x0A00
}

# ----------------------------
# ADC lesen
# ----------------------------
def read_ads1115(i2c_addr, channel, gain, bus_id=1):

    if channel not in [0,1,2,3]:
        raise ValueError("channel 0..3")

    if gain not in GAIN_CONFIG:
        raise ValueError("gain: 2/3,1,2,4,8,16")

    mux = 0x4000 | (channel << 12)

    config = (
        0x8000 |            # start conversion
        mux |
        GAIN_CONFIG[gain] |
        0x0100 |            # single shot
        0x0080 |            # 128 SPS
        0x0003
    )

    with SMBus(bus_id) as bus:
        bus.write_i2c_block_data(
            i2c_addr,
            ADS1115_POINTER_CONFIG,
            [(config >> 8) & 0xFF, config & 0xFF]
        )

        time.sleep(0.01)

        data = bus.read_i2c_block_data(i2c_addr, ADS1115_POINTER_CONVERT, 2)

    raw = (data[0] << 8) | data[1]
    if raw > 0x7FFF:
        raw -= 0x10000

    return raw


# ----------------------------
# Umrechnung
# ----------------------------
def raw_to_vadc(raw):
    return (raw / 32767.0) * FS_VOLT

def vadc_to_vin(vadc):
    return vadc / DIV_K

def vin_to_temp(vin):
    # 0–10V -> -30..+70°C
    if vin <= 0: return T_MIN
    if vin >= 10: return T_MAX
    return T_MIN + (vin/10.0)*(T_MAX-T_MIN)


# ----------------------------
# MAIN
# ----------------------------
def main():

    parser = argparse.ArgumentParser(description="ADS1115 Hardware Test")
    parser.add_argument("address", type=lambda x: int(x,0), help="I2C Adresse z.B. 0x48")
    parser.add_argument("channel", type=int, help="Kanal 0..3")
    parser.add_argument("gain", type=float, help="Gain 2/3,1,2,4,8,16")
    parser.add_argument("-o","--outfile", type=str, help="Ausgabedatei (append)")
    args = parser.parse_args()

    raw = read_ads1115(args.address, args.channel, args.gain)
    vadc = raw_to_vadc(raw)
    vin = vadc_to_vin(vadc)
    temp = vin_to_temp(vin)

    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    line = f"{timestamp}, raw={raw}, vadc={vadc:.3f}V, vin={vin:.3f}V, temp={temp:.2f}"
    print(line)

    if args.outfile:
        with open(args.outfile, "a") as f:
            f.write(line + "\n")


if __name__ == "__main__":
    main()
