تقديم منصة تطوير الهاتف المحمول FPGA iCE40 UltraPlus من Lattice Semiconductor

المقدمة



يوم سعيد للجميع ، أيها الأصدقاء! في الآونة الأخيرة في العمل ، حصلنا على لوحة iCE40 UltraPlus Mobile Development Platform جديدة تمامًا من Lattice Semiconductor. وفقًا للمطورين على موقع iCE40 UltraPlus الرسمي ، فإن MDP عبارة عن لوحة بها 4 iCE40 UltraPlus FPGAs ، يتحكم كل منها في مجموعة الأجهزة الطرفية الخاصة به. الطقم يشمل:



  • شاشة متحركة بدقة 240 × 240 مع واجهة MIPI DSI ؛
  • مستشعر الصورة بدقة 640 × 480 (OVM7692) ؛
  • ميكروفونات منخفضة الطاقة بحجم 4 قطع ؛
  • وحدة BLE لنقل البيانات اللاسلكية ؛
  • ذاكرة فلاش SPI قابلة للبرمجة ؛
  • حزمة من أجهزة الاستشعار المختلفة (الضغط والبوصلة والجيروسكوب والتسارع) ؛
  • حسنًا ، كل أنواع الأزرار والمصابيح.


الشيء الرائع في هذا الحوت هو أنه بمساعدة حزم البرامج الخاصة ، يمكنك نشر الشبكات العصبية للعمل مع الفيديو والصوت. ناهيك عن حقيقة أن شبكات FPGAs الشبكية منخفضة الطاقة وصغيرة الحجم ورخيصة جدًا.



UltraPlus MDP







كحالة اختبار ، وميض RGB LED (D13 في الرسم التخطيطي ، مظلل باللون الأحمر في الصورة على اليسار). بعد مراجعة الوثائق ، نستنتج أن مؤشر LED يتحكم فيه رقم FPGA U3 (مظلل باللون الأحمر في الصورة على اليمين). نتعلم أيضًا من الوثائق أن LED يتم التحكم فيه بواسطة مغير PWM مدمج وبرنامج تشغيل حالي.



نحيط علما بهذه المعلومات.



إعداد السبورة وكتابة البرنامج



توجد مجموعة من وصلات العبور على اللوحة ، والتي يمكنك من خلالها تحديد FPGA الذي يحتاج إلى وميض للعمل مع مجموعة مختارة من الأجهزة الطرفية. نحن مهتمون بثلاث مجموعات من وصلات العبور المسؤولة عن سحب مصدر الطاقة إلى LED وبرمجة FPGA المطلوب.







الإجراء كالتالي:



  1. اضبط مفتاح SW5 على وضع التشغيل / الإيقاف
  2. قافزان في J19 أفقيًا
  3. J26 , 1-2 3-4 ( . , )
  4. J17, J25, J27 9-10 ( )


نعم ، فهمت ، كل شيء ممل ، لكن بدونه لن ينجح.



أيضًا ، لتوصيل مولد إشارة الساعة ، من الضروري ضبط وصلة العبور J23 على الموضع 2-3 (ينتقل الترقيم من الأعلى).







الآن البرنامج. لإنشاء ملف بت للبرنامج الثابت iCE40 UltraPlus MDP ، فإنك تحتاج إلى بيئة تطوير Lattice iCE cube 2 ( رابط إلى صفحة المنتج ) ووميض لوحة Programmer and Deployment Tool نفسها . المنتج مرخص ، ولكن بعد التسجيل ، يمكن الحصول على الترخيص هنا www.latticesemi.com/Support/Licensing/DiamondAndiCEcube2SoftwareLicensing/iceCube2



المحرر في IDE غير مريح للغاية ، لذلك كتبت في Sublime Text ، ولكن لكل منها.



فيما يلي مخطط عام أعطى فهمًا لما يجب القيام به وأين يجب القيام به:







لذلك ظهر مُعدِّل PWM والمحرك الحالي ، الذي ذكرته سابقًا. هذان الجهازان هما وحدات داخلية. من الضروري كتابة جهاز تحكم منطقي وإرسال البيانات لهذا المطبخ بأكمله ليعمل بشكل صحيح. لنبدأ بترتيب وصف "الصندوق الأسود":



entity DriverRGB is
	port (
		-- RGB Led:
		LED0 	: out std_logic;
		LED1 	: out std_logic;
		LED2 	: out std_logic );
end DriverRGB;


لا توجد تهيئة للمزامنة في المربع الأسود. لهذا ، يتم استخدام وحدة داخلية ، والتي يتم الإعلان عنها على النحو التالي:



