लुआ पर प्रोटीन के लिए एक इलेक्ट्रॉनिक घटक मॉडल बनाना

मेरे पास कई दीर्घकालिक निर्माण परियोजनाएं हैं, जिनमें से एक CDP1802 पर आधारित कंप्यूटर का निर्माण है। मुख्य बोर्ड को कागज पर और प्रोटियस में मॉडलिंग किया गया था।

बहुत जल्द यह सवाल उठने लगा कि: प्रोटियस में अनुपस्थित रहने वाले तत्वों के साथ क्या करना है?

कई संसाधन विस्तार से वर्णन करते हैं कि विज़ुअल स्टूडियो में अपना खुद का सी ++ मॉडल कैसे बनाया जाए।

दुर्भाग्य से, लिनक्स के तहत निर्माण करते समय, यह विकल्प बहुत सुविधाजनक नहीं है। और क्या होगा यदि आप C ++ नहीं जानते हैं या यदि आपको डीबगिंग के लिए फ्लाई पर मॉडल को संपादित करने की आवश्यकता है?

और मैं बस मॉडलिंग पर ध्यान केंद्रित करना चाहता हूं, बाकी सब कुछ जितना संभव हो उतना सरल करना।

इसलिए स्क्रिप्ट का उपयोग करके सिमुलेशन मॉडल करने का विचार आया - लूआ पर।

रुचि रखने वालों के लिए, मैं एक कट (2Mb gifs) मांगता हूं।







क्यों जरूरी है?



यदि आप सभी प्रकार की विदेशी चीजों के बारे में भूल जाते हैं, जैसे कि प्रोसेसर मॉडल लिखना, तो मैंने लंबे समय से सिम्युलेटर में कुछ भी करने की आदत खो दी है - मैंने सेंसर को विभिन्न प्रकार के डिबग से जोड़ा, मेरे हाथों में एक आस्टसीलस्कप, एक मल्टीमीटर, जेटीजी / यूएआरटी और खुद को डीबग किया।

लेकिन जब जीपीएस / गति की विफलता और इस तरह के मामले में कार्यक्रम के तर्क की जांच करना आवश्यक था, तो मुझे एक और माइक्रोकंट्रोलर पर जीपीएस इम्यूलेशन लिखना पड़ा।

जब KWP2000 प्रोटोकॉल का उपयोग करके मशीन के लिए टेलीमेट्री करना आवश्यक था, तो लाइव डिबगिंग असुविधाजनक और खतरनाक था। हाँ, और अगर एक - ओह कितना असहज।

सड़क पर डिबग / परीक्षण करने की क्षमता या कहीं पर पूरे सज्जन किट को अपने साथ ले जाने की क्षमता बस असुविधाजनक है (यह मुख्य रूप से शौक परियोजनाओं के बारे में है) एक अच्छी मदद है, इसलिए सिम्युलेटर के लिए जगह है।



विजुअल स्टूडियो सी ++ और जीसीसी



मैं जीसीसी के तहत सभी सॉफ्टवेयर लिखता हूं और मैं इसके तहत मॉडल का निर्माण करना चाहता था, विकसित पुस्तकालयों और कोड का उपयोग करके कि एमएसवीएस के तहत निर्माण करना मुश्किल होगा। समस्या यह थी कि mingw32 DLL त्रिशंकु प्रोटीन के तहत इकट्ठे हुए। __Thiscall और कामरेड के साथ जोड़तोड़ सहित विभिन्न तरीकों की कोशिश की गई, और कोडांतरक कॉल हैक के साथ विकल्प सूट नहीं किया।

ऐसे मामलों में विशाल अनुभव के साथ एक मूंगलो दोस्त ने सुझाव दिया और दिखाया कि वर्चुअल टेबल का उपयोग करके C में C ++ इंटरफ़ेस को कैसे फिर से लिखना है। सुविधाओं में से, "उत्पादन से रुकावट के बिना" लिनक्स के तहत कोडांतरण की संभावना के अलावा, सिद्धांत में, फोरट्रान पर भी मॉडल लिखने की क्षमता - एक इच्छा होगी।



C ++ के तहत नकल



व्यवहार में आभासी वर्गों के "अनुकरण" के साथ विचार इस प्रकार है:

मूल C ++ वर्चुअल क्लास हेडर इस तरह दिखता है

