====== FPGA I²C bridge (registers' map) ======
The following tables provide information on how to access the camera's functionality for an FPGA I²C bridge.
Intel-based FPGA utilizes an [[https://www.intel.com/content/www/us/en/docs/programmable/683091/22-3/introduction-to-the-interface-specifications.html|Avalon interface bus]] to facilitate access to FPGA's "registers". We have reserved addresses beginning with \(0x5000'0000\) for the FX3<->FPGA communication.
Note that one of the limitations of Avalon is that addressing is done on a 4-byte boundary.
Here's a sample code (skipping all error checking) that sets the LED to bright-yellow color FIXME:
S2R::FX3 dev; // auto-open device #0
using S2R::FX3;
dev.vrCmd(FX3Cmd::i2c_bridge, VrCmdOpType::write, 255, 0x08); // red
dev.vrCmd(FX3Cmd::i2c_bridge, VrCmdOpType::write, 255, 0x0A); // green
dev.vrCmd(FX3Cmd::i2c_bridge, VrCmdOpType::write, 0, 0x0C); // blue
The address space is broken down into smaller chunks, grouped by common functionality:
===== FPGA basic status and controls =====
^ FPGA basic status and controls ^^^^^^
^Address ^Name ^Bytes ^Access ^Bit mapping ^Notes ^
|''0x5000'0000''|:!: FPGA Version| 4 |R/O| see [[code#firmware_version_info|Firmware Version Info]] | |
|''0x5000'0004''|:!: FPGA status| 4 |R/O|see Notes for more details\\ \\ ''31:16'' [[code:code#FPGA config status - SPI codes|SPI codes]]\\ ''15:8'' FPGA core temperature\\ ''7:2'' reserved\\ ''1'' DPC done\\ ''0'' SFP active| The bytes of the FPGA status register are allocated according to the little-ending memory layout of the following C-style declaration((For details on ''spi_config_status'' see [[code:code#FPGA config status - SPI codes|SPI codes]])):\\
struct FpgaStatus{
struct State{
// there is an active device in SFP+ cage
bool sfp_active:1;
// DPC calibration is completed
bool dpc_done:1;
// reading of the FPGA's internal temperature sensor in degrees of Fahrenheits
uint8_t reserved:6;
} state;
uint8_t core_temperature;
uint16_t spi_config_status;
};
|
===== FPGA operation mode =====
^ FPGA operation mode((Set the operation mode of the FPGA (e.g. switch into firmware programming) and enable/disable individual media output channels and specific transformation blocks)) ^^^^^^
^Address ^Name ^Bytes ^Access ^Bit mapping ^Notes ^
|''0x5000'0008''|:!: FPGA operation mode| 4 |R/W|''31:20'' reserved| |
|:::|:::|:::|:::|:!: ''19'' CCM| enable Color Correction Matrix transformation block |
|:::|:::|:::|:::|:!: ''18'' Gamma| enable UVC Gamma transformation block |
|:::|:::|:::|:::|:!: ''17:16'' debayer strategy|**De-mosaicing strategy** directs the use of a specific implementation of color reconstruction:\\ ''0'' - use "branchless 5x5", like the one [[https://www.ipol.im/pub/art/2011/g_mhcd/article.pdf|described in here]]\\ ''1'' - use "branching 5x5", for example the one [[http://www.siliconimaging.com/RGB%20Bayer.htm|described here]]\\ ''2'', ''3'' - reserved|
|:::|:::|:::|:::| ''15'' reserved| |
|:::|:::|:::|:::|:!: ''14'' reserved (headphones)| |
|:::|:::|:::|:::|:!: ''13'' reserved (UAC)| |
|:::|:::|:::|:::| ''12'' reserved| |
|:::|:::|:::|:::|:!: ''11'' HDMI output| enable HDMI video output |
|:::|:::|:::|:::|:!: ''10'' SDI output| enable SDI video output |
|:::|:::|:::|:::|:!: ''9'' SFP+ video| enable SFP+ video output |
|:::|:::|:::|:::|:!: ''8'' UVC output| enable UVC output |
|:::|:::|:::|:::| ''7:3'' reserved| |
|:::|:::|:::|:::|:!: ''2'' calibrate DPC| Start DPC calibration process |
|:::|:::|:::|:::|:!: ''1'' enable DPC| enable DPC correction |
|:::|:::|:::|:::|:!: ''0'' FPGA config enable|if set to ''1'', the GPIF becomes read only and waits for an FPGA update bitstream|
===== AWB =====
^ Auto White-Balance adjustments ^^^^^
^Address ^Name ^Bytes ^Access ^Notes ^
|''0x5000'0100''|:!: AWB Red adjustment| 2 |R/W|''int16_t'' value to add to Red component. Default is \(0\)|
|''0x5000'0104''|:!: AWB Green adjustment| 2 |R/W|''int16_t'' value to add to Green component. Default is \(0\)|
|''0x5000'0108''|:!: AWB Blue adjustment| 2 |R/W|''int16_t'' value to add to Blue component. Default is \(0\)|
|''0x5000'010C''|:!: AWB Red total| 4 | R/O | |
|''0x5000'0110''|:!: AWB Green total| 4 | R/O | |
|''0x5000'0114''|:!: AWB Blue total| 4 | R/O | |
|''0x5000'0118''|:!: AWB count total| 4 | R/O | A count of pixels that were used to calculate the \(R/G/B\) totals |
|''0x5000'011C''|:!: AWB status| 1 |R/O| Status and flags pertaining to AWB.\\ ''7:2'' reserved\\ :!: ''1'' - indicates whether a red overexposure is detected\\ :!: ''0'' - set if there is a general overexposure detected |
===== ISP adjustments =====
^ Standard image adjustments ^^^^^^^
^Address ^Name ^Bytes ^Access ^Range ^Range description ^Neutral value ^
|''0x5000'0200''|:!: Brightness| 2 |R/W|\([-1024..1023]\) |\(-1024\) makes the image very dark\\ \(1023\) makes the image very bright |\(0\) |
|''0x5000'0204''|:!: Contrast| 2 |R/W|\([1..2047]\) |\(1\) turns image into grayscale\\ \(2047\) makes all pixels either black or white |\(1023\) |
|''0x5000'0208''|:!: Saturation| 2 |R/W|\([0..900]\) |\([0\%..900\%]\) or grayscale to 9x |\(100\) |
|''0x5000'020C''|:!: Sharpness| 1 |R/W|\([0..255]\) | |\(0\) |
|''0x5000'0210''|:!: Gamma| 1 |R/W|\([0..15]\) | |\(1\) |
|''0x5000'0214''|:!: Hue| 2 |R/W|\([-8192..8191]\) |\([-180°..180°)\) |\(0\) |
===== DPC =====
^ Defective pixel cancellation ^^^^^
^Address ^Name ^Bytes ^Access ^Notes ^
|''0x5000'0300''|:!: DPC Threshold| 2 |R/W| Only consider a pixel to be defective if its value is over the specified threshold |
|''0x5000'0304''|:!: DPC count| 2 |R/O|Once the DPC calibration is done the 16-bit result is stored in here|
===== Image stats =====
^ General image stats ^^^^^
^Address ^Name ^Bytes ^Access ^Notes ^
|''0x5000'0400''|:!: FPS| 2 |R/O|16-bit unsigned value representing number of 10μs units between frame start signals from the image sensor, e.g. a value of \(1000\) means it took 10ms between 2 frame start signals, which corresponds to 100FPS|
|''0x5000'0404''|:!: Y average| 2 |R/O|Average "brightness" value|
===== Color Correction Matrix (a.k.a. CCM or CMX) =====
See [[isp:ccm|Color correction matrix]] article in this Wiki's ISP section for more details. The 16-bit (MSB-LSB) value is defined as \(7+9\) bits, where MSB''[7:1]'' are the integer part and MSB''[0]''LSB''[7:0]'' is the fractional part (effectively that value is 512 times larger than the original fractional part)
^ CMX ^^^^^
^Address ^Name ^Bytes ^Access ^Notes ^
|''0x5000'0500''|:!: CCM_00| 2 |R/W|\(CCM_{00}\)|
|''0x5000'0504''|:!: CCM_01| 2 |R/W|\(CCM_{01}\)|
|''0x5000'0508''|:!: CCM_02| 2 |R/W|\(CCM_{02}\)|
|''0x5000'050C''|:!: CCM_10| 2 |R/W|\(CCM_{10}\)|
|''0x5000'0510''|:!: CCM_11| 2 |R/W|\(CCM_{11}\)|
|''0x5000'0514''|:!: CCM_12| 2 |R/W|\(CCM_{12}\)|
|''0x5000'0518''|:!: CCM_20| 2 |R/W|\(CCM_{20}\)|
|''0x5000'051C''|:!: CCM_21| 2 |R/W|\(CCM_{21}\)|
|''0x5000'0520''|:!: CCM_22| 2 |R/W|\(CCM_{22}\)|
===== Color grading =====
FIXME Move all that out into its very own big block of address space FIXME
^Name ^Address ^Access ^Bit mapping ^Notes ^
|:!: switch|''0x2E''|W|''15:10'' reserved |Controls what information is being read/written by accessing the register ''0x002F''|
|:::|:::|:::|''9:7'' table switch|''000'' - Hue vs. Hue (''14'' bits)\\ ''001'' - Hue vs. Saturation (''12 bits'')\\ ''010'' - Lightness vs. Saturation (''12'' bits)\\ ''011'' - Saturation vs. Saturation (''12'' bits)\\ ''100'' - Lightness vs. Lightness (''12'' bits)\\ ''101'' - Hue vs. Lightness (''12'' bits)\\ ''110-111'' - reserved|
|:::|:::|:::|''6:1'' index LSB| index into a page in the table |
|:::|:::|:::|''0'' access mode| ''0'': "normal mode", in which all the subsequent accesses to the register ''0x002F'' are governed by the values in ''0x002E''\\ ''1'': "bulk access", where after a read or write access to register ''0x002F'' the "Index" value will auto-increment by one so that the next read/wrie will access the subsequent table slot|
|:!: Value|''0x2F''|R/W|''15:0'' value| 16 bits of either signed or unsigned integer value\\ - for a "Hue vs. Hue" table the 14 bits signed value is in range ''[-8192..+8192]'' which maps linearly into a Hue angle range ''-180°..+180°''\\ - for a "Hue vs. Saturation" table (as well as for similar tables %%LvS%% and %%SvS%%) the 12 bit unsigned value in range ''[0..+1280]'' maps linearly into a Saturation range ''[0%..1000%]'' where ''100%'' is the neutral position and ''0%'' produces a greyscale image\\ - for a "Lightness vs. Lightness" table (as well as for similar table %%HvL%%) the 13 bit signed value in range ''[-4096..+4095]'' maps linearly into a Lightness *relative* (adjustment) range ''[-256..255]'' where ''0'' is no adjustment to pixel luminosity value|
===== Media setup =====
==== Video output formats ====
^Name ^Address ^Access ^Bit mapping ^Notes ^
|:!: Video output format|''0x32''|R/W|:!: ''7:4'' - UVC\\ :!: ''3:0'' - FPS code for SDI, SFP+, SDI|Bit depth for all video formats is set in register ''0x49''\\ UVC video formats:\\ :!:''0'' - "RAW" greyscale pre-debayer pixels\\ :!:''1'' - 4:4:4 RGB\\ :!:''2'' - (res) packed YCbCr 4:4:4\\ :!:''3'' - packed YCbCr 4:2:2\\ :!:''4'' - (res) packed YCbCr 4:2:0\\ :!:''5'' - (res) planar YCbCr 4:4:4\\ :!:''6'' - (res) planar YCbCr 4:2:2\\ :!:''7'' - planar YCbCr 4:2:0\\ :!:''8-15'' - (res) MJPEG, MPEG-x/H.26x, etc\\ \\ SDI/HDMI and SFP+ video output formats/FPS are always in unison. See [[code:fx3_hvci_and_fpga_i_c_commands#sdi_fps|SDI FPS]] table below for codes. SDI output is always in a packed (not planar) YUV 4:2:2 format|
|:!: Video output pixel bit depth|''0x33''|R/W|:!: ''7:6'' - HDMI\\ :!: ''5:4'' - SDI\\ :!: ''3:2'' - SFP+\\ :!: ''1:0'' - UVC|Pixel bit values:\\ ''0'' => 8\\ ''1'' => 10\\ ''2'' => 12\\ ''3'' => 14\\ Not all values are valid, for example SDI and SFP+ both do not support ''8''-bit output and UVC currently **only** supports ''8''-bit color depth|
==== FOURCC formats (for UVC) ====
^ UVC's FOURCC codes((A combination of pixel bit depth and video format used for UVC is mapped into standard FOURCC codes as summarized in the following table)) ^^^^^^
^\(_{bit-depth} \backslash ^{video-format}\) ^''0'' (RAW) ^''1'' (RGB) ^''2'' (packed YUV 4:4:4((ordering is UYV))) ^''3'' (packed YUV 4:2:2((macropixel byte ordering: Y0U0Y1V0))) ^''7'' (planar YUV 4:2:0((chroma plane is a interleaved set of U/V samples))) ^
^''0'' (8 bit) |:!: BA81/BYR1/GREY/Y8/Y800 (8bpp)|:!: BI_RGB/RGB (24bpp) |:!: Y444/IYU2 (24bpp) |:!: YUY2/YUYV (16 bpp)|:!: NV12 (12bpp)|
^''1'' (10 bit) |:!: Y10((need to register with MS)) (16bpp((not 10)))|:!: BI_BITFIELDS (48bpp) |:!: Y410 (32bpp((includes 2 bit alpha at [31:30]))) |:!: Y210 (32bpp)\\ YUVP?/Y42T (24bpp?)|:!: P010 (32bpp) |
^''2'' (12 bit) |:!: BYR2 (16pbb((not 12)))|:!: BI_BITFIELDS (48bpp) |:!: Y412((need to register with MS)) (40bpp((or 36?))) |:!: Y212((need to register with MS)) (32bpp((or 24?))) |:!: P012((need to register with MS)) (32bpp((or 24, or 18?))) |
^''3'' (14 bit) |:!: Y16((yes, 16, not 14)) (16bpp((not 14)))|:!: BI_BITFIELDS (48bpp) |:!: Y414((need to register with MS)) (48bpp((or 42?))) |:!: Y214((need to register with MS)) (32bpp((or 28?))) |:!: P014((need to register with MS)) (32bpp((or 21?))) |
==== SDI FPS and pixel clock ====
^ SDI FPS and pixel clock((FPS+resolution pair dictates an SDI pixel clock choice)) ^^^^
^ \(_{code (FPS)} \backslash ^{resolution}\) ^ 1920x1080 ^ 3840x2160 ^ 7680x4320 ^
| ''0x01'' (23.98) | 74.18 | 296.70 | |
| ''0x02'' (24) | 74.25 | 297 | 1188 |
| ''0x04'' (25) | 74.25 | 297 | |
| ''0x05'' (29.97) | 74.18 | 296.70 |
| ''0x06'' (30) | 74.25 | 297 | 1188 |
| ''0x08'' (50) | 148.5 | 594 | |
| ''0x09'' (59.94) | 148.35 | 593.41 | |
| ''0x0A'' (60) | 148.5 | 594 | |
| ''0x0C'' (120) | 297 | 1188 | |
===== Green Screen enhancer =====
//"Green screen", a.k.a. "Chroma Key" on-board optimization is designed to replace a range of colors with a single solid one//
FIXME Move out into its own large address block FIXME
==== band #0 ====
If enabled these setting take precedence over other 3 bands
^Name ^Address ^Bytes ^Access ^Notes ^
|:!: CK control|''0x80''| 1 |R/W|''7:1'' reserved\\ ''0'' enable/disable Chroma Key control|
|:!: CK saturation min|''0x81''| 1 |R/W|[0..255] to specify the minimum saturation threshold|
|:!: CK saturation max|''0x82''| 1 |R/W|[0..255] to specify the maximum saturation threshold|
|:!: CK luma min|''0x83''| 1 |R/W|[0..255] to specify the minimum brightness threshold|
|:!: CK luma max|''0x84''| 1 |R/W|[0..255] to specify the maximum brightness threshold|
|:!: CK hue|''0x85''| 2 |R/W|14 bits of a signed hue value, its [-8K..+8K] range is mapped into [-180°..+180°]|
|:!: CK tolerance|''0x86''| 2 |R/W|13 bits of an unsigned hue tolerance value, valid range is [0..8K], which is mapped into [0°..180°].\\ That value specifies how far to stretch the ''CK hue'' value both ways (symmetrically). If the ''CK tolerance'' is above 90° the covered color space is over 50% of values|
|:!: CK red|''0x87''| 2 |R/W| |
|:!: CK green|''0x88''| 2 |R/W| |
|:!: CK blue|''0x89''| 2 |R/W| |
|Reserved|''0x8A-0x8F''| | | |
==== band #1 ====
Color substitution (if enabled) takes place after the first band had a chance to process the pixels
The layout of the settings is identical to that of band #0 just shifted down by a paragraph and occupying address block ''0x0090-0x009F''
==== band #2 ====
Color substitution (if enabled) takes place after the first and second bands had a chance to process the pixels
The layout of the settings is identical to that of band #0 just shifted down by 2 paragraphs and occupying address block ''0x00A0-0x00AF''
==== band #3 ====
Color substitution (if enabled) takes place after other bands had a chance to process the pixels
The layout of the settings is identical to that of band #0 just shifted down by 3 paragraphs and occupying address block ''0xB0-0xBF''
==== mFT lense access ====
^ mFT lense access ^^^^^
^Address ^Name ^Bytes ^Access ^Notes ^
|''0x4805'0000''|MFT command| 4 |R/W|
struct MftCmd final{
uint8_t param2, param1;
uint8_t cmd_code;
uint8_t cmd_type;
};
static_assert(std::bit_cast(MftCmd{1, 2, 3, 4}) == 0x04030201);
|
|''0x4806'0000''|MFT control| 4 |R/W|
struct MftCtrl final{
bool start : 1; // start command (type, code, param1, param2)
bool pop_input_fifo : 1; // increments the read pointer on input FIFO
uint8_t res0 : 5;
bool reset : 1; // reset MFT block (must clear after set)
uint8_t res1, res2, res3;
};
|
|''0x4807'0000''|MFT status| 4 |R/O|
struct MftStatus final{
bool ready : 1; // MFT lens ready (attached)
bool cmd_done : 1; // command done (finished)
bool in_fifo_empty : 1; // Input FIFO empty
bool in_fifo_full : 1; // Input FIFO full
bool crc_error : 1; // CRC error occurred
bool to_error : 1; // MFT Bus timeout error occurred
uint8_t res0 : 2;
uint8_t res1;
uint8_t in_fifo_data_count; // Input FIFO data count
uint8_t res2;
};
|
|''0x4808'0000''|MFT input FIFO data| 1 |R/O| |
Micro Four Thirds System (mFT) defines a communication protocol in which the "body" (host) issues 4 bytes of data (command type, command code, and two 1-byte parameters) and gets a response of variable number of bytes, depending on the command (including a 0-length data response). See the mFT spec for each individual command's request/response.
FPGA acts as a two-way command repeater and in such capacity it expects a 4 byte command supplied to it as part of an I²C "write" operation and responds with the appropriate return data buffer to a subsequent "read" I²C operation on the same address.
=== MFT access protocol ===
== Usage ==
The mb427 MFT block implements MFT protocol providing communication between the camera body and lens (lens accessories are not yet supported). The current hardware supports type A0,B0 and C0 commands.
== Lens Attach ==
The hardware automatically senses the lens and will immediately attach to the lens. Firmware can tell if a lens is attached by checking the ''mft_status'' bit 0 (ready). If set (''1''), a lens has successfully attached to the body and is ready to accept a command.
== Lens Detach ==
When a lens is removed, hardware automatically initiates the detach MFT sequence. When detached, ''mft_status'' bit 0 (ready) will be clear (''0'').
== Executing an MFT command ==
- Check ready status. If ready ''goto 2''
- Load ''mft_command'' register
- Set start bit in ''mft_command'' register
- Check status bit 1 (''command_done''). If set ''goto 5''
- If read command, check ''input_fifo_data_count'' in ''mft_status'' register (bits 23:16)
- For each byte in fifo:
- Read ''mft_rx_data_port'' and save the data
- Write ''mft_control'' bit 1 (''pop_input_fifo''). This increments the FIFO address pointer and decrements the ''input_fifo_data_count''
- Clear ''mft_control'' bit 1 (''pop_input_fifo'')
- For read commands, the last byte of data is a checksum. To verify the checksum, simply add all (N-1) bytes and compare the sum to last byte (N) returned
- Remember to use unsigned arithmetic
- Finally, clear start bit and ''pop_input_fifo'' bits in the control register