/* * Copyright 2018 Jared Boone * * This file is part of HackRF. * * 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 "hackrf-ui.h" #include "ui_portapack.h" #include "hackrf_core.h" #include "gpio_lpc.h" #include #include /* Pixel data within a font or bitmap byte is "reversed": LSB is left-most pixel. */ static const uint8_t font_fixed_8x16_glyph_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0xff, 0x24, 0x24, 0xff, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x78, 0x14, 0x14, 0x14, 0x18, 0x30, 0x50, 0x50, 0x50, 0x3c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x29, 0x29, 0x19, 0x16, 0x68, 0x98, 0x94, 0x94, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x14, 0x88, 0x54, 0x72, 0x22, 0x62, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x5a, 0x5a, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x10, 0x0c, 0x10, 0x20, 0x20, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x28, 0x28, 0x24, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x04, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x04, 0x18, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x30, 0x40, 0x30, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x30, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x59, 0x55, 0x55, 0x55, 0x39, 0x01, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x14, 0x14, 0x22, 0x3e, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x72, 0x42, 0x42, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x42, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x66, 0x66, 0x5a, 0x5a, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x46, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x10, 0x60, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x22, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x0c, 0x30, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x49, 0x49, 0x55, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x7c, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x1a, 0x26, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x02, 0x02, 0x02, 0x04, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x7e, 0x02, 0x04, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x7e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x22, 0x22, 0x22, 0x1c, 0x02, 0x3e, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x26, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x02, 0x02, 0x3c, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x36, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x49, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, 0x18, 0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x14, 0x14, 0x08, 0x08, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const ui_font_t font_fixed_8x16 = { { 8, 16 }, font_fixed_8x16_glyph_data, 0x20, 95, (8 * 16 + 7U) >> 3 }; static const uint8_t font_fixed_24x19_glyph_data[] = { 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0x00, 0x78, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x77, 0x00, 0xc0, 0x73, 0x00, 0xc0, 0x71, 0x00, 0xc0, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3c, 0x00, 0xfc, 0x1f, 0xe0, 0xff, 0x1f, 0xf8, 0xff, 0x07, 0xfc, 0x07, 0x00, 0x3c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x3f, 0x3c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0xfe, 0x3f, 0x00, 0xfe, 0x1f, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x38, 0xf8, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0x00, 0x80, 0x0f, 0x00, 0xc0, 0x0f, 0x00, 0xe0, 0x0f, 0x00, 0xf8, 0x0f, 0x00, 0x7c, 0x0f, 0x00, 0x1e, 0x0f, 0x00, 0x0f, 0x0f, 0xc0, 0x07, 0x0f, 0xe0, 0x01, 0x0f, 0xf0, 0x00, 0x0f, 0x7c, 0x00, 0x0f, 0x1e, 0x00, 0x0f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xdc, 0xff, 0x07, 0xfc, 0xff, 0x1f, 0xfc, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x00, 0xdc, 0xff, 0x07, 0xfc, 0xff, 0x1f, 0xfc, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xfc, 0xff, 0x7f, 0xfc, 0xff, 0x7f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x03, 0x00, 0xe0, 0x01, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x03, 0x00, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x3f, 0xf8, 0xff, 0x3f, 0xe0, 0xff, 0x3b, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, }; static const ui_font_t font_fixed_24x19 = { { 24, 19 }, font_fixed_24x19_glyph_data, 0x30, 10, (24 * 19 + 7U) >> 3 }; static const uint8_t font_fixed_16x14_glyph_data[] = { 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0x00, 0x03, 0x80, 0x03, 0xc0, 0x03, 0xe0, 0x03, 0x70, 0x03, 0x20, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x00, 0x60, 0x00, 0x70, 0x80, 0x3f, 0xf8, 0x1f, 0xfc, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x06, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x00, 0x60, 0x00, 0x60, 0xc0, 0x3f, 0xc0, 0x7f, 0x00, 0x60, 0x00, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x1f, 0x80, 0x1b, 0xc0, 0x19, 0xe0, 0x18, 0x70, 0x18, 0x38, 0x18, 0x1c, 0x18, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0xfe, 0x7f, 0xfe, 0x7f, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x1f, 0xfe, 0x3f, 0x0e, 0x70, 0x00, 0x60, 0x00, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x00, 0xf6, 0x1f, 0xfe, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x70, 0x00, 0x30, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x07, 0x80, 0x03, 0x80, 0x01, 0xc0, 0x00, 0xe0, 0x00, 0x60, 0x00, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x7f, 0xf8, 0x6f, 0x00, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, }; static const ui_font_t font_fixed_16x14 = { { 16, 14 }, font_fixed_16x14_glyph_data, 0x30, 10, (16 * 14 + 7U) >> 3 }; static const uint8_t bitmap_amp_rx_data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x30, 0x0c, 0x00, 0x30, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x30, 0x00, 0x0c, 0x30, 0x00, 0x0c, 0x60, 0x00, 0x06, 0x60, 0x00, 0x06, 0xc0, 0x00, 0x03, 0xc0, 0x00, 0x03, 0x80, 0x81, 0x01, 0x80, 0x81, 0x01, 0x00, 0xc3, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00 }; static const ui_bitmap_t bitmap_amp_rx = { { 24, 24 }, bitmap_amp_rx_data }; static const uint8_t bitmap_amp_tx_data[] = { 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xc3, 0x00, 0x80, 0x81, 0x01, 0x80, 0x81, 0x01, 0xc0, 0x00, 0x03, 0xc0, 0x00, 0x03, 0x60, 0x00, 0x06, 0x60, 0x00, 0x06, 0x30, 0x00, 0x0c, 0x30, 0x00, 0x0c, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x0c, 0x00, 0x30, 0x0c, 0x00, 0x30, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static const ui_bitmap_t bitmap_amp_tx = { { 24, 24 }, bitmap_amp_tx_data }; static const uint8_t bitmap_antenna_data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x18, 0x60, 0x06, 0x18, 0x60, 0x0c, 0x18, 0x30, 0x0c, 0x18, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x18, 0x0c, 0x30, 0x18, 0x0c, 0x60, 0x18, 0x06, 0x60, 0x18, 0x06, 0xc0, 0x18, 0x03, 0xc0, 0x18, 0x03, 0x80, 0x99, 0x01, 0x80, 0x99, 0x01, 0x00, 0xdb, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00 }; static const ui_bitmap_t bitmap_antenna = { { 24, 24 }, bitmap_antenna_data }; static const uint8_t bitmap_filter_hp_data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0xf8, 0xc7, 0x03, 0xfc, 0xc7, 0x03, 0x0e, 0xc0, 0x03, 0x06, 0xc0, 0x03, 0x03, 0xc0, 0x03, 0x03, 0xc0, 0x83, 0x01, 0xc0, 0x83, 0x01, 0xc0, 0xc3, 0x00, 0xc0, 0xc3, 0x00, 0xc0, 0x63, 0x00, 0xc0, 0x63, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static const ui_bitmap_t bitmap_filter_hp = { { 24, 24 }, bitmap_filter_hp_data }; static const uint8_t bitmap_filter_lp_data[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xe3, 0x1f, 0xc0, 0xe3, 0x3f, 0xc0, 0x03, 0x70, 0xc0, 0x03, 0x60, 0xc0, 0x03, 0xc0, 0xc0, 0x03, 0xc0, 0xc0, 0x03, 0x80, 0xc1, 0x03, 0x80, 0xc1, 0x03, 0x00, 0xc3, 0x03, 0x00, 0xc3, 0x03, 0x00, 0xc6, 0x03, 0x00, 0xc6, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static const ui_bitmap_t bitmap_filter_lp = { { 24, 24 }, bitmap_filter_lp_data }; static const uint8_t bitmap_mixer_data[] = { 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0x81, 0x07, 0x70, 0x00, 0x0e, 0x38, 0x00, 0x1c, 0x7c, 0x00, 0x3e, 0xee, 0x00, 0x77, 0xc6, 0x81, 0x63, 0x86, 0xc3, 0x61, 0x03, 0xe7, 0xc0, 0x03, 0x7e, 0xc0, 0x03, 0x3c, 0xc0, 0x03, 0x3c, 0xc0, 0x03, 0x7e, 0xc0, 0x03, 0xe7, 0xc0, 0x86, 0xc3, 0x61, 0xc6, 0x81, 0x63, 0xee, 0x00, 0x77, 0x7c, 0x00, 0x3e, 0x38, 0x00, 0x1c, 0x70, 0x00, 0x0e, 0xe0, 0x81, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00 }; static const ui_bitmap_t bitmap_mixer = { { 24, 24 }, bitmap_mixer_data }; static const uint8_t bitmap_wire_8_data[] = { 0xff, 0xff }; static const ui_bitmap_t bitmap_wire_8 = { { 2, 8 }, bitmap_wire_8_data }; static const uint8_t bitmap_wire_24_data[] = { 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00 }; static const ui_bitmap_t bitmap_wire_24 = { { 24, 24 }, bitmap_wire_24_data }; static const uint8_t bitmap_waves_data[] = { 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x06, 0x60, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x60, 0x0c, 0x30, 0x06, 0x30, 0x06, 0x30, 0x06, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03 }; __attribute__((unused)) static const ui_bitmap_t bitmap_waves = { { 16, 20 }, bitmap_waves_data }; __attribute__((unused)) static ui_color_t portapack_color_rgb( const uint_fast8_t r, const uint_fast8_t g, const uint_fast8_t b ) { const ui_color_t result = { .v = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3) }; return result; } static const ui_color_t color_background = { 0x001f }; static const ui_color_t color_foreground = { 0xffff }; #define ARRAY_SIZEOF(x) (sizeof(x) / sizeof(x[0])) static void portapack_sleep_milliseconds(const uint32_t milliseconds) { /* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */ delay(milliseconds * 40800); } static struct gpio_t gpio_io_stbx = GPIO(5, 0); /* P2_0 */ static struct gpio_t gpio_addr = GPIO(5, 1); /* P2_1 */ __attribute__((unused)) static struct gpio_t gpio_lcd_te = GPIO(5, 3); /* P2_3 */ __attribute__((unused)) static struct gpio_t gpio_unused = GPIO(5, 7); /* P2_8 */ static struct gpio_t gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */ static struct gpio_t gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */ static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */ typedef struct portapack_t { gpio_t gpio_dir; gpio_t gpio_lcd_rdx; gpio_t gpio_lcd_wrx; gpio_t gpio_io_stbx; gpio_t gpio_addr; gpio_port_t* const gpio_port_data; uint8_t io_reg; } portapack_t; static portapack_t portapack = { .gpio_dir = &gpio_dir, .gpio_lcd_rdx = &gpio_lcd_rdx, .gpio_lcd_wrx = &gpio_lcd_wrx, .gpio_io_stbx = &gpio_io_stbx, .gpio_addr = &gpio_addr, .gpio_port_data = GPIO_LPC_PORT(3), .io_reg = 0x03, }; /* NOTE: Code below assumes the shift value is "8". */ #define GPIO_DATA_SHIFT (8) static const uint32_t gpio_data_mask = 0xFFU << GPIO_DATA_SHIFT; static void portapack_data_mask_set() { portapack.gpio_port_data->mask = ~gpio_data_mask; } static void portapack_data_write_low(const uint32_t value) { portapack.gpio_port_data->mpin = (value << GPIO_DATA_SHIFT); } static void portapack_data_write_high(const uint32_t value) { /* NOTE: Assumes no other bits in the port are masked. */ /* NOTE: Assumes that bits 15 through 8 are masked. */ portapack.gpio_port_data->mpin = value; } static void portapack_dir_read() { portapack.gpio_port_data->dir &= ~gpio_data_mask; gpio_set(portapack.gpio_dir); } static void portapack_dir_write() { gpio_clear(portapack.gpio_dir); portapack.gpio_port_data->dir |= gpio_data_mask; /* TODO: Manipulating DIR[3] makes me queasy. The RFFC5072 DATA pin * is also on port 3, and switches direction periodically... * Time to resort to bit-banding to enforce atomicity? But then, how * to change direction on eight bits efficiently? Or do I care, since * the PortaPack data bus shouldn't change direction too frequently? */ } __attribute__((unused)) static void portapack_lcd_rd_assert() { gpio_clear(portapack.gpio_lcd_rdx); } static void portapack_lcd_rd_deassert() { gpio_set(portapack.gpio_lcd_rdx); } static void portapack_lcd_wr_assert() { gpio_clear(portapack.gpio_lcd_wrx); } static void portapack_lcd_wr_deassert() { gpio_set(portapack.gpio_lcd_wrx); } static void portapack_io_stb_assert() { gpio_clear(portapack.gpio_io_stbx); } static void portapack_io_stb_deassert() { gpio_set(portapack.gpio_io_stbx); } static void portapack_addr(const bool value) { gpio_write(portapack.gpio_addr, value); } static void portapack_lcd_command(const uint32_t value) { portapack_data_write_high(0); /* Drive high byte (with zero -- don't care) */ portapack_dir_write(); /* Turn around data bus, MCU->CPLD */ portapack_addr(0); /* Indicate command */ __asm__("nop"); __asm__("nop"); __asm__("nop"); portapack_lcd_wr_assert(); /* Latch high byte */ portapack_data_write_low(value); /* Drive low byte (pass-through) */ __asm__("nop"); __asm__("nop"); __asm__("nop"); portapack_lcd_wr_deassert(); /* Complete write operation */ portapack_addr(1); /* Set up for data phase (most likely after a command) */ } static void portapack_lcd_write_data(const uint32_t value) { // NOTE: Assumes and DIR=0 and ADDR=1 from command phase. portapack_data_write_high(value); /* Drive high byte */ __asm__("nop"); portapack_lcd_wr_assert(); /* Latch high byte */ portapack_data_write_low(value); /* Drive low byte (pass-through) */ __asm__("nop"); __asm__("nop"); __asm__("nop"); portapack_lcd_wr_deassert(); /* Complete write operation */ } static void portapack_io_write(const bool address, const uint_fast16_t value) { portapack_data_write_low(value); portapack_dir_write(); portapack_addr(address); __asm__("nop"); __asm__("nop"); __asm__("nop"); portapack_io_stb_assert(); __asm__("nop"); __asm__("nop"); __asm__("nop"); portapack_io_stb_deassert(); } static void portapack_lcd_data_write_command_and_data( const uint_fast8_t command, const uint8_t* data, const size_t data_count ) { portapack_lcd_command(command); for(size_t i=0; igpio_pp_tms, tms_value); // 8 ns TMS/TDI to TCK setup __asm__("nop"); __asm__("nop"); __asm__("nop"); gpio_set(jtag_cpld.gpio->gpio_tck); // 15 ns TCK to TMS/TDI hold time // 20 ns TCK high time __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); gpio_clear(jtag_cpld.gpio->gpio_tck); // 20 ns TCK low time // 25 ns TCK falling edge to TDO valid __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); return gpio_read(jtag_cpld.gpio->gpio_pp_tdo); } static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count) { uint32_t result = 0; size_t bit_in_index = count - 1; size_t bit_out_index = 0; while(bit_out_index < count) { const uint32_t tdo = jtag_pp_tck((tms_bits >> bit_in_index) & 1) & 1; result |= (tdo << bit_out_index); bit_in_index--; bit_out_index++; } return result; } static uint32_t jtag_pp_idcode() { cpld_jtag_take(&jtag_cpld); /* TODO: Check if PortaPack TMS is floating or driven by an external device. */ gpio_output(jtag_cpld.gpio->gpio_pp_tms); /* Test-Logic/Reset -> Run-Test/Idle -> Select-DR/Scan -> Capture-DR */ jtag_pp_shift(0b11111010, 8); /* Shift-DR */ const uint32_t idcode = jtag_pp_shift(0, 32); /* Exit1-DR -> Update-DR -> Run-Test/Idle -> ... -> Test-Logic/Reset */ jtag_pp_shift(0b11011111, 8); cpld_jtag_release(&jtag_cpld); return idcode; } static void portapack_if_init() { portapack_data_mask_set(); portapack_data_write_high(0); portapack_dir_read(); portapack_lcd_rd_deassert(); portapack_lcd_wr_deassert(); portapack_io_stb_deassert(); portapack_addr(0); gpio_output(portapack.gpio_dir); gpio_output(portapack.gpio_lcd_rdx); gpio_output(portapack.gpio_lcd_wrx); gpio_output(portapack.gpio_io_stbx); gpio_output(portapack.gpio_addr); /* gpio_input(portapack.gpio_rot_a); */ /* gpio_input(portapack.gpio_rot_b); */ scu_pinmux(SCU_PINMUX_PP_D0, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); scu_pinmux(SCU_PINMUX_PP_D1, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); scu_pinmux(SCU_PINMUX_PP_D2, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); scu_pinmux(SCU_PINMUX_PP_D3, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); scu_pinmux(SCU_PINMUX_PP_D4, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); scu_pinmux(SCU_PINMUX_PP_D5, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); scu_pinmux(SCU_PINMUX_PP_D6, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); scu_pinmux(SCU_PINMUX_PP_D7, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN); scu_pinmux(SCU_PINMUX_PP_DIR, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL); scu_pinmux(SCU_PINMUX_PP_LCD_RDX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); scu_pinmux(SCU_PINMUX_PP_LCD_WRX, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL); scu_pinmux(SCU_PINMUX_PP_IO_STBX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); scu_pinmux(SCU_PINMUX_PP_ADDR, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); /* scu_pinmux(SCU_PINMUX_PP_LCD_TE, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */ /* scu_pinmux(SCU_PINMUX_PP_UNUSED, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */ } static void portapack_lcd_reset() { portapack_lcd_reset_state(false); portapack_sleep_milliseconds(1); portapack_lcd_reset_state(true); portapack_sleep_milliseconds(10); portapack_lcd_reset_state(false); portapack_sleep_milliseconds(120); } static void portapack_lcd_init() { // LCDs are configured for IM[2:0] = 001 // 8080-I system, 16-bit parallel bus // // 0x3a: DBI[2:0] = 101 // MDT[1:0] = XX (if not in 18-bit mode, right?) // Power control B // 0 // PCEQ=1, DRV_ena=0, Power control=3 const uint8_t cmd_cf[] = { 0x00, 0xD9, 0x30 }; portapack_lcd_data_write_command_and_data(0xCF, cmd_cf, ARRAY_SIZEOF(cmd_cf)); // Power on sequence control const uint8_t cmd_ed[] = { 0x64, 0x03, 0x12, 0x81 }; portapack_lcd_data_write_command_and_data(0xED, cmd_ed, ARRAY_SIZEOF(cmd_ed)); // Driver timing control A const uint8_t cmd_e8[] = { 0x85, 0x10, 0x78 }; portapack_lcd_data_write_command_and_data(0xE8, cmd_e8, ARRAY_SIZEOF(cmd_e8)); // Power control A const uint8_t cmd_cb[] = { 0x39, 0x2C, 0x00, 0x34, 0x02 }; portapack_lcd_data_write_command_and_data(0xCB, cmd_cb, ARRAY_SIZEOF(cmd_cb)); // Pump ratio control const uint8_t cmd_f7[] = { 0x20 }; portapack_lcd_data_write_command_and_data(0xF7, cmd_f7, ARRAY_SIZEOF(cmd_f7)); // Driver timing control B const uint8_t cmd_ea[] = { 0x00, 0x00 }; portapack_lcd_data_write_command_and_data(0xEA, cmd_ea, ARRAY_SIZEOF(cmd_ea)); const uint8_t cmd_b1[] = { 0x00, 0x1B }; portapack_lcd_data_write_command_and_data(0xB1, cmd_b1, ARRAY_SIZEOF(cmd_b1)); // Blanking Porch Control // VFP = 0b0000010 = 2 (number of HSYNC of vertical front porch) // VBP = 0b0000010 = 2 (number of HSYNC of vertical back porch) // HFP = 0b0001010 = 10 (number of DOTCLOCK of horizontal front porch) // HBP = 0b0010100 = 20 (number of DOTCLOCK of horizontal back porch) const uint8_t cmd_b5[] = { 0x02, 0x02, 0x0a, 0x14 }; portapack_lcd_data_write_command_and_data(0xB5, cmd_b5, ARRAY_SIZEOF(cmd_b5)); // Display Function Control // PT[1:0] = 0b10 // PTG[1:0] = 0b10 // ISC[3:0] = 0b0010 (scan cycle interval of gate driver: 5 frames) // SM = 0 (gate driver pin arrangement in combination with GS) // SS = 1 (source output scan direction S720 -> S1) // GS = 0 (gate output scan direction G1 -> G320) // REV = 1 (normally white) // NL = 0b100111 (default) // PCDIV = 0b000000 (default?) const uint8_t cmd_b6[] = { 0x0A, 0xA2, 0x27, 0x00 }; portapack_lcd_data_write_command_and_data(0xB6, cmd_b6, ARRAY_SIZEOF(cmd_b6)); // Power Control 1 //VRH[5:0] const uint8_t cmd_c0[] = { 0x1B }; portapack_lcd_data_write_command_and_data(0xC0, cmd_c0, ARRAY_SIZEOF(cmd_c0)); // Power Control 2 //SAP[2:0];BT[3:0] const uint8_t cmd_c1[] = { 0x12 }; portapack_lcd_data_write_command_and_data(0xC1, cmd_c1, ARRAY_SIZEOF(cmd_c1)); // VCOM Control 1 const uint8_t cmd_c5[] = { 0x32, 0x3C }; portapack_lcd_data_write_command_and_data(0xC5, cmd_c5, ARRAY_SIZEOF(cmd_c5)); // VCOM Control 2 const uint8_t cmd_c7[] = { 0x9B }; portapack_lcd_data_write_command_and_data(0xC7, cmd_c7, ARRAY_SIZEOF(cmd_c7)); // Memory Access Control // Invert X and Y memory access order, so upper-left of // screen is (0,0) when writing to display. const uint8_t cmd_36[] = { (1 << 7) | // MY=1 (1 << 6) | // MX=1 (0 << 5) | // MV=0 (1 << 4) | // ML=1: reverse vertical refresh to simplify scrolling logic (1 << 3) // BGR=1: For Kingtech LCD, BGR filter. }; portapack_lcd_data_write_command_and_data(0x36, cmd_36, ARRAY_SIZEOF(cmd_36)); // COLMOD: Pixel Format Set // DPI=101 (16 bits/pixel), DBI=101 (16 bits/pixel) const uint8_t cmd_3a[] = { 0x55 }; portapack_lcd_data_write_command_and_data(0x3A, cmd_3a, ARRAY_SIZEOF(cmd_3a)); //portapack_lcd_data_write_command_and_data(0xF6, { 0x01, 0x30 }); // WEMODE=1 (reset column and page number on overflow) // MDT[1:0] // EPF[1:0]=00 (use channel MSB for LSB) // RIM=0 (If COLMOD[6:4]=101 (65k color), 16-bit RGB interface (1 transfer/pixel)) // RM=0 (system interface/VSYNC interface) // DM[1:0]=00 (internal clock operation) // ENDIAN=0 (doesn't matter with 16-bit interface) const uint8_t cmd_f6[] = { 0x01, 0x30, 0x00 }; portapack_lcd_data_write_command_and_data(0xF6, cmd_f6, ARRAY_SIZEOF(cmd_f6)); // 3Gamma Function Disable const uint8_t cmd_f2[] = { 0x00 }; portapack_lcd_data_write_command_and_data(0xF2, cmd_f2, ARRAY_SIZEOF(cmd_f2)); // Gamma curve selected const uint8_t cmd_26[] = { 0x01 }; portapack_lcd_data_write_command_and_data(0x26, cmd_26, ARRAY_SIZEOF(cmd_26)); // Set Gamma const uint8_t cmd_e0[] = { 0x0F, 0x1D, 0x19, 0x0E, 0x10, 0x07, 0x4C, 0x63, 0x3F, 0x03, 0x0D, 0x00, 0x26, 0x24, 0x04 }; portapack_lcd_data_write_command_and_data(0xE0, cmd_e0, ARRAY_SIZEOF(cmd_e0)); // Set Gamma const uint8_t cmd_e1[] = { 0x00, 0x1C, 0x1F, 0x02, 0x0F, 0x03, 0x35, 0x25, 0x47, 0x04, 0x0C, 0x0B, 0x29, 0x2F, 0x05 }; portapack_lcd_data_write_command_and_data(0xE1, cmd_e1, ARRAY_SIZEOF(cmd_e1)); portapack_lcd_wake(); // Turn on Tearing Effect Line (TE) output signal. const uint8_t cmd_35[] = { 0b00000000 }; portapack_lcd_data_write_command_and_data(0x35, cmd_35, ARRAY_SIZEOF(cmd_35)); } static void portapack_lcd_ramwr_start() { const uint8_t cmd_2c[] = {}; portapack_lcd_data_write_command_and_data(0x2c, cmd_2c, ARRAY_SIZEOF(cmd_2c)); } static void portapack_lcd_set(const uint_fast8_t command, const uint_fast16_t start, const uint_fast16_t end) { const uint8_t data[] = { (start >> 8), (start & 0xff), (end >> 8), (end & 0xff) }; portapack_lcd_data_write_command_and_data(command, data, ARRAY_SIZEOF(data)); } static void portapack_lcd_caset(const uint_fast16_t start_column, uint_fast16_t end_column) { portapack_lcd_set(0x2a, start_column, end_column); } static void portapack_lcd_paset(const uint_fast16_t start_page, const uint_fast16_t end_page) { portapack_lcd_set(0x2b, start_page, end_page); } static void portapack_lcd_start_ram_write( ui_rect_t rect ) { portapack_lcd_caset(rect.point.x, rect.point.x + rect.size.width - 1); portapack_lcd_paset(rect.point.y, rect.point.y + rect.size.height - 1); portapack_lcd_ramwr_start(); } static void portapack_lcd_fill_rectangle( ui_rect_t rect, ui_color_t color ) { portapack_lcd_start_ram_write(rect); portapack_lcd_write_pixels_color(color, rect.size.width * rect.size.height); } static void portapack_draw_bitmap( const ui_point_t point, const ui_bitmap_t bitmap, const ui_color_t foreground, const ui_color_t background ) { const ui_rect_t rect = { .point = point, .size = bitmap.size }; portapack_lcd_start_ram_write(rect); const size_t count = bitmap.size.width * bitmap.size.height; for(size_t i=0; i> 3] & (1U << (i & 0x7)); portapack_lcd_write_pixel(pixel ? foreground : background); } } static ui_bitmap_t portapack_font_glyph( const ui_font_t* const font, const char c ) { if( c >= font->c_start ) { const uint_fast8_t index = c - font->c_start; if( index < font->c_count ) { const ui_bitmap_t bitmap = { .size = font->glyph_size, .data = &font->data[index * font->data_stride] }; return bitmap; } } const ui_bitmap_t bitmap = { .size = font->glyph_size, .data = font->data, }; return bitmap; } static ui_point_t portapack_lcd_draw_int(const ui_point_t point, uint64_t value, size_t field_width) { const ui_point_t point_done = { .x = point.x + font_fixed_8x16.glyph_size.width * field_width, .y = point.y }; ui_point_t point_next = point_done; for(size_t i=0; i 5) ? &font_fixed_24x19 : &font_fixed_16x14; const ui_bitmap_t glyph = portapack_font_glyph(font, c); point.x -= glyph.size.width; if( (i==3) || (i==6) || (i==9) ) { point.x -= 4; } if( (i>=6) && (value == 0) ) { /* Blank out leading zeros. */ const ui_rect_t rect = { point, glyph.size }; portapack_lcd_fill_rectangle(rect, color_background); } else { portapack_draw_bitmap(point, glyph, color_foreground, color_background); } value /= 10; } } static void portapack_ui_set_sample_rate(uint32_t sample_rate) { #if 0 ui_point_t point = { VALUES_X, 320 - 1 * 16 }; portapack_lcd_draw_int(point, sample_rate, 8); #else (void)sample_rate; #endif } static void portapack_ui_set_direction(const rf_path_direction_t direction) { switch(direction) { case RF_PATH_DIRECTION_TX: radio_draw_list[RADIO_DRAW_LIST_ITEM_RF_AMP].bitmap = portapack_lna_on ? &bitmap_amp_tx : &bitmap_wire_24; radio_draw_list[RADIO_DRAW_LIST_ITEM_BB_LNA_AMP].bitmap = &bitmap_amp_tx; radio_draw_list[RADIO_DRAW_LIST_ITEM_BB_VGA_AMP].bitmap = &bitmap_wire_24; break; case RF_PATH_DIRECTION_RX: radio_draw_list[RADIO_DRAW_LIST_ITEM_RF_AMP].bitmap = portapack_lna_on ? &bitmap_amp_rx : &bitmap_wire_24; radio_draw_list[RADIO_DRAW_LIST_ITEM_BB_LNA_AMP].bitmap = &bitmap_amp_rx; radio_draw_list[RADIO_DRAW_LIST_ITEM_BB_VGA_AMP].bitmap = &bitmap_amp_rx; break; case RF_PATH_DIRECTION_OFF: default: break; } portapack_radio_path_redraw(); portapack_direction = direction; } static void portapack_ui_set_filter_bw(uint32_t bandwidth) { ui_point_t point = { VALUES_X, radio_draw_list[RADIO_DRAW_LIST_ITEM_BB_FILTER].point.y + 4 }; portapack_ui_draw_bw_mhz(point, bandwidth); } static void portapack_ui_set_lna_power(bool lna_on) { portapack_lna_on = lna_on; radio_draw_list[RADIO_DRAW_LIST_ITEM_RF_AMP].bitmap = lna_on ? ((portapack_direction == RF_PATH_DIRECTION_TX) ? &bitmap_amp_tx : &bitmap_amp_rx) : &bitmap_wire_24; const char* const label = lna_on ? "14 dB" : " "; ui_point_t point = { VALUES_X, radio_draw_list[RADIO_DRAW_LIST_ITEM_RF_AMP].point.y + 4 }; portapack_lcd_draw_string(point, label); portapack_radio_path_redraw(); } static void portapack_ui_set_bb_lna_gain(const uint32_t gain_db) { ui_point_t point = { VALUES_X, radio_draw_list[RADIO_DRAW_LIST_ITEM_BB_LNA_AMP].point.y + 4 }; portapack_ui_draw_db(point, gain_db); } static void portapack_ui_set_bb_vga_gain(const uint32_t gain_db) { ui_point_t point = { VALUES_X, radio_draw_list[RADIO_DRAW_LIST_ITEM_BB_VGA_AMP].point.y + 4 }; portapack_ui_draw_db(point, gain_db); } static void portapack_ui_set_bb_tx_vga_gain(const uint32_t gain_db) { /* TODO: This function (and code throughout the HackRF project) is mis-labeled? * According to the MAX2837 datasheet diagram, there is no baseband gain in the TX path. * This gets called when the TX IF gain is changed. */ ui_point_t point = { VALUES_X, radio_draw_list[RADIO_DRAW_LIST_ITEM_BB_LNA_AMP].point.y + 4 }; portapack_ui_draw_db(point, gain_db); } static void portapack_ui_set_first_if_frequency(const uint64_t frequency) { (void)frequency; } static void portapack_ui_set_filter(const rf_path_filter_t filter) { radio_draw_list[RADIO_DRAW_LIST_ITEM_RF_MIXER].bitmap = (filter == RF_PATH_FILTER_BYPASS) ? &bitmap_wire_24 : &bitmap_mixer; switch(filter) { default: radio_draw_list[RADIO_DRAW_LIST_ITEM_IMAGE_FILTER].bitmap = &bitmap_wire_24; break; case RF_PATH_FILTER_LOW_PASS: radio_draw_list[RADIO_DRAW_LIST_ITEM_IMAGE_FILTER].bitmap = &bitmap_filter_lp; break; case RF_PATH_FILTER_HIGH_PASS: radio_draw_list[RADIO_DRAW_LIST_ITEM_IMAGE_FILTER].bitmap = &bitmap_filter_hp; break; } portapack_radio_path_redraw(); } static void portapack_ui_set_antenna_bias(bool antenna_bias) { (void)antenna_bias; } static const hackrf_ui_t portapack_ui = { &portapack_ui_init, &portapack_ui_set_frequency, &portapack_ui_set_sample_rate, &portapack_ui_set_direction, &portapack_ui_set_filter_bw, &portapack_ui_set_lna_power, &portapack_ui_set_bb_lna_gain, &portapack_ui_set_bb_vga_gain, &portapack_ui_set_bb_tx_vga_gain, &portapack_ui_set_first_if_frequency, &portapack_ui_set_filter, &portapack_ui_set_antenna_bias, }; const hackrf_ui_t* portapack_detect(void) { if( jtag_pp_idcode() == 0x020A50DD ) { return &portapack_ui; } else { return NULL; } }