Secundus HDMI monitor ad Raspberry Pi3 per DPI interface et FPGA board


Hoc video ostendit: tabulam Raspberry Pi3, ei per GPIO connexum coniunctam esse FPGA tabula Martis Rover2rpi (Cyclone IV), cui HDMI monitor iungitur. Secunda monitor iungitur per modum iungentis HDMI vexillum Raspberry Pi3. Omnia cooperantur sicut ratio monitor duplicalis.

Deinde quomodo hoc effectum sit dicam tibi.

Popularis Raspberry Pi3 tabulam GPIO connectorem habet, per quam varias chartas expansiones coniungere potes: sensores, LEDs, stepper rectores motores et multo plus. Munus exacta cuiusque clavi in ​​iungo dependet a configuratione portus. Configuratio GPIO ALT2 permittit te ad commutandum iungentem modum interfaciendi DPI, Parallel Interface Ostende. Expansio chartarum exstant pro VGA monitores connectendi per DPI. Sed primo, monitores VGA non amplius sunt sicut HDMI communes, et secundo, digitalis interface plus magis quam analogum. DAC autem in talibus tabulis expansionis VGA fieri solet in catenis R-2-R forma et saepe non plus quam 6 minuta per colorem.

In modo ALT2, acus iungo GPIO hanc significationem habent:

Secundus HDMI monitor ad Raspberry Pi3 per DPI interface et FPGA board

Hic RGB fibulas iungentis rubrae, viridis et caeruleae coloravi. Alia signa momenti sunt signa V-SYNC et H-SYNC ac CLK. Frequentia CLK horologii est frequentia ad quam valores pixel ad iungendum output sunt, pendet e modum video delectorum.

Ad monitorem digitalem HDMI coniungere, DPI signa interfaciendi capere debes et ad signa HDMI convertenda. Hoc autem fieri potest, verbi causa, utendo tabula quaedam FPGA. Ut evenit, Martia Rover2rpi tabula ad hos usus idonea est. Etenim optio principalis hanc tabulam coniungendi per nibh specialem huius modi speciem habet:

Secundus HDMI monitor ad Raspberry Pi3 per DPI interface et FPGA board

Haec tabula ad numerum portuum GPIO augere et plura periphericis machinis cinematographicis coniungere. Eodem tempore, 4 GPIO annuit cum hac connexione pro JTAG significationibus adhibita, ut programma ex Raspberry firmware FPGA in FPGA onerare possit. Propter hoc, haec norma nexus mihi non convenit: 4 DPI signa cadunt. Feliciter favos additi in tabula habent RUBUS IDAEUS-GiBUS pinout. Itaque tabulam 90 graduum gyrari possum et eam cum meo rubigine adhuc coniungere;

Secundus HDMI monitor ad Raspberry Pi3 per DPI interface et FPGA board

Utique, programmate externo JTAG uti debebis, sed hoc non obstat.

Adhuc parva quaestio est. Non omnis FPGA paxillus uti potest pro horologio initus. Paucae tantum fibulae dedicatae sunt quae ad hos usus adhiberi possunt. Ita evenit hic ut signum GPIO_0 CLK in FPGA initus non attingat, quod adhiberi potest pro FPGA initus horologii. Sic habui unum filum chlamyde. GPIO_0 iungo ac tabulae CLAVIS[1] signum:

Secundus HDMI monitor ad Raspberry Pi3 per DPI interface et FPGA board

Nunc tibi pauca de FPGA incepto dicam. Summa difficultas in generandis HDMI significationibus frequentiis altissima est. Si in HDMI iungentem pinout spectes, signa RGB videre potes nunc signa differentialia Vide:

Secundus HDMI monitor ad Raspberry Pi3 per DPI interface et FPGA board

