diff --git a/firmware/application/apps/ui_bht_tx.cpp b/firmware/application/apps/ui_bht_tx.cpp
index 8b0d22a584ca90b3b463b687a21cf19217a1212f..acc75f8fe8d2e2872294568002e30d75163cc754 100644
--- a/firmware/application/apps/ui_bht_tx.cpp
+++ b/firmware/application/apps/ui_bht_tx.cpp
@@ -37,119 +37,111 @@ void BHTView::focus() {
 void BHTView::start_tx() {
 	baseband::shutdown();
 	
-	if (tx_type == XYLOS) {
+	transmitter_model.set_rf_amp(true);
+	transmitter_model.set_baseband_bandwidth(1750000);
+	
+	if (target_system == XYLOS) {
 		
 		baseband::run_image(portapack::spi_flash::image_tag_tones);
 		
 		view_xylos.generate_message();
 		
-		//if (view_xylos.tx_mode == XylosView::tx_modes::SINGLE)
-			progressbar.set_max(20);
-		//else if (view_xylos.tx_mode == XylosView::tx_modes::SEQUENCE)
-		//	progressbar.set_max(20 * XY_SEQ_COUNT);
+		//if (tx_mode == SINGLE) {
+			progressbar.set_max(XY_TONE_COUNT);
+		/*} else if (tx_mode == SCAN) {
+			progressbar.set_max(XY_TONE_COUNT * view_xylos.get_scan_remaining());
+		}*/
 		
 		transmitter_model.set_sampling_rate(TONES_SAMPLERATE);
-		transmitter_model.set_rf_amp(true);
-		transmitter_model.set_baseband_bandwidth(1750000);
 		transmitter_model.enable();
 		
 		// Setup tones
 		for (size_t c = 0; c < ccir_deltas.size(); c++)
-			baseband::set_tone(c, ccir_deltas[c], XY_TONE_LENGTH);
+			baseband::set_tone(c, ccir_deltas[c], XY_TONE_DURATION);
 		
 		baseband::set_tones_config(transmitter_model.channel_bandwidth(), XY_SILENCE, XY_TONE_COUNT, false, false);
 		
-	} else if (tx_type == EPAR) {
+	} else if (target_system == EPAR) {
 		
 		baseband::run_image(portapack::spi_flash::image_tag_ook);
 		
-		size_t bitstream_length = view_EPAR.generate_message();
+		auto bitstream_length = view_EPAR.generate_message();
 		
-		progressbar.set_max(2 * 26);
+		//if (tx_mode == SINGLE) {
+			progressbar.set_max(2 * EPAR_REPEAT_COUNT);
+		/*} else if (tx_mode == SCAN) {
+			progressbar.set_max(2 * EPAR_REPEAT_COUNT * view_EPAR.get_scan_remaining());
+		}*/
 		
 		transmitter_model.set_sampling_rate(OOK_SAMPLERATE);
-		transmitter_model.set_rf_amp(true);
-		transmitter_model.set_baseband_bandwidth(1750000);
 		transmitter_model.enable();
 
 		baseband::set_ook_data(
 			bitstream_length,
-			OOK_SAMPLERATE / 580,
-			26,
+			EPAR_BIT_DURATION,
+			EPAR_REPEAT_COUNT,
 			encoder_defs[ENCODER_UM3750].pause_symbols
 		);
 	}
 }
 
+void BHTView::stop_tx() {
+	transmitter_model.disable();
+	baseband::shutdown();
+	tx_mode = IDLE;
+	tx_view.set_transmitting(false);
+	progressbar.set_value(0);
+}
+
 void BHTView::on_tx_progress(const uint32_t progress, const bool done) {
-	//if (view_xylos.tx_mode == XylosView::tx_modes::SINGLE) {
-	
-	if (done) {
-		transmitter_model.disable();
-		view_xylos.tx_mode = XylosView::tx_modes::IDLE;
-		tx_view.set_transmitting(false);
-	}
-	
-	if (tx_type == XYLOS) {
+	if (target_system == XYLOS) {
 		if (done) {
-			if (!checkbox_cligno.value()) {
-				view_xylos.tx_mode = XylosView::tx_modes::IDLE;
-				tx_view.set_transmitting(false);
-				progressbar.set_value(0);
-			} else {
-				chThdSleepMilliseconds(field_tempo.value() * 1000);	// Dirty :(
-				
-				view_xylos.flip_relays();
-				
-				start_tx();
+			if (tx_mode == SINGLE) {
+				if (checkbox_cligno.value()) {
+					// TODO: Thread !
+					chThdSleepMilliseconds(field_tempo.value() * 1000);	// Dirty :(
+					view_xylos.flip_relays();
+					start_tx();
+				} else
+					stop_tx();
+			} else if (tx_mode == SCAN) {
+				if (view_xylos.increment_address())
+					start_tx();
+				else
+					stop_tx();	// Reached end of scan range
 			}
 		} else
 			progressbar.set_value(progress);
-	} else if (tx_type == EPAR) {
+	} else if (target_system == EPAR) {
 		if (done) {
+			
 			if (!view_EPAR.half) {
-				view_EPAR.half = 1;
+				view_EPAR.half = true;
 				start_tx();		// Start second half of transmission
 			} else {
-				view_EPAR.half = 0;
-				progressbar.set_value(0);
-				if (checkbox_cligno.value()) {
-					chThdSleepMilliseconds(field_tempo.value() * 1000);	// Dirty :(
-					
-					view_EPAR.flip_relays();
-					
-					start_tx();
+				view_EPAR.half = false;
+				if (tx_mode == SINGLE) {
+					if (checkbox_cligno.value()) {
+						// TODO: Thread !
+						chThdSleepMilliseconds(field_tempo.value() * 1000);	// Dirty :(
+						view_EPAR.flip_relays();
+						start_tx();
+					} else
+						stop_tx();
+				} else if (tx_mode == SCAN) {
+					if (view_EPAR.increment_address())
+						start_tx();
+					else
+						stop_tx();	// Reached end of scan range
 				}
 			}
 		} else
-			progressbar.set_value((26 * view_EPAR.half) + progress);
+			progressbar.set_value(progress);
 	}
-	
-	/*} else if (view_xylos.tx_mode == XylosView::tx_modes::SEQUENCE) {
-		if (done) {
-			transmitter_model.disable();
-			
-			if (view_xylos.seq_index < (XY_SEQ_COUNT - 1)) {
-				for (c = 0; c < view_xylos.sequence_matin[view_xylos.seq_index].delay; c++)
-					chThdSleepMilliseconds(1000);
-				
-				view_xylos.seq_index++;
-				
-				start_tx();
-			} else {
-				progressbar.set_value(0);
-				view_xylos.tx_mode = XylosView::tx_modes::IDLE;
-				tx_view.set_transmitting(false);
-			}
-		} else {
-			progressbar.set_value((view_xylos.seq_index * 20) + progress);
-		}
-	}*/
 }
 
 BHTView::~BHTView() {
 	transmitter_model.disable();
-	baseband::shutdown();
 }
 
 BHTView::BHTView(NavigationView& nav) {
@@ -158,10 +150,10 @@ BHTView::BHTView(NavigationView& nav) {
 		&labels,
 		&view_xylos,
 		&view_EPAR,
+		&checkbox_scan,
 		&checkbox_cligno,
 		&field_tempo,
 		&progressbar,
-		&text_message,
 		&tx_view
 	});
 	
@@ -174,31 +166,42 @@ BHTView::BHTView(NavigationView& nav) {
 		};
 	};
 	
-	/*button_seq.on_select = [this, &nav](Button&) {
-		if (tx_mode == IDLE) {
-			seq_index = 0;
-			tx_mode = SEQUENCE;
-			tx_view.set_transmitting(true);
-			start_tx();
-		}
-	};*/
-	
 	tx_view.on_start = [this]() {
-		if (view_xylos.tx_mode == XylosView::tx_modes::IDLE) {
-			view_xylos.tx_mode = XylosView::tx_modes::SINGLE;
+		if (tx_mode == IDLE) {
+			if (checkbox_scan.value()) {
+				tx_mode = SCAN;
+			} else {
+				tx_mode = SINGLE;
+			}
+			
+			progressbar.set_value(0);
 			tx_view.set_transmitting(true);
-			tx_type = (tx_type_t)tab_view.selected();
+			target_system = (target_system_t)tab_view.selected();
+			view_EPAR.half = false;
+			
 			start_tx();
 		}
 	};
 	
 	tx_view.on_stop = [this]() {
-		transmitter_model.disable();
-		tx_view.set_transmitting(false);
-		view_xylos.tx_mode = XylosView::tx_modes::IDLE;
+		stop_tx();
 	};
 }
 
+bool EPARView::increment_address() {
+	auto city_code = field_city.value();
+	
+	if (city_code < EPAR_MAX_CITY) {
+		field_city.set_value(city_code + 1);
+		return true;
+	} else
+		return false;
+}
+
+uint32_t EPARView::get_scan_remaining() {
+	return EPAR_MAX_CITY - field_city.value();
+}
+
 void EPARView::flip_relays() {
 	// Invert first relay's state
 	relay_states[0].set_selected_index(relay_states[0].selected_index() ^ 1);
@@ -207,7 +210,7 @@ void EPARView::flip_relays() {
 size_t EPARView::generate_message() {
 	// R2, then R1
 	return gen_message_ep(field_city.value(), field_group.selected_index_value(),
-							1 - half, relay_states[half].selected_index());
+							half ? 0 : 1, relay_states[half].selected_index());
 }
 
 EPARView::EPARView(
@@ -219,18 +222,17 @@ EPARView::EPARView(
 	add_children({
 		&labels,
 		&field_city,
-		&field_group,
-		//&button_scan
+		&field_group
 	});
 
-	field_city.set_value(220);
+	field_city.set_value(0);
 	field_group.set_selected_index(2);
 	
 	field_city.on_change = [this](int32_t) { generate_message(); };
 	field_group.on_change = [this](size_t, int32_t) { generate_message(); };
 	
 	const auto relay_state_fn = [this](size_t, OptionsField::value_t) {
-		this->generate_message();
+		generate_message();
 	};
 	
 	size_t n = 0;
@@ -259,19 +261,25 @@ void XylosView::flip_relays() {
 		relay_states[0].set_selected_index(rs ^ 3);
 }
 
+bool XylosView::increment_address() {
+	auto city_code = field_city.value();
+	
+	if (city_code < XY_MAX_CITY) {
+		field_city.set_value(city_code + 1);
+		return true;
+	} else
+		return false;
+}
+
+uint32_t XylosView::get_scan_remaining() {
+	return XY_MAX_CITY - field_city.value();
+}
+
 void XylosView::generate_message() {
-	//if (tx_mode == SINGLE) {
-		//text_message.set(
-			gen_message_xy(field_header_a.value(), field_header_b.value(), field_city.value(), field_family.value(), 
-							checkbox_wcsubfamily.value(), field_subfamily.value(), checkbox_wcid.value(), field_receiver.value(),
-							relay_states[0].selected_index(), relay_states[1].selected_index(), 
-							relay_states[2].selected_index(), relay_states[3].selected_index());
-		//);
-	/*} else if (tx_mode == SEQUENCE) {
-		//text_message.set(
-			gen_message_xy(sequence_matin[seq_index].code);
-		//);
-	}*/
+	gen_message_xy(field_header_a.value(), field_header_b.value(), field_city.value(), field_family.value(), 
+					checkbox_wcsubfamily.value(), field_subfamily.value(), checkbox_wcid.value(), field_receiver.value(),
+					relay_states[0].selected_index(), relay_states[1].selected_index(), 
+					relay_states[2].selected_index(), relay_states[3].selected_index());
 }
 
 XylosView::XylosView(
@@ -300,7 +308,11 @@ XylosView::XylosView(
 	field_subfamily.set_value(1);
 	field_receiver.set_value(1);
 	
-	field_header_a.on_change = [this](int32_t) { generate_message(); };
+	const auto field_fn = [this](int32_t) {
+		generate_message();
+	};
+	
+	field_header_a.on_change = field_fn;
 	field_header_b.on_change = [this](int32_t) { generate_message(); };
 	field_city.on_change = [this](int32_t) { generate_message(); };
 	field_family.on_change = [this](int32_t) { generate_message(); };
@@ -321,7 +333,7 @@ XylosView::XylosView(
 	checkbox_wcid.set_value(true);
 	
 	const auto relay_state_fn = [this](size_t, OptionsField::value_t) {
-		this->generate_message();
+		generate_message();
 	};
 	
 	size_t n = 0;
diff --git a/firmware/application/apps/ui_bht_tx.hpp b/firmware/application/apps/ui_bht_tx.hpp
index b7ca6f2e6aa1549a711a385945082a5d804e662f..64cf838d462114838b6c2a528119272af63e22fe 100644
--- a/firmware/application/apps/ui_bht_tx.hpp
+++ b/firmware/application/apps/ui_bht_tx.hpp
@@ -34,8 +34,6 @@
 #include "encoders.hpp"
 #include "portapack.hpp"
 
-#define XY_SEQ_COUNT 14
-
 namespace ui {
 
 class XylosView : public View {
@@ -46,39 +44,9 @@ public:
 	
 	void flip_relays();
 	void generate_message();
+	bool increment_address();
+	uint32_t get_scan_remaining();
 	
-	enum tx_modes {
-		IDLE = 0,
-		SINGLE,
-		SEQUENCE
-	};
-	
-	tx_modes tx_mode = IDLE;
-	
-	uint32_t seq_index { 0 };
-	
-	struct sequence_t {
-		const std::string code;
-		const uint32_t delay;
-	};
-	
-	const sequence_t sequence_matin[XY_SEQ_COUNT] = {
-		{ "0000189000B1002B0000", 19 }, // 18:9:0:00	 R1=OFF (1)	
-		{ "0000189200B2110B0000", 16 },	// 18:9:2:00	 R1=ON  (4)	
-		{ "0000189200B1110B0000", 52 },	// 18:9:2:00	 R1=OFF (4)	
-		{ "0000189200B2110B0000", 17 },	// 18:9:2:00	 R1=ON  (4)	
-		{ "0000189200B1110B0000", 16 },	// 18:9:2:00	 R1=OFF (4)	
-		{ "0000189000B0012B0000", 22 },	// 18:9:0:00	 R3=OFF (2)	
-		{ "0000189200B1120B0000", 17 },	// 18:9:2:00	 R3=ON  (6)	
-		{ "0000189200B1110B0000", 17 },	// 18:9:2:00	 R3=OFF (6)	
-		{ "0000181AAAB1000B0000", 17 },	// 18:1:A:AA	 R1=OFF (10)	
-		{ "0000189400B1000B0000", 17 },	// 18:9:4:00	 R1=OFF (7)	
-		{ "0000189200B1120B0000", 14 },	// 18:9:2:00	 R3=ON  (6)	
-		{ "0000189200B1110B0000", 17 },	// 18:9:2:00	 R3=OFF (6)	
-		{ "0000181AAAB1000B0000", 17 },	// 18:1:A:AA	
-		{ "0000189400B0100B0000", 17 }	// 18:9:4:00	 R2=OFF (8)		
-	};
-
 private:
 	Labels labels {
 		{ { 8 * 8, 1 * 8 }, "Header:", Color::light_grey() },
@@ -107,7 +75,7 @@ private:
 	NumberField field_city {
 		{ 16 * 8, 3 * 8 },
 		2,
-		{ 0, 99 },
+		{ 0, XY_MAX_CITY },
 		1,
 		' '
 	};
@@ -154,11 +122,6 @@ private:
 		{ &bitmap_bulb_off, 1 },
 		{ &bitmap_bulb_on, 2 }
 	};
-	
-	Button button_seq {
-		{ 24 * 8, 1 * 8, 40, 32 },
-		"Seq"
-	};
 };
 
 class EPARView : public View {
@@ -169,8 +132,10 @@ public:
 	
 	void flip_relays();
 	size_t generate_message();
+	bool increment_address();
+	uint32_t get_scan_remaining();
 
-	size_t half { 0 };
+	bool half { false };
 	
 private:
 	Labels labels {
@@ -182,9 +147,9 @@ private:
 	NumberField field_city {
 		{ 16 * 8, 1 * 8 },
 		3,
-		{ 0, 255 },
+		{ 0, EPAR_MAX_CITY },
 		1,
-		' '
+		'0'
 	};
 	
 	OptionsField field_group {
@@ -204,11 +169,6 @@ private:
 		{ &bitmap_bulb_off, 0 },
 		{ &bitmap_bulb_on, 1 }
 	};
-	
-	Button button_scan {
-		{ 22 * 8, 1 * 8, 56, 32 },
-		"Scan"
-	};
 };
 
 class BHTView : public View {
@@ -223,15 +183,24 @@ public:
 private:
 	void on_tx_progress(const uint32_t progress, const bool done);
 	void start_tx();
+	void stop_tx();
 	
-	enum tx_type_t {
+	enum target_system_t {
 		XYLOS = 0,
 		EPAR = 1
 	};
 	
-	tx_type_t tx_type = { };
+	target_system_t target_system = { };
+	
+	enum tx_modes {
+		IDLE = 0,
+		SINGLE,
+		SCAN
+	};
+	
+	tx_modes tx_mode = IDLE;
 	
-	Rect view_rect = { 0, 3 * 8, 240, 192 };
+	Rect view_rect = { 0, 3 * 8, 240, 176 };
 	
 	XylosView view_xylos { view_rect };
 	EPARView view_EPAR { view_rect };
@@ -245,27 +214,29 @@ private:
 		{ { 29 * 8, 14 * 16 + 4 }, "s", Color::light_grey() }
 	};
 	
-	ProgressBar progressbar {
-		{ 1 * 8, 14 * 16, 20 * 8, 16 },
-	};
-	Text text_message {
-		{ 1 * 8, 15 * 16, 20 * 8, 16 },
-		""
+	Checkbox checkbox_scan {
+		{ 1 * 8, 25 * 8 },
+		4,
+		"Scan"
 	};
 	
 	Checkbox checkbox_cligno {
-		{ 22 * 8, 14 * 16 },
-		1,
-		"~"
+		{ 16 * 8, 25 * 8 },
+		6,
+		"Cligno"
 	};
 	NumberField field_tempo {
-		{ 27 * 8, 14 * 16 + 4 },
+		{ 26 * 8, 25 * 8 + 4 },
 		2,
 		{ 1, 99 },
 		1,
 		' '
 	};
 	
+	ProgressBar progressbar {
+		{ 0 * 8, 29 * 8, 30 * 8, 16 },
+	};
+	
 	TransmitterView tx_view {
 		16 * 16,
 		10000,
diff --git a/firmware/application/apps/ui_fileman.cpp b/firmware/application/apps/ui_fileman.cpp
index f57afb48d113687b7b8de731334334cc51517a8d..021c628e2f282a4d2c74ed649e457165bf8b7c4f 100644
--- a/firmware/application/apps/ui_fileman.cpp
+++ b/firmware/application/apps/ui_fileman.cpp
@@ -274,11 +274,17 @@ FileManagerView::FileManagerView(
 	add_children({
 		&menu_view,
 		&text_empty,
+		&labels,
+		&text_date,
 		&button_rename,
 		&button_new_dir,
 		&button_delete
 	});
 	
+	menu_view.on_highlight = [this]() {
+		text_date.set(to_string_FAT_timestamp(file_created_date(get_selected_path())));
+	};
+	
 	refresh_list();
 	
 	on_select_entry = [this]() {
diff --git a/firmware/application/apps/ui_fileman.hpp b/firmware/application/apps/ui_fileman.hpp
index e081edb41619c2140c7213d1703b5158c3872160..e408d0fb4d2e74d5935551d666723705a7759d43 100644
--- a/firmware/application/apps/ui_fileman.hpp
+++ b/firmware/application/apps/ui_fileman.hpp
@@ -149,21 +149,30 @@ private:
 	void refresh_widgets(const bool v);
 	void on_rename(NavigationView& nav);
 	void on_delete();
+	
+	Labels labels {
+		{ { 0, 26 * 8 }, "Created ", Color::light_grey() }
+	};
+	
+	Text text_date {
+		{ 8 * 8, 26 * 8 , 19 * 8, 16 },
+		""
+	};
 
 	Button button_rename {
-		{ 0 * 8, 28 * 8, 14 * 8, 32 },
+		{ 0 * 8, 29 * 8, 12 * 8, 32 },
 		"Rename"
 	};
+	Button button_delete {
+		{ 18 * 8, 29 * 8, 12 * 8, 32 },
+		"Delete"
+	};
 	
 	Button button_new_dir {
-		{ 0 * 8, 33 * 8, 14 * 8, 32 },
+		{ 0 * 8, 34 * 8, 14 * 8, 32 },
 		"New dir"
 	};
 	
-	Button button_delete {
-		{ 18 * 8, 28 * 8, 12 * 8, 32 },
-		"Delete"
-	};
 };
 
 } /* namespace ui */
diff --git a/firmware/application/apps/ui_freqman.cpp b/firmware/application/apps/ui_freqman.cpp
index f6bf45a7c024975503974e02a0d85e51f969b5f8..1b6014c80c91097e35f5b4caba1ca2543bd98f0d 100644
--- a/firmware/application/apps/ui_freqman.cpp
+++ b/firmware/application/apps/ui_freqman.cpp
@@ -72,7 +72,7 @@ void FreqManBaseView::populate_categories() {
 	categories.clear();
 	
 	for (size_t n = 0; n < file_list.size(); n++)
-		categories.emplace_back(std::make_pair(file_list[n], n));
+		categories.emplace_back(std::make_pair(file_list[n].substr(0, 14), n));
 	
 	// Alphabetical sort
 	std::sort(categories.begin(), categories.end(), [](auto &left, auto &right) {
diff --git a/firmware/application/apps/ui_freqman.hpp b/firmware/application/apps/ui_freqman.hpp
index 280182537ebb7e7193aa2485cc198c7162c10c7d..7dd05d2e0d8aa6e0ff17fa54c1e5387086d6b19d 100644
--- a/firmware/application/apps/ui_freqman.hpp
+++ b/firmware/application/apps/ui_freqman.hpp
@@ -149,8 +149,8 @@ private:
 	};
 	
 	Button button_new_category {
-		{ 18 * 8, 2, 12 * 8, 20 },
-		"Create new"
+		{ 23 * 8, 2, 7 * 8, 20 },
+		"New"
 	};
 
 	Button button_edit_freq {
diff --git a/firmware/application/apps/ui_rds.cpp b/firmware/application/apps/ui_rds.cpp
index fc4a65c3d24e6c29b5477a1b4c19442ea24afe9f..b81eca0912035768576000b3a61272ffb94c9b0f 100644
--- a/firmware/application/apps/ui_rds.cpp
+++ b/firmware/application/apps/ui_rds.cpp
@@ -260,6 +260,7 @@ RDSView::RDSView(
 	};
 	
 	tx_view.on_stop = [this]() {
+		// Kill tx_thread here ?
 		tx_view.set_transmitting(false);
 		transmitter_model.disable();
 		txing = false;
diff --git a/firmware/application/file.cpp b/firmware/application/file.cpp
index 3307cecbf943cd503f03fd581d7632b3db241ba3..a1f4b3881d9b1790aef3765c735df054306f294f 100644
--- a/firmware/application/file.cpp
+++ b/firmware/application/file.cpp
@@ -205,6 +205,14 @@ void rename_file(const std::filesystem::path& file_path, const std::filesystem::
 	f_rename(reinterpret_cast<const TCHAR*>(file_path.c_str()), reinterpret_cast<const TCHAR*>(new_name.c_str()));
 }
 
+FATTimestamp file_created_date(const std::filesystem::path& file_path) {
+	FILINFO filinfo;
+	
+	f_stat(reinterpret_cast<const TCHAR*>(file_path.c_str()), &filinfo);
+	
+	return { filinfo.fdate, filinfo.ftime };
+}
+
 uint32_t make_new_directory(const std::filesystem::path& dir_path) {
 	return f_mkdir(reinterpret_cast<const TCHAR*>(dir_path.c_str()));
 }
diff --git a/firmware/application/file.hpp b/firmware/application/file.hpp
index 3e2690bd9506fdfb2cc20707f2566ec11dc3a877..d68e3a9f35b74604bad207e837d3c3dd620fc358 100644
--- a/firmware/application/file.hpp
+++ b/firmware/application/file.hpp
@@ -233,8 +233,14 @@ space_info space(const path& p);
 } /* namespace filesystem */
 } /* namespace std */
 
+struct FATTimestamp {
+	uint16_t FAT_date;
+	uint16_t FAT_time;
+};
+
 void delete_file(const std::filesystem::path& file_path);
 void rename_file(const std::filesystem::path& file_path, const std::filesystem::path& new_name);
+FATTimestamp file_created_date(const std::filesystem::path& file_path);
 uint32_t make_new_directory(const std::filesystem::path& dir_path);
 
 std::vector<std::filesystem::path> scan_root_files(const std::filesystem::path& directory, const std::filesystem::path& extension);
@@ -255,6 +261,7 @@ class File {
 public:
 	using Size = uint64_t;
 	using Offset = uint64_t;
+	using Timestamp = uint32_t;
 	using Error = std::filesystem::filesystem_error;
 
 	template<typename T>
@@ -321,8 +328,9 @@ public:
 
 	Result<Size> read(void* const data, const Size bytes_to_read);
 	Result<Size> write(const void* const data, const Size bytes_to_write);
-
+	
 	Result<Offset> seek(const uint64_t Offset);
+	Timestamp created_date();
 	Size size();
 
 	template<size_t N>
diff --git a/firmware/application/main.cpp b/firmware/application/main.cpp
index e16fbe4c9cfffbb0cd4d1ae5c3ad0fd3580666ed..ac6244da9127232661b15ec3253b6b875f49d890 100755
--- a/firmware/application/main.cpp
+++ b/firmware/application/main.cpp
@@ -27,15 +27,14 @@
 //TEST: Check AFSK transmit end, skips last bits ?
 //TEST: Imperial in whipcalc
 
-//BUG: Auto backlight off doesn't work anymore
 //BUG: (Workaround ok) CPLD-related rx ok, tx bad, see portapack.cpp lines 214+ to disable CPLD overlay
 //BUG: SCANNER Lock on frequency, if frequency jump, still locked on first one
 //BUG: SCANNER Multiple slices
 
+//TODO: Open files in File Manager
+//TODO: Ask for filename after record
 //TODO: Make entries disappear from RecentEntries list in ADS-B RX (after 2 minutes with no update ?)
-//TODO: Display file creation/modification date in FileLoadView
 //TODO: Super simple text file viewer
-//TODO: Display recording frequency in Replay (from associated .txt file, if present)
 //TODO: Clean up ReplayThread
 //TODO: Cap Wav viewer position
 //TODO: Adapt wav viewer position step
diff --git a/firmware/application/main.cpp.orig b/firmware/application/main.cpp.orig
deleted file mode 100755
index 103a14e2de66916af29a74a7e4a1c1944cbd4f55..0000000000000000000000000000000000000000
--- a/firmware/application/main.cpp.orig
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
- * Copyright (C) 2016 Furrtek
- *
- * This file is part of PortaPack.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-// Color bitmaps generated with:
-// Gimp image > indexed colors (16), then "xxd -i *.bmp"
-
-//TEST: Menuview refresh, seems to blink a lot
-//TEST: Check AFSK transmit end, skips last bits ?
-//TEST: Imperial in whipcalc
-
-//BUG: Auto backlight off doesn't work anymore
-//BUG: CPLD-related rx ok, tx bad, see portapack.cpp lines 214+ to disable CPLD overlay
-//BUG: REPLAY See what's wrong with quality (format, or need for interpolation filter ?)
-//BUG: SCANNER Lock on frequency, if frequency jump, still locked on first one
-//BUG: SCANNER Multiple slices
-
-//TODO: Cap Wav viewer position
-//TODO: Adapt wav viewer position step
-//TODO: Use unit_auto_scale
-//TODO: Remove make_bistream from encoders.cpp, too complex, stinks. bitstream_append should be enough.
-//TODO: Continue work on proc_afskrx_corr, see python script (it works !)
-//TODO: Super simple text file viewer
-//TODO: De bruijn sequence scanner for encoders
-//TODO: FILEMAN Rename folders
-//TODO: FILEMAN Move files
-//TODO: Frequency and bw settings were removed from modemsetup, put those back in LCR TX
-//TODO: Use separate thread for scanning in EPAR TX
-//TODO: Use separate thread for scanning in LCR TX
-//TODO: REPLAY Convert C16 to C8 on M0 core
-//TODO: Make freqman refresh simpler (use previous black rectangle method)
-//TODO: Merge AFSK and TONES procs ?
-//TODO: NFM RX mode: nav.pop on squelch
-//TODO: MORSE use prosigns
-//TODO: MORSE live keying mode
-//TODO: Use to_string_short_freq wherever possible
-//TODO: SCANNER Waveform widget as FFT view ?
-//TODO: Optimize (and group ?) CTCSS tone gen code
-/*
-Continuous (Fox-oring)
-12s transmit, 48s space (Sprint 1/5th) 
-60s transmit, 240s space (Classic 1/5 min) 
-60s transmit, 360s space (Classic 1/7 min) 
-*/
-<<<<<<< Updated upstream
-=======
-//TODO: Use TransmitterView in TEDI/LCR, Numbers, ...
->>>>>>> Stashed changes
-//TODO: FreqMan: Remove and rename categories
-//TODO: Mousejack ?
-//TODO: Move frequencykeypad from ui_receiver to ui_widget (used everywhere)
-//TODO: ADS-B draw trajectory + GPS coordinates + scale, and playback
-//TODO: RDS multiple groups (sequence)
-//TODO: Use ModalMessageView confirmation for TX ?
-//TODO: Use msgpack for settings, lists... on sd card
-
-// Multimon-style stuff:
-//TODO: CTCSS detector
-//TODO: DMR detector
-//TODO: GSM channel detector
-//TODO: SIGFOX RX/TX
-//TODO: Playdead amnesia and login
-//TODO: Setup: Play dead by default ? Enable/disable ?
-
-// Old or low-priority stuff:
-//TODO: Bodet :)
-//TODO: Analog TV tx with camcorder font character generator
-//TODO: Show address/data bit fields in OOK TX
-//TODO: Scan for OOK TX
-//TODO: Script engine ?
-//TODO: AFSK receiver
-//TODO: Check more OOK encoders
-//BUG (fixed ?): No audio in about when shown second time
-//TODO: Show MD5 mismatches for modules not found, etc...
-//TODO: Module name/filename in modules.hpp to indicate requirement in case it's not found ui_loadmodule
-//BUG: Description doesn't show up first time going to system>module info (UI drawn on top)
-//TODO: Two players tic-tac-toe
-//TODO: Analog TV pong game
-
-#include "ch.h"
-
-#include "portapack.hpp"
-#include "portapack_shared_memory.hpp"
-
-#include "message_queue.hpp"
-
-#include "ui.hpp"
-#include "ui_widget.hpp"
-#include "ui_painter.hpp"
-#include "ui_navigation.hpp"
-
-#include "irq_lcd_frame.hpp"
-#include "irq_controls.hpp"
-#include "irq_rtc.hpp"
-
-#include "event_m0.hpp"
-
-#include "core_control.hpp"
-#include "spi_image.hpp"
-
-#include "debug.hpp"
-#include "led.hpp"
-
-#include "gcc.hpp"
-
-#include "sd_card.hpp"
-
-#include <string.h>
-
-static void event_loop() {
-	ui::Context context;
-	ui::SystemView system_view {
-		context,
-		portapack::display.screen_rect()
-	};
-
-	EventDispatcher event_dispatcher { &system_view, context };
-	MessageHandlerRegistration message_handler_display_sleep {
-		Message::ID::DisplaySleep,
-		[&event_dispatcher](const Message* const) {
-			event_dispatcher.set_display_sleep(true);
-		}
-	};
-
-	event_dispatcher.run();
-}
-
-int main(void) {
-	if( portapack::init() ) {
-		portapack::display.init();
-
-		sdcStart(&SDCD1, nullptr);
-
-		controls_init();
-		lcd_frame_sync_configure();
-		rtc_interrupt_enable();
-
-		event_loop();
-
-		sdcDisconnect(&SDCD1);
-		sdcStop(&SDCD1);
-
-		portapack::shutdown();
-	}
-
-	m4_init(portapack::spi_flash::image_tag_hackrf, portapack::memory::map::m4_code_hackrf);
-	m0_halt();
-
-	return 0;
-}
diff --git a/firmware/application/protocols/bht.hpp b/firmware/application/protocols/bht.hpp
index 31ff1b9d0c90606f60362b6be5ae38c6cb5d0215..af0f297d92a4edbc3dd2f4b4a1e3c25e36e6021d 100644
--- a/firmware/application/protocols/bht.hpp
+++ b/firmware/application/protocols/bht.hpp
@@ -28,9 +28,14 @@
 
 using namespace encoders;
 
-#define XY_TONE_LENGTH	((TONES_SAMPLERATE * 0.1) - 1)		// 100ms
-#define XY_SILENCE 		(TONES_SAMPLERATE * 0.4)			// 400ms
-#define XY_TONE_COUNT	20
+#define XY_TONE_DURATION	((TONES_SAMPLERATE * 0.1) - 1)		// 100ms
+#define XY_SILENCE 			(TONES_SAMPLERATE * 0.4)			// 400ms
+#define XY_TONE_COUNT		20
+#define XY_MAX_CITY			99
+
+#define EPAR_BIT_DURATION	(OOK_SAMPLERATE / 580)
+#define EPAR_REPEAT_COUNT	26
+#define EPAR_MAX_CITY		255
 	
 struct bht_city {
 	std::string name;
diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp
index d87af2f77fdcb79fa44b469629645fc8f0fcba6d..32199cd1b0b9d44769c61557381d1be70e112ae9 100644
--- a/firmware/application/string_format.cpp
+++ b/firmware/application/string_format.cpp
@@ -165,27 +165,35 @@ std::string to_string_datetime(const rtc::RTC& value, const TimeFormat format) {
 	std::string string { "" };
 	
 	if (format == YMDHMS) {
-		string += to_string_dec_uint(value.year(), 4, '0') + "/" +
-					to_string_dec_uint(value.month(), 2, '0') + "/" +
-					to_string_dec_uint(value.day(), 2, '0') + " ";
+		string += to_string_dec_uint(value.year(), 4) + "/" +
+					to_string_dec_uint(value.month(), 2) + "/" +
+					to_string_dec_uint(value.day(), 2) + " ";
 	}
 	
-	string += to_string_dec_uint(value.hour(), 2, '0') + ":" +
-	string += to_string_dec_uint(value.minute(), 2, '0');
+	string += to_string_dec_uint(value.hour(), 2) + ":" +
+	string += to_string_dec_uint(value.minute(), 2);
 	
 	if ((format == YMDHMS) || (format == HMS))
-		string += ":" + to_string_dec_uint(value.second(), 2, '0');
+		string += ":" + to_string_dec_uint(value.second(), 2);
 	
 	return string;
 }
 
 std::string to_string_timestamp(const rtc::RTC& value) {
-	return to_string_dec_uint(value.year(), 4, '0') +
-		to_string_dec_uint(value.month(), 2, '0') +
-		to_string_dec_uint(value.day(), 2, '0') +
-		to_string_dec_uint(value.hour(), 2, '0') +
-		to_string_dec_uint(value.minute(), 2, '0') +
-		to_string_dec_uint(value.second(), 2, '0');
+	return to_string_dec_uint(value.year(), 4) +
+		to_string_dec_uint(value.month(), 2) +
+		to_string_dec_uint(value.day(), 2) +
+		to_string_dec_uint(value.hour(), 2) +
+		to_string_dec_uint(value.minute(), 2) +
+		to_string_dec_uint(value.second(), 2);
+}
+
+std::string to_string_FAT_timestamp(const FATTimestamp& timestamp) {
+	return to_string_dec_uint((timestamp.FAT_date >> 9) + 1980) + "/" +
+		to_string_dec_uint((timestamp.FAT_date >> 5) & 0xF, 2) + "/" +
+		to_string_dec_uint((timestamp.FAT_date & 0x1F), 2) + " " +
+		to_string_dec_uint((timestamp.FAT_time >> 11), 2) + ":" +
+		to_string_dec_uint((timestamp.FAT_time >> 5) & 0x3F, 2);
 }
 
 std::string unit_auto_scale(double n, const uint32_t base_nano, uint32_t precision) {
@@ -208,7 +216,7 @@ std::string unit_auto_scale(double n, const uint32_t base_nano, uint32_t precisi
 	
 	string = to_string_dec_int(integer_part);
 	if (precision)
-		string += '.' + to_string_dec_uint(fractional_part, precision, '0');
+		string += '.' + to_string_dec_uint(fractional_part, precision);
 	
 	if (prefix_index != 3)
 		string += unit_prefix[prefix_index];
diff --git a/firmware/application/string_format.hpp b/firmware/application/string_format.hpp
index dd12927b9325789ee682a05e2f663a767167de38..278088baaadc3368a8e1233052b27b43840facc9 100644
--- a/firmware/application/string_format.hpp
+++ b/firmware/application/string_format.hpp
@@ -25,6 +25,8 @@
 #include <cstdint>
 #include <string>
 
+#include "file.hpp"
+
 // BARF! rtc::RTC is leaking everywhere.
 #include "lpc43xx_cpp.hpp"
 using namespace lpc43xx;
@@ -39,7 +41,7 @@ const char unit_prefix[7] { 'n', 'u', 'm', 0, 'k', 'M', 'G' };
 
 // TODO: Allow l=0 to not fill/justify? Already using this way in ui_spectrum.hpp...
 std::string to_string_bin(const uint32_t n, const uint8_t l = 0);
-std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = 0);
+std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = '0');
 std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0);
 std::string to_string_hex(const uint64_t n, const int32_t l = 0);
 std::string to_string_hex_array(uint8_t * const array, const int32_t l = 0);
@@ -49,6 +51,7 @@ std::string to_string_time_ms(const uint32_t ms);
 
 std::string to_string_datetime(const rtc::RTC& value, const TimeFormat format = YMDHMS);
 std::string to_string_timestamp(const rtc::RTC& value);
+std::string to_string_FAT_timestamp(const FATTimestamp& timestamp);
 
 std::string unit_auto_scale(double n, const uint32_t base_nano, uint32_t precision);
 
diff --git a/firmware/application/ui/ui_menu.cpp b/firmware/application/ui/ui_menu.cpp
index 3291113a607dcbd576b07cf976d46f98fafc9457..6319298b1dbe1ddca16217aa33db0a5a433de046 100644
--- a/firmware/application/ui/ui_menu.cpp
+++ b/firmware/application/ui/ui_menu.cpp
@@ -231,7 +231,10 @@ bool MenuView::set_highlighted(int32_t new_value) {
 		highlighted_item = new_value;
 		item_view(highlighted_item - offset)->highlight();
 	}
-
+	
+	if (on_highlight)
+		on_highlight();
+	
 	return true;
 }
 
diff --git a/firmware/application/ui/ui_menu.hpp b/firmware/application/ui/ui_menu.hpp
index 8444ef3eb2614fdf2ed6466d7e999ba4175488ad..e3526057bb6d729a68358a565b17a3957072ff49 100644
--- a/firmware/application/ui/ui_menu.hpp
+++ b/firmware/application/ui/ui_menu.hpp
@@ -74,6 +74,7 @@ private:
 class MenuView : public View {
 public:
 	std::function<void(void)> on_left { };
+	std::function<void(void)> on_highlight { nullptr };
 
 	MenuView(Rect new_parent_rect = { 0, 0, 240, 304 }, bool keep_highlight = false);
 	
diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp
index 2dac2383128af1aa918f59335a4f4619b59936a3..d1e8044fe31a23e0a92c072dd3264c2c949c4c89 100644
--- a/firmware/common/ui_widget.cpp
+++ b/firmware/common/ui_widget.cpp
@@ -531,7 +531,9 @@ ProgressBar::ProgressBar(
 void ProgressBar::set_max(const uint32_t max) {
 	if (max == _max) return;
 	
-	_value = 0;
+	if (_value > _max)
+		_value = _max;
+	
 	_max = max;
 	set_dirty();
 }