Posted on

Table of Contents

Context

The Fujifilm GFX line of cameras is the most accessible digital 'medium format' system to date, and the Fujinon lenses are optically fantastic and incredibly capable.

Fujifilm GFX50R with 110mm lens held in hand

While there are a handful of dumb mechanical lens adaptors for the G-mount, and a couple of 'smart' adaptors from companies like Fringer, there is very little information about the mount or protocol.

I had a 'the right kind of wrong' idea to figure out GF lens control with the end-goal of (possibly) building a 'medium format' film camera around them.

As all of the currently released GF lenses use fly-by-wire focus, electronic aperture, and some need to be powered up to position floating optical elements - if I want to build a camera around them then I'll need to reverse engineer the mechanical, electrical, and software to even consider camera design.

Disassembling a MCEX-45G

I picked up the 45mm extension tube on a ~25% discount with the intention of using it to bootstrap debugging, and probably provide donor lens/body mount flanges.

Can confirm it works as advertised with the GF 110mm F2.

Close up detail photo of broken stick with green moss and spiderwebs, black background

Lets dive in.

Lens mount basics

The electrical connections between the body and lens are made with 12 spring loaded contacts on the body which mechanically align with 11 contact rectangles on the lens.

My reference drawing for the lens contacts:

Dimensioned mechanical drawing of lens pin shapes and positions

Lens Side

  • The lens-side contacts are 1.6 x 1.3 mm rectangular pads, with the long edge aligned tangentially to the circular mount.

  • When looking at the back of the lens mount, the right-most pin is a 1.3 mm x 1.3 mm square contact.

    • For ease of convention, I'll label this square pad as Pin 1, though I don't know what the official nomenclature is.
  • Based on this numbering scheme, Pin 5 and Pin 6 are mechanically the same contact rectangle, and therefore electrically common.

    • Unlike the body side mount, the lens mount/bayonet is not electrically common with Pin 5 and Pin 6.
  • One interesting point to note - the pinout for the GF 45mm (top) doesn't use all 12 contacts that the body provides, while the GF 110mm (bottom) does.

    Two lenses on table showing the bayonet mount, smaller first lens has 7 visible contacts, the second has 11

Body Side

  • The spring section of the pins have a 1.0 mm diameter, and a maximum achievable travel of 0.8 mm.
  • The spring pins have a conical/round tip.
  • The pins are spaced 6° apart, for a total span/range of 66°. There is no pin on the vertical axis, and from a vertical datum aligned with the center of the lens, the outermost edge pins are aligned to +33° and -33°.
  • The mount (metal ring/bayonet assembly) is electrically common with the exposed metal inside the battery compartment, as well as Pin 5 and Pin 6.

Now lets start opening up the extension tube to learn more...

Tube design

From the rear, a few screws remove the bayonet mount (i.e. the 'lens side mount'). The weathersealing gasket slides off with it, and we can see the simple internal design of the extention tube.

Machined metal ring with 3 overhang features for retention

Black metal tube sitting inside black lens mount assembly with visible gap between the tubes

Looking into the cavity, there are some small screws which allow the removal of the internal baffle cylinder piece.

Machined cylinder, internal walls appear corrugated

The 'female' flange assembly which is found on the camera body has a machined mating face and orange lens alignment dot, backed by a thin spring plate to provide preload against the incoming lens bayonet features.

Side view of metal ring with polished silver appearance, flexible retention plate

Top down views of lens mount ring and thin spring ring

The lens release is a simple spring loaded post that just rests against the main tube assembly.

The main tube assembly is actually two pieces - the thin exterior 'skin', and a thicker machined aluminium piece which has most of the mounting geometry for the mounting flanges and electrical sub-assembly.

Top down view of black anodized extension tube with most parts removed

CAD Models

I took a handful of measurements of each mount and attempted to draw mechanically compatible lens and body mount designs in Solidworks.

3D render of lens and body mount flanges

I'm not 100% on the accuracy of either design, but a motion study showed them mating successfully and I'm confident I'd be able to use these as a starting point for a more manufacture-friendly design.

Flex PCB

As we expected before the tear-down, the extension tube only provides a dumb pass-through to the lens mount, there's no active electronics.

Angled view of extension tube and exposed flex PCB connecting to spring contacts

The pad sections of the flex are held captive against a plastic a ring which supports some tiny pogo-pins.

Plastic bracket with spring contacts removed from camera, top down view

Hindsight tells us that unscrewing the plastic retention bracket behind the pogo-pins is a mistake - I spent the better part of an hour trying to guide the springs back into place with a handmade jig of needles.

