/**
 * EXPERIMENT 3: Sub-GHz RF Spectrum Analyzer
 *
 * Purpose: Visualize RF spectrum activity on CC1101
 * Features: Sub-GHz radio, real-time graphing, frequency scanning
 * Difficulty: Advanced
 *
 * What it does:
 * - Scans across Sub-GHz frequencies (300-928 MHz)
 * - Displays signal strength as a live spectrum graph
 * - Detects and marks peak signals
 * - Adjustable frequency range and sensitivity
 * - Saves capture data to file
 */

var subghz = require("subghz");
var display = require("display");
var keyboard = require("keyboard");
var storage = require("storage");

// Colors
var WHITE = display.color(255, 255, 255);
var BLACK = display.color(0, 0, 0);
var GREEN = display.color(0, 255, 0);
var YELLOW = display.color(255, 255, 0);
var RED = display.color(255, 0, 0);
var BLUE = display.color(0, 150, 255);
var CYAN = display.color(0, 255, 255);

var SCREEN_WIDTH = 320;
var SCREEN_HEIGHT = 170;
var GRAPH_HEIGHT = 100;
var GRAPH_Y_START = 50;

// Frequency configuration (in Hz)
var presets = [
    { name: "315MHz", start: 314000000, end: 316000000, step: 50000 },
    { name: "433MHz", start: 432000000, end: 434000000, step: 50000 },
    { name: "868MHz", start: 867000000, end: 869000000, step: 50000 },
    { name: "915MHz", start: 914000000, end: 916000000, step: 50000 }
];

var currentPreset = 1; // Default to 433MHz
var scanData = [];
var maxRssi = -120;
var minRssi = -30;
var running = true;

// Helper: Draw frequency label
function formatFreq(freq) {
    var mhz = freq / 1000000;
    return mhz.toFixed(2) + "M";
}

// Draw header
function drawHeader() {
    display.fillRect(0, 0, SCREEN_WIDTH, 20, BLACK);
    var preset = presets[currentPreset];
    display.drawText("RF Spectrum: " + preset.name, 5, 5, CYAN);
    display.drawText("RSSI Range: " + minRssi + " to " + maxRssi, 160, 5, YELLOW);
}

// Draw frequency axis
function drawFreqAxis() {
    var preset = presets[currentPreset];
    var y = GRAPH_Y_START + GRAPH_HEIGHT + 5;

    display.fillRect(0, y, SCREEN_WIDTH, 15, BLACK);

    // Start frequency
    display.drawText(formatFreq(preset.start), 5, y, WHITE);

    // Middle frequency
    var midFreq = (preset.start + preset.end) / 2;
    display.drawText(formatFreq(midFreq), SCREEN_WIDTH / 2 - 20, y, WHITE);

    // End frequency
    display.drawText(formatFreq(preset.end), SCREEN_WIDTH - 50, y, WHITE);
}

// Draw spectrum graph
function drawSpectrum() {
    // Clear graph area
    display.fillRect(0, GRAPH_Y_START, SCREEN_WIDTH, GRAPH_HEIGHT, BLACK);

    // Draw grid lines
    var i;
    for (i = 0; i < 5; i = i + 1) {
        var y = GRAPH_Y_START + (i * (GRAPH_HEIGHT / 4));
        var gridColor = display.color(30, 30, 30);
        var j;
        for (j = 0; j < SCREEN_WIDTH; j = j + 2) {
            display.drawPixel(j, y, gridColor);
        }
    }

    // Draw spectrum data
    if (scanData.length > 0) {
        var xScale = SCREEN_WIDTH / scanData.length;

        for (i = 0; i < scanData.length; i = i + 1) {
            var rssi = scanData[i];

            // Normalize RSSI to graph height
            var normalized = (rssi - minRssi) / (maxRssi - minRssi);
            if (normalized < 0) {
                normalized = 0;
            }
            if (normalized > 1) {
                normalized = 1;
            }

            var barHeight = normalized * GRAPH_HEIGHT;
            var x = i * xScale;
            var y = GRAPH_Y_START + GRAPH_HEIGHT - barHeight;

            // Color based on signal strength
            var barColor;
            if (rssi > -60) {
                barColor = RED;
            } else if (rssi > -80) {
                barColor = YELLOW;
            } else {
                barColor = GREEN;
            }

            // Draw bar
            display.fillRect(x, y, xScale, barHeight, barColor);
        }
    }
}

