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.
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.
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:
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.
- For ease of convention, I'll label this square pad as
Based on this numbering scheme,
Pin 5
andPin 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
andPin 6
.
- Unlike the body side mount, the lens mount/bayonet is not electrically common with
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.
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
andPin 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.
Looking into the cavity, there are some small screws which allow the removal of the internal baffle cylinder piece.
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.
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.
CAD Models
I took a handful of measurements of each mount and attempted to draw mechanically compatible lens and body mount designs in Solidworks.
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.
The pad sections of the flex are held captive against a plastic a ring which supports some tiny pogo-pins.
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.
We now have some good hints of which pins are responsible for power, and those which are intended for data.
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.
But you might be asking, "how do you get the wires out of a sealed tube"?
With the exit holes measured and drilled, I started re-assembling the extension tube.
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:
Pin | Voltage | State | Scope/Notes |
---|---|---|---|
1 | ~0V | Never triggers scope, even with varied stimulus/settings. | |
2 | 5.32V | DC | |
3 | 6.72V | DC | |
4 | 8.01V | DC | Battery Voltage. ~100mV ripple when focus motor engages. |
5 | - | - | Used as ground connection. |
6 | - | - | Electrically common with Pin 5 |
7 | 3.4V | Normally high | Infrequent squarewave. No recognisable pattern. |
8 | 3.38V | Normally high | High speed edges, infrequently triggered. Pulses LOW for approx 100-350ns at a 10ms interval. |
9 | 0V | Normally low | Squarewave, data line. |
10 | 3.3V | Normally high | Squarewave, clock line at 1.5MHz. |
11 | 0V | Normally low | Squarewave, data line. |
12 | 3.3V | Normally high | Squarewave, 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.
Signal analysis
A capture of some simple camera operation will start off our analysis:
- Power up,
- Focus, then focus+photo
- Power off
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,
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 out16
and32
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)
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.
- Unsure of what
- 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 # | Camera | Lens |
---|---|---|
1 | 0x00 0x00 0x08 0x20 | - |
2 | 0x?? 0x10 0x80 0x?? | 0x08 0x00 0x88 0x32 |
3 | - | 0x03 0x80 0x08 0x3C |
4 | 0x08 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 # | Camera | Lens |
---|---|---|
1 | 0x00 0x00 0x08 0x20 | - |
2 | 0x?? 0x10 0x80 0x?? | 0x08 0x00 0x88 0x32 |
3 | 0x00 0x00 0x09 0xA6 | 0x03 0x80 0x08 0x3C |
4 | 0x?? 0x00 0x88 0x?? | 0x?? 0x00 0x89 0x?? |
5 | - | 0x00 0x15 0x09 0x9A |
6 | 0x08 0x00 0x89 0xB8 | 0x?? 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 # | Camera | Lens |
---|---|---|
1 | 0x12 0x40 0x18 0xBA | - |
2 | 0x09 0x10 0x80 0x2A | 0x08 0x00 0x98 0xB6 |
3 | 0x00 0x00 0x3F 0xC6 | 0x12 0x40 0x18 0xBA |
4 | 0x0A 0x00 0x98 0x86 | 0x09 0x00 0xBF 0xE0 |
Pin 12 (IRIS) low | ||
5 | 0x00 0x00 0x00 0x00 | 0x00 0x00 0x3F 0xC6 |
6 | 0x08 0x00 0xBF 0xD8 | 0x0A 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.