ٻيو HDMI مانيٽر Raspberry Pi3 تائين DPI انٽرفيس ۽ FPGA بورڊ ذريعي


هي وڊيو ڏيکاري ٿو: هڪ Raspberry Pi3 بورڊ، GPIO کنیکٹر ذريعي ان سان ڳنڍيل هڪ FPGA بورڊ Mars Rover2rpi (سائيڪلون IV) آهي، جنهن سان هڪ HDMI مانيٽر ڳنڍيل آهي. ٻيو مانيٽر Raspberry Pi3 جي معياري HDMI کنیکٹر ذريعي ڳنڍيل آهي. هر شي گڏجي ڪم ڪري ٿي هڪ ڊبل مانيٽر سسٽم وانگر.

اڳتي آئون توهان کي ٻڌايان ٿو ته اهو ڪيئن لاڳو ٿئي ٿو.

مشهور Raspberry Pi3 بورڊ وٽ هڪ GPIO ڪنيڪٽر آهي جنهن جي ذريعي توهان مختلف توسيع ڪارڊ ڳنڍي سگهو ٿا: سينسر، LEDs، اسٽيپر موٽر ڊرائيور ۽ گهڻو ڪجهه. هڪ کنیکٹر تي هر پن جي صحيح فنڪشن پورٽ جي ترتيب تي منحصر آهي. GPIO ALT2 ترتيب توهان کي ڪنيڪٽر کي DPI انٽرفيس موڊ ۾ تبديل ڪرڻ جي اجازت ڏئي ٿي، متوازي انٽرفيس ڊسپلي ڪريو. DPI ذريعي VGA مانيٽر کي ڳنڍڻ لاءِ توسيع ڪارڊ موجود آهن. بهرحال، پهرين، VGA مانيٽر هاڻي HDMI وانگر عام نه آهن، ۽ ٻيو، ڊجيٽل انٽرفيس هڪ اينالاگ کان وڌيڪ بهتر آهي. ان کان علاوه، ڊي اي سي تي اهڙي VGA توسيع بورڊ عام طور تي R-2-R زنجيرن جي صورت ۾ ٺاهيو ويندو آهي ۽ اڪثر ڪري هر رنگ ۾ 6 بٽ کان وڌيڪ ناهي.

ALT2 موڊ ۾، GPIO کنیکٹر پنن کي هيٺين معني آهي:

ٻيو HDMI مانيٽر Raspberry Pi3 تائين DPI انٽرفيس ۽ FPGA بورڊ ذريعي

هتي مون ڪنيڪٽر جي RGB پنن کي ترتيب سان ڳاڙهو، سائو ۽ نيرو ڪيو آهي. ٻيا اهم سگنل آهن V-SYNC ۽ H-SYNC سگنل، گڏوگڏ CLK. CLK گھڙي فریکوئنسي اها فریکوئنسي آهي جنهن تي پکسل جون قيمتون ڪنيڪٽر ڏانهن نڪرنديون آهن؛ اهو منحصر هوندو آهي چونڊيل وڊيو موڊ تي.

هڪ ڊجيٽل HDMI مانيٽر کي ڳنڍڻ لاء، توهان کي انٽرفيس جي DPI سگنلن کي پڪڙڻ ۽ انهن کي HDMI سگنلن ۾ تبديل ڪرڻ جي ضرورت آهي. اهو ٿي سگهي ٿو، مثال طور، ڪجهه قسم جي FPGA بورڊ استعمال ڪندي. جيئن ته اهو نڪتو، مارس Rover2rpi بورڊ انهن مقصدن لاء مناسب آهي. حقيقت ۾، هن بورڊ کي هڪ خاص اڊاپٽر ذريعي ڳنڍڻ جو بنيادي اختيار هن طرح نظر اچي ٿو:

ٻيو HDMI مانيٽر Raspberry Pi3 تائين DPI انٽرفيس ۽ FPGA بورڊ ذريعي

هي بورڊ استعمال ڪيو ويندو آهي GPIO بندرگاهن جو تعداد وڌائڻ ۽ وڌيڪ پردي ڊوائيسز کي راسبري سان ڳنڍڻ لاء. ساڳئي وقت، هن ڪنيڪشن سان 4 GPIO سگنل JTAG سگنلن لاء استعمال ڪيا ويا آهن، انهي ڪري ته راسبري کان پروگرام FPGA فرم ویئر کي FPGA ۾ لوڊ ڪري سگهي ٿو. انهي جي ڪري، هي معياري ڪنيڪشن مون کي مناسب ناهي؛ 4 ڊي پي آئي سگنل نڪرندا آهن. خوشقسمتيءَ سان، بورڊ تي اضافي ڪنبس وٽ راسبي سان مطابقت رکندڙ پن آئوٽ آهي. تنهنڪري مان بورڊ کي 90 درجا گھمائي سگهان ٿو ۽ اڃا به ان کي منهنجي راسبي سان ڳنڍي سگهان ٿو.

