XR232USB - True Random Number Generator @ USB


This ain't yet another ultimate, ultrafast and all-too-miniaturized USB-gadget. It is the "official" USB-version of the XR232-TRNG, taking advantage from the benefits of USB, but retaining fundamental XR232-philosophy of independency, security, transparency and compatibility.



XR232USB - stick ...
XR232USB V1.1:
  • Virtual COM-Port

  • MCU features balancing, random-pooling, blanking out EM-disturbance

  • Entropy source of electronic noise

  • Compatible to the XR232-protocol

  • Delivers random data of demonstrably good statistics

  • Console tool and DLLs provided for Windows and Linux

  • Safe random data rate
    up to 230.400 bps





Concept

The XR232 is a true random number generator device that delivers independent random data to a host computer. The XR232 utilizes simple, rugged and thoroughly tested circuitry and open-source software. A fundamental (and virtually unique) feature of XR232 is the consequent use of regular RS232 access schemes. That is to say, we don't make use of creepy bitbanging or direct hardware access techniques. All communication with an XR232 device is performed via standard RS232 transactions.

Unfortunately, the genuine RS232 ports have become a rare commodity on today's PC-platforms. Many current mainboards or laptops will rather provide multiple USB-ports. This Universal Serial Bus offers great deal of interfacing variety of hardware (including crashdown and bluescreen opportunities as well)... But, positively, it's quite nice to see properly installed USB devices just doing their job with compareably fast transfer rates, hot-plugging, flexible driver mounting, and last but not least, the option to directly use 5 volts of power supply for many USB appliances.

XR232-enthusiasts encouraged me to adopt USB-functionality to the project to open new fields of application and usability to a random number device. Well, I agree, but developing GOOD random number generator for USB is not a trivial task, despite all the fancy stuff on the market... Our usual suspects advertise with precious boxes or stylish sticks, and without any doubt, those hightech gadgets will have the very latest technology from space research and quantum physics on board. Seems the're full carefree-packages with mighty mysterious drivers, colourful windows applications and stunning certificates for the monied and superstitious... (Uh, and with backdoors for the agency...)

Still looking for a serious, transparent, open source and affordable TRNG-solution on USB? You will likely come down to one of the very few noncommercial, honest and freely documented projects, grab your soldering iron and make your own...

BTW, here's my proposal for the long awaited USB-variant of XR232 with XR232-Philosophy:


XR232USB - Blockschema

  1. USB-COM. We refrain from fooling around with USB-emulation on a µC and improvised driver stuff. Instead we make use of a dedicated interface chip that's optimized for the conversion of USB to 'Serial'. The FT232 from FTDI has it all. USB goes in, RS232-TTL-levelled signals come out at the other end. The associated VCP drivers offer "Virtual COM Ports" on OS-level at the host computer. All the FTDI driver stuff seems pretty reliable on both Windows and Linux platforms. Those FT232s have been tested 'in the field' for many years with merely stupid applications - now its ripe enough for the XR232USB ; -)

  2. Microcontroller. The small but strong ATtiny85 directly connects to a FT232's TXD/RXD lines and emulates the XR232-Protokoll. But much more of its computing power is used however for random number production, balancing and safety mechanisms. Like classic XR232, entropy comes from a separate source of electronic noise. The program in the µC (firmware) provides algorithm for optimized extraction of entropy from the limited bandwidth of noise source. Internally it makes intensive use of an entropy buffer (random pool) that allows to overcome short-term disturbance and interference effects on the device without any tradeoff in random data quality. Yet, in case of heavy disturbance, the device may even interrupt the serial data transmission by means of RTS/CTS handshake.

  3. Noise source. This newly designed source of entropy utilizes nonlinearities and chaotic noise effects in a fast comparator IC. In particular, there is no zener diode around and thus no higher voltage supply needed to operate this circuit. As with the XR232, a second amplifier performs quantization that delivers "digital noise" to be processed in a pure digital way by the µC.

From a technical point of view, XR232USB looks very different to the classic XR232. Yet, the continuity is, that we also got clearly defined functional blocks in XR232USB, which enables to keep good transparency with this more sophisticated device as well.

Present circuit goes with an SSOP chip (FT232RL) and some miniaturized but standard components around. This "hybrid approach" with small PCB of less than 25 x 50 mm already makes for a stick. When size and cost doesn't matter, building a deluxe-version in a solid metal case may be worth considering.