class IDSIMMODEL { public: virtual INT isdigital ( CHAR* pinname ) = 0; virtual VOID setup ( IINSTANCE* instance, IDSIMCKT* dsim ) = 0; virtual VOID runctrl ( RUNMODES mode ) = 0; virtual VOID actuate ( REALTIME time, ACTIVESTATE newstate ) = 0; virtual BOOL indicate ( REALTIME time, ACTIVEDATA* newstate ) = 0; virtual VOID simulate ( ABSTIME time, DSIMMODES mode ) = 0; virtual VOID callback ( ABSTIME time, EVENTID eventid ) = 0; };
      
      







और यहां सी संस्करण है; यह हमारा छद्म वर्ग और इसकी आभासी तालिका है



 struct IDSIMMODEL { IDSIMMODEL_vtable* vtable; };
      
      







अब हम उन बिंदुओं के साथ एक संरचना बनाते हैं जो कक्षा के अंदर होते हैं (हम उन्हें बनाएंगे और उन्हें अलग से घोषित करेंगे)

 struct IDSIMMODEL_vtable { int32_t __attribute__ ( ( fastcall ) ) ( *isdigital ) ( IDSIMMODEL* this, EDX, CHAR* pinname ); void __attribute__ ( ( fastcall ) ) ( *setup ) ( IDSIMMODEL* this, EDX, IINSTANCE* inst, IDSIMCKT* dsim ); void __attribute__ ( ( fastcall ) ) ( *runctrl ) ( IDSIMMODEL* this, EDX, RUNMODES mode ); void __attribute__ ( ( fastcall ) ) ( *actuate ) ( IDSIMMODEL* this, EDX, REALTIME atime, ACTIVESTATE newstate ); bool __attribute__ ( ( fastcall ) ) ( *indicate ) ( IDSIMMODEL* this, EDX, REALTIME atime, ACTIVEDATA* data ); void __attribute__ ( ( fastcall ) ) ( *simulate ) ( IDSIMMODEL* this, EDX, ABSTIME atime, DSIMMODES mode ); void __attribute__ ( ( fastcall ) ) ( *callback ) ( IDSIMMODEL* this, EDX, ABSTIME atime, EVENTID eventid ); };
      
      







हम आवश्यक कार्य लिखते हैं और हमारे "वर्ग" का एक उदाहरण बनाते हैं, जिसका हम उपयोग करेंगे

 IDSIMMODEL_vtable VSM_DEVICE_vtable = { .isdigital = vsm_isdigital, .setup = vsm_setup, .runctrl = vsm_runctrl, .actuate = vsm_actuate, .indicate = vsm_indicate, .simulate = vsm_simulate, .callback = vsm_callback, }; IDSIMMODEL VSM_DEVICE = { .vtable = &VSM_DEVICE_vtable, };
      
      







और इसी तरह, सभी वर्गों के साथ जिनकी हमें ज़रूरत है। चूंकि इस तरह की संरचना को कॉल करना बहुत सुविधाजनक नहीं है, आवरण कार्यों को लिखा गया था, कुछ चीजें स्वचालित थीं, गायब थीं, अक्सर उपयोग किए गए कार्यों को जोड़ा गया था। इस लेख को लिखते समय भी, मैंने बहुत सी नई चीजें जोड़ीं, जो दूसरी तरफ से काम थीं।



"इसे जितना संभव हो उतना सरल बनाएं, लेकिन आसान नहीं।"



नतीजतन, कोड बढ़ता गया और यह महसूस किया कि कुछ बदलने की जरूरत है और अधिक बढ़ेगी: एक माइक्रोकंट्रोलर के लिए एक ही एमुलेटर लिखने की तुलना में एक मॉडल बनाने में कम समय और प्रयास नहीं हुआ। डिबगिंग मॉडल की प्रक्रिया में, कुछ को बदलना, प्रयोग करना लगातार आवश्यक था। मुझे हर छोटी चीज पर मॉडल को फिर से इकट्ठा करना था, और सी में वांछित होने के लिए पाठ डेटा के साथ काम करना था। परिचित लोग जो इसमें रुचि रखते हैं, वे भी सी से डरते थे (कोई टर्बो पास्कल का उपयोग करता है, कोई क्यू बेसिक का उपयोग करता है)।



मुझे लुआ के बारे में याद आया: यह पूरी तरह से सी के साथ एकीकृत है, यह तेज, कॉम्पैक्ट, दृश्य, गतिशील टाइपिंग - यह सब आवश्यक है। नतीजतन, मैंने लुआ में सभी सी फ़ंक्शन को समान नामों से दोहराया, मॉडल बनाने के लिए एक पूरी तरह से आत्मनिर्भर तरीका प्राप्त किया जिसमें बिल्कुल भी आश्वस्त होने की आवश्यकता नहीं है। आप केवल एक dll ले सकते हैं और केवल Lua पर किसी भी मॉडल का वर्णन कर सकते हैं। यह सिमुलेशन को रोकने, पाठ स्क्रिप्ट को सही करने और फिर से लड़ाई में पर्याप्त है।

लुआ में मॉडलिंग



मुख्य परीक्षण प्रोटीन 7 में आयोजित किया गया था, लेकिन 8 वें संस्करण में खरोंच और आयात किए गए मॉडल ने उत्कृष्ट व्यवहार किया।



हम कुछ सरल मॉडल बनाएंगे और उनके उदाहरण पर हम देखेंगे कि हम क्या और कैसे कर सकते हैं।

मैं यह नहीं बताऊंगा कि एक चित्रमय मॉडल कैसे बनाया जाता है, यह पूरी तरह से यहाँ और यहाँ वर्णित है , इसलिए मैं लेखन कोड पर ध्यान केंद्रित करूंगा।

यहां 3 डिवाइस हैं जो हम विचार करेंगे। मैं पहली बार एक निमिष एलईडी के साथ शुरू करना चाहता था, लेकिन फिर मैंने फैसला किया कि यह बहुत सुस्त था, मुझे आशा है कि यह सही था।

आइए A_COUNTER से शुरू करें:







यह एक आंतरिक घड़ी जनरेटर के साथ सबसे सरल बाइनरी काउंटर है, इसके सभी आउटपुट आउटपुट हैं।



प्रत्येक मॉडल में एक DLL होता है जो बाहरी दुनिया के साथ मॉडल और बातचीत के व्यवहार का वर्णन करता है। हमारे मामले में, सभी dll मॉडल समान होंगे, लेकिन स्क्रिप्ट अलग-अलग हैं। तो, एक मॉडल बनाएँ:



मॉडल विवरण




 device_pins = { {is_digital=true, name = "A0", on_time=100000, off_time=100000}, {is_digital=true, name = "A1", on_time=100000, off_time=100000}, {is_digital=true, name = "A2", on_time=100000, off_time=100000}, {is_digital=true, name = "A3", on_time=100000, off_time=100000}, --       --     {is_digital=true, name = "A15", on_time=100000, off_time=100000}, }
      
      







device_pins एक आवश्यक वैश्विक चर है जिसमें डिवाइस पिन का विवरण होता है। इस स्तर पर, पुस्तकालय केवल डिजिटल उपकरणों का समर्थन करता है। प्रक्रिया में एनालॉग और मिश्रित प्रकार के लिए समर्थन।

is_digital - हमारा आउटपुट केवल तार्किक स्तरों के साथ काम करता है, जबकि केवल सच ही संभव है

नाम - ग्राफिक मॉडल पर आउटपुट का नाम। यह बिल्कुल मेल खाना चाहिए - प्रोटीन के अंदर आउटपुट का बंधन नाम से जाता है।

शेष दो क्षेत्र अपने लिए बोलते हैं - पिन पिकोसेकंड में स्विच करने का समय।



आवश्यक उपयोगकर्ता-परिभाषित कार्य




वास्तव में, एक स्क्रिप्ट में कुछ बनाने की कोई सख्त आवश्यकता नहीं है। आप कुछ भी नहीं लिख सकते हैं - एक डमी मॉडल होगा, लेकिन न्यूनतम कार्यक्षमता के लिए आपको device_simulate फ़ंक्शन बनाना होगा। यह फ़ंक्शन तब कहा जाएगा जब नोड्स (कंडक्टर) की स्थिति बदलती है, उदाहरण के लिए, तर्क स्तर बदलता है। एक device_init फ़ंक्शन है। इसे मॉडल लोड करने के तुरंत बाद (यदि मौजूद है) कहा जाता है।

आउटपुट स्टेट को किसी एक स्तर पर सेट करने के लिए, set_pin_state फ़ंक्शन है, पहला तर्क यह आउटपुट का नाम लेता है, दूसरा वांछित राज्य, उदाहरण के लिए, SHI, SLO, FLT और इसी तरह



