mirror of
				https://github.com/portapack-mayhem/mayhem-firmware.git
				synced 2025-10-31 18:00:07 +00:00 
			
		
		
		
	Add SD card debug view.
Bus and card configuration data, write and read testing.
This commit is contained in:
		| @@ -164,6 +164,7 @@ CPPSRC = main.cpp \ | ||||
|          ui_debug.cpp \ | ||||
|          ui_baseband_stats_view.cpp \ | ||||
|          ui_sd_card_status_view.cpp \ | ||||
|          ui_sd_card_debug.cpp \ | ||||
|          ui_console.cpp \ | ||||
|          ui_receiver.cpp \ | ||||
|          ui_spectrum.cpp \ | ||||
| @@ -189,6 +190,7 @@ CPPSRC = main.cpp \ | ||||
|          ../common/chibios_cpp.cpp \ | ||||
|          ../common/debug.cpp \ | ||||
|          ../common/gcc.cpp \ | ||||
|          ../common/lfsr_random.cpp \ | ||||
|          core_control.cpp \ | ||||
|          cpld_max5.cpp \ | ||||
|          jtag.cpp \ | ||||
|   | ||||
| @@ -28,6 +28,8 @@ | ||||
|  | ||||
| #include "audio.hpp" | ||||
|  | ||||
| #include "ui_sd_card_debug.hpp" | ||||
|  | ||||
| namespace ui { | ||||
|  | ||||
| /* DebugMemoryView *******************************************************/ | ||||
| @@ -272,7 +274,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { | ||||
| 	add_items<5>({ { | ||||
| 		{ "Memory",      [&nav](){ nav.push<DebugMemoryView>(); } }, | ||||
| 		{ "Radio State", [&nav](){ nav.push<NotImplementedView>(); } }, | ||||
| 		{ "SD Card",     [&nav](){ nav.push<NotImplementedView>(); } }, | ||||
| 		{ "SD Card",     [&nav](){ nav.push<SDCardDebugView>(); } }, | ||||
| 		{ "Peripherals", [&nav](){ nav.push<DebugPeripheralsMenuView>(); } }, | ||||
| 		{ "Temperature", [&nav](){ nav.push<TemperatureView>(); } }, | ||||
| 	} }); | ||||
|   | ||||
							
								
								
									
										409
									
								
								firmware/application/ui_sd_card_debug.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										409
									
								
								firmware/application/ui_sd_card_debug.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,409 @@ | ||||
| /* | ||||
|  * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #include "ui_sd_card_debug.hpp" | ||||
|  | ||||
| #include "string_format.hpp" | ||||
|  | ||||
| #include "file.hpp" | ||||
| #include "lfsr_random.hpp" | ||||
|  | ||||
| #include "ff.h" | ||||
|  | ||||
| #include "ch.h" | ||||
| #include "hal.h" | ||||
|  | ||||
| class SDCardTestThread { | ||||
| public: | ||||
| 	enum Result { | ||||
| 		FailCompare = -8, | ||||
| 		FailReadIncomplete = -7, | ||||
| 		FailWriteIncomplete = -6, | ||||
| 		FailAbort = -5, | ||||
| 		FailFileOpenRead = -4, | ||||
| 		FailFileOpenWrite = -3, | ||||
| 		FailHeap = -2, | ||||
| 		FailThread = -1, | ||||
| 		Incomplete = 0, | ||||
| 		OK = 1, | ||||
| 	}; | ||||
|  | ||||
| 	struct Stats { | ||||
| 		halrtcnt_t write_duration_min { 0 }; | ||||
| 		halrtcnt_t write_duration_max { 0 }; | ||||
| 		halrtcnt_t write_test_duration { 0 }; | ||||
| 		size_t write_bytes { 0 }; | ||||
| 		size_t write_count { 0 }; | ||||
|  | ||||
| 		halrtcnt_t read_duration_min { 0 }; | ||||
| 		halrtcnt_t read_duration_max { 0 }; | ||||
| 		halrtcnt_t read_test_duration { 0 }; | ||||
| 		size_t read_bytes { 0 }; | ||||
| 		size_t read_count { 0 }; | ||||
| 	}; | ||||
|  | ||||
| 	SDCardTestThread( | ||||
| 	) { | ||||
| 		thread = chThdCreateFromHeap(NULL, 2048, NORMALPRIO + 10, SDCardTestThread::static_fn, this); | ||||
| 	} | ||||
|  | ||||
| 	Result result() const { | ||||
| 		return _result; | ||||
| 	} | ||||
|  | ||||
| 	const Stats& stats() const { | ||||
| 		return _stats; | ||||
| 	} | ||||
|  | ||||
| 	~SDCardTestThread() { | ||||
| 		chThdTerminate(thread); | ||||
| 		chThdWait(thread); | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	static constexpr size_t write_size = 16384; | ||||
| 	static constexpr size_t bytes_to_write = 16 * 1024 * 1024; | ||||
| 	static constexpr size_t bytes_to_read = bytes_to_write; | ||||
|  | ||||
| 	static Thread* thread; | ||||
| 	volatile Result _result { Result::Incomplete }; | ||||
| 	Stats _stats; | ||||
|  | ||||
| 	static msg_t static_fn(void* arg) { | ||||
| 		auto obj = static_cast<SDCardTestThread*>(arg); | ||||
| 		obj->_result = obj->run(); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	Result run() { | ||||
| 		const std::string filename { "_PPTEST_.DAT" }; | ||||
|  | ||||
| 		const auto write_result = write(filename); | ||||
| 		if( write_result != Result::OK ) { | ||||
| 			return write_result; | ||||
| 		} | ||||
|  | ||||
| 		if( _stats.write_bytes < bytes_to_write ) { | ||||
| 			return Result::FailWriteIncomplete; | ||||
| 		} | ||||
|  | ||||
| 		if( chThdShouldTerminate() ) { | ||||
| 			return Result::FailAbort; | ||||
| 		} | ||||
|  | ||||
| 		const auto read_result = read(filename); | ||||
| 		if( read_result != Result::OK ) { | ||||
| 			return read_result; | ||||
| 		} | ||||
|  | ||||
| 		f_unlink(filename.c_str()); | ||||
|  | ||||
| 		if( _stats.read_bytes < bytes_to_read ) { | ||||
| 			return Result::FailReadIncomplete; | ||||
| 		} | ||||
|  | ||||
| 		if( chThdShouldTerminate() ) { | ||||
| 			return Result::FailAbort; | ||||
| 		} | ||||
|  | ||||
| 		return Result::OK; | ||||
| 	} | ||||
|  | ||||
| 	Result write(const std::string& filename) { | ||||
| 		const auto buffer = std::make_unique<std::array<uint8_t, write_size>>(); | ||||
| 		if( !buffer ) { | ||||
| 			return Result::FailHeap; | ||||
| 		} | ||||
|  | ||||
| 		File file; | ||||
| 		if( !file.open_for_writing(filename) ) { | ||||
| 			return Result::FailFileOpenWrite; | ||||
| 		} | ||||
|  | ||||
| 		lfsr_word_t v = 1; | ||||
|  | ||||
| 		const halrtcnt_t test_start = halGetCounterValue(); | ||||
| 		while( !chThdShouldTerminate() && file.is_ready() && (_stats.write_bytes < bytes_to_write) ) { | ||||
| 			lfsr_fill(v, | ||||
| 				reinterpret_cast<lfsr_word_t*>(buffer->data()), | ||||
| 				sizeof(*buffer.get()) / sizeof(lfsr_word_t) | ||||
| 			); | ||||
|  | ||||
| 			const halrtcnt_t write_start = halGetCounterValue(); | ||||
| 			if( !file.write(buffer->data(), buffer->size()) ) { | ||||
| 				break; | ||||
| 			} | ||||
| 			const halrtcnt_t write_end = halGetCounterValue(); | ||||
| 			_stats.write_bytes += buffer->size(); | ||||
| 			_stats.write_count++; | ||||
|  | ||||
| 			const halrtcnt_t write_duration = write_end - write_start; | ||||
| 			if( (_stats.write_duration_min == 0) || (write_duration < _stats.write_duration_min) ) { | ||||
| 				_stats.write_duration_min = write_duration; | ||||
| 			} | ||||
| 			if( write_duration > _stats.write_duration_max ) { | ||||
| 				_stats.write_duration_max = write_duration; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		file.close(); | ||||
| 		 | ||||
| 		const halrtcnt_t test_end = halGetCounterValue(); | ||||
| 		_stats.write_test_duration = test_end - test_start; | ||||
|  | ||||
| 		return Result::OK; | ||||
| 	} | ||||
|  | ||||
| 	Result read(const std::string& filename) { | ||||
| 		const auto buffer = std::make_unique<std::array<uint8_t, write_size>>(); | ||||
| 		if( !buffer ) { | ||||
| 			return Result::FailHeap; | ||||
| 		} | ||||
|  | ||||
| 		File file; | ||||
| 		if( !file.open_for_reading(filename) ) { | ||||
| 			return Result::FailFileOpenRead; | ||||
| 		} | ||||
|  | ||||
| 		lfsr_word_t v = 1; | ||||
|  | ||||
| 		const halrtcnt_t test_start = halGetCounterValue(); | ||||
| 		while( !chThdShouldTerminate() && file.is_ready() && (_stats.read_bytes < bytes_to_read) ) { | ||||
| 			const halrtcnt_t read_start = halGetCounterValue(); | ||||
| 			if( !file.read(buffer->data(), buffer->size()) ) { | ||||
| 				break; | ||||
| 			} | ||||
| 			const halrtcnt_t read_end = halGetCounterValue(); | ||||
| 			_stats.read_bytes += buffer->size(); | ||||
| 			_stats.read_count++; | ||||
|  | ||||
| 			const halrtcnt_t read_duration = read_end - read_start; | ||||
| 			if( (_stats.read_duration_min == 0) || (read_duration < _stats.read_duration_min) ) { | ||||
| 				_stats.read_duration_min = read_duration; | ||||
| 			} | ||||
| 			if( read_duration > _stats.read_duration_max ) { | ||||
| 				_stats.read_duration_max = read_duration; | ||||
| 			} | ||||
|  | ||||
| 			if( !lfsr_compare(v, | ||||
| 				reinterpret_cast<lfsr_word_t*>(buffer->data()), | ||||
| 				sizeof(*buffer.get()) / sizeof(lfsr_word_t)) | ||||
| 			) { | ||||
| 				return Result::FailCompare; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		file.close(); | ||||
| 		 | ||||
| 		const halrtcnt_t test_end = halGetCounterValue(); | ||||
| 		_stats.read_test_duration = test_end - test_start; | ||||
|  | ||||
| 		return Result::OK; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| Thread* SDCardTestThread::thread { nullptr }; | ||||
|  | ||||
| namespace ui { | ||||
|  | ||||
| SDCardDebugView::SDCardDebugView(NavigationView& nav) { | ||||
| 	add_children({ { | ||||
| 		&text_title, | ||||
| 		&text_detected_title, | ||||
| 		&text_detected_value, | ||||
| 		&text_bus_width_title, | ||||
| 		&text_bus_width_value, | ||||
| 		&text_card_mode_title, | ||||
| 		&text_card_mode_value, | ||||
| 		// &text_csd_title, | ||||
| 		// &text_csd_value, | ||||
| 		&text_block_size_title, | ||||
| 		&text_block_size_value, | ||||
| 		&text_block_count_title, | ||||
| 		&text_block_count_value, | ||||
| 		&text_capacity_title, | ||||
| 		&text_capacity_value, | ||||
| 		&text_test_write_time_title, | ||||
| 		&text_test_write_time_value, | ||||
| 		&text_test_write_rate_title, | ||||
| 		&text_test_write_rate_value, | ||||
| 		&text_test_read_time_title, | ||||
| 		&text_test_read_time_value, | ||||
| 		&text_test_read_rate_title, | ||||
| 		&text_test_read_rate_value, | ||||
| 		&button_test, | ||||
| 		&button_ok, | ||||
| 	} }); | ||||
|  | ||||
| 	button_test.on_select = [this](Button&){ this->on_test(); }; | ||||
| 	button_ok.on_select = [&nav](Button&){ nav.pop(); }; | ||||
| } | ||||
|  | ||||
| void SDCardDebugView::on_show() { | ||||
| 	sd_card_status_signal_token = sd_card::status_signal += [this](const sd_card::Status status) { | ||||
| 		this->on_status(status); | ||||
| 	}; | ||||
| 	on_status(sd_card::status()); | ||||
| } | ||||
|  | ||||
| void SDCardDebugView::on_hide() { | ||||
| 	sd_card::status_signal -= sd_card_status_signal_token; | ||||
| } | ||||
|  | ||||
| void SDCardDebugView::focus() { | ||||
| 	button_ok.focus(); | ||||
| } | ||||
|  | ||||
| void SDCardDebugView::on_status(const sd_card::Status) { | ||||
| 	text_bus_width_value.set(""); | ||||
| 	text_card_mode_value.set(""); | ||||
| 	// text_csd_value.set(""); | ||||
| 	text_block_size_value.set(""); | ||||
| 	text_block_count_value.set(""); | ||||
| 	text_capacity_value.set(""); | ||||
| 	text_test_write_time_value.set(""); | ||||
| 	text_test_write_rate_value.set(""); | ||||
| 	text_test_read_time_value.set(""); | ||||
| 	text_test_read_rate_value.set(""); | ||||
|  | ||||
| 	const bool is_inserted = sdcIsCardInserted(&SDCD1); | ||||
| 	text_detected_value.set(is_inserted ? "Yes" : " No"); | ||||
|  | ||||
| 	if( is_inserted ) { | ||||
| 		const auto card_width_flags = LPC_SDMMC->CTYPE & 0x10001; | ||||
| 		size_t card_width = 0; | ||||
| 		switch(card_width_flags) { | ||||
| 		case 0x00000: card_width = 1; break; | ||||
| 		case 0x00001: card_width = 4; break; | ||||
| 		case 0x10001: card_width = 8; break; | ||||
| 		default: break; | ||||
| 		} | ||||
|  | ||||
| 		text_bus_width_value.set(card_width ? to_string_dec_uint(card_width, 1) : "X"); | ||||
| 		text_card_mode_value.set("0x" + to_string_hex(SDCD1.cardmode, 8)); | ||||
| 		// text_csd_value.set("0x" + to_string_hex(SDCD1.csd, 8)); | ||||
|  | ||||
| 		BlockDeviceInfo block_device_info; | ||||
| 		if( sdcGetInfo(&SDCD1, &block_device_info) == CH_SUCCESS ) { | ||||
| 			text_block_size_value.set(to_string_dec_uint(block_device_info.blk_size, 5)); | ||||
| 			text_block_count_value.set(to_string_dec_uint(block_device_info.blk_num, 9)); | ||||
| 			const uint64_t capacity = block_device_info.blk_size * uint64_t(block_device_info.blk_num); | ||||
| 			if( capacity >= 1000000000 ) { | ||||
| 				const uint32_t capacity_mb = capacity / 1000000U; | ||||
| 				const uint32_t fraction_gb = capacity_mb % 1000; | ||||
| 				const uint32_t capacity_gb = capacity_mb / 1000U; | ||||
| 				text_capacity_value.set( | ||||
| 					to_string_dec_uint(capacity_gb, 3) + "." + | ||||
| 					to_string_dec_uint(fraction_gb, 3, '0') + " GB" | ||||
| 				); | ||||
| 			} else { | ||||
| 				const uint32_t capacity_kb = capacity / 1000U; | ||||
| 				const uint32_t fraction_mb = capacity_kb % 1000; | ||||
| 				const uint32_t capacity_mb = capacity_kb / 1000U; | ||||
| 				text_capacity_value.set( | ||||
| 					to_string_dec_uint(capacity_mb, 3) + "." + | ||||
| 					to_string_dec_uint(fraction_mb, 3, '0') + " MB" | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static std::string format_ticks_as_ms(const halrtcnt_t value) { | ||||
| 	const uint32_t us = uint64_t(value) * 1000000U / halGetCounterFrequency(); | ||||
| 	const uint32_t ms_frac = us % 1000U; | ||||
| 	const uint32_t ms_int = us / 1000U; | ||||
| 	if( ms_int < 1000 ) { | ||||
| 		return to_string_dec_uint(ms_int, 3) + "." + to_string_dec_uint(ms_frac, 3, '0'); | ||||
| 	} else { | ||||
| 		return "HHH.HHH"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static std::string format_bytes_per_ticks_as_mib(const size_t bytes, const halrtcnt_t ticks) { | ||||
| 	const uint32_t bps = uint64_t(bytes) * halGetCounterFrequency() / ticks; | ||||
| 	const uint32_t kbps = bps / 1000U; | ||||
| 	const uint32_t mbps_frac = kbps % 1000U; | ||||
| 	const uint32_t mbps_int = kbps / 1000U; | ||||
| 	if( mbps_int < 1000 ) { | ||||
| 		return to_string_dec_uint(mbps_int, 3) + "." + to_string_dec_uint(mbps_frac, 3, '0'); | ||||
| 	} else { | ||||
| 		return "HHH.HHH"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void SDCardDebugView::on_test() { | ||||
| 	text_test_write_time_value.set(""); | ||||
| 	text_test_write_rate_value.set(""); | ||||
| 	text_test_read_time_value.set(""); | ||||
| 	text_test_read_rate_value.set(""); | ||||
|  | ||||
| 	SDCardTestThread thread; | ||||
|  | ||||
| 	// uint32_t spinner_phase = 0; | ||||
| 	while( thread.result() == SDCardTestThread::Result::Incomplete ) { | ||||
| 		chThdSleepMilliseconds(100); | ||||
|  | ||||
| 		// spinner_phase += 1; | ||||
| 		// char c = '*'; | ||||
| 		// switch(spinner_phase % 4) { | ||||
| 		// case 0: c = '-';  break; | ||||
| 		// case 1: c = '\\'; break; | ||||
| 		// case 2: c = '|';  break; | ||||
| 		// case 3: c = '/';  break; | ||||
| 		// default: c = '*'; break; | ||||
| 		// } | ||||
| 		// text_test_write_value.set({ c }); | ||||
| 	} | ||||
|  | ||||
| 	if( thread.result() == SDCardTestThread::Result::OK ) { | ||||
| 		const auto stats = thread.stats(); | ||||
| 		const auto write_duration_avg = stats.write_test_duration / stats.write_count; | ||||
|  | ||||
| 		text_test_write_time_value.set( | ||||
| 			format_ticks_as_ms(stats.write_duration_min) + "/" + | ||||
| 			format_ticks_as_ms(write_duration_avg) + "/" + | ||||
| 			format_ticks_as_ms(stats.write_duration_max) | ||||
| 		); | ||||
|  | ||||
| 		text_test_write_rate_value.set( | ||||
| 			format_bytes_per_ticks_as_mib(stats.write_bytes, stats.write_duration_min * stats.write_count) + " " + | ||||
| 			format_bytes_per_ticks_as_mib(stats.write_bytes, stats.write_test_duration) | ||||
| 		); | ||||
|  | ||||
| 		const auto read_duration_avg = stats.read_test_duration / stats.read_count; | ||||
|  | ||||
| 		text_test_read_time_value.set( | ||||
| 			format_ticks_as_ms(stats.read_duration_min) + "/" + | ||||
| 			format_ticks_as_ms(read_duration_avg) + "/" + | ||||
| 			format_ticks_as_ms(stats.read_duration_max) | ||||
| 		); | ||||
|  | ||||
| 		text_test_read_rate_value.set( | ||||
| 			format_bytes_per_ticks_as_mib(stats.read_bytes, stats.read_duration_min * stats.read_count) + " " + | ||||
| 			format_bytes_per_ticks_as_mib(stats.read_bytes, stats.read_test_duration) | ||||
| 		); | ||||
| 	} else { | ||||
| 		text_test_write_time_value.set("Fail: " + to_string_dec_int(toUType(thread.result()), 4)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| } /* namespace ui */ | ||||
							
								
								
									
										203
									
								
								firmware/application/ui_sd_card_debug.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								firmware/application/ui_sd_card_debug.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| /* | ||||
|  * Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc. | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef __UI_SD_CARD_DEBUG_H__ | ||||
| #define __UI_SD_CARD_DEBUG_H__ | ||||
|  | ||||
| #include "ui_widget.hpp" | ||||
| #include "ui_navigation.hpp" | ||||
|  | ||||
| #include "sd_card.hpp" | ||||
|  | ||||
| namespace ui { | ||||
|  | ||||
| class SDCardDebugView : public View { | ||||
| public: | ||||
| 	SDCardDebugView(NavigationView& nav); | ||||
|  | ||||
| 	void on_show() override; | ||||
| 	void on_hide() override; | ||||
|  | ||||
| 	void focus() override; | ||||
|  | ||||
| private: | ||||
| 	SignalToken sd_card_status_signal_token; | ||||
|  | ||||
| 	void on_status(const sd_card::Status status); | ||||
| 	void on_test(); | ||||
|  | ||||
| 	Text text_title { | ||||
| 		{ (240 - (7 * 8)) / 2, 1 * 16, (7 * 8), 16 }, | ||||
| 		"SD Card", | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr size_t detected_characters = 3; | ||||
|  | ||||
| 	Text text_detected_title { | ||||
| 		{ 0, 3 * 16, (8 * 8), 16 }, | ||||
| 		"Detected", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_detected_value { | ||||
| 		{ 240 - (detected_characters * 8), 3 * 16, (detected_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr size_t bus_width_characters = 1; | ||||
|  | ||||
| 	Text text_bus_width_title { | ||||
| 		{ 0, 5 * 16, (9 * 8), 16 }, | ||||
| 		"Bus width", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_bus_width_value { | ||||
| 		{ 240 - (bus_width_characters * 8), 5 * 16, (bus_width_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr size_t card_mode_characters = 10; | ||||
|  | ||||
| 	Text text_card_mode_title { | ||||
| 		{ 0, 6 * 16, (9 * 8), 16 }, | ||||
| 		"Card mode", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_card_mode_value { | ||||
| 		{ 240 - (card_mode_characters * 8), 6 * 16, (card_mode_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	// static constexpr size_t csd_characters = 10; | ||||
|  | ||||
| 	// Text text_csd_title { | ||||
| 	// 	{ 0, 7 * 16, (3 * 8), 16 }, | ||||
| 	// 	"CSD", | ||||
| 	// }; | ||||
|  | ||||
| 	// Text text_csd_value { | ||||
| 	// 	{ 240 - (csd_characters * 8), 7 * 16, (csd_characters * 8), 16 }, | ||||
| 	// 	"", | ||||
| 	// }; | ||||
|  | ||||
| 	static constexpr size_t block_size_characters = 5; | ||||
|  | ||||
| 	Text text_block_size_title { | ||||
| 		{ 0, 8 * 16, (10 * 8), 16 }, | ||||
| 		"Block size", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_block_size_value { | ||||
| 		{ 240 - (block_size_characters * 8), 8 * 16, (block_size_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr size_t block_count_characters = 9; | ||||
|  | ||||
| 	Text text_block_count_title { | ||||
| 		{ 0, 9 * 16, (11 * 8), 16 }, | ||||
| 		"Block count", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_block_count_value { | ||||
| 		{ 240 - (block_count_characters * 8), 9 * 16, (block_count_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr size_t capacity_characters = 10; | ||||
|  | ||||
| 	Text text_capacity_title { | ||||
| 		{ 0, 10 * 16, (8 * 8), 16 }, | ||||
| 		"Capacity", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_capacity_value { | ||||
| 		{ 240 - (capacity_characters * 8), 10 * 16, (capacity_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	/////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| 	static constexpr size_t test_write_time_characters = 23; | ||||
|  | ||||
| 	Text text_test_write_time_title { | ||||
| 		{ 0, 12 * 16, (4 * 8), 16 }, | ||||
| 		"W ms", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_test_write_time_value { | ||||
| 		{ 240 - (test_write_time_characters * 8), 12 * 16, (test_write_time_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr size_t test_write_rate_characters = 23; | ||||
|  | ||||
| 	Text text_test_write_rate_title { | ||||
| 		{ 0, 13 * 16, (6 * 8), 16 }, | ||||
| 		"W MB/s", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_test_write_rate_value { | ||||
| 		{ 240 - (test_write_rate_characters * 8), 13 * 16, (test_write_rate_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	/////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| 	static constexpr size_t test_read_time_characters = 23; | ||||
|  | ||||
| 	Text text_test_read_time_title { | ||||
| 		{ 0, 14 * 16, (4 * 8), 16 }, | ||||
| 		"R ms", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_test_read_time_value { | ||||
| 		{ 240 - (test_read_time_characters * 8), 14 * 16, (test_read_time_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr size_t test_read_rate_characters = 23; | ||||
|  | ||||
| 	Text text_test_read_rate_title { | ||||
| 		{ 0, 15 * 16, (6 * 8), 16 }, | ||||
| 		"R MB/s", | ||||
| 	}; | ||||
|  | ||||
| 	Text text_test_read_rate_value { | ||||
| 		{ 240 - (test_read_rate_characters * 8), 15 * 16, (test_read_rate_characters * 8), 16 }, | ||||
| 		"", | ||||
| 	}; | ||||
|  | ||||
| 	/////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| 	Button button_test { | ||||
| 		{ 16, 17 * 16, 96, 24 }, | ||||
| 		"Test" | ||||
| 	}; | ||||
|  | ||||
| 	Button button_ok { | ||||
| 		{ 240 - 96 - 16, 17 * 16, 96, 24 }, | ||||
| 		"OK" | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| } /* namespace ui */ | ||||
|  | ||||
| #endif/*__UI_SD_CARD_DEBUG_H__*/ | ||||
		Reference in New Issue
	
	Block a user
	 Jared Boone
					Jared Boone