Autorul poate fi contactat la adresa: Login pentru adresa
Scopul proiectului curent este de a folosi cunoștințele dobândite atât în anii precedenți cât și la cursul de PM pentru a le integra într-un dispozitiv cât de cât complet din punct de vedere arhitectural, și anume un mini-PC embedded folosind microcontrollere AVR.
Dispozitivul trebuie să fie capabil de General Purpose computing (deci să nu fie construit specific pentru un task), să aibă intrări și ieșiri human-friendly (monitor prin intermediul unui conector VGA și tastatură prin intermediul PS/2).
Deasemenea, calculatorul trebuie să poată să funcționeze independent de un alt device extern (excepție făcând programarea sa) și ca atare să aibă stocare suficientă, de preferat prin card micro-SD, să aibă posibilitatea să țină timpul chiar și atunci când este oprit (RTC) și să aibă și un mic difuzor. Notabilă este lipsa conectivității ETHERNET/Wi-Fi care în condițiile constrângerilor de timp extreme nu a fost fezabil de proiectat.
Ideea a pornit de la motivul pentru care studiez calculatoarele și sunt fascinat de ele, și anume calculatorul în sine, ideea de device de computație pe care să îl pot înțelege cap-coadă și să îl pot fabrica și programa, ca obiect integrator al cunoștințelor mai mult sau mai puțin utile învățate în această facultate. Având în vedere revoluția DIY, am dorit să construiesc un PC cât mai de bază și cu toate acestea cu utilitate maximă pe care să îl pot folosi pe bune, fără alt calculator, sau debugging serial urât sau butonașe pe care să nu pot tasta nimic complex.
De asemenea, o influență mare o are o altă idee personală de a dezvolta un mini-laptop bazat pe AVR sau ARM Cortex M0+ pentru EECS hacking, capabil atât de computație generală, cât de cât limitată, cât și de interfațare complexă cu elemente electrice externe, de la semiconductori, la motoare, la cabluri seriale/telefonice/ethernet, etc, totul într-un pachet self-contained de dimensiuni sub 10 țoli, portabil. Consider că un astfel de dispozitiv, care poate crește din acest proiect cu integrarea unui monitor, a unei baterii și a unei tastaturi, poate fi foarte util și în acest moment, nu există pe piață ca produs complet și poate fi construit doar cu multă bătaie de cap, folosind de exemplu un PI (Raspberry/Banan) cu ecran, tastatură, baterie și multe fire, care nicidecum nu ar fi la fel de portabil.
De ce este orice lucru construit pe această lume util? În primul rând, la nivel personal, pentru a valida utilitatea unor ani petrecuți în facultăți (6+) printr-un proiect practic, cât de cât complet.
De ce este util pentru alții? Pentru că acest domeniu al Calculatoarelor este atât de extins încât după ani și ani de studii, mulți se găsesc în poziția de a le lipsi cunoștințe absolut esențiale despre ce înseamnă un calculator. Pot să fie programatori excelenți de C++ sau Haskell sau Java și să nu aibă habar ce e un protocol de comunicație, să știe ce e o celulă SRAM, dar să nu înțeleagă un pointer sau Garbage Collection, sau să știe ce înseamnă o interconectare crossbar dar să nu înțeleagă ce e un registru. Cred că un astfel de proiect este deasemenea util pentru a demonstra că un sistem de computație complex și cât de cât complet poate fi orice și din orice, inclusiv din niște amărâte de microcontrollere cu câțiva Kb de memorie.
Pe de altă parte, dă și un pic de bragging rights: Hei, am proiectat, construit și programat un calculator de la zero (aproape).
Având în vedere faptul că outputul VGA (bit-banging practic) va ține ocupat procesorul foarte mult timp, am decis ca acest aspect să fie managed de câtre un microcontroller separat pe post de GPU care sa primească comenzi de la CPU pentru afișare pe ecran prin UART, prin intermediul unui protocol propriu. Astfel, se eliberează CPU-ul pentru alte aspecte, de management al input-ului (tastatură PS/2), al stocării hard (card microSD), al ceasului RTC și bineînțeles al logicii interne a sistemului de operare care va putea executa programe stocare pe hard.
Întrucât era mai simplu de interfațat cardul SD cu procesorul, am decis ca acesta să fie pe 3.3V și GPU pe 5V, celelalte dispozitive fie comunicând direct, fie necesitând level-shifting.
VGA, conform protocolului, necesită valori ale tensiunii de circa 0.7V pe ieșirile RGB și a fost nevoie de divizoare de tensiune. Pentru celelalte cazuri când divizoarele de tensiune nu puteau urca tensiunea, am folosit MOSFEȚI N2700 (în principiu pentru shiftare 3.3V → 5V). Deși am permis output pe 3-biți de culoare (pentru un total de 8 culori RGB), datorită constrângerilor de timing am ales să afișez exclusiv monocrom pe un monitor extern.
Totodată, datorită timing-ului constrâns, am ales ca GPU-ul să aibă un clock extern de 20MHz pentru a permite afișarea a cât mai multor linii. CPU-ul este pe 16MHz.
RTC-ul comunică prin I2C cu o linie adițională de întreruperi și este conectat la o baterie CR de 12 milimetri pentru funcționare continuă pe o perioadă de ani de zile chiar și în lipsa alimentării.
PS/2, conform protocolului, este pe 5 volți, tip I2C.
Speaker-ul nu a necesitat amplificator, și s-a conectat direct la OC1B.
Atât alimentarea cât și programarea se fac prin cablu micro-USB care este conectat la un modul FTDI ce convertește în semnal serial care apoi este demultiplexat prin jumperi (SELECTOR pe schema bloc) pentru a putea alege microcontrollerul programat la un anume moment.
Programarea se poate face și prin intermediul a 2 serii de jumpere ICSP, câte unul pentru fiecare microcontroller.
Pentru debugging, s-au scos de pe placă și două serii de pini seriali, câte unul pentru fiecare microcontroller.
Piesă | Valoare | Bibliotecă | Formă | Descriere |
---|---|---|---|---|
C3 | 22pF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C4 | 22pF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C5 | 100uF | CAP_POL1206 | EIA3216 | Capacitor Polarized |
C6 | 10uF | CAP_POL1206 | EIA3216 | Capacitor Polarized |
C7 | 100nF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C8 | 0.47uF | CAP0603-CAP | 0603-CAP | Capacitor |
C9 | 100nF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C10 | 100nF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C11 | 22pF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C12 | 22pF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C17 | 33uF | CPOL-EUC | PANASONIC_C | POLARIZED CAPACITOR, European symbol |
C20 | 22pF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C21 | 22pF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C22 | 100nF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C23 | 100nF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
C28 | 0.1uF | C-EUC0603 | C0603 | CAPACITOR, European symbol |
CPU3V3 | ATMEGA1284P-AU | ATMEGA1284P-AU | QFP80P1200X1200X120-44N | Microcontroller with Programmable Flash |
D1 | Led Tx CPU→GPU | LED0603 | LED-0603 | LEDs |
D2 | LedPWR | LED0603 | LED-0603 | LEDs |
D3 | TXLED | LED0603 | LED-0603 | LEDs |
D4 | RXLED | LED0603 | LED-0603 | LEDs |
F2 | PTC0603 | PTC0603 | 0603 | Resettable Fuse PTC |
FTDI_SEL | MA03-2 | MA03-2 | PIN HEADER | |
GPU5V | ATMEGA324A-AU | ATMEGA324A-AU | QFP80P1200X1200X120-44N | 8-bit Atmel Microcontroller |
JP4 | UART CPU | PINHD-1×2 | 1×02 | PIN HEADER |
JP5 | UART GPU | PINHD-1×2 | 1×02 | PIN HEADER |
JP6 | USB | USB | ZX62D-B-5PA8 | USB Connectors |
JPCPU | ICSP CPU | PINHD-2×3 | 2×03 | PIN HEADER |
JPGPU | ICSP GPU | PINHD-2×3 | 2×03 | PIN HEADER |
MOSFET_CPUCOMM | MOSFET-NCHANNEL2N7002PW | MOSFET-NCHANNEL2N7002PW | SOT323 | Common NMOSFET Parts |
MOSFET_FTDI_RXGPU | MOSFET-NCHANNEL2N7002PW | MOSFET-NCHANNEL2N7002PW | SOT323 | Common NMOSFET Parts |
MOSFET_FTDI_TXGPU | MOSFET-NCHANNEL2N7002PW | MOSFET-NCHANNEL2N7002PW | SOT323 | Common NMOSFET Parts |
MOSFET_PS2C | MOSFET-NCHANNEL2N7002PW | MOSFET-NCHANNEL2N7002PW | SOT323 | Common NMOSFET Parts |
MOSFET_PS2D | MOSFET-NCHANNEL2N7002PW | MOSFET-NCHANNEL2N7002PW | SOT323 | Common NMOSFET Parts |
MOSFET_SCL | MOSFET-NCHANNEL2N7002PW | MOSFET-NCHANNEL2N7002PW | SOT323 | Common NMOSFET Parts |
MOSFET_SDA | MOSFET-NCHANNEL2N7002PW | MOSFET-NCHANNEL2N7002PW | SOT323 | Common NMOSFET Parts |
MOSFET_SQW | MOSFET-NCHANNEL2N7002PW | MOSFET-NCHANNEL2N7002PW | SOT323 | Common NMOSFET Parts |
PS2 | MINI-DIN6PTH | MINI-DIN6PTH | MINI-DIN6 | mini DIN 6 Connector |
Piesă | Valoare | Librărie | Formă | Descriere |
Q1 | 16MHz | XTAL-4-3225 | NX3225 | Classic 4-pin 3.2 x 2.5mm crystal |
Q4 | 20MHz | XTAL-4-3225 | NX3225 | Classic 4-pin 3.2 x 2.5mm crystal |
R1 | 10k | RESISTOR0603-RES | 0603-RES | Resistor |
R2 | 10k | RESISTOR0603-RES | 0603-RES | Resistor |
R3 | 85 | RESISTOR0603-RES | 0603-RES | Resistor |
R4 | 220 | RESISTOR0603-RES | 0603-RES | Resistor |
R5 | 120 | RESISTOR0603-RES | 0603-RES | Resistor |
R6 | 120 | RESISTOR0603-RES | 0603-RES | Resistor |
R7 | 120 | RESISTOR0603-RES | 0603-RES | Resistor |
R8 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R9 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R10 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R11 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R12 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R13 | 1K | RESISTOR0603-RES | 0603-RES | Resistor |
R14 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R15 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R16 | 1K | RESISTOR0603-RES | 0603-RES | Resistor |
R17 | 18 | RESISTOR0603-RES | 0603-RES | Resistor |
R18 | 18 | RESISTOR0603-RES | 0603-RES | Resistor |
R21 | 100 | RESISTOR0603-RES | 0603-RES | Resistor |
R22 | 100 | RESISTOR0603-RES | 0603-RES | Resistor |
R23 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R24 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R25 | 18 | RESISTOR0603-RES | 0603-RES | Resistor |
R26 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R27 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R28 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R29 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R30 | 1k | RESISTOR0603-RES | 0603-RES | Resistor |
R31 | 220 | RESISTOR0603-RES | 0603-RES | Resistor |
R32 | 220 | RESISTOR0603-RES | 0603-RES | Resistor |
R33 | 220 | RESISTOR0603-RES | 0603-RES | Resistor |
R34 | 220 | RESISTOR0603-RES | 0603-RES | Resistor |
R35 | 220 | RESISTOR0603-RES | 0603-RES | Resistor |
R63 | 22 | R-EU_R0603 | R0603 | RESISTOR, European symbol |
R64 | 22 | R-EU_R0603 | R0603 | RESISTOR, European symbol |
RESET | RST_OFF | TAC_SWITCHPTH | TACTILE-PTH | Momentary Switch |
SPK1 | SMT-0540-S-R | SMT-0540-S-R | SMT-0540-S-R | SMT-0549-S-R |
U2 | CR1220-SMD | CR1220SMT | CR1220-SMD | CR1216/CR1220/CR1225 12mm 3V lithium coin cell |
U4 | DB15 | DB15 | DB15 | DB15 / VGA right angle through-hole female connector. |
U2 | LM3940IMP-3.3 | LM3940IMP-3.3 | SOT230P696X180-4N | Low Dropout Regulator |
U6 | FT231XS | FT231XS | SSOP20 | |
X2 | 32.768kHz | XTAL-3.2×1.5 | XTAL3215 | Low cost SMT crystals, no capacitors included |
Piesă | Valoare | Librărie | Formă | Descriere |
Voi folosi AVR Studio pentru implementarea softului.
Se va scrie atât cod C cât și eventual un pic de ASM.
Pentru implementarea driverului VIDEO se vor scrie librăria de timing de la zero, luând în considerare parametri de timing necesari (20Mhz, video buffer utilizat la maxim (cei 2000 octeți de memorie SRAM de pe microcontrollerul Atmega324A) și output de culoare monocromă).
Pentru PS/2 se va scrie o librărie, folosind standardul PS/2.
Pentru comunicația între CPU → GPU se va scrie un mic protocol de comunicație bazat pe UART-ul AVR-urilor:
Protocolul de comunicație va trimite pachete de dimensiune constantă de 2 octeți (Comandă/Parametru) de tipul:
Comandă | Semnificație | Parametru |
---|---|---|
10 | PUTCHAR | Octetul caracterului aferent |
50 | BACKSPACE | |
100 | GOTOX | Linia la care deplasăm cursorul |
150 | GOTOY | Coloana la care deplasăm cursorul |
200 | COLORFG | 0-8 Culoarea nouă a textului |
225 | COLORBK | 0-8 Culoarea nouă a fundalului |
250 | CLR | Ștergere ecran |
Întrucât nu a mai fost timp pentru a lipi și modului pentru card microSD, nu voi folosi nici o librărie pentru acces la card SD, dar pe viitor intenționez să folosesc scheletul de cod de la laborator pentru acces la card SD și sistemul de fișiere aferent, alături de implementarea unui format executabil care să poată fi copiat în memoria de cod de pe cardul SD și executat.
Realizarea proiectării a durat ceva timp, dar învâțând EAGLE, am reușit să rutez cu un pic de ajutor automat, o placuță pe 2 layere (Front și Back) care arată destul de bine.
În ROBOLAB, primind ajutor de la echipa de PM cărora le muțumesc pe această cale, am realizat plăcuța.
Aici sunt poze cu procesul de etching și lipire.
A fost o mare bătaie de cap lipirea unor componente așa mici, și în mod special a fost dificil să lipesc circa 50 de via-uri de 0.5mm, proces care a durat în jur de 8 ore.
Am observat apoi la primul contact cu curentul electric de 5V că a explodat siguranța SMD care se arde de obicei dacă curentul depășește cu mult 500mA (regulat de obicei prin USB), moment în care nu a mai funcționat plăcuța. După desfacerea siguranței, am avut alimentare, dar nu se putea comunica cu microcontrollerele.
După debugging hardware semnificativ (atât scurturi, întreruperi de trasee, cât și greșeli pe schema electrică care nu au ajuns tipărite și au rămas pe calculator :) ) într-un final, cele 2 controllere au reușit să comunice cu programatorul AVR și fuse-urile au fost date jos.
Nu am apucat sa scriu decat o mica parte din kernelul CPU-ului, care doar copiaza caracterele de la PS/2 la UART-ul scos de pe placa prin cei 2 pini apropiati de CPU.
Am folosit urmatoarele datasheeturi:
* ATMega324P * ATMega1284P
iar celelalte se gasesc in arhiva si la ro.farnell de unde am cumparat piesele din BOM.
* Documentul protocolului PS/2 * Interfatarea PS/2 cu ATTiny * Diverse site-uri cu GPU-uri implementare prin AVR