// Perform spectrum scan
function performScan() {
    var preset = presets[currentPreset];
    var freq = preset.start;
    var samples = [];
    var sampleCount = 0;


    scanData = [];

    // Scan across frequency range
    while (freq <= preset.end) {
        // Set frequency
        subghz.setFrequency(freq);
        delay(10); // Settle time

        // Read RSSI
        var rssi = subghz.getRSSI();
        scanData.push(rssi);

        // Update max/min for auto-scaling
        if (sampleCount === 0 || rssi > maxRssi) {
            maxRssi = rssi;
        }
        if (sampleCount === 0 || rssi < minRssi) {
            minRssi = rssi;
        }

        freq = freq + preset.step;
        sampleCount = sampleCount + 1;

        // Limit samples to screen width
        if (sampleCount >= SCREEN_WIDTH) {
            break;
        }
    }

}

// Save scan data
function saveScan() {
    try {
        var preset = presets[currentPreset];
        var timestamp = now();
        var filename = "/data/rf_scan_" + preset.name + "_" + timestamp + ".txt";

        var data = "RF Spectrum Scan\n";
        data = data + "Band: " + preset.name + "\n";
        data = data + "Start: " + preset.start + " Hz\n";
        data = data + "End: " + preset.end + " Hz\n";
        data = data + "Step: " + preset.step + " Hz\n";
        data = data + "Timestamp: " + timestamp + "\n\n";

        var i;
        var freq = preset.start;
        for (i = 0; i < scanData.length; i = i + 1) {
            data = data + freq + "," + scanData[i] + "\n";
            freq = freq + preset.step;
        }

        storage.write(filename, data);

        // Show confirmation
        display.fillRect(80, 60, 160, 40, BLACK);
        display.drawRect(80, 60, 160, 40, GREEN);
        display.drawText("Scan Saved!", 120, 75, GREEN);
        delay(1000);

    } catch (e) {
    }
}

// Main program
display.fill(BLACK);

// Initial scan
performScan();

// Main loop
while (running) {
    drawHeader();
    drawSpectrum();
    drawFreqAxis();

    // Footer instructions
    display.fillRect(0, 155, SCREEN_WIDTH, 15, BLACK);
    display.drawText("OK:Scan LEFT/RIGHT:Band S:Save BACK:Exit", 5, 155, CYAN);

    // Handle input
    if (keyboard.getSelPress()) {
        performScan();
        while (keyboard.getSelPress()) {
            delay(10);
        }
    }

    if (keyboard.isPressed("LEFT")) {
        currentPreset = currentPreset - 1;
        if (currentPreset < 0) {
            currentPreset = presets.length - 1;
        }
        performScan();
        while (keyboard.isPressed("LEFT")) {
            delay(10);
        }
    }

    if (keyboard.isPressed("RIGHT")) {
        currentPreset = currentPreset + 1;
        if (currentPreset >= presets.length) {
            currentPreset = 0;
        }
        performScan();
        while (keyboard.isPressed("RIGHT")) {
            delay(10);
        }
    }

    if (keyboard.isPressed("S")) {
        saveScan();
        while (keyboard.isPressed("S")) {
            delay(10);
        }
    }

    if (keyboard.getEscPress()) {
        display.fill(BLACK);
        display.drawText("Shutting down...", 100, 80, WHITE);
        subghz.sleep(); // Power down radio
        delay(500);
        running = false;
    }

    delay(100);
}