ٻيو HDMI مانيٽر Raspberry Pi3 تائين DPI انٽرفيس ۽ FPGA بورڊ ذريعي

يقينا، توهان کي هڪ خارجي JTAG پروگرامر استعمال ڪرڻو پوندو، پر اهو مسئلو ناهي.

اڃا هڪ ننڍڙو مسئلو آهي. نه هر FPGA پن هڪ ڪلاڪ ان پٽ طور استعمال ڪري سگهجي ٿو. هتي صرف چند وقف ٿيل پن آهن جيڪي انهن مقصدن لاء استعمال ڪري سگھجن ٿيون. تنهن ڪري اهو هتي ظاهر ٿيو ته GPIO_0 CLK سگنل FPGA ان پٽ تائين نه ٿو پهچي، جيڪو استعمال ڪري سگهجي ٿو FPGA ڪلاڪ ان پٽ جي طور تي. تنهن ڪري مون کي اڃا تائين هڪ تار سکارف تي رکڻو هو. مان ڳنڍان ٿو GPIO_0 ۽ بورڊ جي KEY[1] سگنل:

ٻيو HDMI مانيٽر Raspberry Pi3 تائين DPI انٽرفيس ۽ FPGA بورڊ ذريعي

هاڻي مان توهان کي FPGA پروجيڪٽ بابت ٿورو ٻڌائيندس. HDMI سگنل پيدا ڪرڻ ۾ بنيادي مشڪل تمام گهڻي تعدد آهي. جيڪڏهن توهان ڏسو ٿا HDMI کنیکٹر پن آئوٽ، توهان ڏسي سگهو ٿا ته RGB سگنل هاڻي سيريل فرق سگنل آهن:

ٻيو HDMI مانيٽر Raspberry Pi3 تائين DPI انٽرفيس ۽ FPGA بورڊ ذريعي

فرق سگنل جو استعمال توهان کي ٽرانسميشن لائن تي عام موڊ مداخلت کي منهن ڏيڻ جي اجازت ڏئي ٿو. انهي صورت ۾، هر رنگ سگنل جو اصل اٺ-بٽ ڪوڊ 10-bit TMDS ۾ تبديل ڪيو ويندو آهي (ٽرانزيشن-منٽم ٿيل فرق سگنلنگ). اهو هڪ خاص ڪوڊنگ طريقو آهي جيڪو ڊي سي جزو کي سگنل مان هٽائڻ ۽ فرق واري لائن ۾ سگنل سوئچنگ کي گھٽ ڪرڻ لاءِ. جيئن ته 10 بٽ هاڻي رنگ جي هڪ بائيٽ لاءِ سيريل لائن تي منتقل ٿيڻ جي ضرورت آهي، اهو ظاهر ٿئي ٿو ته سيريلائيزر ڪلاڪ جي رفتار پکسل ڪلاڪ جي رفتار کان 10 ڀيرا وڌيڪ هجڻ گهرجي. جيڪڏهن اسان مثال طور وڊيو موڊ 1280x720 60Hz وٺون ٿا، ته پوءِ هن موڊ جي پکسل فریکوئنسي 74,25 MHz آهي. سيريلائزر هجڻ گهرجي 742,5 MHz.

باقاعده FPGAs، بدقسمتي سان، هن جي قابل نه آهن. جڏهن ته، خوش قسمتي طور تي اسان لاء، FPGA تعمير ٿيل آهي DDIO پنن ۾. اهي نتيجا آهن جيڪي اڳ ۾ ئي آهن، جيئن اهي هئا، 2-to-1 سيريلائيزر. اهو آهي، اهي ٻه بٽ ترتيب ڏئي سگھن ٿا گھڙي جي تعدد جي اڀرندڙ ۽ گرڻ واري ڪنڊن تي. هن جو مطلب آهي ته هڪ FPGA پروجيڪٽ ۾ توهان استعمال ڪري سگهو ٿا 740 MHz نه، پر 370 MHz، پر توهان کي FPGA ۾ DDIO آئوٽ پٽ عناصر استعمال ڪرڻ جي ضرورت آهي. هاڻي 370 MHz اڳ ۾ ئي هڪ مڪمل طور تي حاصل ڪرڻ جي قابل تعدد آهي. بدقسمتي سان، 1280x720 موڊ جي حد آهي. اسان جي سائڪلون IV FPGA ۾ هڪ اعلي ريزوليوشن حاصل نه ٿي ڪري سگھجي مارس روور 2 آرپي بورڊ تي نصب ٿيل.

