diff --git a/firmware/application/apps/analog_audio_app.cpp b/firmware/application/apps/analog_audio_app.cpp
index 3ac619bb2736da2894edabf275a3e5afd0aedf32..448ed602a25aa4bbf339fa7747faed64ebae5178 100644
--- a/firmware/application/apps/analog_audio_app.cpp
+++ b/firmware/application/apps/analog_audio_app.cpp
@@ -103,7 +103,7 @@ AnalogAudioView::AnalogAudioView(
 		&waterfall,
 	});
 	
-	exit_on_squelch = eos;
+	//exit_on_squelch = eos;
 
 	field_frequency.set_value(receiver_model.tuning_frequency());
 	field_frequency.set_step(receiver_model.frequency_step());
@@ -332,9 +332,9 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
 	}
 }
 
-void AnalogAudioView::squelched() {
+/*void AnalogAudioView::squelched() {
 	if (exit_on_squelch) nav_.pop();
-}
+}*/
 
 void AnalogAudioView::handle_coded_squelch(const uint32_t value) {
 	float diff, min_diff = value;
diff --git a/firmware/application/apps/analog_audio_app.hpp b/firmware/application/apps/analog_audio_app.hpp
index 9f879384829dd185eb45c3d6f125e27f1744cd36..58c1fd5037260a1cdb7acdeb0fc9c200ccd59aa4 100644
--- a/firmware/application/apps/analog_audio_app.hpp
+++ b/firmware/application/apps/analog_audio_app.hpp
@@ -113,7 +113,7 @@ private:
 	const Rect nbfm_view_rect { 0 * 8, 1 * 16, 18 * 8, 1 * 16 };
 
 	NavigationView& nav_;
-	bool exit_on_squelch { false };
+	//bool exit_on_squelch { false };
 	
 	RSSI rssi {
 		{ 21 * 8, 0, 6 * 8, 4 },
@@ -188,16 +188,16 @@ private:
 
 	void update_modulation(const ReceiverModel::Mode modulation);
 	
-	void squelched();
+	//void squelched();
 	void handle_coded_squelch(const uint32_t value);
 	
-	MessageHandlerRegistration message_handler_squelch_signal {
+	/*MessageHandlerRegistration message_handler_squelch_signal {
 		Message::ID::RequestSignal,
 		[this](const Message* const p) {
 			(void)p;
 			this->squelched();
 		}
-	};
+	};*/
 	
 	MessageHandlerRegistration message_handler_coded_squelch {
 		Message::ID::CodedSquelch,
diff --git a/firmware/application/apps/ui_adsb_tx.cpp b/firmware/application/apps/ui_adsb_tx.cpp
index 94da234360b1583d89492fdaf6b9dd87fb584ad6..49e847de11f1df068f986a49e814e52f685382e9 100644
--- a/firmware/application/apps/ui_adsb_tx.cpp
+++ b/firmware/application/apps/ui_adsb_tx.cpp
@@ -270,12 +270,11 @@ void ADSBTXThread::run() {
 		
 		chThdSleepMilliseconds(50);
 		
-		if (frame_index == frames_.size()) {
+		frame_index++;
+		if (frame_index >= frames_.size()) {
 			frame_index = 0;
 			//if (regen)
 			//	regen--;
-		} else {
-			frame_index++;
 		}
 	}
 }
diff --git a/firmware/application/apps/ui_scanner.cpp b/firmware/application/apps/ui_scanner.cpp
index 2dda20cf359967c24be318946fc5c6984c968776..5f854ef34059c761f6acc320e37a948c0b7a4416 100644
--- a/firmware/application/apps/ui_scanner.cpp
+++ b/firmware/application/apps/ui_scanner.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
- * Copyright (C) 2016 Furrtek
+ * Copyright (C) 2018 Furrtek
  *
  * This file is part of PortaPack.
  *
@@ -24,34 +24,144 @@
 
 #include "baseband_api.hpp"
 #include "string_format.hpp"
+#include "audio.hpp"
 
 using namespace portapack;
 
 namespace ui {
 
+ScannerThread::ScannerThread(
+	std::vector<rf::Frequency> frequency_list
+) : frequency_list_ {  std::move(frequency_list) }
+{
+	thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ScannerThread::static_fn, this);
+}
+
+ScannerThread::~ScannerThread() {
+	if( thread ) {
+		chThdTerminate(thread);
+		chThdWait(thread);
+		thread = nullptr;
+	}
+}
+
+void ScannerThread::set_scanning(const bool v) {
+	_scanning = v;
+}
+
+msg_t ScannerThread::static_fn(void* arg) {
+	auto obj = static_cast<ScannerThread*>(arg);
+	obj->run();
+	return 0;
+}
+
+void ScannerThread::run() {
+	RetuneMessage message { };
+	uint32_t frequency_index = 0;
+	
+	while( !chThdShouldTerminate() ) {
+		if (_scanning) {
+			// Retune
+			receiver_model.set_tuning_frequency(frequency_list_[frequency_index]);
+			
+			message.range = frequency_index;
+			EventDispatcher::send_message(message);
+			
+			
+			frequency_index++;
+			if (frequency_index >= frequency_list_.size())
+				frequency_index = 0;
+		}
+		
+		chThdSleepMilliseconds(50);
+	}
+}
+
+void ScannerView::handle_retune(uint32_t i) {
+	text_cycle.set(to_string_dec_uint(i) + "/" + to_string_dec_uint(frequency_list.size()));
+}
+
 void ScannerView::focus() {
-	button.focus();
+	field_lna.focus();
 }
 
 ScannerView::~ScannerView() {
-	//receiver_model.disable();
-	//baseband::shutdown();
+	audio::output::stop();
+	receiver_model.disable();
+	baseband::shutdown();
 }
 
 ScannerView::ScannerView(
-	NavigationView& nav
+	NavigationView&
 )
 {
-	//baseband::run_image(portapack::spi_flash::image_tag_wideband_spectrum);
-	
 	add_children({
 		&labels,
-		&button
+		&field_lna,
+		&field_vga,
+		&field_rf_amp,
+		&field_volume,
+		&field_squelch,
+		//&record_view,
+		&text_cycle,
+		//&waterfall,
 	});
 	
-	button.on_select = [this, &nav](Button&) {
-		nav.pop();
+	// DEBUG
+	frequency_list.push_back(466025000);
+	frequency_list.push_back(466050000);
+	frequency_list.push_back(466075000);
+	frequency_list.push_back(466175000);
+	frequency_list.push_back(466206250);
+	frequency_list.push_back(466231250);
+	
+	field_squelch.on_change = [this](int32_t v) {
+		squelch = v;
+	};
+	field_squelch.set_value(30);
+
+	field_volume.set_value((receiver_model.headphone_volume() - audio::headphone::volume_range().max).decibel() + 99);
+	field_volume.on_change = [this](int32_t v) {
+		this->on_headphone_volume_changed(v);
 	};
+	
+	audio::output::start();
+	
+	audio::output::mute();
+	baseband::run_image(portapack::spi_flash::image_tag_nfm_audio);
+	receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
+	receiver_model.set_sampling_rate(3072000);
+	receiver_model.set_baseband_bandwidth(1750000);
+	receiver_model.enable();
+	receiver_model.set_squelch_level(0);
+	receiver_model.set_nbfm_configuration(2);	// 16k
+	audio::output::unmute();
+	
+	// TODO: Scanning thread here
+	scan_thread = std::make_unique<ScannerThread>(frequency_list);
+}
+
+void ScannerView::on_statistics_update(const ChannelStatistics& statistics) {
+	int32_t max_db = statistics.max_db;
+	
+	if (timer < 6)
+		timer++;
+	
+	if (max_db < -squelch) {
+		if (timer == 5) {
+			//audio::output::stop();
+			scan_thread->set_scanning(true);
+		}
+	} else {
+		//audio::output::start();
+		scan_thread->set_scanning(false);
+		timer = 0;
+	}
+}
+
+void ScannerView::on_headphone_volume_changed(int32_t v) {
+	const auto new_volume = volume_t::decibel(v - 99) + audio::headphone::volume_range().max;
+	receiver_model.set_headphone_volume(new_volume);
 }
 
 } /* namespace ui */
diff --git a/firmware/application/apps/ui_scanner.hpp b/firmware/application/apps/ui_scanner.hpp
index b408618eaba8ea1dec056a11b8a21ddd5e83ac21..67cf7a4ab9a67c28ebb60128f7b7958c369f1cb2 100644
--- a/firmware/application/apps/ui_scanner.hpp
+++ b/firmware/application/apps/ui_scanner.hpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
- * Copyright (C) 2016 Furrtek
+ * Copyright (C) 2018 Furrtek
  *
  * This file is part of PortaPack.
  *
@@ -22,16 +22,37 @@
 
 #include "receiver_model.hpp"
 
-#include "spectrum_color_lut.hpp"
-
 #include "ui_receiver.hpp"
 #include "ui_font_fixed_8x16.hpp"
 
 namespace ui {
 
+class ScannerThread {
+public:
+	ScannerThread(std::vector<rf::Frequency> frequency_list);
+	~ScannerThread();
+	
+	void set_scanning(const bool v);
+
+	ScannerThread(const ScannerThread&) = delete;
+	ScannerThread(ScannerThread&&) = delete;
+	ScannerThread& operator=(const ScannerThread&) = delete;
+	ScannerThread& operator=(ScannerThread&&) = delete;
+
+private:
+	std::vector<rf::Frequency> frequency_list_ { };
+	Thread* thread { nullptr };
+	
+	bool _scanning { true };
+
+	static msg_t static_fn(void* arg);
+	
+	void run();
+};
+
 class ScannerView : public View {
 public:
-	ScannerView(NavigationView& nav);
+	ScannerView(NavigationView&);
 	~ScannerView();
 	
 	void focus() override;
@@ -39,13 +60,68 @@ public:
 	std::string title() const override { return "Scanner"; };
 
 private:
+	void on_statistics_update(const ChannelStatistics& statistics);
+	void on_headphone_volume_changed(int32_t v);
+	void handle_retune(uint32_t i);
+	
+	std::vector<rf::Frequency> frequency_list { };
+	int32_t squelch { 0 };
+	uint32_t timer { 0 };
+	
 	Labels labels {
-		{ { 1 * 8, 0 }, "Work in progress...", Color::light_grey() }
+		{ { 0 * 8, 0 * 16 }, "LNA:   VGA:   AMP:  VOL:", Color::light_grey() },
+		{ { 0 * 8, 1 * 16 }, "SQUELCH:  /99", Color::light_grey() },
+		{ { 0 * 8, 3 * 16 }, "Work in progress...", Color::light_grey() }
+	};
+	
+	LNAGainField field_lna {
+		{ 4 * 8, 0 * 16 }
+	};
+
+	VGAGainField field_vga {
+		{ 11 * 8, 0 * 16 }
+	};
+	
+	RFAmpField field_rf_amp {
+		{ 18 * 8, 0 * 16 }
+	};
+	
+	NumberField field_volume {
+		{ 24 * 8, 0 * 16 },
+		2,
+		{ 0, 99 },
+		1,
+		' ',
+	};
+	
+	NumberField field_squelch {
+		{ 8 * 8, 1 * 16 },
+		2,
+		{ 0, 99 },
+		1,
+		' ',
+	};
+	
+	Text text_cycle {
+		{ 0, 5 * 16, 240, 16 },
+		"--/--"
+	};
+	
+	std::unique_ptr<ScannerThread> scan_thread { };
+	
+	MessageHandlerRegistration message_handler_retune {
+		Message::ID::Retune,
+		[this](const Message* const p) {
+			const auto message = *reinterpret_cast<const RetuneMessage*>(p);
+			this->handle_retune(message.range);
+		}
 	};
 	
-	Button button {
-		{ 60, 64, 120, 32 },
-		"Exit"
+	MessageHandlerRegistration message_handler_stats {
+		Message::ID::ChannelStatistics,
+		[this](const Message* const p) {
+			this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
+		}
 	};
 };