Usus signi differentialis sinit te pugnare communem modum impedimenti in linea tradenda. In hoc casu, primigenius octingenti-bit codici uniuscuiusque coloris signo convertitur in TMDS 10-bit. Haec methodus peculiaris coding est ut DC componentem ex signo removeat et signum in linea differentiali commutandi minuat. Cum 10 frena nunc per lineam serialem coloris byte transmittantur, evenit ut horologii serialiser velocitatem 10 times altiorem quam pixel horologii celeritatem esse debeat. Si exempli gratia sumamus modum videndi 1280x720 60Hz, pixel frequentia huius modi est 74,25 MHz. Viderizer debet esse 742,5 MHz.

Regulares FPGAs, proh dolor, hoc non possunt. Sed feliciter nobis FPGA aedificavit in DDIO paxillos. Hae conclusiones iam sunt quasi 2-ad-1 serializers. Hoc est, duo minutas continuos in ortu et cadentibus margines frequentiae horologii emittere possunt. Hoc significat quod in FPGA exstent, uti non potes 740 MHz, sed 370 MHz, sed debes uti elementis DDIO output in FPGA. 370 MHz iam est frequentia omnino utilia. Dolendum est, 1280x720 modus est modus. Superior resolutio fieri non potest in nostra Cyclone IV FPGA in tabula Martis Rover2rpi inaugurata.

Itaque, consilio, initus pixel frequentia CLK ad PLL accedit, ubi multiplicatur 5. In hac frequentia R, G, B in bina bina vertuntur bytes. Hoc est quod facit TMDS encoder. Fons codicis in Verilog HDL simile hoc spectat:

module hdmi(
	input wire pixclk,		// 74MHz
	input wire clk_TMDS2,	// 370MHz
	input wire hsync,
	input wire vsync,
	input wire active,
	input wire [7:0]red,
	input wire [7:0]green,
	input wire [7:0]blue,
	output wire TMDS_bh,
	output wire TMDS_bl,
	output wire TMDS_gh,
	output wire TMDS_gl,
	output wire TMDS_rh,
	output wire TMDS_rl
);

wire [9:0] TMDS_red, TMDS_green, TMDS_blue;
TMDS_encoder encode_R(.clk(pixclk), .VD(red  ), .CD({vsync,hsync}), .VDE(active), .TMDS(TMDS_red));
TMDS_encoder encode_G(.clk(pixclk), .VD(green), .CD({vsync,hsync}), .VDE(active), .TMDS(TMDS_green));
TMDS_encoder encode_B(.clk(pixclk), .VD(blue ), .CD({vsync,hsync}), .VDE(active), .TMDS(TMDS_blue));

reg [2:0] TMDS_mod5=0;  // modulus 5 counter
reg [4:0] TMDS_shift_bh=0, TMDS_shift_bl=0;
reg [4:0] TMDS_shift_gh=0, TMDS_shift_gl=0;
reg [4:0] TMDS_shift_rh=0, TMDS_shift_rl=0;

wire [4:0] TMDS_blue_l  = {TMDS_blue[9],TMDS_blue[7],TMDS_blue[5],TMDS_blue[3],TMDS_blue[1]};
wire [4:0] TMDS_blue_h  = {TMDS_blue[8],TMDS_blue[6],TMDS_blue[4],TMDS_blue[2],TMDS_blue[0]};
wire [4:0] TMDS_green_l = {TMDS_green[9],TMDS_green[7],TMDS_green[5],TMDS_green[3],TMDS_green[1]};
wire [4:0] TMDS_green_h = {TMDS_green[8],TMDS_green[6],TMDS_green[4],TMDS_green[2],TMDS_green[0]};
wire [4:0] TMDS_red_l   = {TMDS_red[9],TMDS_red[7],TMDS_red[5],TMDS_red[3],TMDS_red[1]};
wire [4:0] TMDS_red_h   = {TMDS_red[8],TMDS_red[6],TMDS_red[4],TMDS_red[2],TMDS_red[0]};