-- Generator clock:
component SB_HFOSC is
	generic (
		CLKHF_DIV	: string := "0b00" );
	port (
		CLKHFPU	: in std_logic;
		CLKHFEN	: in std_logic;

		CLKHF 	: out std_logic );
end component;


صورةيمكن لهذه الوحدة أن تولد إشارة بترددات 48 ميجاهرتز ، 24 ميجاهرتز ، 12 ميجاهرتز و 6 ميجاهرتز. المعلمة CLKHF_DIV مسؤولة عن عامل تقسيم التردد ("0b00" ، "0b01" ، "0b10" ، "0b11" ، على التوالي). تمكّن CLKHFPU و CLKHFEN الوحدة من العمل. CLKHF - إشارة الساعة.



بعد ذلك ، نعلن عن مغير PWM وبرنامج التشغيل الحالي:



-- Embedded PWM IP:
component SB_LEDDA_IP is
	port (
		LEDDCS		: in std_logic;
		LEDDCLK		: in std_logic;
		LEDDDAT7	: in std_logic;
		LEDDDAT6	: in std_logic;
		LEDDDAT5	: in std_logic;
		LEDDDAT4	: in std_logic;
		LEDDDAT3	: in std_logic;
		LEDDDAT2	: in std_logic;
		LEDDDAT1	: in std_logic;
		LEDDDAT0	: in std_logic;
		LEDDADDR3	: in std_logic;
		LEDDADDR2	: in std_logic;
		LEDDADDR1	: in std_logic;
		LEDDADDR0	: in std_logic;
		LEDDDEN 	: in std_logic;
		LEDDEXE		: in std_logic;
		LEDDRST		: in std_logic;

		PWMOUT0		: out std_logic;
		PWMOUT1		: out std_logic;
		PWMOUT2		: out std_logic;
		LEDDON		: out std_logic );
end component;


-- RGB Driver:
component SB_RGBA_DRV is
	generic (
		CURRENT_MODE	: string := "0b0";
		RGB0_CURRENT	: string := "0b000000";
		RGB1_CURRENT	: string := "0b000000";
		RGB2_CURRENT	: string := "0b000000" );
	port (
		CURREN		: in std_logic;
		RGBLEDEN	: in std_logic;
		RGB0PWM		: in std_logic;
		RGB1PWM		: in std_logic;
		RGB2PWM		: in std_logic;

		RGB0 		: out std_logic;
		RGB1 		: out std_logic;
		RGB2 		: out std_logic );
end component;


صورةيحتاج مُعدِّل PWM إلى تغذية العنوان والبيانات المسؤولة عن أوضاع تشغيل LED وبعض إشارات التحكم. تتم معالجة المخرجات بعد ذلك بواسطة برنامج تشغيل RGB الحالي ، والذي يقوم بالفعل بإضاءة LED.


يقوم برنامج التشغيل الحالي بمعالجة البيانات من مغير PWM وضبط التيار المزود إلى LED. تحدد المعلمات RGB0_CURRENT و RGB1_CURRENT و RGB2_CURRENT مقدار التيار لكل لون. CURRENT_MODE - وضع الطاقة (ممتلئ أو نصف).



صورة



أجل رائع. هناك عناوين ، وهناك بيانات. حسنا ، ماذا ترسل لهم؟ بشكل عام ، يقدم مطورو Lattice في وثائقهم وصفًا تفصيليًا إلى حد ما ، لكنه ضخم جدًا. سأحاول تلخيص كل شيء في بضعة أسطر من الوصف والرمز من أجل الوضوح.



يتوقع مغير PWM 9 عناوين. كل منهم مسؤول عن وظيفة محددة للحفاظ على عمل LED. يوجد أدناه جدول يوضح قيم وأسماء العناوين:







لإرسال البيانات ، نقوم بتنفيذ آلة الحالة المحدودة:



type LED_Driver is (IDLE, LEDDBR, LEDDONR, LEDDOFR, LEDDBCRR, LEDDBCFR, LEDDPWRR, LEDDPWRG, LEDDPWRB, LEDDCR0, DONE);


الخطوة الأولى هي كتابة البيانات إلى سجل LEDDBR. يخزن قيمة تردد ساعة PWM. تعتبر على النحو التالي:



Register Value N = Fsys/64kHz-1


تبدو بنية سجل البيانات كما يلي:







ستتم إضافة البتتين الأكثر أهمية لقيمة التردد عندما ننتقل إلى سجل LEDDCR0.



when LEDDBR =>
		led_en			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "1001";
		DAT_Bits(7 downto 0)	<= "11101101"; --     (   )
		PWM_state_next		<= LEDDONR;