تنهن ڪري، ڊزائن ۾، ان پٽ پکسل فريڪوئنسي CLK PLL ڏانهن ويندي آهي، جتي ان کي 5 سان ضرب ڪيو ويندو آهي. هن فريڪوئنسي تي، R، G، B بائيٽ بٽ جوڑوں ۾ تبديل ٿي ويندا آهن. اھو اھو آھي جيڪو TMDS انڪوڊر ڪندو آھي. Verilog HDL ۾ سورس ڪوڊ هن طرح ڏسڻ ۾ اچي ٿو:

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

پوءِ ٻاھرين جوڙو DDIO ٻاھرين کي کارايو ويندو آھي، جيڪو ترتيب سان اڀرندڙ ۽ گرڻ واري ڪنارن تي ھڪڙو بٽ سگنل پيدا ڪري ٿو.

DDIO پاڻ کي هيٺ ڏنل Verilog ڪوڊ سان بيان ڪري سگهجي ٿو:

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

پر اهو گهڻو ڪري اهو طريقو ڪم نه ڪندو. توھان کي استعمال ڪرڻ جي ضرورت آھي Alter جي ميگا فنڪشن ALTDIO_OUT کي اصل ۾ فعال ڪرڻ لاءِ DDIO آئوٽ پٽ عناصر. منهنجو پروجيڪٽ ALTDIO_OUT لائبريري جو حصو استعمال ڪري ٿو.

اهو سڀ ڪجهه ٿورو مشڪل ٿي سگهي ٿو، پر اهو ڪم ڪري ٿو.

توھان ويريلوگ HDL ۾ لکيل سڀ ماخذ ڪوڊ ڏسي سگھو ٿا هتي github تي.

FPGA لاءِ مرتب ڪيل فرم ویئر مارس روور 2rpi بورڊ تي نصب ٿيل EPCS چپ ۾ چمڪيو ويو آهي. اهڙيء طرح، جڏهن طاقت FPGA بورڊ تي لاڳو ٿئي ٿي، FPGA کي فليش ميموري کان شروع ڪيو ويندو ۽ شروع ڪيو ويندو.

هاڻي اسان کي Raspberry پاڻ جي تشڪيل جي باري ۾ ٿورو ڳالهائڻ جي ضرورت آهي.

مان تجربا ڪري رهيو آهيان Raspberry PI OS (32 bit) جي بنياد تي Debian Buster، ورجن: آگسٽ 2020،
ڇڏڻ جي تاريخ: 2020-08-20، ڪرنل ورزن: 5.4.

توهان کي ٻه شيون ڪرڻ گهرجن:

  • config.txt فائل کي ايڊٽ ڪريو؛
  • ٻن مانيٽر سان ڪم ڪرڻ لاءِ ايڪس سرور جي ترتيب ٺاھيو.

/boot/config.txt فائل کي ايڊٽ ڪرڻ وقت توھان کي ضرورت آھي:

  1. i2c، i2s، spi جي استعمال کي بند ڪريو؛
  2. اوورلي استعمال ڪندي ڊي پي آئي موڊ کي فعال ڪريو dtoverlay=dpi24؛
  3. وڊيو موڊ کي ترتيب ڏيو 1280 × 720 60Hz، 24 بٽ في پکسل ڊي پي آئي تي؛
  4. فريم بفرز 2 جو گھربل تعداد بيان ڪريو (max_framebuffers=2، صرف پوءِ ٻي ڊيوائس /dev/fb1 ظاهر ٿيندي)

config.txt فائل جو مڪمل متن هن طرح نظر اچي ٿو.

# 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

ان کان پوء، توهان کي X سرور لاء ٻه مانيٽر استعمال ڪرڻ لاء هڪ ترتيب واري فائيل ٺاهڻ جي ضرورت آهي ٻن فريم بفرن تي /dev/fb0 ۽ /dev/fb1:

منهنجي ترتيب واري فائيل /usr/share/x11/xorg.conf.d/60-dualscreen.conf هن طرح آهي

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

خير، جيڪڏهن اهو اڳ ۾ ئي نصب نه آهي، ته پوء توهان کي Xinerama انسٽال ڪرڻ جي ضرورت آهي. پوءِ ڊيسڪ ٽاپ اسپيس کي مڪمل طور تي وڌايو ويندو ٻن مانيٽرز تائين، جيئن مٿي ڏيکاريل ڊيمو وڊيو ۾.

اهو شايد سڀ ڪجهه آهي. هاڻي، Raspberry Pi3 مالڪن کي ٻه مانيٽر استعمال ڪرڻ جي قابل هوندا.

مارس Rover2rpi بورڊ جو تفصيل ۽ سرڪٽ ڊاگرام ڳولي سگھجي ٿو هتي ڏسو.

جو ذريعو: www.habr.com