Arduino Dragino Lora shield (Semtech SX1278 chip) can tune into frequency quite fast. Fasthop feature works at best in OOK continuous mode.
RegPllHop (0x44) bit 7:
Bypasses the main state machine for a quick frequency hop. Writing RegFrfLsb will trigger the frequency change.
1 -> Frf is validated triggered when RegFrfLsb is written.

1. set FastHopOn=1
2. set new Frf (*)
3. wait for TS_HOP
TS_HOP = Frequency synthesizer hop time at most 10 kHz away from the target frequency.
(*) RegFrfLsb must be written to trigger a frequency change.

fasthop-ook-433.jpg

SX1278 library: https://github.com/open-electronics/LoRa/releases

SX1278 datasheet: http://www.semtech.com/apps/filedown/down.php?file=sx1276_77_78_79.pdf

#include <SX1278.h>

#define SERIAL_SPEED        9600
#define F_START             433           // start freq
#define F_STEP              0.025         // 25 kHz step
#define F_CH                50            // channels to rx hop
#define BPS                 1200
#define STATE_STANDBY       1
#define STATE_FSRX          4
#define STATE_RX            5
#define H_DELAY             2
#define M_DELAY             10
#define L_DELAY             100
#define SX_BEGIN            "SX.begin"
#define SX_BITRATE          "SX.readBPS "
#define SX_FREQ             "SX.readFreq "
#define RSSI_THRESHOLD      -80             // dBm
#define CH_FILTER_BW        B00001100       // 25 kHz

#define RegRssiConfig       0x0e
#define RegRxBw             0x12
#define RegPacketConfig1    0x30

#define RegOpMode           0x01
#define RegPaRamp           0x0a
#define RegRssiThresh       0x10
#define RegOokPeak          0x14
#define RegPreambleDetect   0x1f
#define RegSyncConfig       0x27
#define RegPacketConfig2    0x31
#define RegIrqFlags1        0x3e
#define RegIrqFlags2        0x3f
#define RegPllHop           0x44

bool rx = false;

void setup() {
  Serial.begin(SERIAL_SPEED);
  if (SX.begin()) {
    Serial.println(F(SX_BEGIN));
    delay(M_DELAY);
    SX.startModeFSKOOK();
    // OOK
    byte b = SX.SPIread(RegOpMode);
    bitClear(b, 6);
    bitSet(b, 5);
    SX.SPIwrite(RegOpMode, b);

    fastHop(0);
    SX.setFreq(F_START);
    Serial.print(F(SX_FREQ));
    Serial.println(SX.readFreq(), DEC);
    SX.setBPS(BPS);
    Serial.print(F(SX_BITRATE));
    Serial.println(SX.readBPS(), DEC);

    // Channel filter bandwidth control
    SX.SPIwrite(RegRxBw, CH_FILTER_BW);
    
    // Bits 7-6: AutoRestartRxMode, 01 -> On, without waiting for the PLL to re-lock
    // Bit 4: Enables the Sync word generation and detection: 0 -> Off, 1 -> On
    // Bit 5: Sets the polarity of the Preamble. 0 -> 0xAA, 1 -> 0x55
    // Bits 2-0: Size of the Sync word (SyncSize + 1)
    b = SX.SPIread(RegSyncConfig);
    bitClear(b, 7);
    bitSet(b, 6);
    bitClear(b, 4);
    bitClear(b, 5);
    bitClear(b, 2);
    bitClear(b, 1);
    bitClear(b, 0);
    SX.SPIwrite(RegSyncConfig, b);

    // Bits 6-5: Defines DC-free encoding/decoding performed:
    // 00 -> none, 01 -> manchester, 10 -> whitening
    // Bit 7: packet format, 0 -> fixed length, 1 -> variable length
    // Bit 4: crc calc/check, 0 -> off, 1 -> on
    // Bits 2-1: Defines address based filtering in Rx: 00 -> None (Off)
    // Bit 3: Defines the behavior of the packet handler when CRC check fails:
    // 0 -> Clear FIFO and restart new packet reception. No PayloadReady interrupt issued.
    // 1 -> Do not clear FIFO. PayloadReady interrupt issued.
    // Bit 0: Selects the CRC and whitening algorithms:
    // 0 -> CCITT CRC implementation with standard whitening
    // 1 -> IBM CRC implementation with alternate whitening
    b = 0;
    SX.SPIwrite(RegPacketConfig1, b);

    // Bits 6-5: FSK data shaping:
    // 00 -> no shaping, 01 -> Gaussian filter BT = 1.0
    // 10 -> Gaussian filter BT = 0.5, 11 -> Gaussian filter BT = 0.3
    // Bits 3-0: Rise/Fall time of ramp up/down in FSK:
    // 1001 -> 40 us
    b = SX.SPIread(RegPaRamp);
    bitClear(b, 6);
    bitClear(b, 5);
    bitSet(b, 3);
    bitClear(b, 2);
    bitSet(b, 0);
    SX.SPIwrite(RegPaRamp, b);

    // Data processing mode: 0 -> Continuous mode, 1 -> Packet mode
    b = SX.SPIread(RegPacketConfig2);
    bitClear(b, 6);
    SX.SPIwrite(RegPacketConfig2, b);

    // RSSI smoothing.
    // Defines the number of samples taken to average the RSSI result. 001 -> 4 samples
    b = SX.SPIread(RegRssiConfig);
    bitClear(b, 2);
    bitClear(b, 1);
    bitSet(b, 0);
    SX.SPIwrite(RegRssiConfig, b);

    SX.SPIwrite(RegRssiThresh, RSSI_THRESHOLD);

    // Bit 5: enables the Bit Synchronizer:
    // 0 -> bit sync disabled (not possible in packet mode), 1 -> bit sync enabled
    b = SX.SPIread(RegOokPeak);
    bitClear(b, 5);
    SX.SPIwrite(RegOokPeak, b);

    // RegPreambleDetect (0x1f). Enables Preamble detector when set to 1.
    // The AGC settings supersede this bit during the startup / AGC phase.
    // Bit 7: 0 -> turned off, 1 -> turned on
    // Bits 6-5: Number of Preamble bytes to detect to trigger an interrupt.
    // 00 -> 1 byte, 10 -> 3 bytes, 01 -> 2 bytes
    b = SX.SPIread(RegPreambleDetect);
    bitClear(b, 7);
    bitClear(b, 6);
    bitClear(b, 5);
    SX.SPIwrite(RegPreambleDetect, b);

    clearFifoAndFlags();

    SX.setState(STATE_FSRX);
    delay(L_DELAY);
    SX.setState(STATE_RX);
    delay(M_DELAY);
 
    rx = true;
  }
}

void loop() {
  if (rx) {
    float f = F_START;
    for (int c = 0; c < F_CH; c++) {
      fastHop(1);
      SX.setFreq(f);
      delay(H_DELAY);

      float rssi = SX.readRSSIval();
      if (rssi > RSSI_THRESHOLD) {
        Serial.print(f, DEC);
        Serial.print("\t");
        Serial.println(rssi, DEC);
      }

      f = f + F_STEP;
    }
  }
}

void clearFifoAndFlags() {
  // Flag(s) and FIFO are cleared when this bit is set
  byte b = SX.SPIread(RegIrqFlags2);
  bitSet(b, 4);
  SX.SPIwrite(RegIrqFlags2, b);
  delay(M_DELAY);
}

void fastHop(int val) {
  byte b = SX.SPIread(RegPllHop);
  bitWrite(b, 7, val);
  SX.SPIwrite(RegPllHop, b);
}