# # This file is part of LiteI2C # # Copyright (c) 2024 Fin Maaß # SPDX-License-Identifier: BSD-2-Clause from migen import * from migen.genlib.fsm import FSM, NextState from litex.soc.interconnect import stream from litex.soc.interconnect.csr import * from litex.soc.cores.litei2c.common import * from litex.gen.genlib.misc import WaitTimer class MCP9843(Module, AutoCSR): """MCP9843 temperature sensor. Parameters ---------- i2c_addr : int I2C address of the device. Attributes ---------- source : Endpoint(i2c_phy2core_layout), out Data stream. sink : Endpoint(i2c_core2phy_layout), in Control stream. enable : Signal(), out Slave CS signal. """ def __init__(self, i2c_addr=0x18): self.sink = sink = stream.Endpoint(i2c_phy2core_layout) self.source = source = stream.Endpoint(i2c_core2phy_layout) self.enable = Signal() self._status = CSRStatus(fields=[ CSRField("temp", size=13, offset=0, description="Temperature (0°C = 256 * 16)"), ]) self._val_min = CSRStatus(fields=[ CSRField("temp_min", size=13, offset=0, description="Temperature min."), # CSRField("temp_max", size=13, offset=16, description="Temperature max."), ]) self._val_max = CSRStatus(fields=[ CSRField("temp_max", size=13, offset=0, description="Temperature max."), ]) self._settings = CSRStorage(fields=[ CSRField("measurement", size=1, offset=0, description="Enable temperature measurement."), ], description="I2C transfer settings") self.measurement = measurement = Signal() self.temp = temp = Signal(13, reset_less=True) self.temp_min = temp_min = Signal(13, reset_less=True) self.temp_max = temp_max = Signal(13, reset_less=True) temp_not_set = Signal(reset=1, reset_less=True) self.sync += [ If(~measurement, temp_not_set.eq(1), ) ] self.comb += self._status.fields.temp.eq(temp) self.comb += self._val_min.fields.temp_min.eq(temp_min) self.comb += self._val_max.fields.temp_max.eq(temp_max) self.comb += measurement.eq(self._settings.fields.measurement) sample_timer = WaitTimer(10 * 50e6) self.submodules += sample_timer self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", self.enable.eq(0), sample_timer.wait.eq(1), If(sample_timer.done, self.enable.eq(1), NextState("SAMPLE-START"), ) ) fsm.act("SAMPLE-START", self.enable.eq(1), source.valid.eq(1), source.data.eq(int(0b00000101)), source.addr.eq(int(i2c_addr)), source.len_tx.eq(int(1)), source.len_rx.eq(int(2)), source.last.eq(1), If(source.ready, NextState("SAMPLE-WAIT") ), ) fsm.act("SAMPLE-WAIT", self.enable.eq(1), sink.ready.eq(1), If(sink.valid, If(~sink.nack, If(sink.data[12], NextValue(temp, sink.data[0:12]), ).Else( NextValue(temp, (256 * 16) + sink.data[0:12]), ), If(measurement, NextState("SAMPLE-CALC"), ).Else( NextState("IDLE") ), ).Else( NextState("IDLE") ), ) ) fsm.act("SAMPLE-CALC", If(temp_not_set, NextValue(temp_min, temp), NextValue(temp_max, temp), NextValue(temp_not_set, 0), ).Else( If(temp < temp_min, NextValue(temp_min, temp) ), If(temp > temp_max, NextValue(temp_max, temp) ), ), NextState("IDLE") )