# GrifoScope Startup Sequence Analysis ## Obiettivo Identificare la sequenza di inizializzazione che GrifoScope esegue per preparare il radar all'operatività, da replicare in PyBusMonitor1553. ## Analisi Codice C++ ### 1. Inizializzazione Messaggi A1/A2 (Startup Protection) **File**: `cpp/GrifoScope/GrifoMCS/GADS/MCS/MCS_G346/g346/g346_a1a2.cpp` #### A1 - Radar Settings (`GrifoMsg_A1B6::startProtection()` - linea 10-12) ```cpp void GrifoMsg_A1B6::startProtection() { dSymbInt.setFromUser(127); // Symbol Intensity = MAX } ``` #### A1 - Valori di Default (linee 162-163) ```cpp dSymbInt.setFromUser(127); // Symbol Intensity = 127 (massimo) dIfGain.setFromUser(127); // IF Gain = 127 (massimo) dAltBlock.setFromUser(McsG346AltBlock::NORMAL); // Altitude Block = NORMAL ``` #### A2 - Radar Operation Command (`GrifoMsg_A2B7::startProtection()` - linee 414-416) ```cpp void GrifoMsg_A2B7::startProtection() { dSilence.setFromUser(1); // Silence = ON (1) dStby.setFromUser(1); // Standby = ON (1) } ``` #### A2 - Valori di Default (linee 697-698) ```cpp dSilence.setFromUser(1); // Silence = ON (1) - Trasmettitore disabilitato dStby.setFromUser(1); // Standby = ON (1) - Radar in standby ``` ### 2. Campi 1553 ICD **File**: `cpp/GrifoScope/GrifoSdkEif/pub/TH/th_b1553_icd.h` #### Standby Selection (linee 417-424) ```cpp enum stby_selection_t { STBY_OFF, // 0 = Radar operativo STBY_ON // 1 = Radar in standby }; typedef idd_boolfield_u16_t stby_field_t; ``` **Posizione**: Word A2-01, bit 8 (reversed: bit 7 in Python 0-based) #### Silence Selection (linee 428, 443, 457) ```cpp typedef bool silence_selection_t; typedef idd_bitfield_u16_t silence_field_t; union rdr_mode_command_word_t { ... silence_field_t silence; // reserved ... }; ``` **Posizione**: Word A2-01, bit 12 (reversed: bit 3 in Python 0-based) **Valori**: - `0` = Silence OFF → Trasmettitore abilitato - `1` = Silence ON → Trasmettitore disabilitato (modalità sicura) ### 3. Controlli GUI **File**: `cpp/GrifoScope/GrifoMCS/GADS/MCS/MCS_G346/g346/mcs_g346.cpp` (linee 1199-1204) ```cpp QAction* qStby=new QAction(&wb.mainWindow()); qStby->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_F1)); // CTRL+F1 qStby->setStatusTip("STBY!"); qStby->setText("STBY"); AdsWidgetsManager::mapAction(theMsg->A2B7.actSTBY, *qStby); ``` **Shortcut**: `CTRL+F1` per toggle STBY **File**: `cpp/GrifoScope/GrifoMCS/GADS/MCS/MCS_G346/g346/grifocmddock.cpp` (linee 32-33) ```cpp //ui->tb_ads_silence->setVisible(false); ui->tb_ads_silence->setEnabled(false); // Silence button DISABILITATO ``` **Nota**: Il pulsante Silence è disabilitato nell'interfaccia GUI. Questo suggerisce che il controllo Silence potrebbe essere gestito automaticamente o non utilizzato nel sistema G346. ### 4. Azioni Toggle (linee 514-516) ```cpp actSTBY.setObjectName("act_STBY"); actSTBY.attachTo(&dStby); actSTBY.setActionValue(0, 1); // 0=OFF, 1=ON ``` ## Sequenza di Startup Radar ### Fase 1: Inizializzazione Sicura (Power-On) Al primo avvio, GrifoScope imposta: **Messaggio A1 (Radar Settings)**: - `symbol_intensity` = 127 (massimo) - `if_gain` = 127 (massimo) - `altitude_block` = NORMAL - Tutti gli altri campi ai valori di default (tipicamente 0) **Messaggio A2 (Radar Operation)**: - `stby` = 1 (STBY_ON) → Radar in standby - `silence` = 1 (ON) → Trasmettitore disabilitato - `master_mode` = 0 o valore precedente - `designation_control` = NOT_VALID (7 per 3 bit) ### Fase 2: Attivazione ("Run" → Rimozione Standby/Silence) Quando l'operatore preme "Run" e rimuove Standby/Silence: **Messaggio A2 modificato**: - `stby` = 0 (STBY_OFF) → Radar operativo - `silence` = 0 (OFF) → Trasmettitore abilitato - `master_mode` = RWS (o altro modo selezionato) - Altri parametri operativi come range, scan, etc. **Messaggio A1** (può essere aggiornato con valori operativi): - `target_history` = valore desiderato (es. 3) - `symbol_intensity` = valore desiderato - Frequency channel, gains, etc. ## Campi Python Mapping ### Messaggio A1 (`msg_a1.py`) **Già implementati**: - ✅ `symbol_intensity` - BitField(0, 0, 7) - ✅ `if_gain` - BitField(1, 0, 7) - ✅ `target_history` - BitField(0, 8, 3) - ✅ `ground_reject_vel_high` - BitField(0, 15, 1) - ✅ `frequency_channel` - BitField(1, 8, 6) **Mancante**: - ❌ `altitude_block` - BitField (word 0, bits da verificare) ### Messaggio A2 (`msg_a2.py`) **Già implementati**: - ✅ `master_mode` - EnumField(0, 0, 4, MasterMode) - ✅ `designation_control` - EnumField(0, 4, 3, DesignationControl) - ✅ `priority_target_number` - BitField(2, 0, 6) - ✅ `range_scale` - EnumField(1, 0, 4, RangeScale) - ✅ `scan_width` - EnumField(1, 4, 3, ScanWidth) - ✅ `velocity_scale` - EnumField(1, 7, 2, VelocityScale) **Mancanti (CRITICI per startup)**: - ❌ `stby` - BitField(0, 7, 1) # IDD_REVBIT16(8) = bit 7 - ❌ `silence` - BitField(0, 3, 1) # IDD_REVBIT16(12) = bit 3 - ❌ `freeze` - BitField(0, 6, 1) # IDD_REVBIT16(9) = bit 6 - ❌ `ibit_request` - BitField(0, 8, 1) # IDD_REVBIT16(7) = bit 8 ## Implementazione Python Raccomandata ### 1. Completare msg_a2.py ```python # In pybusmonitor1553/lib1553/messages/msg_a2.py # Word 0 - Radar Mode Command (rdr_mode_command_word_t) master_mode = EnumField(0, 0, 4, MasterMode) designation_control = EnumField(0, 4, 3, DesignationControl) stby = BitField(0, 7, 1) # NUOVO - Standby control ibit_request = BitField(0, 8, 1) # NUOVO - IBIT request freeze = BitField(0, 6, 1) # NUOVO - Freeze selection stop_powerup = BitField(0, 5, 1) # NUOVO - Reserved reserved_11 = BitField(0, 11, 1) # NUOVO - Emergency/reserved silence = BitField(0, 3, 1) # NUOVO - Silence control (trasmettitore) sar_exec = BitField(0, 13, 1) # NUOVO - SAR execution type ``` ### 2. Creare Funzione Startup ```python # In pybusmonitor1553/core/radar_startup.py def initialize_radar_safe_state() -> tuple[MsgA1, MsgA2]: """ Crea messaggi A1/A2 con valori di startup sicuri (Standby + Silence ON). Questa è la configurazione iniziale che GrifoScope usa al power-on per proteggere il radar. Returns: (msg_a1, msg_a2): Messaggi pronti per l'invio """ # A1: Radar Settings - valori di default sicuri msg_a1 = MsgA1() msg_a1.symbol_intensity = 127 # Massimo (startup protection) msg_a1.if_gain = 127 # Massimo msg_a1.target_history = 0 # Default msg_a1.ground_reject_vel_high = 0 # Default msg_a1.frequency_channel = 0 # Default # ... altri campi a 0 # A2: Radar Operation - SAFE MODE msg_a2 = MsgA2() msg_a2.master_mode = MasterMode.NO_OPERATION # 0 msg_a2.designation_control = DesignationControl.NOT_VALID # 7 msg_a2.stby = 1 # STANDBY ON msg_a2.silence = 1 # SILENCE ON (TX disabilitato) msg_a2.freeze = 0 # No freeze msg_a2.ibit_request = 0 # No IBIT # ... altri campi a valori di default return msg_a1, msg_a2 def activate_radar_operational() -> MsgA2: """ Crea messaggio A2 per attivare il radar (rimuove Standby e Silence). Questa è l'operazione che l'utente fa in GrifoScope premendo "Run" e disattivando Standby/Silence. Returns: msg_a2: Messaggio A2 con radar pronto all'operatività """ msg_a2 = MsgA2() msg_a2.stby = 0 # STANDBY OFF msg_a2.silence = 0 # SILENCE OFF (TX abilitato) msg_a2.master_mode = MasterMode.RWS # Modo operativo (es. RWS) msg_a2.designation_control = DesignationControl.TWS # Modo designation msg_a2.freeze = 0 msg_a2.ibit_request = 0 # ... configurare altri parametri operativi return msg_a2 def radar_startup_sequence(bc: BusController): """ Esegue la sequenza completa di startup del radar. Replicata da GrifoScope: 1. Invia A1/A2 con valori sicuri (Standby + Silence ON) 2. Attende conferma dal radar (B6/B7) 3. Rimuove Standby e Silence 4. Configura modo operativo Args: bc: BusController connesso al radar """ import time # Step 1: Invia configurazione sicura print("Step 1: Inizializzazione radar (SAFE MODE)") msg_a1, msg_a2 = initialize_radar_safe_state() bc.send_command(1, msg_a1) time.sleep(0.1) bc.send_command(2, msg_a2) time.sleep(0.5) # Attendi stabilizzazione # Step 2: Verifica stato radar print("Step 2: Verifica stato radar") msg_b7 = bc.request_data(7, MsgB7, timeout=1.0) if msg_b7: print(f" Radar status: mode={msg_b7.master_mode}, stby={msg_b7.standby_status}") else: print(" WARNING: Nessuna risposta da B7") # Step 3: Attiva radar (rimuovi Standby/Silence) print("Step 3: Attivazione radar (Standby/Silence OFF)") msg_a2_active = activate_radar_operational() bc.send_command(2, msg_a2_active) time.sleep(0.5) # Step 4: Verifica attivazione print("Step 4: Verifica attivazione") msg_b7 = bc.request_data(7, MsgB7, timeout=1.0) if msg_b7: print(f" Radar active: mode={msg_b7.master_mode}, RF={msg_b7.rf_radiation}") if msg_b7.standby_status == 0 and msg_b7.rf_radiation: print(" ✓ Radar OPERATIVO") else: print(" ⚠ Radar non completamente attivo") print("Startup sequence completata") ``` ### 3. Esempio Utilizzo ```python from pybusmonitor1553.core.bus_controller import BusController from pybusmonitor1553.core.radar_startup import radar_startup_sequence # Connetti al radar bc = BusController(rt_ip="192.168.1.100") bc.connect() # Esegui sequenza startup radar_startup_sequence(bc) # Ora il radar è pronto per comandi operativi # ... invio comandi A2 per cambiare modo, range, etc. bc.disconnect() ``` ## Note Implementative ### Bit Position Conversion (IDD_REVBIT16) **Formula C++**: `IDD_REVBIT16(pos) = 15 - pos` **Esempi**: - `IDD_REVBIT16(8)` → bit 7 in Python (stby) - `IDD_REVBIT16(12)` → bit 3 in Python (silence) - `IDD_REVBIT16(9)` → bit 6 in Python (freeze) - `IDD_REVBIT16(7)` → bit 8 in Python (ibit_request) ### Verificare con B7 (Radar Status Tellback) **Campi B7 da controllare**: - `standby_status` → deve essere 0 quando operativo - `rf_radiation` → deve essere 1 quando TX attivo - `master_mode` → deve corrispondere al comando A2 - `designation_mode` → deve corrispondere al comando A2 ## Riferimenti - **ICD Header**: `cpp/GrifoScope/GrifoSdkEif/pub/TH/th_b1553_icd.h` - **Implementazione A1/A2**: `cpp/GrifoScope/GrifoMCS/GADS/MCS/MCS_G346/g346/g346_a1a2.cpp` - **GUI Controls**: `cpp/GrifoScope/GrifoMCS/GADS/MCS/MCS_G346/g346/mcs_g346.cpp` - **Python Messages**: `pybusmonitor1553/lib1553/messages/msg_a2.py`