ST-LAB/diagram.md
2026-01-08 14:52:33 +01:00

7.4 KiB

graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;

flowchart TD
    %% --- STILI ---
    classDef hw fill:#ffcccc,stroke:#333,stroke-width:2px;
    classDef memory fill:#e1f5fe,stroke:#333,stroke-width:1px;
    classDef logic fill:#fff9c4,stroke:#333,stroke-width:1px;
    
    Start((START)) --> Init
    
    %% --- BLOCCO INIZIALIZZAZIONE ---
    subgraph Init ["1. Inizializzazione Bare Metal"]
        direction TB
        RCC["RCC AHB4ENR & APB1ENR\nAbilita Clock GPIO & USART"]:::hw
        GPIO["GPIO MODER & AFR\nButton=Input, LED=Output, TX=AF"]:::hw
        UART["USART3 CR1 & BRR\nConfigura Baud & Abilita UE"]:::hw
        NVIC["NVIC_EnableIRQ\nAbilita Interrupts al processore"]:::hw
        
        RCC --> GPIO --> UART --> NVIC
    end

    Init --> MainLoop

    %% --- BLOCCO MAIN LOOP ---
    subgraph Main ["2. Main Loop (Polling Button)"]
        direction TB
        MainLoop(while 1)
        
        ReadIDR["Leggi GPIOC->IDR\n(Stato Bottone)"]:::hw
        Debounce[Debounce Delay]:::logic
        
        EdgeCheck{"Rising Edge?\n(Curr=1 && Prev=0)"}:::logic
        
        ToggleOps[Toggle Logic]:::memory
        UpdatePrev[Prev = Curr]:::logic
        
        MainLoop --> ReadIDR --> EdgeCheck
        
        EdgeCheck -- NO --> UpdatePrev
        EdgeCheck -- SI --> ToggleOps
        
        subgraph Toggle ["Logica XOR LED"]
            ReadODR["Leggi GPIOB->ODR"]:::hw
            XOR["Calcola: ODR ^ LED_MASK"]:::logic
            WriteODR["Scrivi GPIOB->ODR"]:::hw
            ReadODR --> XOR --> WriteODR
        end
        
        ToggleOps --> UpdatePrev
        UpdatePrev --> Debounce --> MainLoop
    end

    %% --- BLOCCO INTERRUPT ---
    subgraph ISR ["3. USART3 IRQ Handler"]
        direction TB
        Trigger((IRQ))
        
        CheckTXE{"Flag TXE?\n(Data Reg Empty)"}:::logic
        CheckTC{"Flag TC?\n(Tx Complete)"}:::logic
        
        LoadDR["Scrivi USART3->DR\n(Invia Byte)"]:::hw
        EnableTC["Abilita TCIE\nDisabilita TXEIE"]:::hw
        DisableTC["Disabilita TCIE\nClear TC Flag"]:::hw
        FreeBusy[Set tx_busy = 0]:::memory
        
        Trigger --> CheckTXE
        
        CheckTXE -- "SI: Buffer Pieno" --> LoadDR
        CheckTXE -- "SI: Buffer Finito" --> EnableTC
        CheckTXE -- NO --> CheckTC
        
        CheckTC -- "SI: Fine Trasmissione" --> DisableTC --> FreeBusy
        CheckTC -- NO --> Return((RTI))
    end

    %% --- CONNESSIONI LOGICHE ---
    WriteODR -.-> |"Opzionale: Avvia TX"| Trigger
flowchart TD
    %% --- DEFINIZIONE CLASSI GRAFICHE ---
    classDef userFill fill:#e1f5fe,stroke:#0277bd,stroke-width:2px;
    classDef stmFill fill:#fff9c4,stroke:#fbc02d,stroke-width:2px;
    classDef pcFill fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px;
    classDef term fill:#212121,color:#fff,stroke:#000;

    %% --- CORSIA 1: UTENTE ---
    subgraph User ["👤 Utente (Mondo Fisico)"]
        direction TB
        Start((Inizio))
        PressBtn["Premi Bottone Blu"]:::userFill
        CheckLeds["Osserva i LED"]:::userFill
        CheckPC["Leggi Terminale PC"]:::userFill
    end

    %% --- CORSIA 2: STM32 (FIRMWARE) ---
    subgraph STM32 ["⚙️ STM32 H7 (Bare Metal)"]
        direction TB
        Polling("Ciclo While Infinito"):::stmFill
        IsPressed{"Rilevato\nFronte Salita?"}:::stmFill
        
        ToggleAction["XOR Toggle LEDs\n(ODR ^ Mask)"]:::stmFill
        LoadBuffer["Carica Buffer TX\nAbilita TXE IE"]:::stmFill
        
        subgraph ISR ["Interrupt Service Routine"]
            direction TB
            SendByte["Hardware Invia Byte"]:::stmFill
            CheckDone{"Finito?"}:::stmFill
        end
    end

    %% --- CORSIA 3: PC (SOFTWARE) ---
    subgraph PC ["💻 PC (Arch Linux + Julia)"]
        direction TB
        Listen{"Script Julia\nIn ascolto"}:::pcFill
        ReceiveData["Ricezione Byte\n(/dev/ttyACM0)"]:::pcFill
        PrintTerm["> Stampa a Video"]:::term
    end

    %% --- COLLEGAMENTI ---
    
    %% Flusso Utente -> STM32
    Start --> PressBtn
    PressBtn -- "Pressione fisica" --> Polling
    
    %% Logica STM32
    Polling --> IsPressed
    IsPressed -- No --> Polling
    IsPressed -- Si --> ToggleAction
    
    ToggleAction --> LoadBuffer
    LoadBuffer -.-> |"Trigger IRQ"| SendByte
    SendByte --> CheckDone
    CheckDone -- No --> SendByte
    CheckDone -- Si --> Polling

    %% Feedback Visivo (STM32 -> Utente)
    ToggleAction -.-> |"Luce LED"| CheckLeds

    %% Comunicazione Seriale (STM32 -> PC)
    SendByte == "Cavo USB (Serial)" ==> ReceiveData
    
    %% Logica PC
    Listen --> ReceiveData
    ReceiveData --> PrintTerm
    
    %% Feedback Terminale (PC -> Utente)
    PrintTerm -.-> |"Lettura"| CheckPC
    CheckPC --> PressBtn
flowchart TD
    %% --- STILI ---
    classDef cpu fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    classDef tim fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px
    classDef adc fill:#fff9c4,stroke:#fbc02d,stroke-width:2px
    classDef dma fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
    classDef mem fill:#eeeeee,stroke:#616161,stroke-width:2px,stroke-dasharray: 5 5

    %% --- CORSIA 1: CPU (INIZIALIZZAZIONE) ---
    subgraph Setup ["1. INIZIALIZZAZIONE (CPU)"]
        direction TB
        InitDMA["DMA Setup:\n- Mode: CIRC (Circolare)\n- PData: ADC_DR\n- MData: Buffer[0]\n- Size: 128\n- Incr: Memory (MINC)"]:::cpu
        
        InitADC["ADC Setup:\n- Conv: Single/Continuous\n- Trig: External (Timer)\n- DMA: Enable (Circular)"]:::cpu
        
        InitTIM["TIM Setup:\n- Periodo: Freq Campionamento\n- Master Mode (MMS): Update (TRGO)"]:::cpu
        
        StartAll["START:\n1. ADC_CR |= ADEN\n2. DMA_SxCR |= EN\n3. ADC_CR |= ADSTART\n4. TIM_CR1 |= CEN"]:::cpu
        
        InitDMA --> InitADC --> InitTIM --> StartAll
    end

    StartAll --> LoopTIM

    %% --- CORSIA 2: HARDWARE AUTOMATICO ---
    subgraph Hardware ["2. LOOP HARDWARE (Senza CPU)"]
        direction TB
        
        %% TIM
        LoopTIM(Timer Conta):::tim
        EventUpdate{"Update Event?\n(CNT == ARR)"}:::tim
        TriggerTRGO["Output TRGO\n(Hardware Signal)"]:::tim
        
        LoopTIM --> EventUpdate
        EventUpdate -- NO --> LoopTIM
        EventUpdate -- SI --> TriggerTRGO
        
        %% ADC
        TriggerTRGO --> ADC_Start["ADC Avvia Conv.\n(EXTEN rising)"]:::adc
        ADC_Conv[Campionamento...]:::adc
        FlagEOC{"Fine Conv?\n(ISR & EOC)"}:::adc
        
        ADC_Start --> ADC_Conv --> FlagEOC
        
        %% DMA
        FlagEOC -- SI --> DMA_Req["Richiesta DMA\n(ADC -> DR)"]:::dma
        DMA_Move["Sposta Dato:\nADC_DR -> Buffer[idx]"]:::dma
        DMA_Inc["Incrementa idx:\nidx = (idx + 1) & 127"]:::dma
        
        DMA_Req --> DMA_Move --> DMA_Inc
        
        %% BUFFER
        BufferState{"Buffer Pieno/Metà?\n(TCIF / HTIF)"}:::mem
        DMA_Inc --> BufferState
        
        BufferState -- "Ancora spazio" --> LoopTIM
    end

    %% --- CORSIA 3: INTERRUPT DMA (CPU) ---
    subgraph IRQ ["3. ELABORAZIONE (CPU - Interrupt DMA)"]
        direction TB
        CheckFlag{"Quale Flag DMA?"}:::cpu
        
        TaskHT["Half Transfer (HTIF):Elabora prima metà (0-63)"]:::cpu
        TaskTC["Transfer Complete (TCIF):\nElabora seconda metà (64-127)"]:::cpu
        
        Clear["Clear Flags:\nDMA_LIFCR / HIFCR"]:::cpu
        
        BufferState -.-> |"IRQ Trigger"| CheckFlag
        CheckFlag --> |HTIF| TaskHT
        CheckFlag --> |TCIF| TaskTC
        TaskHT --> Clear
        TaskTC --> Clear
    end