always @(posedge clk_TMDS2)
begin
	TMDS_shift_bh <= TMDS_mod5[2] ? TMDS_blue_h  : TMDS_shift_bh  [4:1];
	TMDS_shift_bl <= TMDS_mod5[2] ? TMDS_blue_l  : TMDS_shift_bl  [4:1];
	TMDS_shift_gh <= TMDS_mod5[2] ? TMDS_green_h : TMDS_shift_gh  [4:1];
	TMDS_shift_gl <= TMDS_mod5[2] ? TMDS_green_l : TMDS_shift_gl  [4:1];
	TMDS_shift_rh <= TMDS_mod5[2] ? TMDS_red_h   : TMDS_shift_rh  [4:1];
	TMDS_shift_rl <= TMDS_mod5[2] ? TMDS_red_l   : TMDS_shift_rl  [4:1];
	TMDS_mod5 <= (TMDS_mod5[2]) ? 3'd0 : TMDS_mod5+3'd1;
end

assign TMDS_bh = TMDS_shift_bh[0];
assign TMDS_bl = TMDS_shift_bl[0];
assign TMDS_gh = TMDS_shift_gh[0];
assign TMDS_gl = TMDS_shift_gl[0];
assign TMDS_rh = TMDS_shift_rh[0];
assign TMDS_rl = TMDS_shift_rl[0];

endmodule

module TMDS_encoder(
	input clk,
	input [7:0] VD,	// video data (red, green or blue)
	input [1:0] CD,	// control data
	input VDE,  	// video data enable, to choose between CD (when VDE=0) and VD (when VDE=1)
	output reg [9:0] TMDS = 0
);

wire [3:0] Nb1s = VD[0] + VD[1] + VD[2] + VD[3] + VD[4] + VD[5] + VD[6] + VD[7];
wire XNOR = (Nb1s>4'd4) || (Nb1s==4'd4 && VD[0]==1'b0);
wire [8:0] q_m = {~XNOR, q_m[6:0] ^ VD[7:1] ^ {7{XNOR}}, VD[0]};

reg [3:0] balance_acc = 0;
wire [3:0] balance = q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7] - 4'd4;
wire balance_sign_eq = (balance[3] == balance_acc[3]);
wire invert_q_m = (balance==0 || balance_acc==0) ? ~q_m[8] : balance_sign_eq;
wire [3:0] balance_acc_inc = balance - ({q_m[8] ^ ~balance_sign_eq} & ~(balance==0 || balance_acc==0));
wire [3:0] balance_acc_new = invert_q_m ? balance_acc-balance_acc_inc : balance_acc+balance_acc_inc;
wire [9:0] TMDS_data = {invert_q_m, q_m[8], q_m[7:0] ^ {8{invert_q_m}}};
wire [9:0] TMDS_code = CD[1] ? (CD[0] ? 10'b1010101011 : 10'b0101010100) : (CD[0] ? 10'b0010101011 : 10'b1101010100);

always @(posedge clk) TMDS <= VDE ? TMDS_data : TMDS_code;
always @(posedge clk) balance_acc <= VDE ? balance_acc_new : 4'h0;

endmodule

Tunc paria in output ad DDIO output pascuntur, quae in ortu et in marginibus ortu et cadentibus unum signum continue producit.

DDIO ipsum cum sequenti Verilog codice describi posse;

module ddio(
	input wire d0,
	input wire d1,
	input wire clk,
	output wire out
	);

reg r_d0;
reg r_d1;
always @(posedge clk)
begin
	r_d0 <= d0;
	r_d1 <= d1;
end
assign out = clk ? r_d0 : r_d1;
endmodule

Sed verisimile non ita operabitur. Opus est ut ALTDDIO_OUT megafunctione Alterius ut elementa re vera efficiant DDIO output. Propositum meum in ALTDDIO_OUT bibliotheca componente utitur.

Hoc omnes paulo captiosius videant, sed operatur.

Omnem fontem codicem in Verilog HDL scriptum inspicere potes hic in github.

Composuit firmware pro FPGA emicuit in EPCS chip in Martio Rover2rpi inaugurata est. Cum igitur potentia tabulae FPGA applicata fuerit, FPGA a mico memoria et initio incipiet.

