Commit ca43a977 authored by Federico Vaga's avatar Federico Vaga

doc|sw: update 1-wire thermometer

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent a83bfa57
......@@ -953,21 +953,10 @@ ID which can be used to uniquely identify a CONV-TTL-BLO.
To access this thermometer, the CONV-TTL-BLO uses a 1-wire interface~\cite{onewire-tech}.
The thermometer is a one-wire slave and the FPGA on-board the CONV-TTL-BLO is
a one-wire master in the communication. To access and control this interface,
a memory-mapped one-wire master core~\cite{onewire-core} is implemented on the
FPGA, as shown in Figure~\ref{fig:onewire}.
\begin{figure}[h]
\centerline{\includegraphics[width=.9\textwidth]{fig/onewire}}
\caption{Interface to the one-wire thermometer}
\label{fig:onewire}
\end{figure}
Data from the thermometer can be obtained one bit at a time by controlling
the one-wire master core as described in its specification manual~\cite{onewire-core}.
Relevant data in the thermometer are listed in Table~\ref{tbl:thermo-data}. More
details about this data and how to obtain it can be found in the device's
datasheet~\cite{ds18b20}.
a one-wire master in the communication (Appendix~\ref{app:memmap-thermo}).
The FPGA on-board the CONV-TTL-BLO has also a driver for the thermometer chip
which makes available the temperature and the unique ID values without accessing
the 1-wire interface.
Note that an example Python script is provided in the \textit{software/diag/} folder
of the main project repository~\cite{ctb-repo}. Section~\ref{sec:repo-software}
......@@ -981,13 +970,11 @@ gives more details about the test scripts in the project repository.
\rowcolors{2}{white}{gray!25}
\begin{tabular}{l l p{.7\textwidth}}
\hline
\multicolumn{1}{c}{\textbf{Data}} & \multicolumn{1}{c}{\textbf{Length}} &
\multicolumn{1}{c}{\textbf{Data}} & \multicolumn{1}{c}{\textbf{Length}} &
\multicolumn{1}{c}{\textbf{Description}} \\
\hline
ID & 48 bits & Unique ID, packed within 64 bits \\
Temp. & 16 bits & Current temperature, multiple resolutions available \\
CRC & 8 bits & CRC for the unique ID and temperature data \newline
The FPGA logic does not interpret the CRC \\
\hline
\end{tabular}
}
......
......@@ -41,177 +41,27 @@ sys.path.append("../ei2c")
from ei2c import *
import ei2cdefine
##------------------------------------------------------------------------------
## OneWire class
##------------------------------------------------------------------------------
class COpenCoresOneWire:
R_CSR = 0x0
R_CDR = 0x4
CSR_DAT_MSK = (1<<0)
CSR_RST_MSK = (1<<1)
CSR_OVD_MSK = (1<<2)
CSR_CYC_MSK = (1<<3)
CSR_PWR_MSK = (1<<4)
CSR_IRQ_MSK = (1<<6)
CSR_IEN_MSK = (1<<7)
CSR_SEL_OFS = 8
CSR_SEL_MSK = (0xF<<8)
CSR_POWER_OFS = 16
CSR_POWER_MSK = (0xFFFF<<16)
CDR_NOR_MSK = (0xFFFF<<0)
CDR_OVD_OFS = 16
CDR_OVD_MSK = (0XFFFF<<16)
def wr_reg(self, addr, val):
self.bus.write(self.cslot, self.base + addr,val)
def rd_reg(self,addr):
return self.bus.read(self.cslot, self.base + addr)
def __init__(self, bus, cslot, base, clk_div_nor, clk_div_ovd):
self.bus = bus
self.base = base
self.cslot = cslot
data = (((clk_div_nor & self.CDR_NOR_MSK) |
((clk_div_ovd<<self.CDR_OVD_OFS) & self.CDR_OVD_MSK)))
self.wr_reg(self.R_CDR, data)
def reset(self, port):
data = (((port<<self.CSR_SEL_OFS) & self.CSR_SEL_MSK) |
self.CSR_CYC_MSK |
self.CSR_RST_MSK)
self.wr_reg(self.R_CSR, data)
tmo = 100
while(self.rd_reg(self.R_CSR) & self.CSR_CYC_MSK):
tmo = tmo -1
if tmo <= 0:
msg = "ERROR: TempID IC20: Not responding"
print(msg)
reg = self.rd_reg(self.R_CSR)
return ~reg & self.CSR_DAT_MSK
def slot(self, port, bit):
data = (((port<<self.CSR_SEL_OFS) & self.CSR_SEL_MSK) |
self.CSR_CYC_MSK |
(bit & self.CSR_DAT_MSK))
self.wr_reg(self.R_CSR, data)
tmo = 100
while(self.rd_reg(self.R_CSR) & self.CSR_CYC_MSK):
tmo = tmo -1
if tmo <= 0:
msg = "ERROR: TempID IC20: Not responding"
print(msg)
reg = self.rd_reg(self.R_CSR)
return reg & self.CSR_DAT_MSK
def read_bit(self, port):
return self.slot(port, 0x1)
def write_bit(self, port, bit):
return self.slot(port, bit)
def read_byte(self, port):
data = 0
for i in range(8):
data |= self.read_bit(port) << i
return data
def write_byte(self, port, byte):
data = 0
byte_old = byte
for i in range(8):
data |= self.write_bit(port, (byte & 0x1)) << i
byte >>= 1
if(byte_old == data):
return 0
else:
return -1
def write_block(self, port, block):
if(160 < len(block)):
return -1
data = []
for i in range(len(block)):
data.append(self.write_byte(port, block[i]))
return data
def read_block(self, port, length):
if(160 < length):
return -1
data = []
for i in range(length):
data.append(self.read_byte(port))
return data
##------------------------------------------------------------------------------
## DS18B20 class
##------------------------------------------------------------------------------
class CDS18B20:
OFFSET_UIDLR = 0xA8
OFFSET_UIDHR = 0xAC
OFFSET_TEMPR = 0xB0
ROM_SEARCH = 0xF0
ROM_READ = 0x33
ROM_MATCH = 0x55
ROM_SKIP = 0xCC
ROM_ALARM_SEARCH = 0xEC
CONVERT_TEMP = 0x44
WRITE_SCRATCHPAD = 0x4E
READ_SCRATCHPAD = 0xBE
COPY_SCRATCHPAD = 0x48
RECALL_EEPROM = 0xB8
READ_POWER_SUPPLY = 0xB4
def __init__(self, onewire, port):
self.onewire = onewire
self.port = port
def __init__(self, elma, slot):
self.elma = elma
self.slot = slot
def read_serial_number(self):
if(1 != self.onewire.reset(self.port)):
msg = "ERROR: TempID IC20: Not responding"
print(msg)
else:
err = self.onewire.write_byte(self.port, self.ROM_READ)
if err != 0:
msg = "ERROR: TempID IC20: Write failed"
print(msg)
family_code = self.onewire.read_byte(self.port)
serial_number = 0
for i in range(6):
serial_number |= self.onewire.read_byte(self.port) << (i*8)
crc = self.onewire.read_byte(self.port)
return ((crc<<56) | (serial_number<<8) | family_code)
def access(self, serial_number):
if(1 != self.onewire.reset(self.port)):
msg = "ERROR: TempID IC20: Not responding"
print(msg)
else:
err = self.onewire.write_byte(self.port, self.ROM_MATCH)
block = []
for i in range(8):
block.append(serial_number & 0xFF)
serial_number >>= 8
self.onewire.write_block(self.port, block)
return 0
l = self.elma.read(self.slot, self.OFFSET_UIDHR)
h = self.elma.read(self.slot, self.OFFSET_UIDLR)
return (h << 32 | l)
def read_temp(self, serial_number):
err = self.access(serial_number)
err = self.onewire.write_byte(self.port, self.CONVERT_TEMP)
time.sleep(0.8)
err = self.access(serial_number)
err = self.onewire.write_byte(self.port, self.READ_SCRATCHPAD)
data = self.onewire.read_block(self.port, 9)
temp = (data[1] << 8) | (data[0])
if(temp & 0x1000):
temp = -0x10000 + temp
temp = temp/16.0
return temp
def read_temp(self):
temp = self.elma.read(self.slot, self.OFFSET_TEMPR) & 0xffff
return temp / 16.0
##------------------------------------------------------------------------------
......@@ -261,7 +111,7 @@ if __name__ == "__main__":
# Create onewire and thermometer objects
onewire = COpenCoresOneWire(elma, slot, baseaddr, 99, 19)
ds18b20 = CDS18B20(onewire, 0)
ds18b20 = CDS18B20(elma, slot)
# Reading of unique ID
unique_id = ds18b20.read_serial_number()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment