- घर पर assemble किए जा सकने वाले minimal कंप्यूटर के लक्ष्य के साथ, Debian Linux, vi, gcc, make चलाने वाले 8MB RAM और 1 MIPS स्तर के सिस्टम को सिर्फ 8-पिन components से लागू किया गया
- अंतिम board STM32G031, 8MB SPI PSRAM, और PL2303GL USB-serial bridge—इन 3 chips से बना है; 8-पिन package की सीमा के कारण उपयोग करने योग्य I/O सिर्फ 6 हैं
- pins की कमी design की मुख्य कठिनाई है: RAM को सामान्य SPI से, SD card को RAM pins साझा करने वाले 1-bit SDIO से, और UART transmission को bit-banging से संभाला गया
- software में मौजूदा ARMv6M assembly आधारित MIPS emulator को reuse किया गया, और 8KB bootloader SD card FAT filesystem के FIRMWARE.BIN से firmware update करता है
- STM32G031 को VOS0 setting के साथ आधिकारिक 64MHz से ऊपर overclock किया गया; 148MHz host CPU पर यह लगभग 1.65MHz MIPS R3000 के स्तर पर Debian को करीब 1 मिनट के अंदर boot करता है
सिर्फ 8-पिन chips से बना minimal Linux कंप्यूटर
- लक्ष्य है घर पर आसानी से assemble हो सकने वाला kit-style modern computer सिर्फ 8-पिन chips से बनाना
- modern computer की न्यूनतम कसौटी Debian Linux, vi, gcc, make चला पाने को माना गया
- पिछले experiments के आधार पर Linux चलाने के लिए न्यूनतम specifications 8MB RAM और 1 MIPS CPU तय किए गए
- storage के लिए SD card, और console connection के लिए USB-serial इस्तेमाल किया गया
- board छोटा circular रूप में है, और ऊपर board-edge USB-C connector है
- जिन्हें soldering का बहुत कम अनुभव है वे भी 45W soldering iron से assemble कर सकें, इसके लिए components और pins की संख्या घटाई गई
components का चयन
- USB connection के लिए PL2303GL चुना गया
- यह बिना external components के चलने वाला USB-serial bridge है, और 100mA का 3.3V regulator output भी देता है
- प्रमुख operating systems के लिए drivers हैं, और macOS पर App Store installation की जरूरत होती है
- विकल्प के रूप में ATTINYx5 और V-USB से USB implementation पर भी विचार किया गया
- USB low-speed specification के हिसाब से bulk endpoint इस्तेमाल नहीं कर सकता, लेकिन प्रमुख OS इसे enforce नहीं करते, इसलिए ACM serial port implementation काम करता है
- V-USB CPU time, flash और RAM काफी ज्यादा लेता है, इसलिए इस project के लिए भारी पड़ता है
- RAM के लिए SOIC-8 SPI PSRAM इस्तेमाल किया गया
- ISSI, APMEMORY, Vilsion आदि related components बनाते हैं, और 8MB parts सामान्य distributors से मिल सकते हैं
- 16MB chips का कई vendors ने वादा किया था, लेकिन वास्तव में supply नहीं हुई—ऐसा आकलन किया गया
- microcontroller के लिए PIC16F, RL78, PSoC1, eZ8, S08CPUv2, STM8, MSP430, AVR, PSoC4, MSPM0C, CH32V003, CH570E, STM32G0 series की तुलना की गई
- अंतिम चयन STM32G031J4M6/STM32G031 series है
- Cortex-M0+ core, official 64MHz, 32KB flash, 8KB RAM देता है
- 8-pin package में performance और memory के लिहाज से यह अन्य candidates से बेहतर था
- STM chips के errata documents की quality चिंता का विषय थी, लेकिन design में on-chip peripherals का minimal उपयोग होने से इसे चुना जा सका
6 I/O pins में समाया hardware design
-
console UART
- UART RX और TX को अन्य functions के साथ combine करना मुश्किल है
- RX share करने पर अन्य operations के दौरान received data छूट सकता है, और TX share करने पर छोटा low pulse भी PC को character जैसा दिख सकता है
- इसलिए 6 I/O में से 2 UART console को दिए गए
- final pin layout में pin 8 को USART2 RX के रूप में इस्तेमाल किया गया, और pin 7 पर UART TX को bit-banging से किया गया
- UART transmission के दौरान पूरी execution रुकती है, इसलिए जितना संभव हो उतना तेज 115,200bps इस्तेमाल किया गया
- एक character भेजने में करीब 87 microseconds लगते हैं, और board अधिकतर समय output नहीं करता, इसलिए यह तरीका स्वीकार्य है
-
RAM connection
- SPI PSRAM QSPI support करता है, लेकिन QSPI के लिए 6 pins चाहिए, इसलिए इसका उपयोग नहीं हो सकता
- dual-SPI बिना अतिरिक्त pins के सामान्य SPI से 2 गुना तेज हो सकता है, लेकिन STM32G031 dual-SPI support नहीं करता
- CPU से dual-SPI bit-bang करने पर भी hardware SPI और DMA combination से आगे निकलना कठिन माना गया
- परिणामस्वरूप RAM को standard SPI से connect किया गया, और सिर्फ इस connection से ही बचे हुए सभी 4 pins इस्तेमाल हो गए
-
SD card connection
- SD card को SPI mode में इस्तेमाल करने के लिए एक और chip select pin चाहिए, लेकिन कोई pin बचा नहीं था
- RAM nCS को inverter से उलटकर SD card nCS के रूप में इस्तेमाल करने का तरीका कुछ cards में problem देता था, और extra component भी चाहिए था
- UART TX pin को low-pass filter के साथ SD card nCS के रूप में share करने का तरीका भी देखा गया, लेकिन इसके लिए 300bps या उससे कम UART चाहिए था और SD card धीमा होने पर यह कमजोर था
- अंतिम समाधान SD card का 1-bit SDIO protocol सीधे implement करना है
- RAM nCS को SD CLK, RAM CLK को SD CMD, और RAM MOSI को SD DAT के रूप में share किया गया
- RAM access SD card को idle state के 1-bit जैसा दिखता है, और SD access RAM को सिर्फ select और deselect दोहराए जाने जैसा दिखता है, इसलिए यह सुरक्षित रूप से काम करता है
- हालांकि SD transaction के बीच RAM access नहीं आ सकता, इसलिए multi-block read/write इस्तेमाल नहीं किया जा सकता
- STM32G031 pin layout के कारण hardware device के रूप में SDIO का उपयोग नहीं हो सकता, इसलिए SD access पूरी तरह bit-banging से किया गया
- assembly implementation लगभग 14 CPU cycles/bit throughput देता है
bootloader और Linux boot flow
-
emulator
- मौजूदा LinuxCard project का MIPS emulator reuse किया गया
- emulator ARMv6M assembly में लिखा गया था और Linux boot कर सकता था
- तेज execution के लिए MIPS-to-ARMv6M JIT भी लिखा गया, लेकिन code size 46KB होने से बहुत बड़ा था और 6KB translation cache में speed gain भी पर्याप्त नहीं था, इसलिए इस्तेमाल नहीं किया गया
- STM32G031 की 32KB flash को 8KB bootloader और 24KB main code में बांटा गया
-
firmware update के लिए bootloader
- debugging pins छोड़ना संभव नहीं था, इसलिए SD card से firmware update करने वाला bootloader चाहिए था
- bootloader में SDIO driver, FAT filesystem driver, flash write code, logging, और bit-banging UART transmission code शामिल हैं
- वास्तविक size करीब 6.5KB है, लेकिन flash block granularity के कारण 8KB region इस्तेमाल होता है
- यह SD card पर FIRMWARE.BIN खोजता है, और basic checks पास होने तथा version बढ़ने की शर्त पूरी होने पर update apply करता है
- application image offset 16 के word को version number के रूप में इस्तेमाल किया जाता है
- bootloader offset 8 का byte bootloader version है, और main app boot text display के अलावा उपयोग नहीं होता
- bootloader FAT filesystem में CLOCK से शुरू होने वाली file या directory भी खोजता है
- उसके बाद आने वाले number को main application की clock speed के रूप में इस्तेमाल किया जाता है; यदि value 32–200MHz range से बाहर हो या value न हो, तो 132MHz इस्तेमाल किया जाता है
-
card partitions और kernel loading
- boot flow को PC boot process जैसा बनाया गया है
- SD card का पहला sector RAM की शुरुआत में पढ़कर jump किया जाता है
- first-stage code type 0xBB partition खोजकर उसे 0x80001000 पर load करता है और फिर jump करता है
- second-stage bootloader active mark किए गए partition को FAT16 के रूप में mount करता है और VMLINUX file को ELF के रूप में load करता है
- kernel command line bootloader में embedded है
- root
/dev/pvd3है, init/sbin/uMIPSinitहै /dev/pvd1को/bootके रूप में mount करने की कोशिश की जाती है- project में partition order FAT partition, bootloader partition, rootfs है
- Windows और macOS first partition को mount करते हैं, इसलिए FAT partition के जरिए files आसानी से डाली और निकाली जा सकती हैं
- boot हुए Linux में भी वही partition
/bootके रूप में दिखता है
performance और overclocking
- STM32G031 की official operating speed 64MHz है, लेकिन internal voltage settings से अधिक clock की कोशिश की गई
- STM documents में VOS2 1.0V और VOS1 1.2V settings हैं, और VOS1 पर लगभग 75MHz से ऊपर स्थिरता अच्छी नहीं रहती
- पुराने documents और similar chips के documents में दिखने वाली VOS0 1.35V setting इस्तेमाल करने पर overclocking headroom काफी बढ़ जाता है
- अधिकांश chips 136MHz पर अच्छी तरह चलते हैं, और कुछ 180MHz तक पहुंचते हैं
- flash memory तेज नहीं होती, इसलिए flash wait states को सही ढंग से manage करना जरूरी है
- 148MHz host CPU पर emulated MIPS CPU, FPU disabled state वाले लगभग 1.65MHz MIPS R3000 जैसा है
- system लगभग 1 मिनट में boot होता है, और vi, make, objdump, gcc चलते हैं
- पूरा Debian system होने के कारण
.debpackages को/bootमें लाकर install किया जा सकता है
assembly और initial run
-
assembly flow
- board खुद बनवाने के लिए design files दी गई हैं, और kit बेचने वाली company की तलाश है
- assembly SD card socket, capacitors, resistors, STM32G031, PL2303GL के क्रम में की जाती है
- R101, R102, R201, R202 को शुरुआत में populate नहीं किया जाता
- bootloader पहले STM32 में लिखना होगा
- R101 और R201 को bridge करके ROM bootloader के लिए serial wiring बनाई जाती है
- यह SD card लगाए बिना और RAM chip अभी solder न की हुई अवस्था में किया जाता है
- bootloader लिखने के बाद R101/R201 bridge हटाया जाता है और R102/R202 को bridge किया जाता है
- इसके बाद APS6408 या VTI7064 RAM chip को U2 position पर solder करने से hardware assembly पूरी हो जाती है
-
firmware और first boot
- SD card कम से कम 1GB का होना चाहिए, और provided disk image लिखी जाती है
- image में first-stage MIPS bootloader, second-stage MIPS bootloader, Linux kernel और firmware copy वाली partition, तथा Debian rootfs शामिल हैं
- FAT partition में FIRMWARE.BIN डालने पर first boot के दौरान bootloader खुद flash करता है
- serial terminal को 115,200bps, 8N1 पर set करें
- first run पर STM32 fuse programmed होता है, और USB-C cable निकालकर फिर लगानी पड़ सकती है
- लगभग 20 seconds बाद Linux kernel boot messages शुरू होते हैं, और पूरा boot करीब 1 मिनट लेता है
- सिर्फ 8MB RAM होने के कारण first command के रूप में
swapon /swapfileचलाना strongly recommended है - swap activate होने में कई tens of seconds लगते हैं, लेकिन उसके बाद ज्यादा programs चलाए जा सकते हैं
download files और usage
- main download uMIPS.8PL.zip है
- archive में board बनाने और चलाने के लिए जरूरी files शामिल हैं
schematics: circuit diagramgerbers: board fabrication के लिए Gerber filessrcs: emulator और bootloader sourcebinaries/SD.img: SD card पर लिखने वाली imageBOOTLOADER.BIN: assembly के दौरान chip पर लिखने वाला bootloaderFIRMWARE.BIN: pre-built firmware image
- boot के बाद default shell
shहै, औरbashभी चलाया जा सकता है - RAM की कमी से बचने के लिए image में शामिल swapfile को
swapon /swapfileसे activate करना बेहतर है - MCU को 120MHz पर चलाने का assumption लें, तो effective CPU speed लगभग 1.5MHz है
- एक simple C program को gcc से compile करने में कई minutes लगते हैं, लेकिन यह काम करता है
- example के तौर पर floating-point और fixed-point Mandelbrot generators source और binary form में दिए गए हैं
- installed tools में vim, make, gcc शामिल हैं, और Debian packages SD card के shared FAT16 partition के जरिए add किए जा सकते हैं
1 टिप्पणियां
Hacker News की राय
यह हिस्सा वाकई शानदार हैकिंग है कि काफी सोच-विचार के बाद यह समाधान निकला: RAM के nCS को SD कार्ड के CLK के रूप में, RAM के CLK को SD कार्ड के CMD के रूप में, और RAM के MOSI को SD कार्ड के DAT के रूप में इस्तेमाल करना
हर डिवाइस के साथ संभावित interaction को देखकर यह भी भरोसेमंद लगता है कि यह सुरक्षित रूप से काम करता है, और यह Hacker News पर आने लायक पूरी तरह है
USB से कनेक्ट करने के लिए अलग chip इस्तेमाल करना default विकल्प बन जाता है, यह देखकर हमेशा थोड़ी निराशा होती है
USB बहुत जटिल protocol है, इसलिए low-speed USB 1.1 चलाने वाले basic V-USB स्तर से आगे जाएं तो खास hardware और काफी बड़े software stack के बिना यह आम तौर पर मुश्किल दिखता है
इसके उलट SPI हास्यास्पद रूप से simple है; इसके लिए न्यूनतम hardware बस इतना चाहिए कि shift register पर्याप्त तेज़ी से clock receive कर सके
पुराने desktop और laptop की तरह बाहर exposed serial/parallel ports होते थे, जिनसे ऐसी low-level communication की जा सकती थी—वे दिन याद आते हैं
अगर साधारण peripherals के लिए UART, I2C, SPI multidrop को छोटी दूरी पर कुछ standard clocks और एक single connector के साथ इस्तेमाल किया जाता, और monitor या external drive जैसे data-heavy devices के लिए सीधे IEEE 802.3 Ethernet पर जाया जाता, तो शायद USB और Ethernet दोनों को अलग-अलग support करने की जरूरत नहीं पड़ती और सिर्फ Ethernet link support करना काफी होता
SPI power supply, hotplug, device discovery, bit errors जैसी USB द्वारा दी जाने वाली कई सुविधाओं को ध्यान में नहीं रखता
software developers के लिए SPI idioms और hardware designers SPI का इस्तेमाल कैसे करते हैं, यह समझना मूल्यवान है
आम तौर पर SPI peripherals के registers भरने के लिए इस्तेमाल होता है, और USB या Ethernet तथा उनके ऊपर की abstraction layers में अक्सर दिखने वाली high-level asynchronous communication से इसका स्वभाव अलग है
SPI frame का कोई universal standard नहीं है, लेकिन idiomatic patterns हैं, और अनगिनत applications में इतना काफी रहा है
व्यावहारिक रूप से SPI और I2C जैसे simple protocols पर्याप्त नहीं हैं
ये तेज़ नहीं हैं, single-ended signaling होने के कारण noise के प्रति बहुत संवेदनशील हैं, और error correction भी नहीं है
ये protocols अपने intended use, यानी PCB पर ICs को आपस में जोड़ने के लिए बहुत अच्छी तरह फिट होते हैं, लेकिन बिना termination वाले ports को बाहर expose कर दें तो कुछ भी guarantee करना मुश्किल है
modern PCs में भी ये protocols और इनके variants खूब इस्तेमाल होते हैं, लेकिन केवल internal bus के रूप में
USB specification को मैंने विस्तार से नहीं देखा है, लेकिन bit-banging की मुख्य समस्या शायद required speed है
microcontroller इतना तेज़ नहीं होता कि pins toggle करते हुए साथ-साथ protocol decode करे और error correction manage करे, इसलिए dedicated hardware चाहिए
I2C को bit-bang करने पर भी यही समस्या आ सकती है
20MHz CPU से मिलने वाली maximum clock लगभग 250KHz है, जो आम maximum speed 400KHz के आधे से थोड़ा ज्यादा है, और 1MHz version तो व्यावहारिक रूप से असंभव है
PHY मौजूद होने की वजह यह है कि communication protocol को hardware पर offload करना बेहद सस्ता पड़ता है
वरना communication को manually manage करने के resources पाने के लिए CPU को जरूरत से कहीं ज्यादा बड़ा चुनना पड़ेगा, और इसलिए modern microcontrollers में I2C, SPI, serial communication के लिए hardware होता है
निष्कर्ष यह है कि SPI, I2C, UART जैसे simple serial protocols external peripherals के लिए बहुत खराब विकल्प हैं
इन्हें उचित speed पर चलाना मुश्किल है, और ये लंबे cables तथा noise झेल नहीं पाते
RS-232 को exception मान लें क्योंकि वह UART नहीं है, फिर भी इन protocols के स्वभाव और design के कारण इन्हें इस तरह इस्तेमाल नहीं किया जा सकता, और इन्हें support करने के लिए specification बदलनी हो तो अंत में USB को फिर से invent करना पड़ेगा
signage या conference room वाली TV screens भी HDMI-CEC से ज्यादा flexible control के लिए अक्सर RS-232 देती हैं
कई मामलों में 9600bps से ज्यादा bitrate की जरूरत नहीं होती, और सबसे आम connector Tx, Rx, GND वाला 3-pin screw terminal है
आजकल के installations में आम तौर पर कहीं न कहीं कम से कम एक RS232-USB adapter होता है, और बड़े rooms में RS232 को Ethernet पर bridge किया जाता है
जब मैं पहली बार इस field में आया तो यह अजीब लगा था, लेकिन यह सोचें कि कई installations दशकों पुराने हैं और components एक-एक करके बदले जाते रहे हैं, तो बात समझ आती है
यह chip करीब 0.10 डॉलर में 2KB RAM, 16KB Flash, 48MHz, 1 CPI पर चलता है
नया CH570 भी SOIC8 में करीब 0.10 डॉलर का है, लेकिन इसमें 100MHz, 16KB RAM, 256KB Flash, USB और 2.4GHz packet radio तक है; मैंने development board order कर रखा है
जो लोग खुद board बनाना चाहते हैं, उनके लिए जरूरी PCB thickness भी लिख देना अच्छा होगा
अगर मुझे सही याद है तो यह करीब 0.8mm है, और “USB-C edge connector” को plug में fit होने के लिए वही thickness चाहिए
लेख बढ़िया है, लेकिन सोचता हूं कि अगर 8-pin requirement को थोड़ा flexible माना जाता तो शायद यह बहुत ज्यादा सरल हो जाता
बस कुछ और pins होने से project complexity काफी घट जाती, और soldering time बस थोड़ा ही बढ़ता
built-in USB वाले कहीं ज्यादा तेज़ chips बहुत हैं
Allwinner V3s भी hand-solderable है, इसमें RAM built-in है, और यह Linux को natively अच्छे से boot करता है
RP2350 भी अच्छा विकल्प है, और इसमें cache built-in वाला शानदार QSPI RAM interface तथा USB support है
यह लगभग 2-चिप वाले प्रोजेक्ट जैसा है
एक तो बस USB-to-serial IC है, और अगर SD कार्ड को न गिनें तो SD कार्ड समेत यह फिर से 3 हो जाता है
कुल पिनों की संख्या इतनी कम है कि इसे dead bug तरीके से बनाकर देखने का मन करता है
microSD-to-SD adapter, solder किए जा सकने वाले microSD holder के तौर पर काफी काम का है
उसे target करके इसी तरह की trick करना भी एक मजेदार hacking होगी
तकनीकी रूप से यह बेहद शानदार प्रोजेक्ट है, लेकिन beginners के लिए नया computer kit बनाने के लक्ष्य से थोड़ा अलग होकर काफी extreme तक चला गया लगता है
beginner के लिए SOIC8 solder करना और SOIC28 solder करना बहुत अलग नहीं है
मेरे हिसाब से SOIC28 भी SOIC8 जितना ही आसान या मुश्किल है
बड़ा chip इस्तेमाल करने पर कम से कम sound, keyboard, और बाद में VGA-स्टाइल असली monitor output तक जोड़ा जा सकता है, जिससे यह कहीं ज्यादा उपयोगी computer बन सकता है
soldering की कठिनाई लगभग नहीं बढ़ती, और रुचि लेने वाले users के लिए expand करने का अच्छा base बनता है
अगर कोई उस दिशा में बनाना चाहता है तो मेरा code इस्तेमाल कर सकता है
मैंने ऐसा इसलिए किया क्योंकि 8-pin वाली कृत्रिम constraint मुझे मजेदार लगी
PCB तक छोड़कर इसे circuit sculpture के रूप में बनाने की अजीब-सी इच्छा होती है
मैं artist या sculptor नहीं हूं, इसलिए कोशिश करने की हिम्मत नहीं की
storage के लिए SD कार्ड की जगह 8-pin SPI Flash इस्तेमाल करना cute लगेगा
आपने कहा था, “निजी कारणों से मुझे RISC-V से allergy है”; वजह जानने की उत्सुकता है
flame war शुरू नहीं करना चाहता, यह बस निजी राय है, लेकिन काफी मजबूत राय है
RISC-V ऐतिहासिक रूप से इतना देर से design हुआ कि बहुत-सा मौजूदा ज्ञान इस्तेमाल किया जा सकता था, लेकिन मेरे हिसाब से उसने उसका लगभग उपयोग नहीं किया
इसलिए जो चीजें शुरुआत से ही सही होनी चाहिए थीं, उन्हें ठीक करने के लिए कई extensions propose हो रहे हैं
additions बढ़ते-बढ़ते 10 साल बाद जाकर यह धीरे-धीरे कुछ हद तक समझ में आने वाले रूप के करीब पहुंच रहा है
यह बहाना भी मुझे स्वीकार नहीं कि सीखने की प्रक्रिया जरूरी थी
जरूरी जानकारी शुरुआत से मौजूद थी, और गलतियां हममें से ज्यादातर लोगों को साफ दिख रही थीं
कुछ extensions तो बुनियादी design problems पर लगाए गए band-aid भर हैं
उदाहरण के लिए shadd2 arrays access करने के लिए proper addressing mode न होने की समस्या पर लगाया गया band-aid है
इसका आम जवाब core के अंदर किसी magic जैसी instruction fusion का वादा करना होता है, जिसका वादा अक्सर किया जाता है लेकिन असल में दिया नहीं जाता
खासकर उन low-cost processors में तो बिल्कुल नहीं, जो RISC-V का इकलौता target लगते हैं
bitfield extract और insert instructions का न होना भी amateurish गलती है, और इसलिए इसे ठीक करने वाला extension भी है
लेकिन ऐसी functionality की जरूरत शुरू से ही स्पष्ट होनी चाहिए थी
register के अंदर किसी खास bit के आधार पर conditional branch करने वाला instruction भी अक्सर दिखता है, इसलिए यह भी शुरुआत से consider की जाने वाली स्पष्ट सुविधा थी
modern software का थोड़ा-सा analysis करने पर भी यह दिख जाता
झुंझलाहट वाली बात यह है कि जानकारी पहले से मौजूद थी
हमें पता था कि modern software क्या करता है, फिर भी सब कुछ ignore किया गया, और नतीजे में हमें थोड़ा update किया हुआ MIPS-1 मिला, ऐसा मुझे लगता है
अब ढेरों extensions जुड़ने से fragmentation बहुत बढ़ गया है
कोई RV23 जैसी कुछ हद तक reasonable final result को target कर सकता है, लेकिन उसे implement करने वाला hardware नहीं है; वरना ऐसे lowest common denominator को target करना पड़ेगा जो हर जगह चलता तो है, पर बेहद खराब performance देता है
असली high-performance computing में RISC-V इस्तेमाल करने की कोशिश करने पर और भी गंभीर design problems हैं, लेकिन वह अगले rant के लिए छोड़ता हूं
लगभग उसी समय design हुआ एक और instruction set था, जिसने modern software कैसा दिखता है इस बारे में मौजूद ज्ञान का सचमुच उपयोग किया, और उसका नतीजा दिखता है: aarch64
प्रोजेक्ट खुद भी बहुत शानदार है, लेकिन यह page छोटे microcontrollers की जानकारी पाने के लिए भी बेहतरीन resource है
WLCSP series इसमें नहीं है, लेकिन यह ARM के लिए MIPS emulator page https://dmitry.gr/?r=05.Projects&proj=33.%20LinuxCard तक भी ले जाता है, जो काफी दिलचस्प लगता है