के साथ शुरू करने के लिए, सुनिश्चित करें कि शुरुआत में सभी आउटपुट एक एकल-लाइन / का उपयोग करके तार्किक 0 में हैं

हम वैश्विक चर के माध्यम से आउटपुट का उल्लेख कर सकते हैं, उदाहरण के लिए, A0 , और इसके नाम के माध्यम से एक स्ट्रिंग स्थिरांक "A0" के रूप में वैश्विक पर्यावरण तालिका _G के माध्यम से

 function device_init() for k, v in pairs(device_pins) do set_pin_state(_G[v.name], SLO) end end
      
      







अब हमें काउंटर को लागू करने की आवश्यकता है; चलो मास्टर ऑसिलेटर के साथ शुरू करते हैं। ऐसा करने के लिए, एक टाइमर_कॉलबैक फ़ंक्शन है जो दो तर्क लेता है - समय और घटना संख्या।

आउटपुट स्थिति सेट करने के बाद device_init में निम्न कॉल जोड़ें:

 set_callback(NOW, PC_EVENT)
      
      







PC_EVENT एक सांख्यिक चर है जिसमें ईवेंट कोड होता है (हमें इसे विश्व स्तर पर घोषित करना चाहिए)

अब इसका मतलब है कि आपको वर्तमान समय से 0 picoseconds के बाद इवेंट हैंडलर को कॉल करने की आवश्यकता है (फ़ंक्शन एक तर्क के रूप में एक सेकंड का एक चित्र लेता है)

और यहाँ फ़ंक्शन हैंडलर है

 function timer_callback(time, eventid) if eventid == PC_EVENT then for k, v in pairs(device_pins) do set_pin_bool(_G[v.name], get_bit(COUNTER, k) ) end COUNTER = COUNTER + 1 set_callback(time + 100 * MSEC, PC_EVENT) end end
      
      







एक घटना पर, set_pin_bool फ़ंक्शन को कहा जाता है , जो दो राज्यों में से एक तर्क के रूप में स्वीकार करके आउटपुट को नियंत्रित करता है - 1/0।



आप देख सकते हैं कि आउटपुट स्विच करने के बाद, set_callback फिर से कहा जाता है, क्योंकि यह फ़ंक्शन गैर-आवधिक घटनाओं को शेड्यूल करता है। समय सेटिंग में अंतर इस तथ्य के कारण है कि set_callback को भविष्य में कहा जाएगा, इसलिए हमें समय के अंतर को जोड़ने की आवश्यकता है, और समय में वर्तमान सिस्टम समय शामिल है



तो वही हुआ
 device_pins = { {is_digital=true, name = "A0", on_time=100000, off_time=100000}, {is_digital=true, name = "A1", on_time=100000, off_time=100000}, {is_digital=true, name = "A2", on_time=100000, off_time=100000}, {is_digital=true, name = "A3", on_time=100000, off_time=100000}, {is_digital=true, name = "A4", on_time=100000, off_time=100000}, {is_digital=true, name = "A5", on_time=100000, off_time=100000}, {is_digital=true, name = "A6", on_time=100000, off_time=100000}, {is_digital=true, name = "A7", on_time=100000, off_time=100000}, {is_digital=true, name = "A8", on_time=100000, off_time=100000}, {is_digital=true, name = "A9", on_time=100000, off_time=100000}, {is_digital=true, name = "A10", on_time=100000, off_time=100000}, {is_digital=true, name = "A11", on_time=100000, off_time=100000}, {is_digital=true, name = "A12", on_time=100000, off_time=100000}, {is_digital=true, name = "A13", on_time=100000, off_time=100000}, {is_digital=true, name = "A14", on_time=100000, off_time=100000}, {is_digital=true, name = "A15", on_time=100000, off_time=100000}, } PC_EVENT = 0 COUNTER = 0 function device_init() for k, v in pairs(device_pins) do set_pin_state(_G[v.name], SLO) end set_callback(0, PC_EVENT) end function timer_callback(time, eventid) if eventid == PC_EVENT then for k, v in pairs(device_pins) do set_pin_bool(_G[v.name], get_bit(COUNTER, k) ) end COUNTER = COUNTER + 1 set_callback(time + 100 * MSEC, PC_EVENT) end end
      
      









बाकी सब कुछ - घोषणा, मॉडल आरंभीकरण, और इसी तरह पुस्तकालय की तरफ से किया जाता है। यद्यपि, ज़ाहिर है, सभी समान सी में किया जा सकता है, और लुआ को प्रोटोटाइप के लिए इस्तेमाल किया जा सकता है, क्योंकि कार्यों के नाम समान हैं।