This project is and will ever be open source. All materials needed for making the XR232USB-device and its current firmware can be found in the download package. There is a simple console tool, compatible to classic XR232 and XR232USB, which provides some elementary quality testing on the randomness delivered and option to generate random data files of any size. All of the XR232USB project is subject to the GPL license.

UpIndex



Hardware



XR232USB - circuit diagram

USB-Interface (IC1)

The project makes use of the mighty FT232RL from FTDI in its standard configuration as a USB-COM-converter. Since those FT232s have been on the market for several years now, and myself having adopted FT232 chips in several applications since 2008, confidence in this technology seems to be justified from my point of view. (In fact, there's not much other hardware and driver solutions around with that reliability features.)

Basic functionality of the FT232: One end connects with USB while the other end provides all (8) RS232-lines that we also find at the 9p-DSUB RS232 connector, but with 5-volts logic levels. These may be directly interfaced to LSTTL, MAX232 or a µC as well. On the part of the PC system, there are certainly drivers needed to make use of this USB-device. Fortunately FTDI provides their so called "virtual COM port" drivers (VCP) for free. For almost any software running on the PC, the virtual serial ports are as real as any real COM ports are as well :)

FT232 in XR232USB: The FT232-terminals TXD, RXD, RTS and CTS are connected to portlines of the µC that provides, among others, real RS232/XR232 protocol funktionality against FT232.

Pros: The FT232RL is one most advanced member of the FT232-family. FT232RL can operate with nearly no external components. In particular, there is no external clocksource needed anymore. The chip has a very small footprint and might be easily integrated or retrofit into many designs formerly using MAX232 for RS232-connection. As mentioned earlier, those FT232xx are pretty reliable piece of technology on almost any Windows (from W98 up!) and Linux environments. Current Linux Kernels even support FT232 devices out of the box, so there is no additional driver modules needed to make use of FT232-based USB-devices. The affordable pricing (about 4 Euros now) and its good availability are in fact further advantages of the FT232-System.

Cons: Is and remains a 'proprietary' solution. There are not much details on the FT232-core and sourcecodes of the drivers available. The chip is, without prejudice, a "black box". More than that, some users may be rather pissed off by the tiny SSOP28-package that requires some SMD expertise to solder in a non-destructive way... Also the PCB-requirements become comparably high with Sub-SMD layouts.

No USB fun without USB drivers! Those drivers for the FT232-Family have always been freely available on the FTDI-Website so far. Once installed, the driver will recognize every FT232 that has ever been plugged in to any USB-port within some seconds. Then a  COM-number will be assigned to that FT232, which seems pretty consistent and independent of the actual USB-port the FT232-device has been attached to. The allocation of COM-numbers may be changed later with admin rights in the extended hardware properties dialog.


Microcontroller (IC2)

We have picked the ATtiny85 from ATMEL-Corporation for this purpose, 'cause it's a small but strong AVR microcontroller featured with sufficient number of I/O ports and other benefits:

The ports PB3/PB1 are directly connected to FT232-lines TXD/RXD. This is the controller's RS232-communications port using XR232 protocol (see details on the Firmware).

The ports PB0/PB2 are logically coupled with FT232's RTS/CTS. These handhake lines enable the controller to deliberately stop a transmission temporarily if disturbance of random noise source was detected.

