258 Linear Timecode (LTC) generator with I2C control

258 : Linear Timecode (LTC) generator with I2C control

Design render

How it works

This is a project that generates Linear Timecode (LTC), most commonly used for audio and/or video syncronization. LTC is a digital signal, though it is often captured and recorded as an audio signal and this project is designed to work with the Tiny Tapeout Audio PMOD, to output a signal suitable for audio and video equipment.

The project uses multiple counters to maintain time and framecount, with serial output of the LTC (80 bit frames, biphase mark code) being output on a single pin.

In addition, it's possible to control the timecode generation and the user bits in the signal using I2C.

This is the updated version (v2), with added I2C control in addition to a series of other tweaks, as the original version (included on TTIHP25a, TTSKY25a and TTGF0.2) had only the bare minimum of functionality.

How to test

Setup

The project should have a 24 MHz clock signal applied and after reset, will start out with a 01:00:00:00 timecode and starts to count.

Configuration using inputs/switches on the demo board

Framerate is by default controlled using inputs ui[2] and ui[3]

FR1/ui[3] FR0/ui[2] Framerate 7 Seg Debug Comment
0 0 24 4
0 1 25 5
1 0 29.97 9 Should also use drop frame
1 1 30 3

Drop frame can be enabled with ui[4] (active high). It can be enabled and will be applied to all framerates, but it only really makes sense for 29.97 fps, where it should always be applied to follow LTC specification and keep the time from drifting.

The color frame flag (if timecode is syncronised to a color video signal) can be configured using ui[5] (active high) and BGF0 and BGF1 (Binary Group Flags) are configured using ui[6] and ui[7] respectively (also active high).

Configuration via I2C

As an alternative to configuring the timecode signal via input switches, it's also possible to change all of the above settings and more usign I2C by writing to a set of registers.

The base address (7 bit) is: 0x42 (0x84 for write and 0x85 for read in 8 bit representation)

To use the configuration for framerate, drop frame, color frame and BGF you need to set bit 7 in register 0x00 (USE in the table below). If this bit is not set, the input pins will be used for the setup configuration and not the setup register (BGF2 is only configurable via I2C and will not be set if using input pins for setup).

The framerate currently in use will be shown in an single digit, abbreviated, human readable form on the 7 segment display. The decimal point will be illuminated, if setup from the I2C controlled register is in use.

Setting time via I2C

The time will start out at 01:00:00:00 after a reset. Changing the time can be done by writing to one or more of the time registers (0x01 though 0x04). The registers use the same binary coded decimal as in the output timecode signal, so that the "tens" are in the upper nibble and the "singles" are in the lower one. This makes it pretty easy to set the time eg. usign a bus pirate where you use a terminal for the I2C commands (eg. [0x84 0x01 0x13 0x37] to set the time to 13:37 for hours:minutes).

Reading from the time and frame registers will return the current time and framecount in the same binary encoded decimal format (eg. [0x84 0x01][0x85 rrrr] with the Bus Pirate).

Setting userbits via I2C

LTC also includes a total of 8 user bit fields, each being 4 bits. Those can be set (and read back) via I2C registers 0x05 to 0x08. The definition of those are not fully defined and the order might not be ideal in all usecases, eg. if using the userbits for dates, the order of "tens" and "singles" might be less natural and flipped compared to settign the time.

I2C Register map

Addr. Register name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 Default on reset
0x00 Setup USE FR1 FR0 DF CF BGF2 BGF1 BGF0 0x00
0x01 Hours - - HRSD1 HRSD0 HRSU3 HRSU2 HRSU1 HRSU0 0x10
0x02 Minutes - MIND2 MIND1 MIND0 MINU3 MINU2 MINU1 MINU0 0x00
0x03 Seconds - SECD2 SECD1 SECD0 SECU3 SECU2 SECU1 SECU0 0x00
0x04 Frame - - FRMD1 FRMD0 FRMU3 FRMU2 FRMU1 FRMU0 0x00
0x05 User bits 1&2 UB1_3 UB1_2 UB1_1 UB1_0 UB2_3 UB2_2 UB2_1 UB2_0 0x00
0x06 User bits 3&4 UB3_3 UB3_2 UB3_1 UB3_0 UB4_3 UB4_2 UB4_1 UB4_0 0x00
0x07 User bits 5&6 UB5_3 UB5_2 UB5_1 UB5_0 UB6_3 UB6_2 UB6_1 UB6_0 0x00
0x08 User bits 7&8 UB7_3 UB7_2 UB7_1 UB7_0 UB8_3 UB8_2 UB8_1 UB8_0 0x00

