Contenidos
Compilar
gcc scan_power_range.c -o scan_power_range -lrtlsdr -lm
Uso básico
Escanear de 200 MHz a 400 MHz con paso de 100 kHz:
./scan_power_range
Parámetros opcionales
./scan_power_range <inicio_hz> <fin_hz> <paso_hz> <ganancia_tenths_db> <margen_db>
Ejemplos
Escaneo completo 200–400 MHz
./scan_power_range 200000000 400000000 100000 0 6
Más fino, paso de 25 kHz
./scan_power_range 200000000 400000000 25000 0 6
Ganancia fija baja
./scan_power_range 200000000 400000000 100000 10 6
Umbral más exigente
./scan_power_range 200000000 400000000 100000 10 10
Código
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
#include <rtl-sdr.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <math.h> #define DEFAULT_START_HZ 200000000ULL #define DEFAULT_END_HZ 400000000ULL #define DEFAULT_STEP_HZ 100000ULL /* 100 kHz */ #define DEFAULT_SAMPLE_RATE 2400000U #define DEFAULT_GAIN_TENTHS_DB 0 /* 0 = auto */ #define DEFAULT_MARGIN_DB 6.0f #define BUFFER_SIZE 16384 #define DISCARD_READS 2 #define MEASURE_READS 4 static float db_from_power(float p) { if (p < 1e-12f) p = 1e-12f; return 10.0f * log10f(p); } static float measure_block_power_db(rtlsdr_dev_t *dev, uint8_t *buffer, int *n_read_out) { double acc = 0.0; int total_iq = 0; int n_read = 0; for (int r = 0; r < MEASURE_READS; r++) { if (rtlsdr_read_sync(dev, buffer, BUFFER_SIZE, &n_read) < 0 || n_read <= 0) { return -999.0f; } for (int i = 0; i + 1 < n_read; i += 2) { float I = ((float)buffer[i] - 127.5f) / 128.0f; float Q = ((float)buffer[i + 1] - 127.5f) / 128.0f; acc += (double)(I * I + Q * Q); total_iq++; } } if (n_read_out) *n_read_out = n_read; if (total_iq <= 0) return -999.0f; float avg_power = (float)(acc / total_iq); return db_from_power(avg_power); } int main(int argc, char **argv) { uint64_t start_hz = DEFAULT_START_HZ; uint64_t end_hz = DEFAULT_END_HZ; uint64_t step_hz = DEFAULT_STEP_HZ; uint32_t sample_rate = DEFAULT_SAMPLE_RATE; int gain_tenths_db = DEFAULT_GAIN_TENTHS_DB; float margin_db = DEFAULT_MARGIN_DB; if (argc > 1) start_hz = strtoull(argv[1], NULL, 10); if (argc > 2) end_hz = strtoull(argv[2], NULL, 10); if (argc > 3) step_hz = strtoull(argv[3], NULL, 10); if (argc > 4) gain_tenths_db = atoi(argv[4]); if (argc > 5) margin_db = strtof(argv[5], NULL); if (start_hz >= end_hz) { fprintf(stderr, "Error: start_hz debe ser menor que end_hz\n"); return 1; } if (step_hz == 0) { fprintf(stderr, "Error: step_hz no puede ser 0\n"); return 1; } rtlsdr_dev_t *dev = NULL; if (rtlsdr_open(&dev, 0) < 0) { fprintf(stderr, "No se pudo abrir RTL-SDR\n"); return 1; } if (rtlsdr_set_sample_rate(dev, sample_rate) < 0) { fprintf(stderr, "No se pudo configurar sample rate\n"); rtlsdr_close(dev); return 1; } if (gain_tenths_db <= 0) { rtlsdr_set_tuner_gain_mode(dev, 0); } else { rtlsdr_set_tuner_gain_mode(dev, 1); rtlsdr_set_tuner_gain(dev, gain_tenths_db); } uint8_t buffer[BUFFER_SIZE]; int n_read = 0; fprintf(stderr, "Escaneando desde %llu Hz hasta %llu Hz | paso=%llu Hz | gain=%d | margen=%.1f dB\n", (unsigned long long)start_hz, (unsigned long long)end_hz, (unsigned long long)step_hz, gain_tenths_db, margin_db); /* Calibración inicial de ruido en la primera frecuencia */ if (rtlsdr_set_center_freq(dev, (uint32_t)start_hz) < 0) { fprintf(stderr, "No se pudo fijar frecuencia inicial\n"); rtlsdr_close(dev); return 1; } rtlsdr_reset_buffer(dev); for (int i = 0; i < DISCARD_READS; i++) { if (rtlsdr_read_sync(dev, buffer, BUFFER_SIZE, &n_read) < 0) { fprintf(stderr, "Error en lectura de descarte\n"); rtlsdr_close(dev); return 1; } } float baseline_db = measure_block_power_db(dev, buffer, &n_read); if (baseline_db < -900.0f) { fprintf(stderr, "No se pudo medir ruido inicial\n"); rtlsdr_close(dev); return 1; } fprintf(stderr, "Ruido inicial: %.2f dB\n", baseline_db); fprintf(stderr, "Umbral inicial: %.2f dB\n\n", baseline_db + margin_db); int detections = 0; for (uint64_t freq = start_hz; freq <= end_hz; freq += step_hz) { if (rtlsdr_set_center_freq(dev, (uint32_t)freq) < 0) { fprintf(stderr, "No se pudo fijar frecuencia %llu\n", (unsigned long long)freq); continue; } rtlsdr_reset_buffer(dev); for (int i = 0; i < DISCARD_READS; i++) { if (rtlsdr_read_sync(dev, buffer, BUFFER_SIZE, &n_read) < 0) { fprintf(stderr, "Error en lectura de descarte en %llu\n", (unsigned long long)freq); break; } } float power_db = measure_block_power_db(dev, buffer, &n_read); if (power_db < -900.0f) continue; float threshold_db = baseline_db + margin_db; if (power_db > threshold_db) { printf("DETECTADO | frecuencia=%llu Hz | potencia=%.2f dB | umbral=%.2f dB\n", (unsigned long long)freq, power_db, threshold_db); fflush(stdout); detections++; } else { /* Adaptación suave del ruido solo si no estamos detectando */ baseline_db = 0.98f * baseline_db + 0.02f * power_db; } } if (detections == 0) { printf("No se detectó potencia por encima del umbral en el rango.\n"); } else { printf("\nTotal detecciones: %d\n", detections); } rtlsdr_close(dev); return 0; } |