Input PB4 is fed with "digital noise" coming from the external electronic noise source. This is a squarewave-shaped high frequency signal with some hundreds of kilohertz bandwidth and strong random characteristics. As a matter of fact, we do NOT use the internal ADC of the microcontroller, because it could not deliver sufficiently independent randomness at all. Even if we only took the LSB from ADC probes of an externally injected analog noise, these bits would surely correlate with some internal processes in the AVR core, making this method inacceptable for  independent random number generation. (ATMEL recommends to mitigate this effect with a feature called "noise reduction" - but that does not mean anything else than completely stopping the controller's programme execution for the duration of every single AD-cycle, thus cracking down all computational performance of the AVR most of the time, which is no option for this application as well.)
The current solution offers strict separation between the "digital part" (AVR) and the "analog part" (the comparator noise source and quantization amplifier). Again, XR232-philosophy!

The RESET input of the µC is coupled to the RTS output on the FT232 with a small capacitor. As soon as the Host regularly opens a serial port regularly (with hardware handshake) and has some characters to transmit in the transmit buffer, RTS falls to 0 volts (Low level, inverted logic compared to RS232/V24 levels). The capacitor (C10, 10nF) differentiates the falling edge of that signal and delivers short negative pulse to safely trigger the reset line of the µC. Since RESET Being a nonmaskable interrupt, the reset-method will always work, even if the controller's firmware should seriously crash or hangup. The controller may always be reset just by a closing and reopen of the serial port, initiated by host software.

The LED is pinned to +5V and to the port output PB2 via current limiting resistor R1 (1k0). Same portline is driving the CTS input at the FT232. This LED lights up every time the serial port is regularly being accessed (CTS activated = pulled LOW).
Should this LED flicker while the serial port was continuously open, this is an indicator that the noise source has experienced external RF-disturbance (or severe voltage instability on USB). In this case, the logic will have already prevented forwarding of possibly corrupted random data  to the PC (see Firmware).


Noise Source (IC3)

A conventional noise generator based on a zener diode cannot be operated with a voltage lower than 10 volts approximately. However, on USB we will only get about 5 volts without extra magic... I have done some quite exhaustive experimentation with voltage doubling, more exotic components, photodiodes, op-amps, resistive noise and other stuff, but it did not convince. Some concepts were indeed working, but too instable, too narrow-banded, too sensitive for electromagnetic interference, or too complex - or all too-gether :-(

Finally I came to elaborate the following circuit based on a quite common and standard component: the LM393 double analog comparator. My circuit utilizes a strange effect that is normally unwanted in a regular comparator setup. Because of its small hysteresis and very high amplification factors, if one applies feedback to the negative comparator input, such comparator will tend to instability and chaotic oscillation. Yet, with few external components, it IS possible controlling this effect and enforce stable noise generation with frequencies range up to the cutoff frequency of the comparator.
Just to mention, the present circuit, which delivers reproducible results with any breed of LM393, has been optimized by empiric testing and experimentation with real components in real circuits, rather than theory and simulation stuff.

Pros: Much entropy for little money! Those LM393 have been around the electronics world for decades and are still available from manufacturers in large scale. The proposed noise circuitry works reliable with operating voltage from 4 V up. The second comparator system is beneficially used to build the "1-bit-digitizer" and thus delivers the attached microcontroller with a digital signal. It seems, that feedback to the first (sensitive) noise generating stage is negligible in this application. So, this second stage will separate the microcontroller from the noise system. Since the comparator level for this buffer stage is not floating but fixed by means of R3/R4, no tendency for self-oscillation could be observed. Testing many different series of the LM393 has shown noise spectra up to 300 kHz. Current consumption is unter 1 mA.

Cons: There IS sensitivity for RF-interference in the unshielded circuit assembly. This effect could be demonstrated with household transmitters, like radio remote controls, GSM 900/1800-MHz mobile devices, and a 2400-MHz WLAN adaptor, being placed only few centimeters nearby the comparator circuit. Overall, the sensitivity for UHF and microwaves seem smaller than classical noise source in XR232 build of discrete components. As a matter of fact, even elementary means of electromagnetic shielding will drastically reduce RF-disturbance.
Similar effects are caused by fluctuation at the USB supply voltage. In a real-life PC system, we often have to deal with lower-frequency mumbling on the voltage rails, that is caused by peak loads of CPU, HDDs, CD/DVD-drives or graphic cards. Yet those tiny capacitors on the mainboard could not remove deepest "bass" notes from these fluctuations. Fortunately our comparator noise source does not draw much current (less than 1mA), so we are fine with filtering the 5 volts with an simple R-C filter (R7=470 ohms / C9=47 µF).

Just to mention, all parameters of the circuit are kept well within the datasheet limits. Half a dozen of LM393s have been tested successfully in this circuit, so I tend to be optimistic that the noise generator will work with most comparators of this type exactly the way it should.


ISP-Connector (X2)

Directly soldered onto the board, the PDIP version of ATtiny85 will need less than 4 mm of headroom, which is already compact enough for the intended "XR232USB-Stick".
Fusebit configuration and flashing of the µC is still possible "in system", by means of the 6-pin-SIL connector, named X2 here (see picture).
In the development of the circuit, port assignments of the ATtiny85 have been chosen in such way, that ISP access will not collide with output terminals of the FT232 or the controller, as long as the RS232/FT232 port is surely "closed".

Since there is no "official" connection scheme for single-line ISP/SPI connectors, the sequence of signal lines on X2 has been setup for pure practical reasons (layout). See following diagram!


2X5P (ATMEL-ISP) to XR232USB (6P SIL)

Note: As soon as the ATtiny85 contains a suitable bootloader, we would not necessarily need X2 for flashing a new firmware.

UpIndex



Firmware

Of course, the firmware for the ATtiny85 has been written in pure assembler language. It's all about performance and transparency. For those who do not understand even well commented assembly source, the following remarks and explanations may help you out.


Collecting random data

Being a pure software implementation, the sampling method shall be customized for the respective source of entropy. In here, we got an electronic noise as an entropy source of limited bandwidth. This analog noise is then converted by second comparator into a squarewave'd signal of variable pulse length. All entropy of this "digital noise" is being vested in the time domain. Microcontroller's ports can read such signal without any further information loss.

My proposed method of bitsampling is to continuously take probes of that digital noise with the highest oversampling factor possible. As long as the digtal level remains unchanged, a fast binary counter is free running and thereby measuring the actual duration of the signal's state. Only with the next level change, the LSB of this counter will be taken to provide exactly one new random bit. This method has two benefits: It offers pretty good balancing of random data and it is quite insensitive against predominant spectral components. In contrast to simple S&H-schemes, no aliasing products occur, even if the sampling clock reaches or exceeds upper frequency boundaries of the noise. (Yet, the overall entropy of the gained random data would degrade.)
Overall efficiency is similar to the Von Neumann method. Despite the digitized noise at the second comparator's output will most likely have a remaining bias of some percent, the first computational steps of bitsampling make sure that the bits harvested from the noise source will only have a few 0.01 percent.
In a second step every 8 random bits are combined to form a byte, which is then XORed with older byte from the random pool. Doing so, all bytes in the random pool are repeatedly refreshed with an average processing speed of several 100 kbits.
Since the procedure delivers a numerical value that indicates pulselength as a by-product, it is easy to detect irregularly long periods (= low frequency components) in the source signal. This could indicate disturbance/interference effects on the electronic circuitry, in such case there may be 'preventive/compensative measures' necessary (resort to random pool data or even interrupt the data transfer).

The bitsampling routine of a current firmware can check momentary state of the noise signal more than 1 million times per second. Values of the pulswidth counter ranged between 2...14 units (forwarded in a special debugging setup). This would be equivalent to a noise spectrum with frequency components of roughly 38...220 kHz. (When digital noise was directed to a frequency counter, we get average frequency of 140 kHz, which leads to the estimate that this kind of entropy source may deliver about 280 kBit/s (= 35 kByte/s) of random data at maximum.) The internal random pool of nearly 500 bytes (= 4000 bits) is thus refreshed about 70 times per second. This value has also been counterchecked by further measures/testing. Of course, these values will slightly change with any programming modification, but it's good to know the dimensions. Conclusively, it should be no problem to fetch random data from the device even with an average rate of 230.400 bps.


Differences between XR232 and XR232USB:
With the classical XR232 an oversampling of the noise source is not recommended (and already limited by the reduced bandwidth of the optocouplers). In classical XR232 the digitized noise is only balanced by frequency divider, then sampled with regenerated TXD clock pattern, added with start/stopbits and then directly sent to RXD. In classic XR232 the random data delivered will always reflect some kind of snapshot from the momentary state of the noise source.
The microcontroller in XR232USB does pretty more processing with the noise. First the µC samples and processes random data bits in a continuous way to permanently refresh some random pool. This pool is not only forming a short-time buffer, it accumulates and preserves entropy, even if there is no random data requested by the host. Thus, in XR232USB, the operations of reading random and actually sampling that data from the noise source, are de-coupled from a timing perspective.


Read out of random data

According to XR232 protocol the host requests random data bytes by sending a special or "magic character" to the serial port. This is the "U", ASCII code 85, or 1010101010 in binary notation (start and stopbits highlighted). The device answers with exactly one byte of random per magic character received.
That hard-wired logic of XR232 worked in realtime. Yet, any microcontroller may also be fast enough to detect TXD-level changes and respond with serial characters up to a certain baudrate. (Effective programming in machine language provided...)
One clear advantage of the µC is the option to make use of internal SRAM to establish a kind of Random-Pool. This allows to buffer serial access and thus largely de-couple the process of random data sampling from random data delivery.
To achieve this, the bitsampling routine must run with highest priority and without the risk of being interrupted by interrupts, so there is no interrupts at all. All TXD/RXD-related operations are in fact done by the 'polling' method and are thus only side jobs of the main programme, whose main task is to sample and process random data bits with highest processing speed achievable. This works fine up to 230400 and even higher baudrates with tolerable timing jitter on the serial bits. (Which we owe the fact that timing-errors cannot accumulate in XR232 protocol!)
BTW, there's certainly separate address-counters for reads and writes into the random pool.


XR232USB Timing
XR232USB access timing (do not scale from this drawing...)
tRES  = Hardware-Reset, only initializing (few ms)
tdis1 = short disturbance < 20 ms (completely bufferd thru Random-Pool)
tdis2 = long disturbance > 20 ms (cause CTS-interruption and launches Restart)
tR1 = detection time for a "long" disturbance, about 20 ms
tR2 = deadtime (time to wait for noise source to recover)
tR3 = regeneration time (refreshing Random-Pool)

Reset

Hardware reset may be triggered by powering up the device (power-up/brownout reset) or by pulling the µC's RESET-line to Low-level (external RESET). As already mentioned in the Hardware section, controller's RESET is also triggered by the falling edge of RTS coming from FT232.

RTS goes Low after the interface has just been opened by the host and first characters are ready to be sent in the transmit buffer. The device shall react by pulling down CTS (within the specified timeout-periods) as soon as the device is ready to receive any characters. (Seems that RTS-CTS flow control is more flexible compared to DTR-DSR, which does not allow both parties to temporarily interrupt transmissions.)

Reset:
Directly after Power-on or Hardware Reset induced by RTS, the firmware keeps CTS line deactivated. This is to signalize the PC that the device is not ready yet. First of all the firmware will re-initialize the registers and ports and then refresh the random pool in SRAM. To ensure that corrupted random data remains in the pool but also to benefit from older entropy being "recycled", the whole random pool is rotated some thousands of times. After about 1/10 of second, firmware then activates CTS to tell host that it is now for delivery of random data.
If there has been severe disturbance whilst in transmit mode, uncorrupted random data from the pool would rapidly exhaust and the firmware cannot deliver fresh random data so far. Thus, the firmware must deactivate CTS and sit the disturbance out. If disturbance has passed, the firmware will jump into the Reset procedure, do the big refresh of random pool and then re-activate CTS to resume transmission.


Handling of interference

The random number generator does its best to guarantee that supplied random data was not corrupted by external disturbance.
If however serious interference occured, the software should be alarmed.

Due to its electronic working principle, the noise source has sensitivity for RF-interference and AF-fluctuations on its supply voltage. Both effects can be coped with by several physical and electronic measures, but in a µC-based appliance, it should also be monitored and, of course, compensated as required.

The noise source normally delivers bandwidth-limited noise in a frequency range of some tens up to hundreds kHz. Disturbance of this circuit will cause lower frequencies to occur, in extreme, static output levels. These effects can be safely detected by the firmware. The random bitsampling routine would not do further random data writes as long as the noise source is "down". This feature protects the random pool from catching "spurious patterns" that may be induced by subliminal interference of the noise source. To conclude, any shorter interference will only cause short interruption of the process of random bit harvesting, but this is completely uncritical as long as the pool gets refreshed fast enough to recover.

However, some disturbance of longer duration, say, some 1/100 seconds, may lead to performance problems, if random data is continuously requested with high baudrates. Only trustworthy method to cope with this: Stop delivery of random data. Wait untilnoise source has safely recovered. Refresh the pool thoroughly.

The second disturbance depicted in the diagram lasts approx. 5 ms (tdis2). After 2 ms (tR1) the firmware has recognized a longer interruption of noise. Now CTS must be deactivated to prevent reading of degraded random data. Now the program waits until the noise-source has recovered (tR2). After this "dead time" of further 3 ms (tR2), wideband noise returned, so the firmware launches an extended reset (coldstart) and refresh the pool thoroughly. Finally it activates CTS and transmission goes on!

Effects at host side:
If the XR232-software running on the host PC has been configured for a generous RTS-CTS-timeout, there might be interference on the noise source of random generator even seconds lasting, without an interface error being detected. This means, there is no need to even reinitialize the COM-port for continuation of the data transfer! This option seems meaningful for unsupervised generation of large random files, or with applications, where fast recovery from possible disturbance has the highest priority.
If on the host PC a stricter timeout for RTS-CTS was applied, longer disturbance and CTS-deactivation will surely exceed the timeout and lead to an interface error. The software will have to close the COM-port and reinitialize it after some latency time.



Identification string

Firmware measures approximate baudrate by the leading startbits of the magic characters sent by the host. If incoming characters' baudrate is under approx. 2400 bps, the firmware immediately switches to an "identification mode".
In this mode the device will respond with an ASCII-string identifying the device and build date of the firmware, one character of the string in turn for every magic character issued by the host and repeated forever, als long as the host sends its magic characters.
This enables XR232-software to differentiate betweeen real/classic XR232 and XR232USB devices and their firmware version. Software may then use higher transmission with XR232USB as with classic XR232. The identification string is located in the flash area by the firmware code.
Note, that the identification mode must be stopped by closing the serial port before regular random data transfer will resume.


Bootloader

A Bootloader that fulfils all technical and ideological requirements of this project, is available. Have a look at my recent project One-Way-Loader.

UpIndex



Software

New XR232-console-tool

The commandline tool "XR232NT" is a 32-bit executable, available for win32 and linux systems. It has been written under that marvellous and platform-independent FreeBASIC. The software makes consequent use of block transmission methods, favourable for both, XR232 and XR232USB (genuine and virtual serial port) implementations under recent OS. Robust error handling allows unattended operation (e.g. to produce large random files).
New reasonable features and bugfixes are likely to show up in future versions.


Features of XR232NT:

Library functions

On certain requests, i offer diverted XR232-specific Library (.dll / .so) now. This will ultimately enable programmers to make use of XR232/XR232USB without being bothered by specific serial port stuff. Please have a look at it, since it is still 'beta' and i will appreciate any constructive feedback.

UpIndex



Manufacture

You will find a proven PCB layout for XR232USB hardware version 1.0 in the zipped package as usual in a high resolution bitmap graphics format. (Me neither use vector graphics nor proprietary layout software, so please refrain from asking!)
While current version with mixed component already makes a nice "stick", i would maintain this variant for the time being.

Requirements of this PCB reproduction and soldering are comparably high only because of the one SSOP chip.

General recommendation: First solder FT232RL with a minimum of (leaded) tin, then the minimum of external wiring needed for connecting with USB. Check for proper recognition of FT232 chip and assignment of a new COM- resp. /dev/ttyUSB port, few seconds after plugging into any USB port. Additional testing may include a temporary connection soldered between TXD-RXD and RTS-CTS, which would basically allow some loopback testing by means of a terminal programme. After successfull completion of these tests, you can do the remaining components much much more relaxed...
However, this is definitely no project for beginners, and you must either be very good in improvisation or you should have some SMD-specific tools at hand!

The package includes a PDF worksheet with bill of materials, site plan and other circuit documentation.


Heavy Metal

(Well, actually it's light metal...) Picture below shows a slightly modified XR232USB-PCB in die-cast aluminium housing. That's not only giving (justified) premium look-and-feel, it actually provides excellent mechanical and electromagnetic protection against RF-Flooding and other possible disturbance.

XR232USB deluxe


UpIndex



Screenshots

Screenshots "XR232NT.EXE"


Hex-dump



Raw random data
visualized in bitmap






Testing digital sum value (block/overall) from random
data and byte-valencies





Picture shows the accumulated
Byte-frequencies


IMPORTANT NOTE: These integrated checks are merely 'illustrative' and should only prove basic functionality of the XR232/XR232USB hardware. It is of course recommended to run any sophisticated tests (e.g. DIEHARD) over a large amount of random data sampled from the TRNG under realistic conditions before using such device for crypto or other critical application.


Up | Index




Downloads



Links




Up | Index


Revision history: 09/2011, 07/2012, 11/2012, 07/2013, 01/2014, 07/2014, 04/2015, 11/2016, 12/2019, 09/2020, 03/2023