हम सिमुलेशन शुरू करते हैं और हमारे मॉडल के काम का निरीक्षण करते हैं







डिबगिंग सुविधाएँ





मुख्य लक्ष्य मॉडल के लेखन और उनके डिबगिंग की सुविधा प्रदान करना था, इसलिए हम उपयोगी जानकारी प्रदर्शित करने के लिए कुछ विकल्पों पर विचार करेंगे



पाठ संदेश




संदेश लॉग में आउटपुट करने के लिए 4 फ़ंक्शन, पिछले दो स्वचालित रूप से सिमुलेशन के रोक के लिए अग्रणी हैं



 out_log("This is just a message") out_warning("This is warning") out_error("This is error") out_fatal("This is fatal error")
      
      











लुआ की क्षमताओं के लिए धन्यवाद, आप आसानी से, आसानी से, जल्दी और स्पष्ट रूप से किसी भी जानकारी को दिखा सकते हैं, जिसकी आपको आवश्यकता है:



 out_log("We have "..#device_pins.." pins in our device")
      
      







अब हम अपने दूसरे मॉडल - रोम चिप्स पर चलते हैं, और देखते हैं

पॉप-अप


हम अपने रॉम को मॉडल करेंगे और इसे ऑपरेशन के दौरान चलाएंगे।

यहां निष्कर्षों की घोषणाएं अलग नहीं हैं, लेकिन हमें अपने माइक्रोकिरिट के गुणों को जोड़ने की जरूरत है, सबसे पहले - एक फ़ाइल से मेमोरी डंप लोड करने की क्षमता:







यह मॉडल बनाते समय एक टेक्स्ट स्क्रिप्ट में किया जाता है:

{फ़ाइल = "छवि फ़ाइल", FILENAME, FALSE ,, छवि / *। BIN}




अब इसे ऐसा बनाते हैं कि जब सिमुलेशन को रोक दिया गया था, तो आप मॉडल के बारे में महत्वपूर्ण जानकारी देख सकते थे, जैसे कि इसकी मेमोरी की सामग्री, पता बस की सामग्री, डेटा बस और ऑपरेटिंग समय। बाइनरी डेटा को सुविधाजनक रूप में आउटपुट करने के लिए, मैमोरी_पॉप है।

 function device_init() local romfile = get_string_param("file") rom = read_file(romfile) mempop, memid = create_memory_popup("My ROM dump") set_memory_popup(mempop, rom, string.len(rom)) end function on_suspend() if nil == debugpop then debugpop, debugid = create_debug_popup("My ROM vars") print_to_debug_popup(debugpop, string.format("Address: %.4X\nData: %.4X\n", ADDRESS, string.byte(rom, ADDRESS))) dump_to_debug_popup(debugpop, rom, 32, 0x1000) elseif debugpop then print_to_debug_popup(debugpop, string.format("Address: %.4X\nData: %.4X\n", ADDRESS, string.byte(rom, ADDRESS))) dump_to_debug_popup(debugpop, rom, 32, 0x1000) end end
      
      





पोज़ के दौरान on_suspend फ़ंक्शन को कहा जाता है (यदि उपयोगकर्ता द्वारा घोषित किया गया है)। यदि विंडो नहीं बनाई गई है, तो इसे बनाएं।

स्मृति को एक संकेतक के रूप में पुस्तकालय में स्थानांतरित किया जाता है, फिर आपको बाद में कुछ भी जारी करने की आवश्यकता नहीं है - सब कुछ लुआ कचरा कलेक्टर द्वारा किया जाएगा। और हम उस प्रकार की एक डिबग विंडो बनाएँगे जहाँ हमें चर की आवश्यकता होती है और मास्किंग के लिए हम ऑफसेट 0,1000 से 32 बाइट्स डंप करेंगे:







अंत में, हम OE, VPP और अन्य CE निष्कर्षों को अनदेखा करते हुए, ROM के एल्गोरिथ्म को लागू करते हैं



 function device_simulate() for i = 0, 14 do if 1 == get_pin_bool(_G["A"..i]) then ADDRESS = set_bit(ADDRESS, i) else ADDRESS = clear_bit(ADDRESS, i) end end for i = 0, 7 do set_pin_bool(_G["D"..i], get_bit(string.byte(rom, ADDRESS), i)) end end
      
      











चलो हमारे "डिबगर" के लिए कुछ करें:

एक सॉफ्टवेयर UART बनाएं, जिसमें हम डेटा बस की सामग्री का उत्पादन करेंगे
 device_pins = { {is_digital=true, name = "D0", on_time=1000, off_time=1000}, {is_digital=true, name = "D1", on_time=1000, off_time=1000}, {is_digital=true, name = "D2", on_time=1000, off_time=1000}, {is_digital=true, name = "D3", on_time=1000, off_time=1000}, {is_digital=true, name = "D4", on_time=1000, off_time=1000}, {is_digital=true, name = "D5", on_time=1000, off_time=1000}, {is_digital=true, name = "D6", on_time=1000, off_time=1000}, {is_digital=true, name = "D7", on_time=1000, off_time=1000}, {is_digital=true, name = "TX", on_time=1000, off_time=1000}, } -- UART events UART_STOP = 0 UART_START = 1 UART_DATA=2 -- Constants BAUD=9600 BAUDCLK = SEC/BAUD BIT_COUNTER = 0 ----------------------------------------------------------------- DATA_BUS = 0 function device_init() end function device_simulate() for i = 0, 7 do if 1 == get_pin_bool(_G["D"..i]) then DATA_BUS = set_bit(DATA_BUS, i) else DATA_BUS = clear_bit(DATA_BUS, i) end end uart_send(string.format("[%d] Fetched opcode %.2X\r\n", systime(), DATA_BUS)) end function timer_callback(time, eventid) uart_callback(time, eventid) end function uart_send (string) uart_text = string char_count = 1 set_pin_state(TX, SHI) -- set TX to 1 in order to have edge transition set_callback(BAUDCLK, UART_START) --schedule start end function uart_callback (time, event) if event == UART_START then next_char = string.byte(uart_text, char_count) if next_char == nil then return end char_count = char_count +1 set_pin_state(TX, SLO) set_callback(time + BAUDCLK, UART_DATA) end if event == UART_STOP then set_pin_state(TX, SHI) set_callback(time + BAUDCLK, UART_START) end if event == UART_DATA then if get_bit(next_char, BIT_COUNTER) == 1 then set_pin_state(TX, SHI) else set_pin_state(TX, SLO) end if BIT_COUNTER == 7 then BIT_COUNTER = 0 set_callback(time + BAUDCLK, UART_STOP) return end BIT_COUNTER = BIT_COUNTER + 1 set_callback(time + BAUDCLK, UART_DATA) end end
      
      











उत्पादकता



एक दिलचस्प सवाल जिसने मुझे चिंतित किया। मैंने 4040 बाइनरी काउंटर का मॉडल लिया जो प्रोटीस 7 के साथ आता है और मेरा एनालॉग बना।

पल्स जनरेटर का उपयोग करते हुए, इसने दोनों मॉडलों के इनपुट के लिए 100 kHz की आवृत्ति के साथ एक मेन्डेर खिलाया



प्रोटीन का 4040 = 15-16% सीपीयू लोड

C = 25-28% CPU लोड पर लाइब्रेरी

लाइब्रेरी और लुआ 5.2 = 98-100% सीपीयू लोड

लाइब्रेरी और लुआ 5.3a = 76-78% सीपीयू लोड



मैंने स्रोतों की तुलना नहीं की, लेकिन जाहिरा तौर पर उन्होंने संस्करण 5.3 में आभासी मशीन को बहुत अनुकूलित किया। फिर भी, यह काम की सुविधा के लिए काफी सहिष्णु है।

और मैंने अनुकूलन समस्याओं से निपटने के लिए शुरुआत भी नहीं की।



यह पूरी परियोजना एक सहज विचार के रूप में पैदा हुई थी, और बहुत कुछ करने की आवश्यकता है:

तत्काल योजना







निश्चित रूप से, मैं उन समान विचारधारा वाले लोगों को ढूंढना चाहूंगा जो कोड लिखने में भाग नहीं लेना चाहते हैं, फिर विचारों और प्रतिक्रिया से। वास्तव में, अब उन लक्ष्यों और उद्देश्यों के लिए बहुत हार्डकोड किया गया है जिनकी मुझे आवश्यकता थी।



विज्ञापन और एसएमएस के बिना डाउनलोड करें



कोड के साथ भंडार

जीडीबी के लिए तैयार पुस्तकालय और डिबगिंग प्रतीक यहां हैं



All Articles