يسجل سجل LEDDONR الوقت الذي يكون فيه مؤشر LED نشطًا. تحتوي الوثائق على جدول للمراسلات التي تنتمي إليها مجموعة البتات لوقت حرق LED معين.



when LEDDONR =>
		led_en			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "1010";
		DAT_Bits(7 downto 0)	<= "00010001"; --    (0.5 c)


يحتوي سجل LEDDOFR على بيانات عن المدة التي يظل فيها مؤشر LED غير نشط. بالضبط نفس القيم كما في LEDDONR.



when LEDDOFR =>
		led_en			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "1011";
		DAT_Bits(7 downto 0)	<= "00010001"; --    (0.5 c)
		PWM_state_next		<= LEDDBCRR;


LEDDBCRR - بيانات عن مدة LED soft-on.



when LEDDBCRR =>
		led_en			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "0101";
		DAT_Bits(7)		<= '1'; --   ()
		DAT_Bits(6)		<= '1'; --   
		DAT_Bits(5)		<= '1'; --    
		DAT_Bits(4)		<= '0'; -- RESERVED
		DAT_Bits(3 downto 0)	<= "0011"; --   (0.5 )
		PWM_state_next		<= LEDDBCFR;


LEDDBCRR - بيانات عن مدة إيقاف تشغيل LED.



when LEDDBCFR =>
		led_en			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "0110";
		DAT_Bits(7)		<= '1'; --   () (disable/enable)
		DAT_Bits(6)		<= '0'; -- PWM Range Extend
		DAT_Bits(5)		<= '1'; --    
		DAT_Bits(4)		<= '0'; -- RESERVED
		DAT_Bits(3 downto 0)	<= "0011"; --   (0.5 )
		PWM_state_next		<= LEDDPWRR;


تسجل المسجلات LEDDPWRR و LEDDPWRG و LEDDPWRB البيانات حول سطوع المصابيح الحمراء والزرقاء والأخضر على التوالي. يتم حساب قيمة السطوع كنسبة مئوية بالمعادلة التالية:



ADC(%) = PulseWidth/256


لذلك ، تعطي قيم السطوع المختلفة مزيجًا من الألوان ، بحيث يمكنك اللعب وتحقيق هدفك المثالي.



when LEDDPWRR =>
		led_en			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "0001";
		DAT_Bits(7 downto 0)	<= "00000001"; -- RED Pulse Width
		PWM_state_next		<= LEDDPWRG;


when LEDDPWRG =>
		led_en			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "0010";
		DAT_Bits(7 downto 0)	<= "11111111"; -- GREEN Pulse Width
		PWM_state_next		<= LEDDPWRB;


when LEDDPWRB =>
		led_en 			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "0011";
		DAT_Bits(7 downto 0)	<= "00011111"; -- BLUE Pulse Width
		PWM_state_next		<= LEDDCR0;


حسنًا ، يسجل آخر سجل LEDDCR0 معلومات التمكين وأهم بتين من تردد إشارة ساعة PWM:



when LEDDCR0 =>
		led_en			<= '1';
		led_cs			<= '1';
		led_exe			<= '0';
		LEDD_ADR		<= "1000";
		DAT_Bits(7)		<= '1'; --   ()
		DAT_Bits(6)		<= '1'; -- Flick Rate Select Bit (125/250 Hz)
		DAT_Bits(5)		<= '0'; --    (1/0)
		DAT_Bits(4) 		<= '0'; --      
		DAT_Bits(3)		<= '1'; -- Blinking Sequence Quick Stop Enable Bit
		DAT_Bits(2)		<= '0'; -- PWM Mode Selection Bit
		DAT_Bits(1 downto 0)	<= "10"; --    
		PWM_state_next		<= DONE;


أمثلة على التنفيذ



RGB







بنفسجي / أبيض







تلخيص



حسنا هذا كل شيء. من خلال تغيير المعلمات ، يمكنك تحقيق تأثير تنفس جميل لمصباح LED بألوان مختلفة وسطوع من خلال تغيير القيم في السجلات LEDDPWRR أو LEDDPWRG أو LEDDPWRB أو القيمة الحالية لبرنامج تشغيل RGB. فيما يلي روابط للكود على GitHub وجميع الوثائق اللازمة.



في المستقبل ، أخطط لاختبار كعكات أخرى ، وإذا أمكن ، أضعها هنا للمراجعة.



دليل مستخدم لوحة التقييم رمز

دليل استخدام برنامج التشغيل iCE40 LED




All Articles