mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-01-06 21:27:40 +00:00
Merge pull request #39 from sharebrained/hackrf_firmware_boot
Hackrf firmware boot
This commit is contained in:
commit
6acce63a26
@ -23,12 +23,15 @@ PATH_BOOTSTRAP=bootstrap
|
||||
PATH_APPLICATION=application
|
||||
PATH_BASEBAND=baseband
|
||||
|
||||
# TODO: Pass these (as #defines?) to Makefiles, use values in code.
|
||||
PAD_BOOTSTRAP=0x10000
|
||||
PAD_BASEBAND=0x10000
|
||||
PAD_HACKRF_FIRMWARE=0x10000
|
||||
PAD_BASEBAND=0x20000
|
||||
|
||||
TARGET=portapack-h1-firmware
|
||||
|
||||
TARGET_BOOTSTRAP=$(PATH_BOOTSTRAP)/bootstrap
|
||||
TARGET_HACKRF_FIRMWARE=hackrf_one_usb_ram
|
||||
TARGET_APPLICATION=$(PATH_APPLICATION)/build/application
|
||||
TARGET_BASEBAND=$(PATH_BASEBAND)/build/baseband
|
||||
|
||||
@ -53,12 +56,17 @@ program: $(TARGET).bin
|
||||
sleep 1s
|
||||
hackrf_spiflash -w $(TARGET).bin
|
||||
|
||||
$(TARGET).bin: $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin
|
||||
cat $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin >$(TARGET).bin
|
||||
$(TARGET).bin: $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin
|
||||
cat $(TARGET_BOOTSTRAP)_pad.bin $(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin $(TARGET_BASEBAND)_pad.bin $(TARGET_APPLICATION).bin >$(TARGET).bin
|
||||
|
||||
$(TARGET_BOOTSTRAP)_pad.bin: $(TARGET_BOOTSTRAP).elf
|
||||
$(CP) -O binary --pad-to $(PAD_BOOTSTRAP) $(TARGET_BOOTSTRAP).elf $(TARGET_BOOTSTRAP)_pad.bin
|
||||
|
||||
$(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin: $(TARGET_HACKRF_FIRMWARE).dfu
|
||||
# TODO: Not confident this is reliable. It certainly won't work on Windows.
|
||||
cp $(TARGET_HACKRF_FIRMWARE).dfu $(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin
|
||||
dd if=/dev/null of=$(TARGET_HACKRF_FIRMWARE)_dfu_pad.bin bs=1 count=1 seek=$(PAD_HACKRF_FIRMWARE)
|
||||
|
||||
$(TARGET_BASEBAND)_pad.bin: $(TARGET_BASEBAND).elf
|
||||
$(CP) -O binary --pad-to $(PAD_BASEBAND) $(TARGET_BASEBAND).elf $(TARGET_BASEBAND)_pad.bin
|
||||
|
||||
|
@ -124,6 +124,7 @@ CPPSRC = main.cpp \
|
||||
event.cpp \
|
||||
message_queue.cpp \
|
||||
hackrf_hal.cpp \
|
||||
portapack.cpp \
|
||||
portapack_shared_memory.cpp \
|
||||
portapack_io.cpp \
|
||||
i2c_pp.cpp \
|
||||
|
@ -296,6 +296,11 @@ void ClockManager::init() {
|
||||
clock_generator.reset_plls();
|
||||
}
|
||||
|
||||
void ClockManager::shutdown() {
|
||||
run_from_irc();
|
||||
clock_generator.reset();
|
||||
}
|
||||
|
||||
void ClockManager::run_from_irc() {
|
||||
change_clock_configuration(cgu::CLK_SEL::IRC);
|
||||
}
|
||||
@ -377,14 +382,14 @@ void ClockManager::change_clock_configuration(const cgu::CLK_SEL clk_sel) {
|
||||
|
||||
set_m4_clock_to_irc();
|
||||
|
||||
update_peripheral_clocks(clk_sel);
|
||||
|
||||
if( clk_sel == cgu::CLK_SEL::PLL1 ) {
|
||||
set_m4_clock_to_pll1();
|
||||
} else {
|
||||
power_down_pll1();
|
||||
}
|
||||
|
||||
update_peripheral_clocks(clk_sel);
|
||||
|
||||
start_peripherals(clk_sel);
|
||||
|
||||
if( clk_sel != cgu::CLK_SEL::XTAL ) {
|
||||
@ -393,6 +398,7 @@ void ClockManager::change_clock_configuration(const cgu::CLK_SEL clk_sel) {
|
||||
|
||||
/* If not using PLL1, disable clock feeding GP_CLKIN */
|
||||
if( clk_sel != cgu::CLK_SEL::PLL1 ) {
|
||||
stop_audio_pll();
|
||||
disable_gp_clkin_source();
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
}
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
void run_from_irc();
|
||||
void run_at_full_speed();
|
||||
|
@ -23,15 +23,8 @@
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
static constexpr uint32_t m4_text_flash_image_offset = 0x10000;
|
||||
static constexpr size_t m4_text_size = 0x8000;
|
||||
static constexpr uint32_t m4_text_flash_base = LPC_SPIFI_DATA_CACHED_BASE + m4_text_flash_image_offset;
|
||||
static constexpr uint32_t m4_text_ram_base = 0x10080000;
|
||||
|
||||
/* TODO: OK, this is cool, but how do I put the M4 to sleep so I can switch to
|
||||
* a different image? Other than asking the old image to sleep while the M0
|
||||
* makes changes?
|
||||
@ -39,14 +32,14 @@ static constexpr uint32_t m4_text_ram_base = 0x10080000;
|
||||
* I suppose I could force M4MEMMAP to an invalid memory reason which would
|
||||
* cause an exception and effectively halt the M4. But that feels gross.
|
||||
*/
|
||||
void m4_init() {
|
||||
void m4_init(const portapack::spi_flash::region_t from, void* const to) {
|
||||
/* Initialize M4 code RAM */
|
||||
std::memcpy((void*)m4_text_ram_base, (void*)m4_text_flash_base, m4_text_size);
|
||||
std::memcpy(to, from.base_address(), from.size);
|
||||
|
||||
/* M4 core is assumed to be sleeping with interrupts off, so we can mess
|
||||
* with its address space and RAM without concern.
|
||||
*/
|
||||
LPC_CREG->M4MEMMAP = m4_text_ram_base;
|
||||
LPC_CREG->M4MEMMAP = reinterpret_cast<uint32_t>(to);
|
||||
|
||||
/* Reset M4 core */
|
||||
LPC_RGU->RESET_CTRL[0] = (1 << 13);
|
||||
|
@ -22,6 +22,10 @@
|
||||
#ifndef __M4_STARTUP_H__
|
||||
#define __M4_STARTUP_H__
|
||||
|
||||
void m4_init();
|
||||
#include <cstddef>
|
||||
|
||||
#include "spi_image.hpp"
|
||||
|
||||
void m4_init(const portapack::spi_flash::region_t from, void* const to);
|
||||
|
||||
#endif/*__M4_STARTUP_H__*/
|
||||
|
@ -22,43 +22,29 @@
|
||||
#include "ch.h"
|
||||
#include "test.h"
|
||||
|
||||
#include "hackrf_hal.hpp"
|
||||
#include "hackrf_gpio.hpp"
|
||||
using namespace hackrf::one;
|
||||
#include "lpc43xx_cpp.hpp"
|
||||
using namespace lpc43xx;
|
||||
|
||||
#include "portapack.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "portapack_hal.hpp"
|
||||
#include "portapack_io.hpp"
|
||||
|
||||
#include "cpld_update.hpp"
|
||||
|
||||
#include "message_queue.hpp"
|
||||
|
||||
#include "si5351.hpp"
|
||||
#include "clock_manager.hpp"
|
||||
|
||||
#include "wm8731.hpp"
|
||||
#include "radio.hpp"
|
||||
#include "touch.hpp"
|
||||
#include "touch_adc.hpp"
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_painter.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
|
||||
#include "receiver_model.hpp"
|
||||
|
||||
#include "irq_ipc.hpp"
|
||||
#include "irq_lcd_frame.hpp"
|
||||
#include "irq_controls.hpp"
|
||||
|
||||
#include "event.hpp"
|
||||
|
||||
#include "i2c_pp.hpp"
|
||||
#include "spi_pp.hpp"
|
||||
|
||||
#include "m4_startup.hpp"
|
||||
#include "spi_image.hpp"
|
||||
|
||||
#include "debug.hpp"
|
||||
#include "led.hpp"
|
||||
@ -67,12 +53,6 @@ using namespace hackrf::one;
|
||||
|
||||
#include <string.h>
|
||||
|
||||
I2C i2c0(&I2CD0);
|
||||
SPI ssp0(&SPID1);
|
||||
SPI ssp1(&SPID2);
|
||||
|
||||
wolfson::wm8731::WM8731 audio_codec { i2c0, portapack::wm8731_i2c_address };
|
||||
|
||||
/* From ChibiOS crt0.c:
|
||||
* Two stacks available for Cortex-M, main stack or process stack.
|
||||
*
|
||||
@ -146,112 +126,6 @@ static spi_bus_t ssp0 = {
|
||||
* _default_exit() (default is infinite loop)
|
||||
*/
|
||||
|
||||
si5351::Si5351 clock_generator {
|
||||
i2c0, si5351_i2c_address
|
||||
};
|
||||
|
||||
ClockManager clock_manager {
|
||||
i2c0, clock_generator
|
||||
};
|
||||
|
||||
ReceiverModel receiver_model {
|
||||
clock_manager
|
||||
};
|
||||
|
||||
class Power {
|
||||
public:
|
||||
void init() {
|
||||
/* VAA powers:
|
||||
* MAX5864 analog section.
|
||||
* MAX2837 registers and other functions.
|
||||
* RFFC5072 analog section.
|
||||
*
|
||||
* Beware that power applied to pins of the MAX2837 may
|
||||
* show up on VAA and start powering other components on the
|
||||
* VAA net. So turn on VAA before driving pins from MCU to
|
||||
* MAX2837.
|
||||
*/
|
||||
/* Turn on VAA */
|
||||
gpio_vaa_disable.clear();
|
||||
gpio_vaa_disable.output();
|
||||
|
||||
/* 1V8 powers CPLD internals.
|
||||
*/
|
||||
/* Turn on 1V8 */
|
||||
gpio_1v8_enable.set();
|
||||
gpio_1v8_enable.output();
|
||||
|
||||
/* Set VREGMODE for switching regulator on HackRF One */
|
||||
gpio_vregmode.set();
|
||||
gpio_vregmode.output();
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
static Power power;
|
||||
|
||||
static void init() {
|
||||
for(const auto& pin : pins) {
|
||||
pin.init();
|
||||
}
|
||||
|
||||
/* Configure other pins */
|
||||
LPC_SCU->SFSI2C0 =
|
||||
(1U << 3)
|
||||
| (1U << 11)
|
||||
;
|
||||
|
||||
power.init();
|
||||
|
||||
gpio_max5864_select.set();
|
||||
gpio_max5864_select.output();
|
||||
|
||||
gpio_max2837_select.set();
|
||||
gpio_max2837_select.output();
|
||||
|
||||
led_usb.setup();
|
||||
led_rx.setup();
|
||||
led_tx.setup();
|
||||
|
||||
clock_manager.init();
|
||||
clock_manager.run_at_full_speed();
|
||||
|
||||
clock_manager.start_audio_pll();
|
||||
audio_codec.init();
|
||||
|
||||
clock_manager.enable_first_if_clock();
|
||||
clock_manager.enable_second_if_clock();
|
||||
clock_manager.enable_codec_clocks();
|
||||
radio::init();
|
||||
|
||||
touch::adc::init();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void __late_init(void) {
|
||||
|
||||
reset();
|
||||
|
||||
/*
|
||||
* System initializations.
|
||||
* - HAL initialization, this also initializes the configured device drivers
|
||||
* and performs the board-specific initializations.
|
||||
* - Kernel initialization, the main() function becomes a thread and the
|
||||
* RTOS is active.
|
||||
*/
|
||||
halInit();
|
||||
|
||||
/* After this call, scheduler, systick, heap, etc. are available. */
|
||||
/* By doing chSysInit() here, it runs before C++ constructors, which may
|
||||
* require the heap.
|
||||
*/
|
||||
chSysInit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
CH_IRQ_HANDLER(RTC_IRQHandler) {
|
||||
@ -600,18 +474,8 @@ message_handlers[Message::ID::TestResults] = [&system_view](const Message* const
|
||||
};
|
||||
*/
|
||||
|
||||
portapack::IO portapack::io {
|
||||
portapack::gpio_dir,
|
||||
portapack::gpio_lcd_rd,
|
||||
portapack::gpio_lcd_wr,
|
||||
portapack::gpio_io_stbx,
|
||||
portapack::gpio_addr,
|
||||
portapack::gpio_lcd_te,
|
||||
portapack::gpio_unused,
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
init();
|
||||
portapack::init();
|
||||
|
||||
if( !cpld_update_if_necessary() ) {
|
||||
chSysHalt();
|
||||
@ -622,7 +486,7 @@ int main(void) {
|
||||
|
||||
portapack::io.init();
|
||||
ui::Context context;
|
||||
context.display.init();
|
||||
portapack::display.init();
|
||||
|
||||
sdcStart(&SDCD1, nullptr);
|
||||
|
||||
@ -639,17 +503,17 @@ int main(void) {
|
||||
context,
|
||||
{ 0, 0, 240, 320 }
|
||||
};
|
||||
ui::Painter painter { context.display };
|
||||
ui::Painter painter;
|
||||
EventDispatcher event_dispatcher { &system_view, painter, context };
|
||||
|
||||
context.message_map[Message::ID::FSKPacket] = [](const Message* const p) {
|
||||
const auto message = static_cast<const FSKPacketMessage*>(p);
|
||||
(void)message;
|
||||
led_usb.toggle();
|
||||
};
|
||||
|
||||
m4txevent_interrupt_enable();
|
||||
m4_init();
|
||||
|
||||
m4_init(portapack::spi_flash::baseband, portapack::spi_flash::m4_text_ram_base);
|
||||
|
||||
while(true) {
|
||||
const auto events = event_dispatcher.wait();
|
||||
|
183
firmware/application/portapack.cpp
Normal file
183
firmware/application/portapack.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "portapack.hpp"
|
||||
#include "portapack_hal.hpp"
|
||||
|
||||
#include "hackrf_hal.hpp"
|
||||
#include "hackrf_gpio.hpp"
|
||||
using namespace hackrf::one;
|
||||
|
||||
#include "si5351.hpp"
|
||||
#include "clock_manager.hpp"
|
||||
|
||||
#include "i2c_pp.hpp"
|
||||
|
||||
#include "touch_adc.hpp"
|
||||
|
||||
namespace portapack {
|
||||
|
||||
portapack::IO io {
|
||||
portapack::gpio_dir,
|
||||
portapack::gpio_lcd_rd,
|
||||
portapack::gpio_lcd_wr,
|
||||
portapack::gpio_io_stbx,
|
||||
portapack::gpio_addr,
|
||||
portapack::gpio_lcd_te,
|
||||
portapack::gpio_unused,
|
||||
};
|
||||
|
||||
lcd::ILI9341 display;
|
||||
|
||||
I2C i2c0(&I2CD0);
|
||||
SPI ssp0(&SPID1);
|
||||
SPI ssp1(&SPID2);
|
||||
|
||||
wolfson::wm8731::WM8731 audio_codec { i2c0, portapack::wm8731_i2c_address };
|
||||
|
||||
si5351::Si5351 clock_generator {
|
||||
i2c0, hackrf::one::si5351_i2c_address
|
||||
};
|
||||
|
||||
ClockManager clock_manager {
|
||||
i2c0, clock_generator
|
||||
};
|
||||
|
||||
ReceiverModel receiver_model {
|
||||
clock_manager
|
||||
};
|
||||
|
||||
class Power {
|
||||
public:
|
||||
void init() {
|
||||
/* VAA powers:
|
||||
* MAX5864 analog section.
|
||||
* MAX2837 registers and other functions.
|
||||
* RFFC5072 analog section.
|
||||
*
|
||||
* Beware that power applied to pins of the MAX2837 may
|
||||
* show up on VAA and start powering other components on the
|
||||
* VAA net. So turn on VAA before driving pins from MCU to
|
||||
* MAX2837.
|
||||
*/
|
||||
/* Turn on VAA */
|
||||
gpio_vaa_disable.clear();
|
||||
gpio_vaa_disable.output();
|
||||
|
||||
/* 1V8 powers CPLD internals.
|
||||
*/
|
||||
/* Turn on 1V8 */
|
||||
gpio_1v8_enable.set();
|
||||
gpio_1v8_enable.output();
|
||||
|
||||
/* Set VREGMODE for switching regulator on HackRF One */
|
||||
gpio_vregmode.set();
|
||||
gpio_vregmode.output();
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
gpio_1v8_enable.clear();
|
||||
gpio_vaa_disable.set();
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
static Power power;
|
||||
|
||||
void init() {
|
||||
for(const auto& pin : pins) {
|
||||
pin.init();
|
||||
}
|
||||
|
||||
/* Configure other pins */
|
||||
LPC_SCU->SFSI2C0 =
|
||||
(1U << 3)
|
||||
| (1U << 11)
|
||||
;
|
||||
|
||||
power.init();
|
||||
|
||||
gpio_max5864_select.set();
|
||||
gpio_max5864_select.output();
|
||||
|
||||
gpio_max2837_select.set();
|
||||
gpio_max2837_select.output();
|
||||
|
||||
led_usb.setup();
|
||||
led_rx.setup();
|
||||
led_tx.setup();
|
||||
|
||||
clock_manager.init();
|
||||
clock_manager.run_at_full_speed();
|
||||
|
||||
clock_manager.start_audio_pll();
|
||||
audio_codec.init();
|
||||
|
||||
clock_manager.enable_first_if_clock();
|
||||
clock_manager.enable_second_if_clock();
|
||||
clock_manager.enable_codec_clocks();
|
||||
radio::init();
|
||||
|
||||
touch::adc::init();
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
sdcStop(&SDCD1);
|
||||
|
||||
display.shutdown();
|
||||
|
||||
radio::disable();
|
||||
audio_codec.reset();
|
||||
clock_manager.shutdown();
|
||||
|
||||
power.shutdown();
|
||||
// TODO: Wait a bit for supplies to discharge?
|
||||
|
||||
chSysDisable();
|
||||
hackrf::one::reset();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void __late_init(void) {
|
||||
|
||||
reset();
|
||||
|
||||
/*
|
||||
* System initializations.
|
||||
* - HAL initialization, this also initializes the configured device drivers
|
||||
* and performs the board-specific initializations.
|
||||
* - Kernel initialization, the main() function becomes a thread and the
|
||||
* RTOS is active.
|
||||
*/
|
||||
halInit();
|
||||
|
||||
/* After this call, scheduler, systick, heap, etc. are available. */
|
||||
/* By doing chSysInit() here, it runs before C++ constructors, which may
|
||||
* require the heap.
|
||||
*/
|
||||
chSysInit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} /* namespace portapack */
|
48
firmware/application/portapack.hpp
Normal file
48
firmware/application/portapack.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "portapack_io.hpp"
|
||||
|
||||
#include "receiver_model.hpp"
|
||||
|
||||
#include "spi_pp.hpp"
|
||||
#include "wm8731.hpp"
|
||||
#include "lcd_ili9341.hpp"
|
||||
|
||||
#include "radio.hpp"
|
||||
|
||||
namespace portapack {
|
||||
|
||||
extern portapack::IO io;
|
||||
|
||||
extern lcd::ILI9341 display;
|
||||
|
||||
extern SPI ssp0;
|
||||
extern SPI ssp1;
|
||||
|
||||
extern wolfson::wm8731::WM8731 audio_codec;
|
||||
|
||||
extern ReceiverModel receiver_model;
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
} /* namespace portapack */
|
@ -36,8 +36,7 @@
|
||||
#include "hackrf_gpio.hpp"
|
||||
using namespace hackrf::one;
|
||||
|
||||
#include "spi_pp.hpp"
|
||||
extern SPI ssp1;
|
||||
#include "portapack.hpp"
|
||||
|
||||
namespace radio {
|
||||
|
||||
@ -75,7 +74,7 @@ static constexpr SPIConfig ssp_config_max5864 = {
|
||||
.cpsr = ssp1_cpsr,
|
||||
};
|
||||
|
||||
static spi::arbiter::Arbiter ssp1_arbiter(ssp1);
|
||||
static spi::arbiter::Arbiter ssp1_arbiter(portapack::ssp1);
|
||||
|
||||
static spi::arbiter::Target ssp1_target_max2837 {
|
||||
ssp1_arbiter,
|
||||
|
@ -22,13 +22,8 @@
|
||||
#include "receiver_model.hpp"
|
||||
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "radio.hpp"
|
||||
#include "wm8731.hpp"
|
||||
|
||||
// TODO: Nasty. Put this in an #include somewhere, or a shared system state
|
||||
// object?
|
||||
|
||||
extern wolfson::wm8731::WM8731 audio_codec;
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
rf::Frequency ReceiverModel::tuning_frequency() const {
|
||||
return tuning_frequency_;
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include "ui_console.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
void Console::write(const std::string message) {
|
||||
|
@ -26,8 +26,6 @@
|
||||
#include "ui_painter.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
|
||||
#include "lcd_ili9341.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ui {
|
||||
@ -35,10 +33,8 @@ namespace ui {
|
||||
class Console : public Widget {
|
||||
public:
|
||||
constexpr Console(
|
||||
const Rect parent_rect,
|
||||
lcd::ILI9341& display
|
||||
) : Widget { parent_rect },
|
||||
display(display)
|
||||
const Rect parent_rect
|
||||
) : Widget { parent_rect }
|
||||
{
|
||||
}
|
||||
|
||||
@ -52,7 +48,6 @@ private:
|
||||
static constexpr Color foreground { Color::white() };
|
||||
|
||||
Point pos { 0, 0 };
|
||||
lcd::ILI9341& display;
|
||||
|
||||
void crlf();
|
||||
};
|
||||
|
@ -27,7 +27,10 @@
|
||||
#include "ui_debug.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
|
||||
extern ReceiverModel receiver_model;
|
||||
#include "portapack.hpp"
|
||||
#include "m4_startup.hpp"
|
||||
#include "spi_image.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -97,13 +100,14 @@ void NavigationView::focus() {
|
||||
/* SystemMenuView ********************************************************/
|
||||
|
||||
SystemMenuView::SystemMenuView(NavigationView& nav) {
|
||||
add_items<6>({ {
|
||||
add_items<7>({ {
|
||||
{ "Receiver", [&nav](){ nav.push(new ReceiverView { nav, receiver_model }); } },
|
||||
{ "Capture", [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||
{ "Analyze", [&nav](){ nav.push(new NotImplementedView { nav }); } },
|
||||
{ "Setup", [&nav](){ nav.push(new SetupMenuView { nav }); } },
|
||||
{ "About", [&nav](){ nav.push(new AboutView { nav }); } },
|
||||
{ "Debug", [&nav](){ nav.push(new DebugMenuView { nav }); } },
|
||||
{ "HackRF", [&nav](){ nav.push(new HackRFFirmwareView { nav }); } },
|
||||
} });
|
||||
}
|
||||
|
||||
@ -146,6 +150,34 @@ Context& SystemView::context() const {
|
||||
return context_;
|
||||
}
|
||||
|
||||
/* HackRFFirmwareView ****************************************************/
|
||||
|
||||
HackRFFirmwareView::HackRFFirmwareView(NavigationView& nav) {
|
||||
button_yes.on_select = [&nav](Button&){
|
||||
shutdown();
|
||||
|
||||
m4_init(spi_flash::hackrf, reinterpret_cast<void*>(0x10000000));
|
||||
|
||||
while(true) {
|
||||
__WFE();
|
||||
}
|
||||
};
|
||||
|
||||
button_no.on_select = [&nav](Button&){
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
add_children({ {
|
||||
&text_title,
|
||||
&button_yes,
|
||||
&button_no,
|
||||
} });
|
||||
}
|
||||
|
||||
void HackRFFirmwareView::focus() {
|
||||
button_no.focus();
|
||||
}
|
||||
|
||||
/* NotImplementedView ****************************************************/
|
||||
|
||||
NotImplementedView::NotImplementedView(NavigationView& nav) {
|
||||
|
@ -107,6 +107,29 @@ private:
|
||||
Context& context_;
|
||||
};
|
||||
|
||||
class HackRFFirmwareView : public View {
|
||||
public:
|
||||
HackRFFirmwareView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
private:
|
||||
Text text_title {
|
||||
{ 6 * 8, 7 * 16, 19 * 8, 16 },
|
||||
"Enter HackRF Mode?"
|
||||
};
|
||||
|
||||
Button button_yes {
|
||||
{ 4 * 8, 13 * 16, 8 * 8, 24 },
|
||||
"Yes",
|
||||
};
|
||||
|
||||
Button button_no {
|
||||
{ 18 * 8, 13 * 16, 8 * 8, 24 },
|
||||
"No",
|
||||
};
|
||||
};
|
||||
|
||||
class NotImplementedView : public View {
|
||||
public:
|
||||
NotImplementedView(NavigationView& nav);
|
||||
|
@ -21,11 +21,8 @@
|
||||
|
||||
#include "ui_receiver.hpp"
|
||||
|
||||
// TODO: Nasty. Put this in an #include somewhere, or a shared system state
|
||||
// object?
|
||||
|
||||
#include "wm8731.hpp"
|
||||
extern wolfson::wm8731::WM8731 audio_codec;
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
|
@ -26,7 +26,9 @@
|
||||
#include "ui_widget.hpp"
|
||||
#include "spectrum_color_lut.hpp"
|
||||
|
||||
#include "lcd_ili9341.hpp"
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include "message.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
@ -180,14 +182,14 @@ class WaterfallView : public Widget {
|
||||
public:
|
||||
void on_show() override {
|
||||
const auto screen_r = screen_rect();
|
||||
context().display.scroll_set_area(screen_r.top(), screen_r.bottom());
|
||||
display.scroll_set_area(screen_r.top(), screen_r.bottom());
|
||||
}
|
||||
|
||||
void on_hide() override {
|
||||
/* TODO: Clear region to eliminate brief flash of content at un-shifted
|
||||
* position?
|
||||
*/
|
||||
context().display.scroll_disable();
|
||||
display.scroll_disable();
|
||||
}
|
||||
|
||||
void paint(Painter& painter) override {
|
||||
@ -212,7 +214,6 @@ public:
|
||||
pixel_row[i] = pixel_color;
|
||||
}
|
||||
|
||||
auto& display = context().display;
|
||||
const auto draw_y = display.scroll(1);
|
||||
|
||||
display.draw_pixels(
|
||||
|
@ -99,7 +99,7 @@ int main(void) {
|
||||
/* NOTE: MEMMAP registers are ORed with the shadow address to create the
|
||||
* actual address.
|
||||
*/
|
||||
LPC_CREG->M0APPMEMMAP = LPC_SPIFI_DATA_CACHED_BASE + 0x20000;
|
||||
LPC_CREG->M0APPMEMMAP = LPC_SPIFI_DATA_CACHED_BASE + 0x40000;
|
||||
|
||||
/* Change M0APP_RST to 0 */
|
||||
LPC_RGU->RESET_CTRL[1] = 0;
|
||||
|
@ -225,6 +225,11 @@ void ILI9341::init() {
|
||||
io.lcd_backlight(1);
|
||||
}
|
||||
|
||||
void ILI9341::shutdown() {
|
||||
io.lcd_backlight(0);
|
||||
lcd_reset();
|
||||
}
|
||||
|
||||
void ILI9341::fill_rectangle(ui::Rect r, const ui::Color c) {
|
||||
const auto r_clipped = r.intersect(screen_rect());
|
||||
if( !r_clipped.is_empty() ) {
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
void operator=(const ILI9341&) = delete;
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
void fill_rectangle(ui::Rect r, const ui::Color c);
|
||||
void fill_circle(
|
||||
|
68
firmware/common/spi_image.hpp
Normal file
68
firmware/common/spi_image.hpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SPI_IMAGE_H__
|
||||
#define __SPI_IMAGE_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
namespace portapack {
|
||||
namespace spi_flash {
|
||||
|
||||
struct region_t {
|
||||
const size_t offset;
|
||||
const size_t size;
|
||||
|
||||
constexpr const void* base_address() {
|
||||
return reinterpret_cast<void*>(LPC_SPIFI_DATA_CACHED_BASE + offset);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr region_t bootstrap {
|
||||
.offset = 0x00000,
|
||||
.size = 0x10000,
|
||||
};
|
||||
|
||||
constexpr region_t hackrf {
|
||||
.offset = 0x10010, // Image starts at 0x10 into .dfu file.
|
||||
.size = 0x8000,
|
||||
};
|
||||
|
||||
constexpr region_t baseband {
|
||||
.offset = 0x20000,
|
||||
.size = 0x8000,
|
||||
};
|
||||
|
||||
constexpr region_t application {
|
||||
.offset = 0x40000,
|
||||
.size = 0x40000,
|
||||
};
|
||||
|
||||
// TODO: Refactor into another header that defines memory regions.
|
||||
constexpr void* m4_text_ram_base = reinterpret_cast<void*>(0x10080000);
|
||||
|
||||
} /* namespace spi_flash */
|
||||
} /* namespace portapack */
|
||||
|
||||
#endif/*__SPI_IMAGE_H__*/
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include "ui_painter.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
Style Style::invert() const {
|
||||
@ -33,7 +36,7 @@ Style Style::invert() const {
|
||||
|
||||
size_t Painter::draw_char(const Point p, const Style& style, const char c) {
|
||||
const auto glyph = style.font.glyph(c);
|
||||
display_.draw_glyph(p, glyph, style.foreground, style.background);
|
||||
display.draw_glyph(p, glyph, style.foreground, style.background);
|
||||
return glyph.advance().x;
|
||||
}
|
||||
|
||||
@ -41,7 +44,7 @@ size_t Painter::draw_string(Point p, const Style& style, const std::string text)
|
||||
size_t width = 0;
|
||||
for(const auto c : text) {
|
||||
const auto glyph = style.font.glyph(c);
|
||||
display_.draw_glyph(p, glyph, style.foreground, style.background);
|
||||
display.draw_glyph(p, glyph, style.foreground, style.background);
|
||||
const auto advance = glyph.advance();
|
||||
p += advance;
|
||||
width += advance.x;
|
||||
@ -50,11 +53,11 @@ size_t Painter::draw_string(Point p, const Style& style, const std::string text)
|
||||
}
|
||||
|
||||
void Painter::draw_hline(Point p, size_t width, const Color c) {
|
||||
display_.fill_rectangle({ p, { static_cast<Dim>(width), 1 } }, c);
|
||||
display.fill_rectangle({ p, { static_cast<Dim>(width), 1 } }, c);
|
||||
}
|
||||
|
||||
void Painter::draw_vline(Point p, size_t height, const Color c) {
|
||||
display_.fill_rectangle({ p, { 1, static_cast<Dim>(height) } }, c);
|
||||
display.fill_rectangle({ p, { 1, static_cast<Dim>(height) } }, c);
|
||||
}
|
||||
|
||||
void Painter::draw_rectangle(const Rect r, const Color c) {
|
||||
@ -65,7 +68,7 @@ void Painter::draw_rectangle(const Rect r, const Color c) {
|
||||
}
|
||||
|
||||
void Painter::fill_rectangle(const Rect r, const Color c) {
|
||||
display_.fill_rectangle(r, c);
|
||||
display.fill_rectangle(r, c);
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
@ -25,8 +25,6 @@
|
||||
#include "ui.hpp"
|
||||
#include "ui_text.hpp"
|
||||
|
||||
#include "lcd_ili9341.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ui {
|
||||
@ -41,11 +39,7 @@ struct Style {
|
||||
|
||||
class Painter {
|
||||
public:
|
||||
Painter(
|
||||
lcd::ILI9341& display
|
||||
) : display_(display)
|
||||
{
|
||||
}
|
||||
Painter() { };
|
||||
|
||||
Painter(const Painter&) = delete;
|
||||
Painter(Painter&&) = delete;
|
||||
@ -58,8 +52,6 @@ public:
|
||||
void fill_rectangle(const Rect r, const Color c);
|
||||
|
||||
private:
|
||||
lcd::ILI9341& display_;
|
||||
|
||||
void draw_hline(Point p, size_t width, const Color c);
|
||||
void draw_vline(Point p, size_t height, const Color c);
|
||||
};
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "lcd_ili9341.hpp"
|
||||
#include "message.hpp"
|
||||
|
||||
#include <memory>
|
||||
@ -48,7 +47,6 @@ std::string to_string_hex(const uint32_t n, const int32_t l = 0);
|
||||
|
||||
struct Context {
|
||||
FocusManager focus_manager;
|
||||
lcd::ILI9341 display;
|
||||
MessageHandlerMap message_map;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user