External hardware

This should work with the audio PMOD connected to the bidirectional port, to give levels useable for audio gear. for I2C communication, you will need to use the pass through connections as SDA and SCL are also on the bidirectional port (uio[0] and uio[1] respectively).

If you have line level audio input on your computer (or using a USB audio interface), there are software that can listen to the input and show the timecode (https://timecodesync.com/ have a free to download and use tool for macOS and Windows).

It is possible to listen to this "audio", but it is not a pleasant sound, so be careful if you use headphones or powerfull speakers

If testing with a logic analyzer or similar, uio[7] can be directly connected (3.3v digital signal) and referenced to GND.

For communicating with the device via I2C, someting like a Bus Pirate or similar can be used. Remember to add/enable pullup resistors to the 3.3v rail.

IO

#InputOutputBidirectional
0FRAMERATE_DEBUG_7SEGI2C_SDA
1FRAMERATE_DEBUG_7SEGI2C_SCL
2FRAMERATE_0FRAMERATE_DEBUG_7SEG
3FRAMERATE_1FRAMERATE_DEBUG_7SEG
4DFFRAMERATE_DEBUG_7SEGDEBUG_SETTIME_OUT
5CFFRAMERATE_DEBUG_7SEGDEBUG_I2C_OUT
6BGF_0FRAMERATE_DEBUG_7SEGDEBUG_I2C_OUT
7BGF_1REG_CONF_ACTIVELTC_OUT

Chip location

Controller Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux tt_um_chip_rom (Chip ROM) tt_um_factory_test (Tiny Tapeout Factory Test) tt_um_htfab_asicle2 (Asicle v2) tt_um_htfab_caterpillar (Simon's Caterpillar) tt_um_urish_simon (Simon Says memory game) tt_um_microlane_demo (microlane demo project) tt_um_ygdes_hdsiso8_dlhq (ttihp-HDSISO8) tt_um_ygdes_hdsiso8_rs (ttihp-HDSISO8RS) tt_um_YannGuidon_TinyScanChain (TinyScanChain5L) tt_um_MichaelBell_photo_frame (Photo Frame) tt_um_digital_clock_example (7-Segment Digital Desk Clock) tt_um_miniMAC (miniMAC_5L) tt_um_tinymoa_ihp0p4_16x16 (TinyMOA-IHP0P4-16x16) tt_um_glyph_mode_hd (Glyph Mode HD) tt_um_prism_lite (ihp_cmos51_prism) tt_um_htfab_rotfpga2 (ROTFPGA v2) tt_um_SotaSoC (SotaSoC) tt_um_essen (Fast bfloat multiplication) tt_um_calonso88_spi_i2c_reg_bank (Register bank accessible through SPI and I2C) tt_um_urish_usb_cdc (USB CDC (Serial) Device) tt_um_urish_rings (VGA Rings) tt_um_toivoh_demo (Orion Iron Ion [TT08 demo competition]) tt_um_2048_vga_game (2048 sliding tile puzzle game (VGA)) tt_um_pakesson_glitcher (Glitcher) tt_um_chatelao_fp8_multiplier (OCP MXFP8 Streaming MAC Unit) tt_um_algofoogle_raybox_zero (raybox-zero TTIHP0p4 edition) tt_um_flummer_ltc (Linear Timecode (LTC) generator with I2C control) tt_um_lledoux_s3fdp_seqcomb (Pattern-Guided Arithmetic Optimizations with MLIR) tt_um_snake_game (SnakeGame) tt_um_spongent88 (Spongent-88 Hash Accelerator) tt_um_lledoux_bf16_diminished_kulisch (Pattern-Guided Arithmetic Optimizations with MLIR kulisch bf16) tt_um_float_synth_nikleberg (float_synth) tt_um_silicon_strummer (Silicon Strummer) tt_um_vga_clock (VGA clock) tt_um_urish_sic1 (SIC-1 8-bit SUBLEQ Single Instruction Computer) tt_um_algofoogle_vgaringosc (Ring osc on VGA) tt_um_tinymoa_ihp0p4_8x8 (TinyMOA-IHP0P4-8x8) tt_um_tinytapeout_logo_screensaver (VGA Screensaver with Tiny Tapeout Logo) tt_um_lisa (LISA 8-Bit Microcontroller) tt_um_nicklausthompson_twi_monitor (TWI Monitor) Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available Available