This is an old revision of the document!


RetroPM

Introducere

Proiectul constă în implementarea unui “PC” inspirat de cele old school pentru care interfața cu utilizatorul se rezuma la introducerea unor comenzi în terminal. O sa îl numesc RetroPM.

Prin acest proiect, mi-am propus sa replic un sistem ce poate reproduce într-un mod minimal gestionarea de fișiere și utilizatori.

Descriere generală

RetroPM se bazează în principal pe comunicarea dintre 3 microcontrollere cu scopuri diferite:

  • ESP32: Se ocupa de Afișarea pe 2 display-uri input-ul si output-ul pentru utilizator (comenzile în timp ce se tastează, un prompt cu utilizatorul curent etc.) și cu conectarea la un server NTP pentru a afișa ora actuala pe display.
  • STM32F103: Se ocupa de logica principala (FSM-ul) a sistemului. Acesta este responsabil de procesarea input-ului, de a decide dacă o comanda este invalida, ce privilegii are un user când când dorește sa modifice un fișier etc.
  • Raspberry Pi Pico: Se ocupa de prelucrarea input-ului de la utilizator (tastele sunt procesate în caractere ASCII) pentru a le comunica către STM32.

Hardware Design

Lista componente:

  • STM32F103
  • Raspberry Pi Pico
  • ESP32
  • Modul microSD + microSD 32GB
  • Shift registers
  • Diode, Resistori
  • Pushbuttons
  • Memorie EEPROM
  • Ecran OLED
  • Ecran LCD 16×2
  • Sursa alimentare
  • Level shifter

Schema pentru Raspberry Pi Pico (partea de “tastatura”):

Schema pentru ESP32 (celelalte periferice: display, microSD):

(Notita: Am uitat sa pun in schema I2C-ul pentru ESP32, are rezistenta de pull-up ca STM32 si foloseste un singur bus pentru ambele display-uri)

Schema pentru STM32 (microcontroller principal):

Software Design

Pentru STM32 și Raspeberry Pi Pico am folosit Rust, cu biblioteci de Hardware Layer Abstraction. Pentru ESP32, am folosit Arduino IDE și C++. Lista bibliotecilor folosite:

  • C++
    • SPI.h, SD.h pentru modulul de microSD
    • Adafruit_GFX, Adafruit_SH110X, hd44780 pentru cele doua display-uri
    • Wire pentru I2C
    • HardwareSerial pentru UART
  • Rust
    • rp2040_hal - pentru Pico
    • stm32f1xx_hal, eeprom34x (pentru a scrie/citi din IC-ul de memorie) - pentru STM32F103

Pentru partea de procesare de tastatura, a trebuit în primul rând sa implementez o funcție asemănătoare cu cea de shiftOut din Arduino.h (nu am găsit-o în vreu crate de Rust). Folosind 2 shift registeri ca output-uri (fiecare cu 5 coloane din matricea de butoane asignate), și 4 coloane ca input-uri pentru a reduce numărul de pini folosiți pe placa, am folosit o tehnica de matrix scanning pentru a decide ce buton a fost apăsat de utilizator. Astfel am putut sa scanez mai multe butoane în același ciclu de loop. (Lucrul acesta a fost folosit pentru a reproduce efectul de shift + lowercase = uppercase).

Code snippet: Prima parte din loop se ocupa cu scanarea și stocarea intr-o matrice de tip bool dacă tasta de la poziția i,j a fost apăsată.

        // Bits 9:5 for first shift register
        // Bits 4:0 for second shift register
        let mut bits = 0x0200u16; // 0000_0010_0000_0000
 
        // Mask for second shift register -> 0000_0000_0001_1111
        let mask = 0x001Fu16;
 
        for col in (0u8..10u8).rev() {
            // Byte to serial input for first shift register.
            let byte_higher = !((bits >> 5).to_be_bytes()[1]);
 
            // Byte to serial input for second shift register.
            let byte_lower = !((bits & mask).to_be_bytes()[1]);
 
            latch_pin_1.set_low().unwrap();
            latch_pin_2.set_low().unwrap();
            // Shift out value from register
            kb_lib::shift_out(&byte_lower, &mut data_pin_2, &mut clock_pin_2, &mut delay, kb_lib::BitOrder::LSBFIRST);
            kb_lib::shift_out(&byte_higher, &mut data_pin_1, &mut clock_pin_1, &mut delay, kb_lib::BitOrder::LSBFIRST);
 
            // Read from the input pins for scanning:
            let idx = if col == 9 { 9usize } else { 8 - col as usize };
 
            if rows0.is_low().unwrap() { 
                keyState[0][idx] = true;
            } else {
                keyState[0][idx] = false;
            }
 
            if rows1.is_low().unwrap() {
                keyState[1][idx] = true;
            } else {
                keyState[1][idx] = false;
            }
 
            if rows2.is_low().unwrap() {
                if idx == 0 {
                    is_shift_pressed = true;
                } else {
                    keyState[2][idx] = true;
                }
            } else {
                keyState[2][idx] = false;
            }
 
            if rows3.is_low().unwrap() {
                keyState[3][idx] = true;
            } else {
                keyState[3][idx] = false;
            }
 
            bits >>= 1;
            latch_pin_1.set_high().unwrap();
            latch_pin_2.set_high().unwrap();
        }

A doua parte se ocupa cu comunicarea către STM32:

for i in 0..4 {
            for j in 0..10 {
                if keyState[i][j] {
 
                    if is_shift_pressed {
                        last_key_pressed = kb_lib::SHIFT_KEYS[i][j];
                        is_shift_pressed = !is_shift_pressed;
                    } else {
                        last_key_pressed = KEYS[i][j];
                    }
                    delay.delay_ms(100);
                    write!(uart,"{}", &last_key_pressed).unwrap();
                    delay.delay_ms(100);
                    break;
                }
            }
        }

Pentru partea de logica principala, atât în STM32, cât și în ESP32 am folosit logica unor FSM-uri.

Rezultate Obţinute

Care au fost rezultatele obţinute în urma realizării proiectului vostru.

Concluzii

Download

O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului: surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-).

Fişierele se încarcă pe wiki folosind facilitatea Add Images or other files. Namespace-ul în care se încarcă fişierele este de tipul :pm:prj20??:c? sau :pm:prj20??:c?:nume_student (dacă este cazul). Exemplu: Dumitru Alin, 331CC → :pm:prj2009:cc:dumitru_alin.

Jurnal

Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului.

Bibliografie/Resurse

Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe Resurse Software şi Resurse Hardware.

Export to PDF

pm/prj2023/gpatru/retropm.1685381625.txt.gz · Last modified: 2023/05/29 20:33 by irina_cristina.nita
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0