Size comparison between 1mm metal slug and 1x4mm spring against a thumb

We now have some good hints of which pins are responsible for power, and those which are intended for data.

Top-down view of flex PCB separate from assemblies, mix of thin and thick traces

Back view of flex-PCB, two thick traces occupy 60% of visible surface area

Attaching debug probes

With the electrical sub-assemblies out of the tube we begin by removing the Kapton tape protecting the through-hole pins, solder silicone wires onto the camera side of the flex, and then re-apply fresh Kapton tape to protect the joins from electrical contact with the tube/mount.

Flex PCB held in Stickvise, white wires soldered to contacts

But you might be asking, "how do you get the wires out of a sealed tube"?

Metal tube sections wrapped in masking tape, holes drilled in sides

Inner tube section with hole in side, angled shot

Outer tube surface with hole drilled under lens release clip, angled shot

With the exit holes measured and drilled, I started re-assembling the extension tube.

Angled top view showing debug wires running through drilled external holes

Reassembled macro tube with debug wires dangling out the side

Once the tube was re-assembled, I identified each debug wire by checking for continuity with the lens mount pins, and then soldered on a terminal strip to make debug connections easier.

Electrical Behaviour

We'll start by identifying our power pins. Some immediate clues can be gleaned from looking at the flex PCB and by probing the pins on the camera.

The ground was assumed to be Pin 5 as it has higher-current traces and is common with Pin 6 on the lens mount side. It's also electrically common with the GFX body mount.

After poking around with a multimeter and oscilloscope for a few minutes, we have a rough pinout:

PinVoltageStateScope/Notes
1~0VNever triggers scope, even with varied stimulus/settings.
25.32VDC
36.72VDC
48.01VDCBattery Voltage. ~100mV ripple when focus motor engages.
5--Used as ground connection.
6--Electrically common with Pin 5
73.4VNormally highInfrequent squarewave. No recognisable pattern.
83.38VNormally highHigh speed edges, infrequently triggered.
Pulses LOW for approx 100-350ns at a 10ms interval.
90VNormally lowSquarewave, data line.
103.3VNormally highSquarewave, clock line at 1.5MHz.
110VNormally lowSquarewave, data line.
123.3VNormally highSquarewave, goes low when iris closes.

I now know what's safe to connect to the logic analyser and could start sniffing for communications between the body and lens.

Camera with tube and lens, connected to Saleae logic analyser

Signal analysis

A capture of some simple camera operation will start off our analysis:

  • Power up,
  • Focus, then focus+photo
  • Power off

Logic analyser waveform capture of signal pins

Data Lines

Lets start by looking into the data lines first. We can see some one-way data transfers, as well as request/response style behaviour. This lets us make the following observations about these data pins:

  • Pin 9 is the body's DATA OUT line,
  • Pin 10 is a 1.5MHz SPI-style clock signal,
  • Pin 11 is the body's DATA IN line,

Packet capture showing clock and two data waveforms

With this in mind, lets identify the properties of the communications bus and determine if it's a fairly typical SPI or some Fuji special sauce:

  • A transaction seems to consist of 32-bits at minimum,
    • Almost all transactions are 32-bits long.
    • During startup, a pair of 1048-bit long transactions occur with a 3ms gap - these are the longest identified transactions.
    • As the division of 1048 and the potential bits-per-transfer should be an integer, we can reasonably throw out 16 and 32 bit transfer sizes.
    • Therefore it's reasonable to assume byte-level layout of packets.
  • We can also determine the clock behaviour, by looking at the first falling edge and any 8-bit aligned end:
    • The clock is high when inactive (CPOL = 1).
    • Data appears to be timed for the clock's trailing edge (CPHA = 1)

Analysis capture of clock waveform

Other IO

Pin 1 is intended as a signalling line due to the trace thickness, but I saw no activity.

Pin 7 seems to be related to auto-focus motor activation.

Pin 12 correlates to the iris closing.

Protocol Analysis

We can now sniff the packets being sent between the lens and body. From a few test captures, there's a few key packet sequences that are immediately obvious.

Startup/Identification packets

After the camera is powered on with a GF 45mm F2.8 lens, a series of 131B transactions occur (each sent twice 3ms apart). These transactions are from the lens to the body and describe the lens.

The first transaction starts with 0x00 0x00, the second transaction starts with 0xFF 0xFF. Both end with what I'm assuming is a single checksum byte.

The payload (hex formatted) looks like this:

