Package: tdc7201
TDC7201 driver for Raspberry PiThis project contains a python3 module for interfacing with the Texas Instruments TDC7201 Time-to-Digital-Converter chip through SPI.
As much as possible, it hides the internal implementation details (like SPI transactions, and chip registers and their field encodings) from the user.All code is GPLv3+ licensed unless explicitly stated otherwise.For more information on the chip, seehttps://www.ti.com/product/TDC7201Usageimporttdc7201tdc=tdc7201.TDC7201()# Create TDC object with SPI interface.tdc.initGPIO()# Set pin directions and default values for non-SPI signals.tdc.set_SPI_clock_speed(12500000)tdc.on()tdc.configure(meas_mode=2,num_stop=3,clock_cntr_stop=1,timeout=0.0005)status=tdc.measure(simulate=True)tdc.off()SettingsHardware pin assignments are done ininitGPIO(), which should only be called once.
Most other important parameters are set in theconfigure()method;
note that the chip can only be (re)configured while it is on.MethodsinitGPIO(enable=12,osc_enable=16,trig1=7,int1=37,trig2=11,int2=32,start=18,stop=22,verbose=False)Assigns and initializes all the non-SPI pins.
Your actual hardware (wiring between RPi and chip) needs to match this setup.
No arguments are required, but the defaults match my prototype and are somewhat arbitrary.
You can see all assignments by calling withverbose=True.
Pin numbers followGPIO.BOARDconventions,
i.e. they are the pin numbers on the 2x20 pin header.
Only 3 pins (enable,trig1,int1) are absolutely required;
the others can be skipped by assigningNoneto them.
Ifosc_enableisNone, then there will be no signal to turn an external clock on or off; this is OK if you supply the chip clock yourself.
Iftrig2and/orint2isNone, then side 2 of the chip will not work correctly, but side 1 still will.
Thestoppin is only required if you want the Raspberry Pi to generate STOP signals for testing, i.e. if you plan to runtdc.measure(simulate=True).
If you are hooked up to real signals to measure, then you can and should setstop=None.
Thestartpin is only required if you want the Raspberry Pi to generate a START signal; this could be hooked directly to the chip START, or used to trigger some external hardware.
Note that if you start a measurement, and the chip never sees a START signal, it will hang indefinitely waiting for one.on()Takes the chip out of reset.configure(side=1,force_cal=True,meas_mode=2,trig_falling=False,falling=False,calibration2_periods=10,avg_cycles=1,num_stop=1,clock_cntr_stop=0,clock_cntr_ovf=0xFFFF,timeout=None)Set up various control parameters in the chip configuration registers.side-
Which side of the chip to configure. Default is 1. 2 does not work yet.retain_state-
DefaultFalse.
IfTrue, will ignore all other arguments, and instead use the same settings
as from the previous call toon().
Behavior is undefined if there was no previous call.force_cal-
IfTrue, will recalibrate the chip after every attempted measurement.
This is recommended (and, in this version, required and default).
IfFalse, will only recalibrate after a "successful" measurement,
with timeouts and some other results considered unsuccessful.
(This currently does not work.)meas_mode-
Sets the measurement mode.
Mode 1 is recommended for times less than 2000 nS; mode 2 for greater.trig_falling-
IfTrue, sets the chip to use falling edge on TRIG to indicate chip is ready.
The default isFalse, which has it use rising edge on TRIG.falling-
IfTrue, sets the chip to trigger on falling edges of START and STOP.
The default isFalse, which has it trigger on rising edges.calibration2_periods- The number of clock cycles to recalibrate for. The allowed values are 2, 10 (hardware default), 20, and 40.
If you specify any other value, will round up (if below 40) or down (if above 40) to the next legal value.avg_cycles-
The number of measurements to average over.
The allowed values are 1, 2, 4, 8, 16, 32, 64, and 128.
The default is 1, which means no averaging.
If you use anything larger, the chip will run that many measurements and then report only the average values.
This can be useful in a noisy environment.
(Averaging does not currently work withmeasure(simulate=True).)num_stop-
The chip starts timing on a pulse on the START pin, and then can record timings for up to 5 pulses on the STOP pin.
Allowed values are 1, 2, 3, 4, 5.
The default is 1, which means the measurement will terminate as soon as a single STOP pulse is received.
Ifnum_stop==3, the measurement will terminate after recording 3 STOP pulses or after timing out, whichever comes first.clock_cntr_stop = N- If N is non-zero, the chip will ignore STOP pulses for N clock cycles after START.clock_cntr_ovf = N- The chip will end measurement ("time out" or "clock counter overflow") after N clock cycles even ifnum_stopSTOP pulses have not been received.
Default (and maximum) is 65535 = 0xFFFF.timeout = T- You can also specify the overflow period as a time in seconds. For example, if T is 0.0005, the timeout period will be 500 microseconds. If bothtimeoutandclock_cntr_ovfare specified,timeoutwins.Note thatclock_cntr_ovfmust be greater thanclock_cntr_stop,
or the measurement will time out before it begins accepting stop pulses.measure(simulate=False,error_prefix='',log_file=None)Runs a single measurement, waiting for the chip INT1 pin to go low indicating completion.
Will time out after 1 or more milliseconds if measurement doesn't complete.
(Themeasure()timeout must be an integer number of mS,
and is adjusted to be longer than the timeout set for the chip.)
Ifsimulate=True, then generates START and/or STOP signals to send to the chip
(for testing when your actual signal source is not yet available);
this requires that the appropriate RPi pins be connected to START and/or STOP,
and thatinitGPIO()not be called withstart=Noneorstop=Nonerespectively.
(Simulate does not currently work with averaging.)
If it does complete, callsread_regs24()to download the raw register data,
and thencount_pulses().
Theerror_prefixstring will be prepended to any error messages from this call tomeasure();
this allows you to easily identify which call had the problem.
Iflog_fileis an already-open file handle,
will write any error messages to that file instead of printing them.
Returns 0-5 for number of pulses seen, or 6-13 for various kinds of errors.compute_tofs()Takes the raw register data dowloaded by the last measurement
and computes the time-of-flight for each pulse seen,
leaving them in thetdc.tof1totdc.tof5variables.
Returns 0 to 5 for the number of pulses seen,
or 6 if an error prevented the computation.count_pulses()Examines the raw register data dowloaded by the last measurement
and returns 0 to 5 for the number of pulses seen,
or 6 if an error prevented the computation.
This is about 8 times faster thancompute_tofs(),
because it does less work.off()Asserts reset and waits 1 uS for it to take effect.
This will terminate any measurement in progress,
and make the chip unresponsive to SPI until the next call toon().clear_status(verbose=False,force=False)Clears any set interrupt status register bits to prepare for next measurement.
This isn't supposed to be necessary, but I was having problems without doing it.
Ifverbose==True, prints detailed step-by-step results for debugging.
Ifforce==True, tries to clear all IS bits even if some or all of them appear not to be set.set_SPI_clock_speed(speed,force=False)Attempts to set the SPI interface clock speed tospeed(in Hz).
Minimum legal value is 50000 (50 kHz), spec maximum is 25000000 (25 MHz),
and highest "overclocked" speed we've seen work is 33300000 (33.3 MHz).
The SPI clock is a hardware division of the CPU clock, so there are two important things to note.
(1) The exact clock speed set may be restricted (by hardware) to only certain values in that range, so you may not get exactly what you ask for.
(2) The SPI clock will slow down or speed up if the CPU clock does (for example, for thermal management, turbo mode, or due to user over- or under-clocking of the Raspberry Pi).
The CPU (and the SPI driver, and this module) can not tell what the CPU clock speed is, so there is no way to compensate for this in software.
Therefore, it's probably a bad idea to overclock the SPI speed
if you know that your CPU will also be overclocked,
since that might result in a speed that doesn't work.
But all this should mostly be invisible to the user, as it only affects SPI communication speed, and does not affect performance of the TDC7201 measurements (unless the TDC7201 is also being clocked by some submultiple of the Pi clock, which is a really really bad idea).Ifforce=False, values in the spec range are silent,
and overclocking up to 33.3 MHz is allowed with a warning.
Ifforce=True, all speeds are allowed with a warning.
This should only be used for testing, not production.The casual user should be able to get by with only the above methods; the following low-level methods give more detailed access to the hardware, but you'll need to know what you're doing.write8(reg,val)Write a single 8-bit value to an 8-bit chip register.
This only makes sense for 8-bit registers (addresses 0 through 9).read8(reg)Read a single 8-bit value from an 8-bit chip register.
This only makes sense for 8-bit registers (addresses 0 through 9).write16(reg,val)Write a 16-bit value to a pair of 8-bit registers.
This only makes sense if reg isCOARSE_CNTR_OVF_H(4),CLOCK_CNTR_OVF_H(6), orCLOCK_CNTR_STOP_MASK_H(8).read16(reg)Read a pair of 8-bit registers and return them as a 16-bit value.
This only makes sense if reg isCOARSE_CNTR_OVF_H(4),CLOCK_CNTR_OVF_H(6), orCLOCK_CNTR_STOP_MASK_H(8).write24(reg,val)Write a 24-bit value to a 24-bit chip register.
This should probably never be used since those contain measurement and calibration results.read24(reg)Read a 24-bit value from a 24-bit chip register.
This only makes sense for 24-bit registers (addresses 16 through 28).read_regs8()Read all of the 8-bit side 1 chip registers into thetdc.reg1list.
(It should be possible to make this read the side 2 registers, but it doesn't yet.)
This is much faster than looping over the registers in Python.read_regs24()Read all of the 24-bit side 1 chip registers (measurement and calibration results) into thetdc.reg1list.
(It should be possible to make this read the side 2 registers, but it doesn't yet.)
This is much faster than looping over the registers in Python.read_regs()Read all of the side 1 chip registers (including measurement results) into thetdc.reg1list.
(It should be possible to make this read the side 2 registers, but it doesn't yet.)
This is much faster than looping over the registers in Python.
Equivalent toread_regs8()plusread_regs24().print_regs1()Print the internal copy of the side 1 chip registers. Note that, if this is not immediately preceded byread_regs(), the internal copy and the actual chip registers may be out of sync.tof_mm1(time_n)Compute time-of-flight in seconds using Measurement Mode 1 equation.tof_mm2(time1,time_n,count)Compute time-of-flight in seconds using Measurement Mode 2 equations.compute_tofs()Check how many pulses we got, and compute the TOF for each pulse.cleanup()Put the TDC7201 into reset, close the SPI device, and free all the GPIO pins.
Should normally only be called just before exiting.
The tdc object will still exist,
but you would have to manually reopentdc._spiand set its parameters,
plus callinitGPIO()andon(),
before it would be usable again.exit()Clean up the SPI and GPIO pins (i.e. callcleanup()), and then exit.