Merge pull request #645 from jboone/master
Sync up PortaPack UI changes.
This commit is contained in:
@ -26,16 +26,6 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
static const uint8_t cpld_xc2c64a_row_address[CPLD_XC2C64A_ROWS] = {
|
||||
0x00, 0x40, 0x60, 0x20, 0x30, 0x70, 0x50, 0x10, 0x18, 0x58, 0x78, 0x38, 0x28, 0x68, 0x48, 0x08,
|
||||
0x0c, 0x4c, 0x6c, 0x2c, 0x3c, 0x7c, 0x5c, 0x1c, 0x14, 0x54, 0x74, 0x34, 0x24, 0x64, 0x44, 0x04,
|
||||
0x06, 0x46, 0x66, 0x26, 0x36, 0x76, 0x56, 0x16, 0x1e, 0x5e, 0x7e, 0x3e, 0x2e, 0x6e, 0x4e, 0x0e,
|
||||
0x0a, 0x4a, 0x6a, 0x2a, 0x3a, 0x7a, 0x5a, 0x1a, 0x12, 0x52, 0x72, 0x32, 0x22, 0x62, 0x42, 0x02,
|
||||
0x03, 0x43, 0x63, 0x23, 0x33, 0x73, 0x53, 0x13, 0x1b, 0x5b, 0x7b, 0x3b, 0x2b, 0x6b, 0x4b, 0x0b,
|
||||
0x0f, 0x4f, 0x6f, 0x2f, 0x3f, 0x7f, 0x5f, 0x1f, 0x17, 0x57, 0x77, 0x37, 0x27, 0x67, 0x47, 0x07,
|
||||
0x05, 0x45,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CPLD_XC2C_IR_INTEST = 0b00000010,
|
||||
CPLD_XC2C_IR_BYPASS = 0b11111111,
|
||||
@ -292,7 +282,7 @@ bool cpld_xc2c64a_jtag_checksum(
|
||||
|
||||
uint8_t dr[CPLD_XC2C64A_BYTES_IN_ROW];
|
||||
for(size_t row=0; row<CPLD_XC2C64A_ROWS; row++) {
|
||||
const size_t address = cpld_xc2c64a_row_address[row];
|
||||
const size_t address = cpld_hackrf_row_addresses.address[row];
|
||||
cpld_xc2c64a_jtag_read_row(jtag, address, dr);
|
||||
|
||||
const size_t mask_index = verify->mask_index[row];
|
||||
@ -388,7 +378,7 @@ void cpld_xc2c64a_jtag_sram_write(
|
||||
cpld_xc2c_jtag_sram_write(jtag);
|
||||
|
||||
for(size_t row=0; row<CPLD_XC2C64A_ROWS; row++) {
|
||||
const uint8_t address = cpld_xc2c64a_row_address[row];
|
||||
const uint8_t address = cpld_hackrf_row_addresses.address[row];
|
||||
cpld_xc2c64a_jtag_sram_write_row(jtag, address, &program->row[row].data[0]);
|
||||
}
|
||||
|
||||
@ -416,7 +406,7 @@ bool cpld_xc2c64a_jtag_sram_verify(
|
||||
const size_t mask_index = (data_row >= 0) ? verify->mask_index[data_row] : 0;
|
||||
const uint8_t* const expected = (data_row >= 0) ? &program->row[data_row].data[0] : NULL;
|
||||
const uint8_t* const mask = (data_row >= 0) ? &verify->mask[mask_index].value[0] : NULL;
|
||||
const uint8_t next_address = (address_row < CPLD_XC2C64A_ROWS) ? cpld_xc2c64a_row_address[address_row] : 0;
|
||||
const uint8_t next_address = (address_row < CPLD_XC2C64A_ROWS) ? cpld_hackrf_row_addresses.address[address_row] : 0;
|
||||
matched &= cpld_xc2c64a_jtag_sram_compare_row(jtag, expected, mask, next_address);
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,10 @@ typedef struct {
|
||||
uint8_t mask_index[CPLD_XC2C64A_ROWS];
|
||||
} cpld_xc2c64a_verify_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t address[CPLD_XC2C64A_ROWS];
|
||||
} cpld_xc2c64a_row_addresses_t;
|
||||
|
||||
bool cpld_xc2c64a_jtag_checksum(
|
||||
const jtag_t* const jtag,
|
||||
const cpld_xc2c64a_verify_t* const verify,
|
||||
@ -66,5 +70,6 @@ bool cpld_xc2c64a_jtag_sram_verify(
|
||||
|
||||
extern const cpld_xc2c64a_program_t cpld_hackrf_program_sram;
|
||||
extern const cpld_xc2c64a_verify_t cpld_hackrf_verify;
|
||||
extern const cpld_xc2c64a_row_addresses_t cpld_hackrf_row_addresses;
|
||||
|
||||
#endif/*__CPLD_XC2C_H__*/
|
||||
|
@ -41,6 +41,7 @@ void hackrf_ui_set_bb_tx_vga_gain_null(const uint32_t gain_db) { UNUSED(gain_db)
|
||||
void hackrf_ui_set_first_if_frequency_null(const uint64_t frequency) { UNUSED(frequency); }
|
||||
void hackrf_ui_set_filter_null(const rf_path_filter_t filter) { UNUSED(filter); }
|
||||
void hackrf_ui_set_antenna_bias_null(bool antenna_bias) { UNUSED(antenna_bias); }
|
||||
void hackrf_ui_set_clock_source_null(clock_source_t source) { UNUSED(source); }
|
||||
|
||||
/* Null UI function table, used if there's no hardware UI detected. Eliminates the
|
||||
* need to check for null UI before calling a function in the table.
|
||||
@ -58,19 +59,17 @@ static const hackrf_ui_t hackrf_ui_null = {
|
||||
&hackrf_ui_set_first_if_frequency_null,
|
||||
&hackrf_ui_set_filter_null,
|
||||
&hackrf_ui_set_antenna_bias_null,
|
||||
&hackrf_ui_set_clock_source_null,
|
||||
};
|
||||
|
||||
const hackrf_ui_t* portapack_detect(void) __attribute__((weak));
|
||||
const hackrf_ui_t* rad1o_ui_setup(void) __attribute__((weak));
|
||||
|
||||
static const hackrf_ui_t* ui = NULL;
|
||||
|
||||
const hackrf_ui_t* hackrf_ui(void) {
|
||||
/* Detect on first use. If no UI hardware is detected, use a stub function table. */
|
||||
if( ui == NULL ) {
|
||||
#ifdef HACKRF_ONE
|
||||
if( portapack_detect ) {
|
||||
ui = portapack_detect();
|
||||
if( portapack_hackrf_ui_init ) {
|
||||
ui = portapack_hackrf_ui_init();
|
||||
}
|
||||
#endif
|
||||
#ifdef RAD1O
|
||||
|
@ -22,7 +22,7 @@
|
||||
#ifndef HACKRF_UI_H
|
||||
#define HACKRF_UI_H
|
||||
|
||||
#include <rf_path.h>
|
||||
#include <hackrf_core.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*hackrf_ui_init_fn)(void);
|
||||
@ -37,6 +37,7 @@ typedef void (*hackrf_ui_set_bb_tx_vga_gain_fn)(const uint32_t gain_db);
|
||||
typedef void (*hackrf_ui_set_first_if_frequency_fn)(const uint64_t frequency);
|
||||
typedef void (*hackrf_ui_set_filter_fn)(const rf_path_filter_t filter);
|
||||
typedef void (*hackrf_ui_set_antenna_bias_fn)(bool antenna_bias);
|
||||
typedef void (*hackrf_ui_set_clock_source_fn)(clock_source_t source);
|
||||
|
||||
typedef struct {
|
||||
hackrf_ui_init_fn init;
|
||||
@ -51,6 +52,7 @@ typedef struct {
|
||||
hackrf_ui_set_first_if_frequency_fn set_first_if_frequency;
|
||||
hackrf_ui_set_filter_fn set_filter;
|
||||
hackrf_ui_set_antenna_bias_fn set_antenna_bias;
|
||||
hackrf_ui_set_clock_source_fn set_clock_source;
|
||||
} hackrf_ui_t;
|
||||
|
||||
/* TODO: Lame hack to know that PortaPack was detected.
|
||||
|
@ -39,6 +39,10 @@
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <libopencm3/lpc43xx/ssp.h>
|
||||
|
||||
#ifdef HACKRF_ONE
|
||||
#include "portapack.h"
|
||||
#endif
|
||||
|
||||
#include "gpio_lpc.h"
|
||||
|
||||
#define WAIT_CPU_CLOCK_INIT_DELAY (10000)
|
||||
@ -712,6 +716,41 @@ void cpu_clock_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
clock_source_t activate_best_clock_source(void)
|
||||
{
|
||||
#ifdef HACKRF_ONE
|
||||
/* Ensure PortaPack reference oscillator is off while checking for external clock input. */
|
||||
if( portapack_reference_oscillator && portapack()) {
|
||||
portapack_reference_oscillator(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
clock_source_t source = CLOCK_SOURCE_HACKRF;
|
||||
|
||||
/* Check for external clock input. */
|
||||
if (si5351c_clkin_signal_valid(&clock_gen)) {
|
||||
source = CLOCK_SOURCE_EXTERNAL;
|
||||
} else {
|
||||
#ifdef HACKRF_ONE
|
||||
/* Enable PortaPack reference oscillator (if present), and check for valid clock. */
|
||||
if( portapack_reference_oscillator && portapack() ) {
|
||||
portapack_reference_oscillator(true);
|
||||
delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */
|
||||
if (si5351c_clkin_signal_valid(&clock_gen)) {
|
||||
source = CLOCK_SOURCE_PORTAPACK;
|
||||
} else {
|
||||
portapack_reference_oscillator(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */
|
||||
}
|
||||
|
||||
si5351c_set_clock_source(&clock_gen, (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN);
|
||||
hackrf_ui()->set_clock_source(source);
|
||||
return source;
|
||||
}
|
||||
|
||||
void ssp1_set_mode_max2837(void)
|
||||
{
|
||||
spi_bus_start(max2837.bus, &ssp_config_max2837);
|
||||
|
@ -264,6 +264,12 @@ typedef enum {
|
||||
HW_SYNC_MODE_ON = 1,
|
||||
} hw_sync_mode_t;
|
||||
|
||||
typedef enum {
|
||||
CLOCK_SOURCE_HACKRF = 0,
|
||||
CLOCK_SOURCE_EXTERNAL = 1,
|
||||
CLOCK_SOURCE_PORTAPACK = 2,
|
||||
} clock_source_t;
|
||||
|
||||
void delay(uint32_t duration);
|
||||
|
||||
/* TODO: Hide these configurations */
|
||||
@ -294,6 +300,8 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom);
|
||||
bool sample_rate_set(const uint32_t sampling_rate_hz);
|
||||
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz);
|
||||
|
||||
clock_source_t activate_best_clock_source(void);
|
||||
|
||||
#if (defined HACKRF_ONE || defined RAD1O)
|
||||
void enable_rf_power(void);
|
||||
void disable_rf_power(void);
|
||||
|
577
firmware/common/portapack.c
Normal file
577
firmware/common/portapack.c
Normal file
@ -0,0 +1,577 @@
|
||||
/*
|
||||
* 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 "portapack.h"
|
||||
|
||||
#include "hackrf_core.h"
|
||||
#include "gpio_lpc.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
|
||||
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_if_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_if_t;
|
||||
|
||||
static portapack_if_t portapack_if = {
|
||||
.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_if.gpio_port_data->mask = ~gpio_data_mask;
|
||||
}
|
||||
|
||||
static void portapack_data_write_low(const uint32_t value) {
|
||||
portapack_if.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_if.gpio_port_data->mpin = value;
|
||||
}
|
||||
|
||||
static void portapack_dir_read() {
|
||||
portapack_if.gpio_port_data->dir &= ~gpio_data_mask;
|
||||
gpio_set(portapack_if.gpio_dir);
|
||||
}
|
||||
|
||||
static void portapack_dir_write() {
|
||||
gpio_clear(portapack_if.gpio_dir);
|
||||
portapack_if.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_if.gpio_lcd_rdx);
|
||||
}
|
||||
|
||||
static void portapack_lcd_rd_deassert() {
|
||||
gpio_set(portapack_if.gpio_lcd_rdx);
|
||||
}
|
||||
|
||||
static void portapack_lcd_wr_assert() {
|
||||
gpio_clear(portapack_if.gpio_lcd_wrx);
|
||||
}
|
||||
|
||||
static void portapack_lcd_wr_deassert() {
|
||||
gpio_set(portapack_if.gpio_lcd_wrx);
|
||||
}
|
||||
|
||||
static void portapack_io_stb_assert() {
|
||||
gpio_clear(portapack_if.gpio_io_stbx);
|
||||
}
|
||||
|
||||
static void portapack_io_stb_deassert() {
|
||||
gpio_set(portapack_if.gpio_io_stbx);
|
||||
}
|
||||
|
||||
static void portapack_addr(const bool value) {
|
||||
gpio_write(portapack_if.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_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_if.gpio_dir);
|
||||
gpio_output(portapack_if.gpio_lcd_rdx);
|
||||
gpio_output(portapack_if.gpio_lcd_wrx);
|
||||
gpio_output(portapack_if.gpio_io_stbx);
|
||||
gpio_output(portapack_if.gpio_addr);
|
||||
/* gpio_input(portapack_if.gpio_rot_a); */
|
||||
/* gpio_input(portapack_if.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_state(const bool active) {
|
||||
portapack_if.io_reg = (portapack_if.io_reg & 0xfe) | (active ? (1 << 0) : 0);
|
||||
portapack_io_write(1, portapack_if.io_reg);
|
||||
}
|
||||
|
||||
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; i<data_count; i++) {
|
||||
portapack_lcd_write_data(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void portapack_lcd_sleep_out() {
|
||||
const uint8_t cmd_11[] = {};
|
||||
portapack_lcd_data_write_command_and_data(0x11, cmd_11, ARRAY_SIZEOF(cmd_11));
|
||||
// "It will be necessary to wait 120msec after sending Sleep Out
|
||||
// command (when in Sleep In Mode) before Sleep In command can be
|
||||
// sent."
|
||||
portapack_sleep_milliseconds(120);
|
||||
}
|
||||
|
||||
static void portapack_lcd_display_on() {
|
||||
const uint8_t cmd_29[] = {};
|
||||
portapack_lcd_data_write_command_and_data(0x29, cmd_29, ARRAY_SIZEOF(cmd_29));
|
||||
}
|
||||
|
||||
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, const 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(
|
||||
const 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_write_pixel(const ui_color_t pixel) {
|
||||
portapack_lcd_write_data(pixel.v);
|
||||
}
|
||||
|
||||
static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n) {
|
||||
while(n--) {
|
||||
portapack_lcd_write_data(c.v);
|
||||
}
|
||||
}
|
||||
|
||||
static void portapack_lcd_wake() {
|
||||
portapack_lcd_sleep_out();
|
||||
portapack_lcd_display_on();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void portapack_backlight(const bool on) {
|
||||
portapack_if.io_reg = (portapack_if.io_reg & 0x7f) | (on ? (1 << 7) : 0);
|
||||
portapack_io_write(1, portapack_if.io_reg);
|
||||
}
|
||||
|
||||
void portapack_reference_oscillator(const bool on) {
|
||||
const uint8_t mask = 1 << 6;
|
||||
portapack_if.io_reg = (portapack_if.io_reg & ~mask) | (on ? mask : 0);
|
||||
portapack_io_write(1, portapack_if.io_reg);
|
||||
}
|
||||
|
||||
void portapack_fill_rectangle(
|
||||
const ui_rect_t rect,
|
||||
const ui_color_t color
|
||||
) {
|
||||
portapack_lcd_start_ram_write(rect);
|
||||
portapack_lcd_write_pixels_color(color, rect.size.width * rect.size.height);
|
||||
}
|
||||
|
||||
void portapack_clear_display(const ui_color_t color) {
|
||||
const ui_rect_t rect_screen = { { 0, 0 }, { 240, 320 } };
|
||||
portapack_fill_rectangle(rect_screen, color);
|
||||
}
|
||||
|
||||
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<count; i++) {
|
||||
const uint8_t pixel = bitmap.data[i >> 3] & (1U << (i & 0x7));
|
||||
portapack_lcd_write_pixel(pixel ? foreground : background);
|
||||
}
|
||||
}
|
||||
|
||||
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 bool jtag_pp_tck(const bool tms_value) {
|
||||
gpio_write(jtag_cpld.gpio->gpio_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(void) {
|
||||
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 bool portapack_detect(void) {
|
||||
return jtag_pp_idcode() == 0x020A50DD;
|
||||
}
|
||||
|
||||
static const portapack_t portapack_instance = {
|
||||
};
|
||||
|
||||
static const portapack_t* portapack_pointer = NULL;
|
||||
|
||||
const portapack_t* portapack(void) {
|
||||
return portapack_pointer;
|
||||
}
|
||||
|
||||
void portapack_init(void) {
|
||||
if( portapack_detect() ) {
|
||||
portapack_if_init();
|
||||
portapack_lcd_reset();
|
||||
portapack_lcd_init();
|
||||
portapack_pointer = &portapack_instance;
|
||||
} else {
|
||||
portapack_pointer = NULL;
|
||||
}
|
||||
}
|
95
firmware/common/portapack.h
Normal file
95
firmware/common/portapack.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __PORTAPACK_H__
|
||||
#define __PORTAPACK_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define ARRAY_SIZEOF(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
typedef struct ui_color_t {
|
||||
uint16_t v;
|
||||
} ui_color_t;
|
||||
|
||||
typedef struct ui_point_t {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
} ui_point_t;
|
||||
|
||||
typedef struct ui_size_t {
|
||||
int16_t width;
|
||||
int16_t height;
|
||||
} ui_size_t;
|
||||
|
||||
typedef struct ui_rect_t {
|
||||
ui_point_t point;
|
||||
ui_size_t size;
|
||||
} ui_rect_t;
|
||||
|
||||
typedef struct ui_bitmap_t {
|
||||
ui_size_t size;
|
||||
const uint8_t* const data;
|
||||
} ui_bitmap_t;
|
||||
|
||||
typedef struct ui_font_t {
|
||||
const ui_size_t glyph_size;
|
||||
const uint8_t* const data;
|
||||
char c_start;
|
||||
size_t c_count;
|
||||
size_t data_stride;
|
||||
} ui_font_t;
|
||||
|
||||
typedef struct portapack_t {
|
||||
} portapack_t;
|
||||
|
||||
void portapack_init(void);
|
||||
|
||||
/* If the "portapack" symbol is defined, PortaPack support is compiled in */
|
||||
/* If the portapack() call returns non-NULL, a PortaPack was detected and is initialized. */
|
||||
const portapack_t* portapack(void) __attribute__((weak));
|
||||
|
||||
void portapack_backlight(const bool on);
|
||||
|
||||
void portapack_reference_oscillator(const bool on) __attribute__((weak));
|
||||
|
||||
void portapack_fill_rectangle(
|
||||
const ui_rect_t rect,
|
||||
const ui_color_t color
|
||||
);
|
||||
|
||||
void portapack_clear_display(const ui_color_t color);
|
||||
|
||||
void portapack_draw_bitmap(
|
||||
const ui_point_t point,
|
||||
const ui_bitmap_t bitmap,
|
||||
const ui_color_t foreground,
|
||||
const ui_color_t background
|
||||
);
|
||||
|
||||
ui_bitmap_t portapack_font_glyph(
|
||||
const ui_font_t* const font,
|
||||
const char c
|
||||
);
|
||||
|
||||
#endif/*__PORTAPACK_H__*/
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "si5351c.h"
|
||||
|
||||
enum pll_sources active_clock_source;
|
||||
enum pll_sources active_clock_source = PLL_SOURCE_UNINITIALIZED;
|
||||
|
||||
/* write to single register */
|
||||
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val)
|
||||
@ -239,25 +239,14 @@ void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_num
|
||||
|
||||
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source)
|
||||
{
|
||||
si5351c_configure_clock_control(drv, source);
|
||||
active_clock_source = source;
|
||||
if( source != active_clock_source ) {
|
||||
si5351c_configure_clock_control(drv, source);
|
||||
active_clock_source = source;
|
||||
}
|
||||
}
|
||||
|
||||
void si5351c_activate_best_clock_source(si5351c_driver_t* const drv)
|
||||
{
|
||||
uint8_t device_status = si5351c_read_single(drv, 0);
|
||||
|
||||
if (device_status & SI5351C_LOS) {
|
||||
/* CLKIN not detected */
|
||||
if (active_clock_source == PLL_SOURCE_CLKIN) {
|
||||
si5351c_set_clock_source(drv, PLL_SOURCE_XTAL);
|
||||
}
|
||||
} else {
|
||||
/* CLKIN detected */
|
||||
if (active_clock_source == PLL_SOURCE_XTAL) {
|
||||
si5351c_set_clock_source(drv, PLL_SOURCE_CLKIN);
|
||||
}
|
||||
}
|
||||
bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) {
|
||||
return (si5351c_read_single(drv, 0) & SI5351C_LOS) == 0;
|
||||
}
|
||||
|
||||
void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable)
|
||||
|
@ -29,6 +29,7 @@ extern "C"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "i2c_bus.h"
|
||||
|
||||
@ -59,6 +60,7 @@ extern "C"
|
||||
#define SI5351C_LOS (1<<4)
|
||||
|
||||
enum pll_sources {
|
||||
PLL_SOURCE_UNINITIALIZED = -1,
|
||||
PLL_SOURCE_XTAL = 0,
|
||||
PLL_SOURCE_CLKIN = 1,
|
||||
};
|
||||
@ -84,7 +86,7 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll
|
||||
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv);
|
||||
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on);
|
||||
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source);
|
||||
void si5351c_activate_best_clock_source(si5351c_driver_t* const drv);
|
||||
bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv);
|
||||
|
||||
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val);
|
||||
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg);
|
||||
|
@ -19,16 +19,9 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "hackrf-ui.h"
|
||||
|
||||
#include "ui_portapack.h"
|
||||
|
||||
#include "hackrf_core.h"
|
||||
#include "gpio_lpc.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include "portapack.h"
|
||||
|
||||
/* Pixel data within a font or bitmap byte is "reversed": LSB is left-most pixel. */
|
||||
|
||||
@ -225,6 +218,14 @@ static const ui_bitmap_t bitmap_mixer = {
|
||||
{ 24, 24 }, bitmap_mixer_data
|
||||
};
|
||||
|
||||
static const uint8_t bitmap_oscillator_data[] = {
|
||||
0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0x81, 0x07, 0x70, 0x00, 0x0e, 0x38, 0x00, 0x1c, 0x1c, 0x00, 0x38, 0x0e, 0x03, 0x70, 0x86, 0x07, 0x60, 0xc6, 0x0f, 0x60, 0xc3, 0x0c, 0xc0, 0xe3, 0x1c, 0xc0, 0x63, 0x18, 0xc6, 0x63, 0x18, 0xc6, 0x03, 0x38, 0xc7, 0x03, 0x30, 0xc3, 0x06, 0xf0, 0x63, 0x06, 0xe0, 0x61, 0x0e, 0xc0, 0x70, 0x1c, 0x00, 0x38, 0x38, 0x00, 0x1c, 0x70, 0x00, 0x0e, 0xe0, 0x81, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00
|
||||
};
|
||||
|
||||
static const ui_bitmap_t bitmap_oscillator = {
|
||||
{ 24, 24 }, bitmap_oscillator_data
|
||||
};
|
||||
|
||||
static const uint8_t bitmap_wire_8_data[] = {
|
||||
0xff, 0xff
|
||||
};
|
||||
@ -241,12 +242,28 @@ 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
|
||||
static const uint8_t bitmap_blank_24_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
__attribute__((unused)) static const ui_bitmap_t bitmap_waves = {
|
||||
{ 16, 20 }, bitmap_waves_data
|
||||
static const ui_bitmap_t bitmap_blank_24 = {
|
||||
{ 24, 24 }, bitmap_blank_24_data
|
||||
};
|
||||
|
||||
static const uint8_t bitmap_waves_rx_data[] = {
|
||||
0xc0, 0x00, 0x60, 0x00, 0x70, 0x06, 0x30, 0x07, 0x38, 0x03, 0x98, 0x33, 0x98, 0x39, 0x98, 0x19, 0xcc, 0x18, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x18, 0x98, 0x19, 0x98, 0x39, 0x98, 0x33, 0x38, 0x03, 0x30, 0x07, 0x70, 0x06, 0x60, 0x00, 0xc0, 0x00
|
||||
};
|
||||
|
||||
static const ui_bitmap_t bitmap_waves_rx = {
|
||||
{ 16, 24 }, bitmap_waves_rx_data
|
||||
};
|
||||
|
||||
static const uint8_t bitmap_waves_tx_data[] = {
|
||||
0x00, 0x03, 0x00, 0x06, 0x60, 0x0e, 0xe0, 0x0c, 0xc0, 0x1c, 0xcc, 0x19, 0x9c, 0x19, 0x98, 0x19, 0x18, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x18, 0x33, 0x98, 0x19, 0x9c, 0x19, 0xcc, 0x19, 0xc0, 0x1c, 0xe0, 0x0c, 0x60, 0x0e, 0x00, 0x06, 0x00, 0x03
|
||||
};
|
||||
|
||||
static const ui_bitmap_t bitmap_waves_tx = {
|
||||
{ 16, 24 }, bitmap_waves_tx_data
|
||||
};
|
||||
|
||||
__attribute__((unused)) static ui_color_t portapack_color_rgb(
|
||||
@ -263,524 +280,6 @@ __attribute__((unused)) static ui_color_t portapack_color_rgb(
|
||||
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; i<data_count; i++) {
|
||||
portapack_lcd_write_data(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void portapack_lcd_write_pixel(const ui_color_t pixel) {
|
||||
portapack_lcd_write_data(pixel.v);
|
||||
}
|
||||
|
||||
static void portapack_lcd_write_pixels_color(ui_color_t c, size_t n) {
|
||||
while(n--) {
|
||||
portapack_lcd_write_data(c.v);
|
||||
}
|
||||
}
|
||||
|
||||
static void portapack_backlight(const bool on) {
|
||||
portapack.io_reg = (portapack.io_reg & 0x7f) | (on ? (1 << 7) : 0);
|
||||
portapack_io_write(1, portapack.io_reg);
|
||||
}
|
||||
|
||||
static void portapack_lcd_reset_state(const bool active) {
|
||||
portapack.io_reg = (portapack.io_reg & 0xfe) | (active ? (1 << 0) : 0);
|
||||
portapack_io_write(1, portapack.io_reg);
|
||||
}
|
||||
|
||||
static void portapack_lcd_sleep_out() {
|
||||
const uint8_t cmd_11[] = {};
|
||||
portapack_lcd_data_write_command_and_data(0x11, cmd_11, ARRAY_SIZEOF(cmd_11));
|
||||
// "It will be necessary to wait 120msec after sending Sleep Out
|
||||
// command (when in Sleep In Mode) before Sleep In command can be
|
||||
// sent."
|
||||
portapack_sleep_milliseconds(120);
|
||||
}
|
||||
|
||||
static void portapack_lcd_display_on() {
|
||||
const uint8_t cmd_29[] = {};
|
||||
portapack_lcd_data_write_command_and_data(0x29, cmd_29, ARRAY_SIZEOF(cmd_29));
|
||||
}
|
||||
|
||||
static void portapack_lcd_wake() {
|
||||
portapack_lcd_sleep_out();
|
||||
portapack_lcd_display_on();
|
||||
}
|
||||
|
||||
static bool jtag_pp_tck(const bool tms_value) {
|
||||
gpio_write(jtag_cpld.gpio->gpio_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<count; i++) {
|
||||
const uint8_t pixel = bitmap.data[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,
|
||||
@ -811,33 +310,30 @@ static ui_point_t portapack_lcd_draw_string(ui_point_t point, const char* s) {
|
||||
return point;
|
||||
}
|
||||
|
||||
static void portapack_lcd_clear() {
|
||||
const ui_rect_t rect_screen = { { 0, 0 }, { 240, 320 } };
|
||||
portapack_lcd_fill_rectangle(rect_screen, color_background);
|
||||
}
|
||||
|
||||
typedef struct draw_list_t {
|
||||
const ui_bitmap_t* bitmap;
|
||||
const ui_point_t point;
|
||||
} draw_list_t;
|
||||
|
||||
static draw_list_t radio_draw_list[] = {
|
||||
{ &bitmap_antenna, { 32, 64 } },
|
||||
{ &bitmap_wire_8, { 43, 88 } },
|
||||
{ &bitmap_amp_rx, { 32, 96 } },
|
||||
{ &bitmap_wire_8, { 43, 120 } },
|
||||
{ &bitmap_filter_hp, { 32, 128 } },
|
||||
{ &bitmap_wire_8, { 43, 152 } },
|
||||
{ &bitmap_mixer, { 32, 160 } },
|
||||
{ &bitmap_wire_8, { 43, 184 } },
|
||||
{ &bitmap_amp_rx, { 32, 192 } },
|
||||
{ &bitmap_wire_8, { 43, 216 } },
|
||||
{ &bitmap_mixer, { 32, 224 } },
|
||||
{ &bitmap_wire_8, { 43, 248 } },
|
||||
{ &bitmap_filter_lp, { 32, 256 } },
|
||||
{ &bitmap_wire_8, { 43, 280 } },
|
||||
{ &bitmap_amp_rx, { 32, 288 } },
|
||||
{ &bitmap_wire_8, { 43, 312 } },
|
||||
{ &bitmap_antenna, { 32, 64 } },
|
||||
{ &bitmap_wire_8, { 43, 88 } },
|
||||
{ &bitmap_wire_24, { 32, 96 } },
|
||||
{ &bitmap_wire_8, { 43, 120 } },
|
||||
{ &bitmap_filter_hp, { 32, 128 } },
|
||||
{ &bitmap_wire_8, { 43, 152 } },
|
||||
{ &bitmap_mixer, { 32, 160 } },
|
||||
{ &bitmap_wire_8, { 43, 184 } },
|
||||
{ &bitmap_amp_rx, { 32, 192 } },
|
||||
{ &bitmap_wire_8, { 43, 216 } },
|
||||
{ &bitmap_mixer, { 32, 224 } },
|
||||
{ &bitmap_wire_8, { 43, 248 } },
|
||||
{ &bitmap_filter_lp, { 32, 256 } },
|
||||
{ &bitmap_wire_8, { 43, 280 } },
|
||||
{ &bitmap_amp_rx, { 32, 288 } },
|
||||
{ &bitmap_wire_8, { 43, 312 } },
|
||||
{ &bitmap_oscillator, { 208, 288 } },
|
||||
{ &bitmap_blank_24, { 60, 60 } },
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@ -848,17 +344,28 @@ typedef enum {
|
||||
RADIO_DRAW_LIST_ITEM_BB_LNA_AMP = 8,
|
||||
RADIO_DRAW_LIST_ITEM_BB_MIXER = 10,
|
||||
RADIO_DRAW_LIST_ITEM_BB_FILTER = 12,
|
||||
RADIO_DRAW_LIST_ITEM_BB_VGA_AMP = 14
|
||||
RADIO_DRAW_LIST_ITEM_BB_VGA_AMP = 14,
|
||||
RADIO_DRAW_LIST_ITEM_CLOCK = 16,
|
||||
RADIO_DRAW_LIST_ITEM_WAVES = 17,
|
||||
} radio_draw_list_item_t;
|
||||
|
||||
static const uint8_t VALUES_X = 72;
|
||||
static ui_point_t portapack_ui_label_point(const radio_draw_list_item_t item) {
|
||||
const uint8_t VALUES_X = 72;
|
||||
ui_point_t point = { VALUES_X, radio_draw_list[item].point.y + 4 };
|
||||
return point;
|
||||
}
|
||||
|
||||
static ui_point_t portapack_ui_draw_db(ui_point_t point, const uint32_t db) {
|
||||
static ui_point_t portapack_ui_draw_string(const radio_draw_list_item_t item, const char* s) {
|
||||
return portapack_lcd_draw_string(portapack_ui_label_point(item), s);
|
||||
}
|
||||
|
||||
static ui_point_t portapack_ui_draw_db(const radio_draw_list_item_t item, const uint32_t db) {
|
||||
ui_point_t point = portapack_ui_label_point(item);
|
||||
point = portapack_lcd_draw_int(point, db, 2);
|
||||
return portapack_lcd_draw_string(point, " dB");
|
||||
}
|
||||
|
||||
static ui_point_t portapack_ui_draw_bw_mhz(ui_point_t point, const uint64_t hz) {
|
||||
static ui_point_t portapack_ui_draw_bw_mhz(const radio_draw_list_item_t item, const uint64_t hz) {
|
||||
const uint32_t lsd = 1000000 / 100;
|
||||
const uint32_t round_offset = lsd / 2;
|
||||
|
||||
@ -866,18 +373,21 @@ static ui_point_t portapack_ui_draw_bw_mhz(ui_point_t point, const uint64_t hz)
|
||||
const uint32_t mhz = hz_offset / 1000000;
|
||||
const uint32_t frac = hz_offset / lsd;
|
||||
|
||||
ui_point_t point = portapack_ui_label_point(item);
|
||||
point = portapack_lcd_draw_int(point, mhz, 2);
|
||||
point = portapack_lcd_draw_string(point, ".");
|
||||
point = portapack_lcd_draw_int(point, frac, 2);
|
||||
return portapack_lcd_draw_string(point, " MHz");
|
||||
}
|
||||
|
||||
static void portapack_draw_radio_path(
|
||||
const draw_list_t* const draw_list,
|
||||
const size_t count
|
||||
) {
|
||||
for( size_t i=0; i<count; i++ ) {
|
||||
portapack_draw_bitmap(draw_list[i].point, *draw_list[i].bitmap, color_foreground, color_background);
|
||||
static void portapack_draw_radio_path_item(const radio_draw_list_item_t item) {
|
||||
portapack_draw_bitmap(radio_draw_list[item].point, *radio_draw_list[item].bitmap, color_foreground, color_background);
|
||||
}
|
||||
|
||||
static void portapack_radio_path_item_update(const radio_draw_list_item_t item, const ui_bitmap_t* const bitmap) {
|
||||
if( bitmap != radio_draw_list[item].bitmap ) {
|
||||
radio_draw_list[item].bitmap = bitmap;
|
||||
portapack_draw_radio_path_item(item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -885,41 +395,51 @@ static rf_path_direction_t portapack_direction = RF_PATH_DIRECTION_OFF;
|
||||
static bool portapack_lna_on = false;
|
||||
|
||||
static void portapack_radio_path_redraw() {
|
||||
portapack_draw_radio_path(radio_draw_list, ARRAY_SIZEOF(radio_draw_list));
|
||||
for( size_t i=0; i<ARRAY_SIZEOF(radio_draw_list); i++ ) {
|
||||
portapack_draw_radio_path_item(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void portapack_ui_init() {
|
||||
portapack_if_init();
|
||||
portapack_lcd_reset();
|
||||
portapack_lcd_init();
|
||||
portapack_lcd_clear();
|
||||
portapack_backlight(1);
|
||||
static void portapack_ui_init(void) {
|
||||
portapack_clear_display(color_background);
|
||||
portapack_backlight(true);
|
||||
portapack_radio_path_redraw();
|
||||
}
|
||||
|
||||
static void portapack_ui_set_frequency(uint64_t frequency) {
|
||||
static char last[10] = " ";
|
||||
|
||||
ui_point_t point = { 240 - 20, 16 };
|
||||
|
||||
uint64_t value = frequency;
|
||||
char s[10];
|
||||
for(int i=0; i<10; i++) {
|
||||
const char c = '0' + value % 10;
|
||||
s[i] = ((i>=6) && (value == 0)) ? ' ' : c;
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
for(int i=0; i<10; i++) {
|
||||
const char c = s[i];
|
||||
|
||||
const ui_font_t* const font = (i > 5) ? &font_fixed_24x19 : &font_fixed_16x14;
|
||||
const ui_bitmap_t glyph = portapack_font_glyph(font, c);
|
||||
|
||||
point.x -= glyph.size.width;
|
||||
point.x -= font->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);
|
||||
}
|
||||
if( c != last[i] ) {
|
||||
const ui_bitmap_t glyph = portapack_font_glyph(font, c);
|
||||
|
||||
value /= 10;
|
||||
if( c == ' ' ) {
|
||||
/* Blank out leading zeros. */
|
||||
const ui_rect_t rect = { point, glyph.size };
|
||||
portapack_fill_rectangle(rect, color_background);
|
||||
} else {
|
||||
portapack_draw_bitmap(point, glyph, color_foreground, color_background);
|
||||
}
|
||||
last[i] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -935,51 +455,48 @@ static void portapack_ui_set_sample_rate(uint32_t sample_rate) {
|
||||
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;
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_WAVES, &bitmap_waves_tx);
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_AMP, portapack_lna_on ? &bitmap_amp_tx : &bitmap_wire_24);
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, &bitmap_amp_tx);
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, &bitmap_wire_24);
|
||||
portapack_ui_draw_string(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, " ");
|
||||
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;
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_WAVES, &bitmap_waves_rx);
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_AMP, portapack_lna_on ? &bitmap_amp_rx : &bitmap_wire_24);
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, &bitmap_amp_rx);
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, &bitmap_amp_rx);
|
||||
break;
|
||||
|
||||
case RF_PATH_DIRECTION_OFF:
|
||||
default:
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_WAVES, &bitmap_blank_24);
|
||||
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);
|
||||
portapack_ui_draw_bw_mhz(RADIO_DRAW_LIST_ITEM_BB_FILTER, 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_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_AMP, lna_on
|
||||
? ((portapack_direction == RF_PATH_DIRECTION_TX) ? &bitmap_amp_tx : &bitmap_amp_rx)
|
||||
: &bitmap_wire_24;
|
||||
: &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();
|
||||
portapack_ui_draw_string(RADIO_DRAW_LIST_ITEM_RF_AMP, label);
|
||||
}
|
||||
|
||||
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);
|
||||
portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, 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);
|
||||
portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, gain_db);
|
||||
}
|
||||
|
||||
static void portapack_ui_set_bb_tx_vga_gain(const uint32_t gain_db) {
|
||||
@ -987,8 +504,7 @@ static void portapack_ui_set_bb_tx_vga_gain(const uint32_t gain_db) {
|
||||
* 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);
|
||||
portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db);
|
||||
}
|
||||
|
||||
static void portapack_ui_set_first_if_frequency(const uint64_t frequency) {
|
||||
@ -996,30 +512,44 @@ static void portapack_ui_set_first_if_frequency(const uint64_t 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;
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_MIXER, (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;
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_IMAGE_FILTER, &bitmap_wire_24);
|
||||
break;
|
||||
|
||||
case RF_PATH_FILTER_LOW_PASS:
|
||||
radio_draw_list[RADIO_DRAW_LIST_ITEM_IMAGE_FILTER].bitmap = &bitmap_filter_lp;
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_IMAGE_FILTER, &bitmap_filter_lp);
|
||||
break;
|
||||
|
||||
case RF_PATH_FILTER_HIGH_PASS:
|
||||
radio_draw_list[RADIO_DRAW_LIST_ITEM_IMAGE_FILTER].bitmap = &bitmap_filter_hp;
|
||||
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_IMAGE_FILTER, &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 = {
|
||||
static void portapack_ui_set_clock_source(clock_source_t source) {
|
||||
ui_point_t label_point = radio_draw_list[RADIO_DRAW_LIST_ITEM_CLOCK].point;
|
||||
label_point.x -= 0;
|
||||
label_point.y -= 16;
|
||||
|
||||
const char* s = "HRF";
|
||||
switch(source) {
|
||||
case CLOCK_SOURCE_EXTERNAL: { s = "EXT"; break; }
|
||||
case CLOCK_SOURCE_PORTAPACK: { s = "PPK"; break; }
|
||||
default:
|
||||
case CLOCK_SOURCE_HACKRF: { s = "HRF"; break; }
|
||||
}
|
||||
|
||||
portapack_lcd_draw_string(label_point, s);
|
||||
}
|
||||
|
||||
const hackrf_ui_t portapack_hackrf_ui = {
|
||||
&portapack_ui_init,
|
||||
&portapack_ui_set_frequency,
|
||||
&portapack_ui_set_sample_rate,
|
||||
@ -1032,11 +562,12 @@ static const hackrf_ui_t portapack_ui = {
|
||||
&portapack_ui_set_first_if_frequency,
|
||||
&portapack_ui_set_filter,
|
||||
&portapack_ui_set_antenna_bias,
|
||||
&portapack_ui_set_clock_source,
|
||||
};
|
||||
|
||||
const hackrf_ui_t* portapack_detect(void) {
|
||||
if( jtag_pp_idcode() == 0x020A50DD ) {
|
||||
return &portapack_ui;
|
||||
const hackrf_ui_t* portapack_hackrf_ui_init() {
|
||||
if( portapack() ) {
|
||||
return &portapack_hackrf_ui;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -22,40 +22,8 @@
|
||||
#ifndef __UI_PORTAPACK_H__
|
||||
#define __UI_PORTAPACK_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include "hackrf-ui.h"
|
||||
|
||||
typedef struct ui_color_t {
|
||||
uint16_t v;
|
||||
} ui_color_t;
|
||||
|
||||
typedef struct ui_point_t {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
} ui_point_t;
|
||||
|
||||
typedef struct ui_size_t {
|
||||
int16_t width;
|
||||
int16_t height;
|
||||
} ui_size_t;
|
||||
|
||||
typedef struct ui_rect_t {
|
||||
ui_point_t point;
|
||||
ui_size_t size;
|
||||
} ui_rect_t;
|
||||
|
||||
typedef struct ui_bitmap_t {
|
||||
ui_size_t size;
|
||||
const uint8_t* const data;
|
||||
} ui_bitmap_t;
|
||||
|
||||
typedef struct ui_font_t {
|
||||
const ui_size_t glyph_size;
|
||||
const uint8_t* const data;
|
||||
char c_start;
|
||||
size_t c_count;
|
||||
size_t data_stride;
|
||||
} ui_font_t;
|
||||
|
||||
const hackrf_ui_t* portapack_detect(void);
|
||||
const hackrf_ui_t* portapack_hackrf_ui_init() __attribute__((weak));
|
||||
|
||||
#endif/*__UI_PORTAPACK_H__*/
|
||||
|
@ -19,7 +19,6 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "hackrf-ui.h"
|
||||
#include "ui_rad1o.h"
|
||||
|
||||
/* Weak functions from rad1o app */
|
||||
@ -35,6 +34,7 @@ void hackrf_ui_setBBTXVGAGain(const uint32_t gain_db) __attribute__((weak));
|
||||
void hackrf_ui_setFirstIFFrequency(const uint64_t freq) __attribute__((weak));
|
||||
void hackrf_ui_setFilter(const rf_path_filter_t filter) __attribute__((weak));
|
||||
void hackrf_ui_setAntennaBias(bool antenna_bias) __attribute__((weak));
|
||||
void hackrf_ui_setClockSource(clock_source_t source) __attribute__((weak));
|
||||
|
||||
static void rad1o_ui_init(void) {
|
||||
hackrf_ui_init();
|
||||
@ -84,6 +84,10 @@ static void rad1o_ui_set_antenna_bias(bool antenna_bias) {
|
||||
hackrf_ui_setAntennaBias(antenna_bias);
|
||||
}
|
||||
|
||||
static void rad1o_ui_set_clock_source(clock_source_t source) {
|
||||
hackrf_ui_setClockSource(source);
|
||||
}
|
||||
|
||||
static const hackrf_ui_t rad1o_ui = {
|
||||
&rad1o_ui_init,
|
||||
&rad1o_ui_set_frequency,
|
||||
@ -97,6 +101,7 @@ static const hackrf_ui_t rad1o_ui = {
|
||||
&rad1o_ui_set_first_if_frequency,
|
||||
&rad1o_ui_set_filter,
|
||||
&rad1o_ui_set_antenna_bias,
|
||||
&rad1o_ui_set_clock_source,
|
||||
};
|
||||
|
||||
const hackrf_ui_t* rad1o_ui_setup(void) {
|
||||
|
@ -22,6 +22,8 @@
|
||||
#ifndef __UI_RAD1O_H__
|
||||
#define __UI_RAD1O_H__
|
||||
|
||||
const hackrf_ui_t* rad1o_ui_setup(void);
|
||||
#include "hackrf-ui.h"
|
||||
|
||||
const hackrf_ui_t* rad1o_ui_setup(void) __attribute__((weak));
|
||||
|
||||
#endif/*__UI_RAD1O_H__*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -82,7 +82,7 @@ SET(HACKRF_OPTS "-D${BOARD} -DLPC43XX -D${MCU_PARTNO} -DTX_ENABLE -D'VERSION_STR
|
||||
|
||||
SET(LDSCRIPT_M4 "-T${PATH_HACKRF_FIRMWARE_COMMON}/${MCU_PARTNO}_M4_memory.ld -Tlibopencm3_lpc43xx_rom_to_ram.ld -T${PATH_HACKRF_FIRMWARE_COMMON}/LPC43xx_M4_M0_image_from_text.ld")
|
||||
|
||||
SET(LDSCRIPT_M4_DFU "-T${PATH_HACKRF_FIRMWARE_COMMON}/${MCU_PARTNO}_M4_memory.ld -Tlibopencm3_lpc43xx.ld -T${PATH_HACKRF_FIRMWARE_COMMON}/LPC43xx_M4_M0_image_from_text.ld")
|
||||
SET(LDSCRIPT_M4_RAM "-T${PATH_HACKRF_FIRMWARE_COMMON}/${MCU_PARTNO}_M4_memory.ld -Tlibopencm3_lpc43xx.ld -T${PATH_HACKRF_FIRMWARE_COMMON}/LPC43xx_M4_M0_image_from_text.ld")
|
||||
|
||||
SET(LDSCRIPT_M0 "-T${PATH_HACKRF_FIRMWARE_COMMON}/LPC43xx_M0_memory.ld -Tlibopencm3_lpc43xx_m0.ld")
|
||||
|
||||
@ -103,14 +103,38 @@ SET(CFLAGS_M4 "-std=gnu99 ${CFLAGS_COMMON} ${CPUFLAGS_M4} -DLPC43XX_M4")
|
||||
SET(CXXFLAGS_M4 "-std=gnu++0x ${CFLAGS_COMMON} ${CPUFLAGS_M4} -DLPC43XX_M4")
|
||||
SET(LDFLAGS_M4 "${LDFLAGS_COMMON} ${CPUFLAGS_M4} ${LDSCRIPT_M4} -Xlinker -Map=m4.map")
|
||||
|
||||
SET(CFLAGS_M4_DFU "-std=gnu99 ${CFLAGS_COMMON} ${CPUFLAGS_M4} -DLPC43XX_M4 -DDFU_MODE")
|
||||
SET(LDFLAGS_M4_DFU "${LDFLAGS_COMMON} ${CPUFLAGS_M4} ${LDSCRIPT_M4_DFU} -Xlinker -Map=m4.map")
|
||||
SET(CFLAGS_M4_RAM "-std=gnu99 ${CFLAGS_COMMON} ${CPUFLAGS_M4} -DLPC43XX_M4")
|
||||
SET(LDFLAGS_M4_RAM "${LDFLAGS_COMMON} ${CPUFLAGS_M4} ${LDSCRIPT_M4_RAM} -Xlinker -Map=m4.map")
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
include_directories("${LIBOPENCM3}/include/")
|
||||
include_directories("${PATH_HACKRF_FIRMWARE_COMMON}")
|
||||
|
||||
macro(DeclareTarget project_name variant_suffix cflags ldflags)
|
||||
add_library(${project_name}${variant_suffix}_objects OBJECT ${SRC_M4} m0_bin.s)
|
||||
set_target_properties(${project_name}${variant_suffix}_objects PROPERTIES COMPILE_FLAGS "${cflags}")
|
||||
add_dependencies(${project_name}${variant_suffix}_objects ${project_name}_m0.bin)
|
||||
add_executable(${project_name}${variant_suffix}.elf $<TARGET_OBJECTS:${project_name}${variant_suffix}_objects>)
|
||||
add_dependencies(${project_name}${variant_suffix}.elf libopencm3_${project_name})
|
||||
|
||||
target_link_libraries(
|
||||
${project_name}${variant_suffix}.elf
|
||||
c
|
||||
nosys
|
||||
opencm3_lpc43xx
|
||||
m
|
||||
)
|
||||
|
||||
set_target_properties(${project_name}${variant_suffix}.elf PROPERTIES LINK_FLAGS "${ldflags}")
|
||||
|
||||
add_custom_target(
|
||||
${project_name}${variant_suffix}.bin ALL
|
||||
DEPENDS ${project_name}${variant_suffix}.elf
|
||||
COMMAND ${CMAKE_OBJCOPY} -Obinary ${project_name}${variant_suffix}.elf ${project_name}${variant_suffix}.bin
|
||||
)
|
||||
endmacro()
|
||||
|
||||
macro(DeclareTargets)
|
||||
SET(SRC_M4
|
||||
${SRC_M4}
|
||||
@ -178,52 +202,9 @@ macro(DeclareTargets)
|
||||
COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_NAME}_m0.elf ${PROJECT_NAME}_m0.bin
|
||||
)
|
||||
|
||||
# Object files to be linked for SPI flash versions
|
||||
add_library(${PROJECT_NAME}_objects OBJECT ${SRC_M4} m0_bin.s)
|
||||
set_target_properties(${PROJECT_NAME}_objects PROPERTIES COMPILE_FLAGS "${CFLAGS_M4}")
|
||||
add_dependencies(${PROJECT_NAME}_objects ${PROJECT_NAME}_m0.bin)
|
||||
add_executable(${PROJECT_NAME}.elf $<TARGET_OBJECTS:${PROJECT_NAME}_objects>)
|
||||
add_dependencies(${PROJECT_NAME}.elf libopencm3_${PROJECT_NAME})
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME}.elf
|
||||
c
|
||||
nosys
|
||||
opencm3_lpc43xx
|
||||
m
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_FLAGS "${LDFLAGS_M4}")
|
||||
|
||||
add_custom_target(
|
||||
${PROJECT_NAME}.bin ALL
|
||||
DEPENDS ${PROJECT_NAME}.elf
|
||||
COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
|
||||
)
|
||||
|
||||
# DFU - using a differnet LD script to run directly from RAM
|
||||
# Object files to be linked for DFU flash versions
|
||||
add_library(${PROJECT_NAME}_dfu_objects OBJECT ${SRC_M4} m0_bin.s)
|
||||
set_target_properties(${PROJECT_NAME}_dfu_objects PROPERTIES COMPILE_FLAGS "${CFLAGS_M4_DFU}")
|
||||
add_dependencies(${PROJECT_NAME}_dfu_objects ${PROJECT_NAME}_m0.bin)
|
||||
add_executable(${PROJECT_NAME}_dfu.elf $<TARGET_OBJECTS:${PROJECT_NAME}_dfu_objects>)
|
||||
add_dependencies(${PROJECT_NAME}_dfu.elf libopencm3_${PROJECT_NAME})
|
||||
|
||||
target_link_libraries(
|
||||
${PROJECT_NAME}_dfu.elf
|
||||
c
|
||||
nosys
|
||||
opencm3_lpc43xx
|
||||
m
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT_NAME}_dfu.elf PROPERTIES LINK_FLAGS "${LDFLAGS_M4_DFU}")
|
||||
|
||||
add_custom_target(
|
||||
${PROJECT_NAME}_dfu.bin
|
||||
DEPENDS ${PROJECT_NAME}_dfu.elf
|
||||
COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_NAME}_dfu.elf ${PROJECT_NAME}_dfu.bin
|
||||
)
|
||||
DeclareTarget("${PROJECT_NAME}" "" "${CFLAGS_M4}" "${LDFLAGS_M4}")
|
||||
DeclareTarget("${PROJECT_NAME}" "_ram" "${CFLAGS_M4_RAM}" "${LDFLAGS_M4_RAM}")
|
||||
DeclareTarget("${PROJECT_NAME}" "_dfu" "${CFLAGS_M4_RAM} -DDFU_MODE" "${LDFLAGS_M4_RAM}")
|
||||
|
||||
add_custom_target(
|
||||
${PROJECT_NAME}.dfu ${DFU_ALL}
|
||||
|
@ -27,7 +27,7 @@ include(../hackrf-common.cmake)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PATH_HACKRF_CPLD_DATA_C}
|
||||
COMMAND ${PATH_CPLD_BITSTREAM_TOOL} --code ${PATH_HACKRF_CPLD_XSVF} >${PATH_HACKRF_CPLD_DATA_C}
|
||||
COMMAND ${PATH_CPLD_BITSTREAM_TOOL} --xsvf ${PATH_HACKRF_CPLD_XSVF} --hackrf-data ${PATH_HACKRF_CPLD_DATA_C}
|
||||
DEPENDS ${PATH_CPLD_BITSTREAM_TOOL} ${PATH_HACKRF_CPLD_XSVF}
|
||||
)
|
||||
|
||||
@ -66,6 +66,7 @@ set(SRC_M4
|
||||
if(BOARD STREQUAL "HACKRF_ONE")
|
||||
SET(SRC_M4
|
||||
${SRC_M4}
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/portapack.c"
|
||||
"${PATH_HACKRF_FIRMWARE_COMMON}/ui_portapack.c"
|
||||
)
|
||||
endif()
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "usb_api_transceiver.h"
|
||||
#include "usb_bulk_buffer.h"
|
||||
#include "cpld_xc2c.h"
|
||||
#include "portapack.h"
|
||||
|
||||
#include "hackrf-ui.h"
|
||||
|
||||
@ -191,6 +192,10 @@ int main(void) {
|
||||
halt_and_flash(6000000);
|
||||
}
|
||||
|
||||
#ifdef HACKRF_ONE
|
||||
portapack_init();
|
||||
#endif
|
||||
|
||||
#ifndef DFU_MODE
|
||||
usb_set_descriptor_by_serial_number();
|
||||
#endif
|
||||
|
@ -273,7 +273,7 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
||||
|
||||
|
||||
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
|
||||
si5351c_activate_best_clock_source(&clock_gen);
|
||||
activate_best_clock_source();
|
||||
|
||||
hw_sync_enable(_hw_sync_mode);
|
||||
|
||||
|
@ -6,6 +6,7 @@ bits_of_address = 7
|
||||
bits_of_data = 274
|
||||
bytes_of_data = (bits_of_data + 7) // 8
|
||||
bits_in_program_row = bits_of_address + bits_of_data
|
||||
address_sequence = (0x00, 0x40, 0x60, 0x20, 0x30, 0x70, 0x50, 0x10, 0x18, 0x58, 0x78, 0x38, 0x28, 0x68, 0x48, 0x08, 0x0c, 0x4c, 0x6c, 0x2c, 0x3c, 0x7c, 0x5c, 0x1c, 0x14, 0x54, 0x74, 0x34, 0x24, 0x64, 0x44, 0x04, 0x06, 0x46, 0x66, 0x26, 0x36, 0x76, 0x56, 0x16, 0x1e, 0x5e, 0x7e, 0x3e, 0x2e, 0x6e, 0x4e, 0x0e, 0x0a, 0x4a, 0x6a, 0x2a, 0x3a, 0x7a, 0x5a, 0x1a, 0x12, 0x52, 0x72, 0x32, 0x22, 0x62, 0x42, 0x02, 0x03, 0x43, 0x63, 0x23, 0x33, 0x73, 0x53, 0x13, 0x1b, 0x5b, 0x7b, 0x3b, 0x2b, 0x6b, 0x4b, 0x0b, 0x0f, 0x4f, 0x6f, 0x2f, 0x3f, 0x7f, 0x5f, 0x1f, 0x17, 0x57, 0x77, 0x37, 0x27, 0x67, 0x47, 0x07, 0x05, 0x45,)
|
||||
|
||||
def values_list_line_wrap(values):
|
||||
line_length = 16
|
||||
@ -102,8 +103,6 @@ def extract_programming_data(commands):
|
||||
}
|
||||
|
||||
def validate_programming_data(programming_data):
|
||||
expected_address_sequence = (0x00, 0x40, 0x60, 0x20, 0x30, 0x70, 0x50, 0x10, 0x18, 0x58, 0x78, 0x38, 0x28, 0x68, 0x48, 0x08, 0x0c, 0x4c, 0x6c, 0x2c, 0x3c, 0x7c, 0x5c, 0x1c, 0x14, 0x54, 0x74, 0x34, 0x24, 0x64, 0x44, 0x04, 0x06, 0x46, 0x66, 0x26, 0x36, 0x76, 0x56, 0x16, 0x1e, 0x5e, 0x7e, 0x3e, 0x2e, 0x6e, 0x4e, 0x0e, 0x0a, 0x4a, 0x6a, 0x2a, 0x3a, 0x7a, 0x5a, 0x1a, 0x12, 0x52, 0x72, 0x32, 0x22, 0x62, 0x42, 0x02, 0x03, 0x43, 0x63, 0x23, 0x33, 0x73, 0x53, 0x13, 0x1b, 0x5b, 0x7b, 0x3b, 0x2b, 0x6b, 0x4b, 0x0b, 0x0f, 0x4f, 0x6f, 0x2f, 0x3f, 0x7f, 0x5f, 0x1f, 0x17, 0x57, 0x77, 0x37, 0x27, 0x67, 0x47, 0x07, 0x05, 0x45,)
|
||||
|
||||
# Validate program blocks:
|
||||
|
||||
# There should be two extracted program blocks. The first contains the
|
||||
@ -113,7 +112,7 @@ def validate_programming_data(programming_data):
|
||||
|
||||
# First program phase writes the bitstream to flash (or SRAM) with
|
||||
# special bit(s) not asserted, so the bitstream is not yet valid.
|
||||
assert(extract_addresses(programming_data['program'][0]) == expected_address_sequence)
|
||||
assert(extract_addresses(programming_data['program'][0]) == address_sequence)
|
||||
|
||||
# Second program phase updates a single row to finish the programming
|
||||
# process.
|
||||
@ -129,8 +128,8 @@ def validate_programming_data(programming_data):
|
||||
assert(programming_data['verify'][0] == programming_data['verify'][1])
|
||||
|
||||
# Check the row address order of the second verify block.
|
||||
assert(extract_addresses(programming_data['verify'][0]) == expected_address_sequence)
|
||||
assert(extract_addresses(programming_data['verify'][1]) == expected_address_sequence)
|
||||
assert(extract_addresses(programming_data['verify'][0]) == address_sequence)
|
||||
assert(extract_addresses(programming_data['verify'][1]) == address_sequence)
|
||||
|
||||
# Checks across programming and verification:
|
||||
|
||||
@ -150,12 +149,13 @@ def make_sram_program(program_blocks):
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
action_group = parser.add_mutually_exclusive_group(required=True)
|
||||
action_group.add_argument('--checksum', action='store_true', help='Calculate bitstream read-back CRC32 value')
|
||||
action_group.add_argument('--code', action='store_true', help='Generate C code for bitstream loading/programming/verification')
|
||||
action_group = parser.add_argument_group(title='outputs')
|
||||
action_group.add_argument('--checksum', action='store_true', help='Print bitstream verification CRC32 value')
|
||||
action_group.add_argument('--hackrf-data', type=str, help='C data file for HackRF bitstream loading/programming/verification')
|
||||
action_group.add_argument('--portapack-data', type=str, help='C++ data file for PortaPack bitstream loading/programming/verification')
|
||||
parser.add_argument('--crcmod', action='store_true', help='Use Python crcmod library instead of built-in CRC32 code')
|
||||
parser.add_argument('--debug', action='store_true', help='Enable debug output')
|
||||
parser.add_argument('hackrf_xc2c_cpld_xsvf', type=str, help='HackRF Xilinx XC2C64A CPLD XSVF file containing erase/program/verify phases')
|
||||
parser.add_argument('--xsvf', required=True, type=str, help='HackRF Xilinx XC2C64A CPLD XSVF file containing erase/program/verify phases')
|
||||
args = parser.parse_args()
|
||||
|
||||
#######################################################################
|
||||
@ -163,7 +163,7 @@ args = parser.parse_args()
|
||||
# against the CPLD.
|
||||
#######################################################################
|
||||
|
||||
with open(args.hackrf_xc2c_cpld_xsvf, "rb") as f:
|
||||
with open(args.xsvf, "rb") as f:
|
||||
from xsvf import XSVFParser
|
||||
commands = XSVFParser().parse(f, debug=args.debug)
|
||||
|
||||
@ -203,7 +203,7 @@ if args.checksum:
|
||||
|
||||
print('0x%s' % crc.hexdigest().lower())
|
||||
|
||||
if args.code:
|
||||
if args.hackrf_data:
|
||||
program_sram = make_sram_program(program_blocks)
|
||||
verify_block = verify_blocks[1]
|
||||
verify_masks = tuple(frozenset(extract_mask(verify_block)))
|
||||
@ -237,5 +237,42 @@ if args.code:
|
||||
'\t}',
|
||||
'};',
|
||||
'',
|
||||
'const cpld_xc2c64a_row_addresses_t cpld_hackrf_row_addresses = { {',
|
||||
))
|
||||
print('\n'.join(result))
|
||||
result.extend(['\t%s' % line for line in hex_lines(address_sequence)])
|
||||
result.extend((
|
||||
'} };',
|
||||
'',
|
||||
))
|
||||
with open(args.hackrf_data, 'w') as f:
|
||||
f.write('\n'.join(result))
|
||||
|
||||
if args.portapack_data:
|
||||
program_sram = make_sram_program(program_blocks)
|
||||
verify_block = verify_blocks[1]
|
||||
verify_masks = extract_mask(verify_block)
|
||||
|
||||
result = []
|
||||
result.extend((
|
||||
'/*',
|
||||
' * WARNING: Auto-generated file. Do not edit.',
|
||||
'*/',
|
||||
'#include "hackrf_cpld_data.hpp"',
|
||||
'namespace hackrf {',
|
||||
'namespace one {',
|
||||
'namespace cpld {',
|
||||
'const ::cpld::xilinx::XC2C64A::verify_blocks_t verify_blocks { {',
|
||||
))
|
||||
data_lines = [', '.join(['0x%02x' % n for n in row['data'].to_bytes(bytes_of_data, byteorder='big')]) for row in program_sram]
|
||||
mask_lines = [', '.join(['0x%02x' % n for n in mask.to_bytes(bytes_of_data, byteorder='big')]) for mask in verify_masks]
|
||||
lines = ['{ 0x%02x, { { %s } }, { { %s } } }' % data for data in zip(address_sequence, data_lines, mask_lines)]
|
||||
result.extend('\t%s,' % line for line in lines)
|
||||
result.extend((
|
||||
'} };',
|
||||
'} /* namespace hackrf */',
|
||||
'} /* namespace one */',
|
||||
'} /* namespace cpld */',
|
||||
'',
|
||||
))
|
||||
with open(args.portapack_data, 'w') as f:
|
||||
f.write('\n'.join(result))
|
||||
|
@ -125,7 +125,8 @@ int main(void)
|
||||
printf("Operacake found, address: 0x%02x\n", operacakes[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HACKRF_ISSUE_609_IS_FIXED
|
||||
uint32_t cpld_crc = 0;
|
||||
result = hackrf_cpld_checksum(device, &cpld_crc);
|
||||
if ((result != HACKRF_SUCCESS) && (result != HACKRF_ERROR_USB_API_VERSION)) {
|
||||
@ -136,6 +137,7 @@ int main(void)
|
||||
if(result == HACKRF_SUCCESS) {
|
||||
printf("CPLD checksum: 0x%08x\n", cpld_crc);
|
||||
}
|
||||
#endif /* HACKRF_ISSUE_609_IS_FIXED */
|
||||
|
||||
result = hackrf_close(device);
|
||||
if (result != HACKRF_SUCCESS) {
|
||||
|
@ -2105,6 +2105,7 @@ int ADDCALL hackrf_operacake_gpio_test(hackrf_device* device, const uint8_t addr
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HACKRF_ISSUE_609_IS_FIXED
|
||||
int ADDCALL hackrf_cpld_checksum(hackrf_device* device,
|
||||
uint32_t* crc)
|
||||
{
|
||||
@ -2133,6 +2134,7 @@ int ADDCALL hackrf_cpld_checksum(hackrf_device* device,
|
||||
return HACKRF_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif /* HACKRF_ISSUE_609_IS_FIXED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // __cplusplus defined.
|
||||
|
@ -254,9 +254,10 @@ extern ADDAPI int ADDCALL hackrf_set_clkout_enable(hackrf_device* device, const
|
||||
extern ADDAPI int ADDCALL hackrf_operacake_gpio_test(hackrf_device* device,
|
||||
uint8_t address,
|
||||
uint16_t* test_result);
|
||||
|
||||
#ifdef HACKRF_ISSUE_609_IS_FIXED
|
||||
extern ADDAPI int ADDCALL hackrf_cpld_checksum(hackrf_device* device,
|
||||
uint32_t* crc);
|
||||
#endif /* HACKRF_ISSUE_609_IS_FIXED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // __cplusplus defined.
|
||||
|
Reference in New Issue
Block a user