4c52 3130 3641 0000 4653 534e 5730 3036
4746 3435 6d6d 4632 2e38 2052 2057 5200
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
3234 3033 3338 3636 3035 0156 0100 0100
0100 0100 c801 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000

Doing a little bit of conversion we find:

  • The first chunk of data is ASCII: LR106A FSSNW006GF45mmF2.8 R WR
    • Not sure what the first string section means yet.
    • Part of the last section is obvious as the lens is officially labelled as GF45mmF2.8 R WR.
  • The second block of data in the payload is likely some combination of binary data and potentially ASCII formatted numbers with no obvious meaning.

Sniffing the GF 110mm F2 startup packet we see similar behaviour:

4c52 3130 3441 0000 4653 534e 5731 3034
4746 3131 306d 6d46 3220 5220 4c4d 2057
5200 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
3035 4330 3030 3234 0000 0160 0110 0110
0110 0110 c801 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
  • The first section of data is ASCII: LR104A FSSNW104GF110mmF2 R LM WR
  • The second block is different and similarly unrecognisable.

After the lens packets, and only when the GF110mm is mounted, the camera body describes itself to the lens.

5350 5833 0000 0000 0000 4746 5820 3530
5200 0000 0000 0000 0000 0000 0000 4746
5820 3530 5200 0000 0000 0000 0035 3933
3533 3433 3833 3633 3131 3831 3131 3339
3744 3031 3031 3130 3834 3102 2001 3501
0001 0001 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
  • The first section of data is ASCII: SPX3 GFX 50R GFX 50R (whitespace trimmed)
    • Unsure of what SPX3 represents.
    • The repeated pair of GFX 50R string sequences match the body under test.
  • The second chunk of data is another unknown mix of potentially ASCII, and unprintable bytes.

'Idle' packets

When the camera is powered on but is otherwise sitting idle, we see a burst of transactions occur every 40ms.

These packets represent the bulk of 'noise' when reading packet traces, so understanding, decoding and then filtering them represents a worthwhile effort.

Transmission #CameraLens
10x00 0x00 0x08 0x20-
20x?? 0x10 0x80 0x??0x08 0x00 0x88 0x32
3-0x03 0x80 0x08 0x3C
40x08 0x00 0x88 0x??0x?? 0x00 0x80 0x??

On every third burst (120ms interval), we have 2 additional transactions for a total of 6 total.

Transmission #CameraLens
10x00 0x00 0x08 0x20-
20x?? 0x10 0x80 0x??0x08 0x00 0x88 0x32
30x00 0x00 0x09 0xA60x03 0x80 0x08 0x3C
40x?? 0x00 0x88 0x??0x?? 0x00 0x89 0x??
5-0x00 0x15 0x09 0x9A
60x08 0x00 0x89 0xB80x?? 0x00 0x80 0x??

For both the 4 and 6 packet bursts, when I marked the first bytes as 0x?? this was to represent them varying between subsequent bursts. Sampling 5 random sequences of packets gives the impression that there isn't obvious packet counting behaviour though.

The final bytes marked 0x?? are an assumed CRC byte which is changing due to the cycling first byte...

Iris packets

Looking for packets we don't recognise around the IRIS control IO line (Pin 12) changing state, I found the following series of transactions. This whole sequence spans 275 ms.

Transmission #CameraLens
10x12 0x40 0x18 0xBA-
20x09 0x10 0x80 0x2A0x08 0x00 0x98 0xB6
30x00 0x00 0x3F 0xC60x12 0x40 0x18 0xBA
40x0A 0x00 0x98 0x860x09 0x00 0xBF 0xE0
Pin 12 (IRIS) low
50x00 0x00 0x00 0x000x00 0x00 0x3F 0xC6
60x08 0x00 0xBF 0xD80x0A 0x00 0x80 0x22
Silent for 40ms
6 bursts of IDLE packets
Pin 12 (IRIS) high

These packets add some confidence to a gut feel that the first byte is acting as some kind of identifier - we can see the camera send packets to the lens and receive packets in matching order, however the middle two bytes vary.

To get any deeper meaning out of this I think I'm going to make/find some better tools for packet analysis and experimentation.

What's next?

There are three key areas which need to progress as part of the reverse engineering effort:

  • 3D print or machine some test lens mount assemblies to check compatibility,
  • Better understand the behaviour of the extra IO signals, and measure current consumption on the various DC supply lines in anticipation of making functional interface electronics,
  • Develop a SPI man-in-the-middle bridge to build out tooling and firmware as part of reverse-engineering the communications protocol.
    • Being able to detect, log and then filter out common packets should make finding unique packets easier, and give clues as to what might be inside.