Nunc opus est pauca loqui de ipso Raspberry configuratione.

Experimenta facio in Raspberry PI OS (32 bis) innixa in Debian Buster, Version: Augusti 2020,
Release date:2020-08-20, Kernel version:5.4.

Duo facere debes:

  • config.txt lima in emendo;
  • creare in X server configurationem operari cum duobus monitoribus.

Cum lima /boot/config.txt edere debes:

  1. disable usus i2c, i2s, spi;
  2. enable DPI mode using overlay dtoverlay=dpi24;
  3. configure vide modum 1280Γ—720 60Hz, 24 frusta per pixel in DPI;
  4. specificare numerum framebuffers 2 (max_framebuffers=2, tunc solum erit secundus fabrica /dev/fb1 apparebit)

Plenus textus fasciculi config.txt hoc spectat.

# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1

# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
disable_overscan=1

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16

# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720

# uncomment if hdmi display is not detected and composite is being output
hdmi_force_hotplug=1

# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4

# uncomment for composite PAL
#sdtv_mode=2

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

# Uncomment some or all of these to enable the optional hardware interfaces
#dtparam=i2c_arm=on
#dtparam=i2s=on
#dtparam=spi=on

dtparam=i2c_arm=off
dtparam=spi=off
dtparam=i2s=off

dtoverlay=dpi24
overscan_left=0
overscan_right=0
overscan_top=0
overscan_bottom=0
framebuffer_width=1280
framebuffer_height=720
display_default_lcd=0
enable_dpi_lcd=1
dpi_group=2
dpi_mode=87
#dpi_group=1
#dpi_mode=4
dpi_output_format=0x6f027
dpi_timings=1280 1 110 40 220 720 1 5 5 20 0 0 0 60 0 74000000 3

# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18

# Additional overlays and parameters are documented /boot/overlays/README

# Enable audio (loads snd_bcm2835)
dtparam=audio=on

[pi4]
# Enable DRM VC4 V3D driver on top of the dispmanx display stack
#dtoverlay=vc4-fkms-v3d
max_framebuffers=2

[all]
#dtoverlay=vc4-fkms-v3d
max_framebuffers=2

Post hoc, limam configurationem creare debes pro X servitore uti duobus monitoribus in duobus framebuffers /dev/fb0 et /dev/fb1;

Meum configuration file /usr/share/x11/xorg.conf.d/60-dualscreen.conf sic est

Section "Device"
        Identifier      "LCD"
        Driver          "fbturbo"
        Option          "fbdev" "/dev/fb0"
        Option          "ShadowFB" "off"
        Option          "SwapbuffersWait" "true"
EndSection

Section "Device"
        Identifier      "HDMI"
        Driver          "fbturbo"
        Option          "fbdev" "/dev/fb1"
        Option          "ShadowFB" "off"
        Option          "SwapbuffersWait" "true"
EndSection

Section "Monitor"
        Identifier      "LCD-monitor"
        Option          "Primary" "true"
EndSection

Section "Monitor"
        Identifier      "HDMI-monitor"
        Option          "RightOf" "LCD-monitor"
EndSection

Section "Screen"
        Identifier      "screen0"
        Device          "LCD"
        Monitor         "LCD-monitor"
EndSection

Section "Screen"
        Identifier      "screen1"
        Device          "HDMI" 
	Monitor         "HDMI-monitor"
EndSection

Section "ServerLayout"
        Identifier      "default"
        Option          "Xinerama" "on"
        Option          "Clone" "off"
        Screen 0        "screen0"
        Screen 1        "screen1" RightOf "screen0"
EndSection

Bene, si iam non est constitutus, debes Xinerama instituere. Tunc spatium escritorii ad duos monitores plene dilatabitur, ut in demo video supra demonstratum est.

Ita sane omnia. Nunc, Raspberry Pi3 dominis duobus monitoribus uti poterit.

Descriptio et circuitus tabulae Martis Rover2rpi inveniri possunt hinc.

Source: www.habr.com