====== 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