PortaPack Sync, take 2 (#215)

* Power: Turn off additional peripheral clock branches.

* Update schematic with new symbol table and KiCad standard symbols.
Fix up wires.

* Schematic: Update power net labels.

* Schematic: Update footprint names to match library changes.

* Schematic: Update header vendor and part numbers.

* Schematic: Specify (arbitrary) value for PDN# net.

* Schematic: Remove fourth fiducial. Not standard practice, and was taking up valuable board space.

* Schematic: Add reference oscillator -- options for clipped sine or HCMOS output.

* Schematic: Update copyright year.

* Schematic: Remove CLKOUT to CPLD. It was a half-baked idea.

* Schematic: Add (experimental) GPS circuit.
Add note about charging circuit.
Update date and revision to match PCB.

* PCB: Update from schematic change: now revision 20180819.
Diff was extensive due to net renumbering...

* PCB: Fix GPS courtyard to accommodate crazy solder paste recommendation in integration manual.
PCB: Address DRC clearance violation between via and oscillator pad.

* PCB: Update copyright on drawing.

* Update schematic and PCB date and revision.

* gitignore: Sublime Text editor project/workspace files

* Power: Power up or power down peripheral clock at appropriate times, so firmware doesn't freeze...

* Clocking: Fix incorrect shift for CGU IDIVx_CTRL.PD field.

* LPC43xx: Add CGU IDIVx struct/union type.

* Power: Switch off unused IDIV dividers. Make note of active IDIVs and their use.

* HackRF Mode: Upgrade firmware to 2018.01.1 (API 1.02)

* MAX V CPLD: Refactor class to look more like Xilinx CoolRunner II CPLD class.

* MAX V CPLD: Add BYPASS, SAMPLE support.
Rename enter_isp -> enable, exit_isp -> disable.
Use SAMPLE at start of flash process, which somehow addresses the problem where CFM wouldn't load into SRAM (and become the active bitstream) after flashing.

* MAX V CPLD: Reverse verify data checking logic to make it a little faster.

* CPLD: After reprogramming flash, immediately clamp I/O signals, load to SRAM, and "execute" the new bitstream.

* Si5351: Refactor code, make one of the registers more type-safe.
Clock Manager: Track selected reference clock source for later use in user interface.

* Clock Manager: Add note about PPM only affecting Si5351C PLLA, which always runs from the HackRF 25MHz crystal.
It is assumed an external clock does not need adjustment, though I am open to being convinced otherwise...

* PPM UI: Show "EXT" when showing PPM adjustment and reference clock is external.

* CPLD: Add pins and logic for new PortaPack hardware feature(s).

* CPLD: Bitstream to support new hardware features.

* Clock Generator: Add a couple more setter methods for ClockControl registers.

* Clock Manager: Use shared MCU CLKIN clock control configuration constant.

* Clock Manager: Reduce MCU CLKIN driver current. 2mA should be plenty.

* Clock Manager: Remove redundant clock generator output enable.

* Bootstrap: Remove unnecessary ldscript hack to locate SPIFI mode change code in RAM.

* Bootstrap: Get CPU operating at max frequency as soon as possible.
Update SPIFI speed comment.
Make some more LPC43xx types into unions with uint32_t.

* Bootstrap: Explicitly configure IDIVB for SPIFI, despite LPC43xx bootloader setting it.

* Clock Manager: Init peripherals before CPLD reconfig. Do the clock generator setup after, so we can check presence of PortaPack reference clock with the help of the latest CPLD bitstream.

* Clock Manager: Reverse sense of conditional that determines crystal or non-crystal reference source. This is for an expected upcoming change where multiple external options can be differentiated.

* Bootstrap: Consolidate clock configuration, update SPIFI rate comment.

* Clock Manager: Use IDIVA for clock source for all peripherals, instead of PLL1. Should make switching easier going forward.
Don't use IRC as clock during initial clock manager configuration. Until we switch to GP_CLKIN, we should go flat out...

* ChibiOS M0: Change default clock speed to 204MHz, since bootstrap now maxes out clock speed before starting M0 execution.

* PortaPack IO: Expose method to set reference oscillator enable pin.

* Pin configuration: Do SPIFI pin config with other pins, in preparation for eliminating separate bootloader.

* Pin configuration: Disable input buffers on pins that are never read.

* Revert "ChibiOS M0: Change default clock speed to 204MHz, since bootstrap now maxes out clock speed before starting M0 execution."

This reverts commit c0e2bb6cc4cc656769323bdbb8ee5a16d2d5bb03.

* PCB: Change PCB stackup, Tg, clarify solder mask color, use more metric.

* PCB: Move HackRF header P9 to B.CrtYd layer.

* PCB: Change a Tg reference I missed.

* PCB: Update footprints for parts with mismatched CAD->tape rotation.
Adjust a few layer choice and line thickness bits.

* PCB: Got cold feet, switched back to rectangular pads.

* PCB: Add Eco layers to be visible and Gerber output.

* PCB: Use aux origin for plotting, for tidier coordinates.

* PCB: Output Gerber job file, because why not?

* Schematic: Correct footprints for two reference-related components.

* Schematic: Remove manfuacturer and part number for DNP component.

* Schematic: Specify resistor value, manufacturer, part number for reference oscillator series termination.

* PCB: Update netlist and footprints from schematic.

* Netlist: Updated component values, footprints.

* PCB: Nudge some components and traces to address DRC clearance violations.

* PCB: Allow KiCad to update zone timestamps (again?!).

* PCB: Generate *all* Gerber layers.

* Schematic, PCB: Update revision to 20181025.

* PCB: Adjust fab layer annotations orientation and font size.

* PCB: Hide mounting hole reference designators on silk layer.

* PCB: Shrink U1, U3 pads to get 0.2mm space between pads.

* PCB: Set pad-to-mask clearance to zero, leave up to fab. Set minimum mask web to 0.2mm for non-black options.

* PCB: Revise U1 pad shape, mask, paste, thermal drills.
Clearance is improved at corner pads.

* PCB: Tweak U3 for better thermal pad/drill/mask/paste design.

* PCB: Change solder mask color to blue.

* Schematic, PCB: Update revision to 20181029.

* PCB: Bump minimum mask web down a tiny bit because KiCad is having trouble with math.

* Update schematic

* Remove unused board files.

* Add LPC43xx functions.

* chibios: Replace code with per-peripheral structs defining clocks, interrupts, and reset bits.

* LPC43xx: Add MCPWM peripheral struct.

* clock generator: Use recommended PLL reset register value.

Datasheet recommends a value. AN619 is quiet on the topic, claims the low nibble is default 0b0000.

* GPIO: Tweak masking of SCU function.

I don't remember why I thought this was necessary...

* HAL: Explicitly turn on timer peripheral clocks used as systicks, during init.

* SCU: Add struct to hold pin configuration.

* PAL: Add functions to address The Glitch.

https://greatscottgadgets.com/2018/02-28-we-fixed-the-glitch/

* PAL/board: New IO initialization code

Declare initial state for SCU pin config, GPIOs. Apply initial state during PAL init. Perform VAA slow turn-on to address The Glitch.

* Merge M0 and M4 to eliminate need for bootstrap firmware

During _early_init, detect if we're running on the M4 or M0.
If M4: do M4-specific core initialization, reset peripherals, speed up SPIFI clock, start M0, go to sleep.
If M0: do all the other things.

* Pins: Miscellaneous SCU configuration tweaks.

* Little code clarity improvement.

* bootstrap: Remove, not necessary.

* Clock Manager: Large re-working to support external references.

* Clock Manager: Actually store chosen clock reference

Similarly-named local was covering a member and discarding the value.

* Clock Manager: Reference type which contains source, frequency.

* Setup: Display reference source, frequency in frequency correction screen.

* LPC43xx API: Add extern "C" for use from C++.

* Use LPC43xx API for SGPIO, GPDMA, I2S initialization.

* I2S: Add BASE_AUDIO_CLK management.

* Add MOTOCON_PWM clock/reset structure.

* Serial: Fix dumb typos.

* Serial: Remove extra reference operator.

* Serial: Cut-and-paste error in structure type name.

* Move SCU structure from PAL to LPC43xx API.

It'd be nice if I gave some thought to where code should live before I commit it.

* VAA power: Move code to HackRF board file

It doesn't belong in PAL.

* MAX5 CPLD: Add SAMPLE and EXTEST methods.

* Flash image: Change packing scheme to use flash more efficiently.

Application is now a single image for both M4 bootstrap and M0.
Baseband images come immediately after application binary. No need to align to large blocks (and waste lots of flash).

* Clock Manager: Remove PLL1 power down function.

* Move and rename peripherals reset function to board module.

* Remove unused peripheral/clock management.

* Clock Manager: Extract switch to IRC into separate function.

* Clock Manager: More explicit shutdown of clocks, clock generator.

* Move initialization to board module.

* ChibiOS: Rename "application" board, add "baseband" board.

There are now two ChibiOS "boards", one which runs the application and does the hardware setup. The other board, "baseband", does very little setup.

* Clock Manager: Remove unused crystal enable/disable code.

* Clock Manager: Restore clock configuration to SPIFI bootloader state before app shutdown.

* Reset peripherals on app shutdown.

Be careful not to reset M0APP (the core we're running on) or GPIO (which is holding the hardware in a stable state).

* M4/baseband hal_lld_init: use IDIVA, which is configured earlier by M0.

This was causing problems during restart into HackRF mode. Baseband hal_lld_init changed M4 clock from IDIVA (set by M0) to PLL1, which was unceremoniously turned off during shutdown.

* Audio app: Stop audio PLL on shutdown.

* M4 HAL: Make LPC43XX_M4_CLK_SRC optional.

This was changing the BASE_M4_CLK when a baseband was run.

* LPC43xx C++ layer: Fix IDIVx constructor IDIV narrow field width.

* Application board: hide the peripherals_reset function, as it isn't useful except during hardware init.

* Consolidate hardware init code to some degree.

ClockManager is super-overloaded and murky in its purpose.
Migrate audio from IDIVC to IDIVD, to more closely resemble initial clock scheme, so it's simpler to get back to it during shutdown.

* Migrate some startup code to application board.

* Si5351: Use correct methods for reset().

update_output_enable_control() doesn't reset the enabled outputs to the reset state, unless the object is freshly initialized, which it isn't when performing firmware shutdown.
For similar reasons, use set_clock_control() instead of setting internal state and then using the update function.

* GPIO: Set SPIFI CS pin to match input buffer state coming out of bootloader.

* Change application board.c to .cpp, with required dependent changes

* Board: Clean up SCU configuration code/data.

* I2S: Add shutdown code and use it.

* LPC43xx: Consolidate a bunch of structures that had been scattered all over.

...because I'm an undisciplined coder.

* I2S: Fix ordering of branch and base clock disable.

Core was hanging, presumably because the register interface on the branch/peripheral was unresponsive after the base clock was disabled.

* Controls: Save and expose raw navigation wheel switch state

I need to do some work on debouncing and ignoring simultaneous key presses.

* Controls: Add debug view for switches state.

* Controls: Ignore all key presses until all keys are released.

This should address some mechanical quirks of the navigation wheel used on the PortaPack.

* Clock Manager: Wait for only the necessary PLL to lock.

Wasn't working on PortaPacks without a built-in clock reference, as that uses the other PLL.
TODO: Switching PLLs may be kind of pointless now...

* CMake: Pull HackRF project from GitHub and build.

* CMake: Remove commented code.

* CMake: Clone HackRF via HTTPS, not SSH.

* CMake: Extra pause for slow post-DFU firmware boot-up.

* CMake: TODO to fix SVF/XSVF file source.

* CMake: Ask HackRF hackrf_usb to make DFU binary.

* Travis-CI: Add dfu-util, now that HackRF firmware is being built for inclusion.

* Travis-CI: Update build environment to Ubuntu xenial

Previously Trusty.

* Travis-CI: Incorrectly structured my request for dfu-util package.

I'm soooo talented.

* ldscript: Mark flash, ram with correct R/W/X flags.

* ldscript: Enlarge M0 flash region to 1Mbyte, the size of the HackRF SPI flash.

* Receiver: Hide PPM adjustment if clock source is not HackRF crystal.

* Documentation: Update product photos and README.

* Documentation: Add TCXO feature to README description.

* Application: Rearrange files to match HAVOC directory structure.

* Map view in AIS (#213)

* Added GeoMapView to AISRecentEntryDetailView

* Added autoupdate in AIS map

* Revert "Map view in AIS (#213)"

This reverts commit 262c030224.

This commit will be cherry-picked onto a clean branch, then re-committed after a troublesome pull request is reverted.

* Revert "Upstream merge to make new revision of PortaPack work (#206)"

This reverts commit 920b98f7c9.

This pull request was missing some changes and was preventing firmware from functioning on older PortaPacks.

* CPLD: Pull bitstream from HackRF project.

* SGPIO: Identify pins on CPLD by their new functions. Pull down HOST_SYNC_EN.

* CPLD: Don't load HackRF CPLD bitstream into RAM.

Trying to converge CPLD implementations, so this shouldn't be necesssary. HOWEVER, it would be good to *check* the CPLD contents and provide a way to update, if necessary.

* CPLD: Tweak clock generator config to match CPLD timing changes in HackRF.

* PinConfig: Drive CPLD pins correctly.

* CMake: Use jboone/hackrf master branch, now that CPLD fixes are there.

* CMake: Fix HackRF CPLD SVF dependency.

Build would break on the first pass, but work if you restarted make.

* CMake: Fix my misuse of the HackRF CMake configuration -- was building from too deep in the directory tree

* CMake: Work-around for CMake 3.5 not supporting ExternalProject_Add SOURCE_SUBDIR.

* CMake: Choose a CMP0005 policy to quiet CMake warnings.

* Settings: Show active clock reference. Only show PPM adjustment for HackRF source.

* Radio Settings: Change reference clock text color.

Make consistent color with other un-editable text.
TODO: This is a bit of a hack to get ui::Text objects to support custom colors, like the Label structures used elsewhere.
This commit is contained in:
Jared Boone 2019-02-03 19:25:11 +01:00 committed by Furrtek
parent 262c030224
commit e7c0fa394b
76 changed files with 3585 additions and 4053 deletions

View File

@ -1,6 +1,11 @@
language: cpp
cache: apt
matrix:
include:
- os: linux
compiler: gcc
cache: apt
dist: xenial
notifications:
irc:
@ -27,6 +32,9 @@ script:
- popd
addons:
apt:
packages:
- dfu-util
artifacts:
paths:
- $(ls build/firmware/portapack-h1-havoc-*.tar.bz2 | tr "\n" ":")

View File

@ -19,6 +19,8 @@
#
cmake_minimum_required(VERSION 2.8.9)
cmake_policy(SET CMP0005 NEW)
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/firmware/toolchain-arm-cortex-m.cmake)
project(portapack-h1)

View File

@ -86,7 +86,7 @@ Tetra info? | 0% | Same
Except where specified in subdirectories of this project, all work is offered under the following license:
Copyright (C) 2013-2015 Jared Boone, ShareBrained Technology, Inc.
Copyright (C) 2013-2019 Jared Boone, ShareBrained Technology, Inc.
Copyright (C) 2015-2016 Furrtek

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

View File

@ -25,12 +25,6 @@ set(COMMON ${PROJECT_SOURCE_DIR}/common)
set(CHIBIOS ${PROJECT_SOURCE_DIR}/chibios)
set(CHIBIOS_PORTAPACK ${PROJECT_SOURCE_DIR}/chibios-portapack)
set(HACKRF_FIRMWARE_FILENAME hackrf_one_usb.dfu)
set(HACKRF_FIRMWARE_IMAGE ${PROJECT_SOURCE_DIR}/${HACKRF_FIRMWARE_FILENAME})
set(HACKRF_CPLD_SVF_FILENAME hackrf_cpld_portapack.svf)
set(HACKRF_CPLD_SVF_PATH ${PROJECT_SOURCE_DIR}/${HACKRF_CPLD_SVF_FILENAME})
set(EXTRACT_CPLD_DATA ${PROJECT_SOURCE_DIR}/tools/extract_cpld_data.py)
set(EXTRACT_SVF_DATA_XC2C64A ${PROJECT_SOURCE_DIR}/tools/extract_svf_data_xc2c64a.py)
set(STRIP_DFU ${PROJECT_SOURCE_DIR}/tools/strip_dfu.py)
@ -40,6 +34,29 @@ set(MAKE_IMAGE_CHUNK ${PROJECT_SOURCE_DIR}/tools/make_image_chunk.py)
set(FIRMWARE_NAME portapack-h1-havoc)
set(FIRMWARE_FILENAME ${FIRMWARE_NAME}.bin)
include(ExternalProject)
find_program(MAKE_EXE NAMES gmake nmake make)
ExternalProject_Add(hackrf
GIT_REPOSITORY https://github.com/jboone/hackrf.git
# SOURCE_SUBDIR firmware
# SOURCE_SUBDIR isn't available in CMake 3.5 (Ubuntu 16.04 LTS), so the following is a work-around:
CONFIGURE_COMMAND ${CMAKE_COMMAND} -DUSER_INTERFACE=PORTAPACK "-GUnix Makefiles" ../hackrf/firmware
BUILD_COMMAND ${MAKE_EXE} hackrf_usb.dfu
INSTALL_COMMAND ""
)
ExternalProject_Get_Property(hackrf SOURCE_DIR)
ExternalProject_Get_Property(hackrf BINARY_DIR)
set(hackrf_SOURCE_DIR ${SOURCE_DIR})
set(hackrf_BINARY_DIR ${BINARY_DIR})
set(HACKRF_FIRMWARE_DFU_FILENAME hackrf_usb.dfu)
set(HACKRF_FIRMWARE_BIN_FILENAME hackrf_usb.bin)
set(HACKRF_FIRMWARE_DFU_IMAGE ${hackrf_BINARY_DIR}/hackrf_usb/${HACKRF_FIRMWARE_DFU_FILENAME})
set(HACKRF_FIRMWARE_BIN_IMAGE ${hackrf_BINARY_DIR}/hackrf_usb/${HACKRF_FIRMWARE_BIN_FILENAME})
set(HACKRF_CPLD_SVF_FILENAME default.svf)
set(HACKRF_CPLD_SVF_PATH ${hackrf_SOURCE_DIR}/firmware/cpld/sgpio_if/${HACKRF_CPLD_SVF_FILENAME})
add_subdirectory(application)
add_subdirectory(baseband)
@ -59,8 +76,8 @@ add_custom_target(
add_custom_target(
program
COMMAND dfu-util --device 1fc9:000c --download ${HACKRF_FIRMWARE_IMAGE}
COMMAND sleep 1s
COMMAND dfu-util --device 1fc9:000c --download ${HACKRF_FIRMWARE_DFU_IMAGE}
COMMAND sleep 3s
COMMAND hackrf_spiflash -w ${FIRMWARE_FILENAME}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FIRMWARE_FILENAME}
)
@ -69,11 +86,11 @@ add_custom_target(
add_custom_command(
OUTPUT ${FIRMWARE_NAME}-${GIT_REVISION}.tar.bz2 ${FIRMWARE_NAME}-${GIT_REVISION}.zip
COMMAND cp ${LICENSE_PATH} LICENSE
COMMAND cp ${HACKRF_FIRMWARE_IMAGE} ${HACKRF_FIRMWARE_FILENAME}
COMMAND tar -c -j -f ${FIRMWARE_NAME}-${GIT_REVISION}.tar.bz2 ${FIRMWARE_FILENAME} ${HACKRF_FIRMWARE_FILENAME} LICENSE
COMMAND zip -9 -q ${FIRMWARE_NAME}-${GIT_REVISION}.zip ${FIRMWARE_FILENAME} ${HACKRF_FIRMWARE_FILENAME} LICENSE
COMMAND rm -f LICENSE ${HACKRF_FIRMWARE_FILENAME}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FIRMWARE_FILENAME} ${LICENSE_PATH} ${HACKRF_FIRMWARE_IMAGE}
COMMAND cp ${HACKRF_FIRMWARE_DFU_IMAGE} ${HACKRF_FIRMWARE_DFU_FILENAME}
COMMAND tar -c -j -f ${FIRMWARE_NAME}-${GIT_REVISION}.tar.bz2 ${FIRMWARE_FILENAME} ${HACKRF_FIRMWARE_DFU_FILENAME} LICENSE
COMMAND zip -9 -q ${FIRMWARE_NAME}-${GIT_REVISION}.zip ${FIRMWARE_FILENAME} ${HACKRF_FIRMWARE_DFU_FILENAME} LICENSE
COMMAND rm -f LICENSE ${HACKRF_FIRMWARE_DFU_FILENAME}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FIRMWARE_FILENAME} ${LICENSE_PATH} ${HACKRF_FIRMWARE_DFU_IMAGE}
VERBATIM
)

View File

@ -82,7 +82,7 @@ set(HACKRF_CPLD_DATA_HPP ${CMAKE_CURRENT_BINARY_DIR}/hackrf_cpld_data.hpp)
set(HACKRF_CPLD_DATA_CPP ${CMAKE_CURRENT_BINARY_DIR}/hackrf_cpld_data.cpp)
# Imported source files and paths
include(${CHIBIOS_PORTAPACK}/boards/GSG_HACKRF_ONE/board.cmake)
include(${CHIBIOS_PORTAPACK}/boards/PORTAPACK_APPLICATION/board.cmake)
include(${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx_M0/platform.cmake)
include(${CHIBIOS}/os/hal/hal.cmake)
include(${CHIBIOS_PORTAPACK}/os/ports/GCC/ARMCMx/LPC43xx_M0/port.cmake)
@ -405,7 +405,7 @@ add_custom_command(
add_custom_command(
OUTPUT ${HACKRF_CPLD_DATA_HPP} ${HACKRF_CPLD_DATA_CPP}
COMMAND ${EXTRACT_SVF_DATA_XC2C64A} ${HACKRF_CPLD_SVF_PATH} hackrf::one::cpld::verify_blocks ${HACKRF_CPLD_DATA_CPP}
DEPENDS ${EXTRACT_SVF_DATA_XC2C64A} ${HACKRF_CPLD_SVF_PATH}
DEPENDS ${EXTRACT_SVF_DATA_XC2C64A} hackrf
)
add_executable(${PROJECT_NAME}.elf ${CSRC} ${CPPSRC} ${ASMSRC})

View File

@ -30,6 +30,11 @@
// #include "ui_sd_card_debug.hpp"
#include "portapack.hpp"
using namespace portapack;
#include "irq_controls.hpp"
namespace ui {
/* DebugMemoryView *******************************************************/
@ -244,6 +249,74 @@ void RegistersView::focus() {
button_done.focus();
}
/* ControlsSwitchesWidget ************************************************/
void ControlsSwitchesWidget::on_show() {
display.fill_rectangle(
screen_rect(),
Color::black()
);
}
bool ControlsSwitchesWidget::on_key(const KeyEvent key) {
key_event_mask = 1 << toUType(key);
return true;
}
void ControlsSwitchesWidget::paint(Painter& painter) {
const std::array<Rect, 7> button_rects { {
{ 64, 32, 16, 16 }, // Right
{ 0, 32, 16, 16 }, // Left
{ 32, 64, 16, 16 }, // Down
{ 32, 0, 16, 16 }, // Up
{ 32, 32, 16, 16 }, // Select
{ 16, 96, 16, 16 }, // Encoder phase 0
{ 48, 96, 16, 16 }, // Encoder phase 1
} };
const auto pos = screen_pos();
auto switches_raw = control::debug::switches();
auto switches_debounced = get_switches_state().to_ulong();
auto switches_event = key_event_mask;
for(const auto r : button_rects) {
const auto c =
((switches_event & 1) ?
Color::red() :
((switches_debounced & 1) ?
Color::green() :
((switches_raw & 1) ?
Color::yellow() :
Color::blue()
)
)
);
painter.fill_rectangle(r + pos, c);
switches_raw >>= 1;
switches_debounced >>= 1;
switches_event >>= 1;
}
}
void ControlsSwitchesWidget::on_frame_sync() {
set_dirty();
}
/* DebugControlsView *****************************************************/
DebugControlsView::DebugControlsView(NavigationView& nav) {
add_children({
&text_title,
&switches_widget,
&button_done,
});
button_done.on_select = [&nav](Button&){ nav.pop(); };
}
void DebugControlsView::focus() {
switches_widget.focus();
}
/* DebugPeripheralsMenuView **********************************************/
DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
@ -261,7 +334,7 @@ DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) {
[](const size_t register_number) { return portapack::clock_generator.read_register(register_number); }
); } },
{ audio::debug::codec_name(), ui::Color::white(), nullptr, [&nav](){ nav.push<RegistersView>(
audio::debug::codec_name(), RegistersWidgetConfig { (size_t)audio::debug::reg_count(), (size_t)audio::debug::reg_bits() },
audio::debug::codec_name(), RegistersWidgetConfig { audio::debug::reg_count(), audio::debug::reg_bits() },
[](const size_t register_number) { return audio::debug::reg_read(register_number); }
); } },
});
@ -277,7 +350,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
//{ "SD Card", ui::Color::white(), nullptr, [&nav](){ nav.push<SDCardDebugView>(); } },
{ "Peripherals", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugPeripheralsMenuView>(); } },
{ "Temperature", ui::Color::white(), nullptr, [&nav](){ nav.push<TemperatureView>(); } },
});
{ "Controls", ui::Color::white(), nullptr, [&nav](){ nav.push<DebugControlsView>(); } }, });
on_left = [&nav](){ nav.pop(); };
}

View File

@ -218,6 +218,56 @@ private:
};
};
class ControlsSwitchesWidget : public Widget {
public:
ControlsSwitchesWidget(
Rect parent_rect
) : Widget { parent_rect },
key_event_mask(0)
{
set_focusable(true);
}
void on_show() override;
bool on_key(const KeyEvent key) override;
void paint(Painter& painter) override;
private:
uint8_t key_event_mask;
MessageHandlerRegistration message_handler_frame_sync {
Message::ID::DisplayFrameSync,
[this](const Message* const) {
this->on_frame_sync();
}
};
void on_frame_sync();
};
class DebugControlsView : public View {
public:
explicit DebugControlsView(NavigationView& nav);
void focus() override;
private:
Text text_title {
{ 64, 16, 184, 16 },
"Controls State",
};
ControlsSwitchesWidget switches_widget {
{ 80, 80, 80, 112 },
};
Button button_done {
{ 72, 264, 96, 24 },
"Done"
};
};
/*class DebugLCRView : public View {
public:
DebugLCRView(NavigationView& nav, std::string lcrstring);

View File

@ -111,11 +111,39 @@ SetRadioView::SetRadioView(
) {
button_cancel.on_select = [&nav](Button&){
nav.pop();
},
};
const auto reference = portapack::clock_manager.get_reference();
std::string source_name("---");
switch(reference.source) {
case ClockManager::ReferenceSource::Xtal: source_name = "HackRF"; break;
case ClockManager::ReferenceSource::PortaPack: source_name = "PortaPack"; break;
case ClockManager::ReferenceSource::External: source_name = "External"; break;
}
value_source.set(source_name);
value_source_frequency.set(to_string_dec_uint(reference.frequency / 1000000, 2) + "." + to_string_dec_uint((reference.frequency % 1000000) / 100, 4, '0') + " MHz");
label_source.set_style(&style_text);
value_source.set_style(&style_text);
value_source_frequency.set_style(&style_text);
add_children({
&labels,
&label_source,
&value_source,
&value_source_frequency,
});
if( reference.source == ClockManager::ReferenceSource::Xtal ) {
add_children({
&labels_correction,
&field_ppm,
});
}
add_children({
&labels_bias,
&check_bias,
&button_done,
&button_cancel

View File

@ -125,17 +125,41 @@ public:
std::string title() const override { return "Radio settings"; };
private:
Labels labels {
{ { 2 * 8, 2 * 16 }, "Frequency correction:", Color::light_grey() },
{ { 6 * 8, 3 * 16 }, "PPM", Color::light_grey() },
{ { 24, 7 * 16 }, "CAUTION: Ensure that all", Color::red() },
{ { 28, 8 * 16 }, "devices attached to the", Color::red() },
{ { 8, 9 * 16 }, "antenna connector can accept", Color::red() },
{ { 68, 10 * 16 }, "a DC voltage!", Color::red() }
const Style style_text {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::light_grey(),
};
Text label_source {
{ 0, 1 * 16, 17 * 8, 16 },
"Reference Source:"
};
Text value_source {
{ (240 - 11 * 8), 1 * 16, 11 * 8, 16 },
"---"
};
Text value_source_frequency {
{ (240 - 11 * 8), 2 * 16, 11 * 8, 16 },
"---"
};
Labels labels_correction {
{ { 2 * 8, 4 * 16 }, "Frequency correction:", Color::light_grey() },
{ { 6 * 8, 5 * 16 }, "PPM", Color::light_grey() },
};
Labels labels_bias {
{ { 24, 8 * 16 }, "CAUTION: Ensure that all", Color::red() },
{ { 28, 9 * 16 }, "devices attached to the", Color::red() },
{ { 8, 10 * 16 }, "antenna connector can accept", Color::red() },
{ { 68, 11 * 16 }, "a DC voltage!", Color::red() }
};
NumberField field_ppm {
{ 2 * 8, 3 * 16 },
{ 2 * 8, 5 * 16 },
3,
{ -50, 50 },
1,
@ -143,7 +167,7 @@ private:
};
Checkbox check_bias {
{ 28, 12 * 16 },
{ 28, 13 * 16 },
5,
"Turn on bias voltage"
};

View File

@ -222,6 +222,10 @@ void shutdown() {
audio_codec->reset();
input::stop();
output::stop();
i2s::i2s0::shutdown();
clock_manager.stop_audio_pll();
}
void set_rate(const Rate rate) {

View File

@ -29,56 +29,8 @@ using namespace hackrf::one;
#include "lpc43xx_cpp.hpp"
using namespace lpc43xx;
static void set_clock(LPC_CGU_BASE_CLK_Type& clk, const cgu::CLK_SEL clock_source) {
clk.AUTOBLOCK = 1;
clk.CLK_SEL = toUType(clock_source);
}
static constexpr uint32_t systick_count(const uint32_t clock_source_f) {
return clock_source_f / CH_FREQUENCY;
}
static constexpr uint32_t systick_load(const uint32_t clock_source_f) {
return systick_count(clock_source_f) - 1;
}
constexpr uint32_t clock_source_irc_f = 12000000;
constexpr uint32_t clock_source_pll1_boot_f = 96000000;
//constexpr uint32_t clock_source_gp_clkin = 20000000;
constexpr uint32_t clock_source_pll1_step_f = 100000000;
constexpr uint32_t clock_source_pll1_f = 200000000;
constexpr auto systick_count_irc = systick_load(clock_source_irc_f);
constexpr auto systick_count_pll1 = systick_load(clock_source_pll1_f);
constexpr auto systick_count_pll1_step = systick_load(clock_source_pll1_step_f);
constexpr uint32_t si5351_vco_f = 800000000;
constexpr uint32_t i2c0_bus_f = 400000;
constexpr uint32_t i2c0_high_period_ns = 900;
constexpr I2CClockConfig i2c_clock_config_400k_boot_clock {
.clock_source_f = clock_source_pll1_boot_f,
.bus_f = i2c0_bus_f,
.high_period_ns = i2c0_high_period_ns,
};
constexpr I2CClockConfig i2c_clock_config_400k_fast_clock {
.clock_source_f = clock_source_pll1_f,
.bus_f = i2c0_bus_f,
.high_period_ns = i2c0_high_period_ns,
};
constexpr I2CConfig i2c_config_boot_clock {
.high_count = i2c_clock_config_400k_boot_clock.i2c_high_count(),
.low_count = i2c_clock_config_400k_boot_clock.i2c_low_count(),
};
constexpr I2CConfig i2c_config_fast_clock {
.high_count = i2c_clock_config_400k_fast_clock.i2c_high_count(),
.low_count = i2c_clock_config_400k_fast_clock.i2c_low_count(),
};
constexpr si5351::Inputs si5351_inputs {
.f_xtal = si5351_xtal_f,
.f_clkin = si5351_clkin_f,
@ -225,9 +177,9 @@ static constexpr ClockControl::MultiSynthSource get_reference_clock_generator_pl
}
constexpr ClockControls si5351_clock_control_common { {
{ ClockControl::ClockCurrentDrive::_6mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Fractional, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_6mA, ClockControl::ClockSource::MS_Group, ClockControl::ClockInvert::Invert, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_6mA, ClockControl::ClockSource::MS_Group, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Fractional, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Group, ClockControl::ClockInvert::Invert, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Group, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_8mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
{ ClockControl::ClockCurrentDrive::_6mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
@ -235,8 +187,8 @@ constexpr ClockControls si5351_clock_control_common { {
{ ClockControl::ClockCurrentDrive::_2mA, ClockControl::ClockSource::MS_Self, ClockControl::ClockInvert::Normal, get_reference_clock_generator_pll(ClockManager::ReferenceSource::Xtal), ClockControl::MultiSynthMode::Integer, ClockControl::ClockPowerDown::Power_Off },
} };
ClockManager::ReferenceSource ClockManager::get_reference_source() const {
return reference_source;
ClockManager::Reference ClockManager::get_reference() const {
return reference;
}
static void portapack_tcxo_enable() {
@ -255,38 +207,6 @@ static void portapack_tcxo_disable() {
#include "hackrf_gpio.hpp"
using namespace hackrf::one;
void ClockManager::init_peripherals() {
/* Must be sure to run the M4 core from IRC when messing with the signal
* generator that sources the GP_CLKIN signal that drives the micro-
* controller's PLL1 input.
*/
/* When booting from SPIFI, PLL1 is already running at 288MHz. */
/* TODO: Refactor this blob, there's too much knowledge about post-boot
* state, which can change depending on where we're running from -- SPIFI
* or RAM or ???
*/
// PLL1 is running at 288 MHz upon bootstrap exit.
LPC_CGU->IDIVA_CTRL.word =
( 0 << 0) /* PD */
| ( 2 << 2) /* IDIV (/3) */
| ( 1 << 11) /* AUTOBLOCK */
| ( 9 << 24) /* PLL1 */
;
const auto clk_sel = cgu::CLK_SEL::IDIVA;
set_clock(LPC_CGU->BASE_M4_CLK, clk_sel);
set_clock(LPC_CGU->BASE_PERIPH_CLK, clk_sel);
set_clock(LPC_CGU->BASE_APB1_CLK, clk_sel);
set_clock(LPC_CGU->BASE_APB3_CLK, clk_sel);
set_clock(LPC_CGU->BASE_SDIO_CLK, clk_sel);
set_clock(LPC_CGU->BASE_SSP1_CLK, clk_sel);
// IDIVC should no longer be in use.
LPC_CGU->IDIVC_CTRL.PD = 1;
i2c0.start(i2c_config_boot_clock);
}
void ClockManager::init_clock_generator() {
clock_generator.reset();
clock_generator.set_crystal_internal_load_capacitance(CrystalInternalLoadCapacitance::XTAL_CL_8pF);
@ -299,11 +219,11 @@ void ClockManager::init_clock_generator() {
);
clock_generator.enable_output(clock_generator_output_mcu_clkin);
const auto reference_source = choose_reference_source();
reference = choose_reference();
clock_generator.disable_output(clock_generator_output_mcu_clkin);
const auto ref_pll = get_reference_clock_generator_pll(reference_source);
const auto ref_pll = get_reference_clock_generator_pll(reference.source);
const ClockControls si5351_clock_control = ClockControls { {
si5351_clock_control_common[0].ms_src(ref_pll),
si5351_clock_control_common[1].ms_src(ref_pll),
@ -330,15 +250,14 @@ void ClockManager::init_clock_generator() {
// Wait for both PLLs to lock.
// TODO: Disable the unused PLL?
while((clock_generator.device_status() & 0x60) != 0);
const uint8_t device_status_mask = (ref_pll == ClockControl::MultiSynthSource::PLLB) ? 0x40 : 0x20;
while((clock_generator.device_status() & device_status_mask) != 0);
clock_generator.set_clock_control(
clock_generator_output_mcu_clkin,
si5351_clock_control_common[clock_generator_output_mcu_clkin].ms_src(ref_pll).clk_pdn(ClockControl::ClockPowerDown::Power_On)
);
clock_generator.enable_output(clock_generator_output_mcu_clkin);
set_m4_clock_to_pll1();
}
uint32_t ClockManager::measure_gp_clkin_frequency() {
@ -364,23 +283,23 @@ ClockManager::ReferenceSource ClockManager::detect_reference_source() {
}
}
ClockManager::ReferenceSource ClockManager::choose_reference_source() {
ClockManager::Reference ClockManager::choose_reference() {
const auto detected_reference = detect_reference_source();
if( (detected_reference == ReferenceSource::External) ||
(detected_reference == ReferenceSource::PortaPack) ) {
const auto frequency = measure_gp_clkin_frequency();
if( (frequency >= 9850000) && (frequency <= 10150000) ) {
return detected_reference;
return { detected_reference, 10000000 };
}
}
portapack_tcxo_disable();
return ReferenceSource::Xtal;
return { ReferenceSource::Xtal, 10000000 };
}
void ClockManager::shutdown() {
// run_from_irc();
clock_generator.reset();
}
@ -488,110 +407,6 @@ uint32_t ClockManager::get_frequency_monitor_measurement_in_hertz() {
return LPC_CGU->FREQ_MON.FCNT * 25000;
}
void ClockManager::enable_xtal_oscillator() {
LPC_CGU->XTAL_OSC_CTRL.BYPASS = 0;
LPC_CGU->XTAL_OSC_CTRL.ENABLE = 1;
}
void ClockManager::disable_xtal_oscillator() {
LPC_CGU->XTAL_OSC_CTRL.ENABLE = 0;
}
void ClockManager::set_m4_clock_to_pll1() {
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
* core clock speed to the 110 - 204MHz range.
*/
/* Set M4 clock to safe default speed (~12MHz IRC) */
i2c0.stop();
// All other peripherals capable of running at 204 MHz.
LPC_CGU->IDIVA_CTRL.word =
( 0 << 0) /* PD */
| ( 0 << 2) /* IDIV (/1) */
| ( 1 << 11) /* AUTOBLOCK */
| ( 1 << 24) /* IRC */
;
systick_adjust_period(systick_count_irc);
halLPCSetSystemClock(clock_source_irc_f);
// SPIFI clock
LPC_CGU->IDIVB_CTRL.word =
( 0 << 0) /* PD */
| ( 0 << 2) /* IDIV (/1) */
| ( 1 << 11) /* AUTOBLOCK */
| ( 1 << 24) /* IRC */
;
/* Step into the 90-110MHz M4 clock range */
/* Fclkin = 40M
* /N=2 = 20M = PFDin
* Fcco = PFDin * (M=10) = 200M
* Fclk = Fcco / (2*(P=1)) = 100M
*/
cgu::pll1::ctrl({
.pd = 1,
.bypass = 0,
.fbsel = 0,
.direct = 0,
.psel = 0,
.autoblock = 1,
.nsel = 1,
.msel = 9,
.clk_sel = cgu::CLK_SEL::GP_CLKIN,
});
cgu::pll1::enable();
while( !cgu::pll1::is_locked() );
/* Switch M4 clock to PLL1 running at intermediate rate */
// All other peripherals capable of running at 204 MHz.
LPC_CGU->IDIVA_CTRL.word =
( 0 << 0) /* PD */
| ( 0 << 2) /* IDIV (/1) */
| ( 1 << 11) /* AUTOBLOCK */
| ( 9 << 24) /* PLL1 */
;
systick_adjust_period(systick_count_pll1_step);
halLPCSetSystemClock(clock_source_pll1_step_f);
// SPIFI clock
LPC_CGU->IDIVB_CTRL.word =
( 0 << 0) /* PD */
| ( 0 << 2) /* IDIV (/1) */
| ( 1 << 11) /* AUTO BLOCK */
| ( 9 << 24) /* PLL1 */
;
/* Delay >50us at 90-110MHz clock speed */
volatile uint32_t delay = 1400;
while(delay--);
// SPIFI clock
LPC_CGU->IDIVB_CTRL.word =
( 0 << 0) /* PD */
| ( 1 << 2) /* IDIV (/2) */
| ( 1 << 11) /* AUTOBLOCK */
| ( 9 << 24) /* PLL1 */
;
/* Remove /2P divider from PLL1 output to achieve full speed */
cgu::pll1::direct();
systick_adjust_period(systick_count_pll1);
halLPCSetSystemClock(clock_source_pll1_f);
i2c0.start(i2c_config_fast_clock);
}
void ClockManager::power_down_pll1() {
/* Power down PLL1 if not needed */
cgu::pll1::disable();
}
void ClockManager::start_audio_pll() {
cgu::pll0audio::ctrl({
.pd = 1,
@ -629,11 +444,13 @@ void ClockManager::start_audio_pll() {
cgu::pll0audio::clock_enable();
set_base_audio_clock_divider(1);
set_clock(LPC_CGU->BASE_AUDIO_CLK, cgu::CLK_SEL::IDIVC);
LPC_CGU->BASE_AUDIO_CLK.AUTOBLOCK = 1;
LPC_CGU->BASE_AUDIO_CLK.CLK_SEL = toUType(cgu::CLK_SEL::IDIVD);
}
void ClockManager::set_base_audio_clock_divider(const size_t divisor) {
LPC_CGU->IDIVC_CTRL.word =
LPC_CGU->IDIVD_CTRL.word =
(0 << 0)
| ((divisor - 1) << 2)
| (1 << 11)
@ -646,7 +463,3 @@ void ClockManager::stop_audio_pll() {
cgu::pll0audio::power_down();
while( cgu::pll0audio::is_locked() );
}
void ClockManager::stop_peripherals() {
i2c0.stop();
}

View File

@ -38,18 +38,22 @@ public:
PortaPack, /* 10 MHz TCXO on 20180820 and newer PortaPack revisions. */
External, /* HackRF external clock input SMA, or from PortaPack with TCXO feature. */
};
using ReferenceFrequency = uint32_t;
typedef struct {
ReferenceSource source;
ReferenceFrequency frequency;
} Reference;
constexpr ClockManager(
I2C& i2c0,
si5351::Si5351& clock_generator
) : i2c0(i2c0),
clock_generator(clock_generator),
reference_source(ReferenceSource::Xtal)/*
_clock_f(0)*/
reference({ReferenceSource::Xtal, 10000000})
{
}
void init_peripherals();
void init_clock_generator();
void shutdown();
@ -73,33 +77,26 @@ public:
uint32_t get_frequency_monitor_measurement_in_hertz();
ReferenceSource get_reference_source() const;
Reference get_reference() const;
private:
I2C& i2c0;
si5351::Si5351& clock_generator;
ReferenceSource reference_source;
//uint32_t _clock_f;
Reference reference;
void set_gp_clkin_to_clkin_direct();
void start_frequency_monitor_measurement(const cgu::CLK_SEL clk_sel);
void wait_For_frequency_monitor_measurement_done();
void enable_xtal_oscillator();
void disable_xtal_oscillator();
void set_m4_clock_to_irc();
void set_m4_clock_to_pll1();
void power_down_pll1();
void stop_peripherals();
uint32_t measure_gp_clkin_frequency();
ClockManager::ReferenceSource detect_reference_source();
ClockManager::ReferenceSource choose_reference_source();
ReferenceSource detect_reference_source();
Reference choose_reference();
};
#endif/*__CLOCK_MANAGER_H__*/

View File

@ -224,8 +224,6 @@ void EventDispatcher::handle_local_queue() {
void EventDispatcher::handle_rtc_tick() {
sd_card::poll_inserted();
portapack::poll_ext_clock();
portapack::temperature_logger.second_tick();
uint32_t backlight_timer = portapack::persistent_memory::config_backlight_timer();
@ -294,6 +292,19 @@ void EventDispatcher::handle_switches() {
portapack::bl_tick_counter = 0;
if( switches_state.count() == 0 ) {
// If all keys are released, we are no longer in a key event.
in_key_event = false;
}
if( in_key_event ) {
// If we're in a key event, return. We will ignore all additional key
// presses until the first key is released. We also want to ignore events
// where the last key held generates a key event when other pressed keys
// are released.
return;
}
if( EventDispatcher::display_sleep ) {
// Swallow event, wake up display.
if( switches_state.any() ) {
@ -309,6 +320,8 @@ void EventDispatcher::handle_switches() {
if( !event_bubble_key(event) ) {
context.focus_manager().update(top_widget, event);
}
in_key_event = true;
}
}
}

View File

@ -99,6 +99,7 @@ private:
bool sd_card_present = false;
static bool display_sleep;
bool halt = false;
bool in_key_event = false;
eventmask_t wait();
void dispatch(const eventmask_t events);

View File

@ -34,17 +34,16 @@ void Si5351::reset() {
write_register(Register::InterruptStatusSticky, 0x00);
write_register(Register::InterruptStatusMask, 0xf0);
update_output_enable_control();
disable_output_mask(0xff);
write_register(Register::OEBPinEnableControlMask, 0xff);
write_register(Register::PLLInputSource, 0x00);
_clock_control = {
set_clock_control({
ClockControl::power_off(), ClockControl::power_off(),
ClockControl::power_off(), ClockControl::power_off(),
ClockControl::power_off(), ClockControl::power_off(),
ClockControl::power_off(), ClockControl::power_off()
};
update_all_clock_control();
});
write(std::array<uint8_t, 70> { Register::CLK3_0DisableState });

View File

@ -455,10 +455,6 @@ public:
write_register(Register::CLKControl_Base + n, _clock_control[n]);
}
bool clkin_status() {
return ((device_status() & DeviceStatus::LOS_Mask) == DeviceStatus::LOS_ValidClockAtCLKIN);
}
template<size_t N>
void write_registers(const uint8_t reg, const std::array<uint8_t, N>& values) {
std::array<uint8_t, N + 1> data;

View File

@ -122,11 +122,13 @@ static bool touch_update() {
}
}
static bool switches_update(const uint8_t switches_raw) {
static uint8_t switches_raw = 0;
static bool switches_update(const uint8_t raw) {
// TODO: Only fire event on press, not release?
bool switch_changed = false;
for(size_t i=0; i<switch_debounce.size(); i++) {
switch_changed |= switch_debounce[i].feed((switches_raw >> i) & 1);
switch_changed |= switch_debounce[i].feed((raw >> i) & 1);
}
return switch_changed;
@ -149,7 +151,7 @@ static bool encoder_read() {
void timer0_callback(GPTDriver* const) {
eventmask_t event_mask = 0;
if( touch_update() ) event_mask |= EVT_MASK_TOUCH;
const auto switches_raw = portapack::io.io_update(touch_pins_configs[touch_phase]);
switches_raw = portapack::io.io_update(touch_pins_configs[touch_phase]);
if( switches_update(switches_raw) ) {
event_mask |= EVT_MASK_SWITCHES;
if( encoder_read() ) event_mask |= EVT_MASK_ENCODER;
@ -206,3 +208,13 @@ EncoderPosition get_encoder_position() {
touch::Frame get_touch_frame() {
return touch_frame;
}
namespace control {
namespace debug {
uint8_t switches() {
return switches_raw;
}
} /* debug */
} /* control */

View File

@ -44,4 +44,12 @@ SwitchesState get_switches_state();
EncoderPosition get_encoder_position();
touch::Frame get_touch_frame();
namespace control {
namespace debug {
uint8_t switches();
} /* debug */
} /* control */
#endif/*__IRQ_CONTROLS_H__*/

View File

@ -83,7 +83,6 @@ TransmitterModel transmitter_model;
TemperatureLogger temperature_logger;
bool antenna_bias { false };
bool prev_clkin_status { false };
uint8_t bl_tick_counter { 0 };
void set_antenna_bias(const bool v) {
@ -94,22 +93,73 @@ bool get_antenna_bias() {
return antenna_bias;
}
bool get_ext_clock() {
return prev_clkin_status;
static constexpr uint32_t systick_count(const uint32_t clock_source_f) {
return clock_source_f / CH_FREQUENCY;
}
void poll_ext_clock() {
auto clkin_status = clock_generator.clkin_status();
if (clkin_status != prev_clkin_status) {
prev_clkin_status = clkin_status;
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
clock_manager.init_peripherals();
}
static constexpr uint32_t systick_load(const uint32_t clock_source_f) {
return systick_count(clock_source_f) - 1;
}
constexpr uint32_t i2c0_bus_f = 400000;
constexpr uint32_t i2c0_high_period_ns = 900;
typedef struct {
uint32_t clock_f;
uint32_t systick_count;
uint32_t idivb;
uint32_t idivc;
} clock_config_t;
static constexpr uint32_t idiv_config(const cgu::CLK_SEL clk_sel, const uint32_t idiv) {
return cgu::IDIV_CTRL { 0, idiv-1, 1, clk_sel };
}
constexpr clock_config_t clock_config_irc {
12000000, systick_load(12000000),
idiv_config(cgu::CLK_SEL::IRC, 1),
idiv_config(cgu::CLK_SEL::IRC, 1),
};
constexpr clock_config_t clock_config_pll1_boot {
96000000, systick_load(96000000),
idiv_config(cgu::CLK_SEL::PLL1, 9),
idiv_config(cgu::CLK_SEL::PLL1, 3),
};
constexpr clock_config_t clock_config_pll1_step {
100000000, systick_load(100000000),
idiv_config(cgu::CLK_SEL::PLL1, 1),
idiv_config(cgu::CLK_SEL::PLL1, 1),
};
constexpr clock_config_t clock_config_pll1 {
200000000, systick_load(200000000),
idiv_config(cgu::CLK_SEL::PLL1, 2),
idiv_config(cgu::CLK_SEL::PLL1, 1),
};
constexpr I2CClockConfig i2c_clock_config_400k_boot_clock {
.clock_source_f = clock_config_pll1_boot.clock_f,
.bus_f = i2c0_bus_f,
.high_period_ns = i2c0_high_period_ns,
};
constexpr I2CClockConfig i2c_clock_config_400k_fast_clock {
.clock_source_f = clock_config_pll1.clock_f,
.bus_f = i2c0_bus_f,
.high_period_ns = i2c0_high_period_ns,
};
constexpr I2CConfig i2c_config_boot_clock {
.high_count = i2c_clock_config_400k_boot_clock.i2c_high_count(),
.low_count = i2c_clock_config_400k_boot_clock.i2c_low_count(),
};
constexpr I2CConfig i2c_config_fast_clock {
.high_count = i2c_clock_config_400k_fast_clock.i2c_high_count(),
.low_count = i2c_clock_config_400k_fast_clock.i2c_low_count(),
};
enum class PortaPackModel {
R1_20150901,
@ -150,119 +200,165 @@ Backlight* backlight() {
: static_cast<portapack::Backlight*>(&backlight_on_off);
}
static void configure_unused_mcu_peripherals_power_down(const bool power_down) {
LPC_CGU->IDIVD_CTRL.PD = power_down;
LPC_CGU->IDIVE_CTRL.PD = power_down;
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
LPC_CGU->BASE_USB1_CLK.PD = power_down;
LPC_CGU->BASE_SPI_CLK.PD = power_down;
LPC_CGU->BASE_PHY_RX_CLK.PD = power_down;
LPC_CGU->BASE_PHY_TX_CLK.PD = power_down;
LPC_CGU->BASE_LCD_CLK.PD = power_down;
LPC_CGU->BASE_SSP0_CLK.PD = power_down;
LPC_CGU->BASE_UART0_CLK.PD = power_down;
LPC_CGU->BASE_UART1_CLK.PD = power_down;
LPC_CGU->BASE_UART2_CLK.PD = power_down;
LPC_CGU->BASE_UART3_CLK.PD = power_down;
LPC_CGU->BASE_OUT_CLK.PD = power_down;
LPC_CGU->BASE_CGU_OUT0_CLK.PD = power_down;
LPC_CGU->BASE_CGU_OUT1_CLK.PD = power_down;
}
static LPC_CGU_BASE_CLK_Type* const base_clocks_idivc[] = {
&LPC_CGU->BASE_PERIPH_CLK,
&LPC_CGU->BASE_M4_CLK,
&LPC_CGU->BASE_APB1_CLK,
&LPC_CGU->BASE_APB3_CLK,
&LPC_CGU->BASE_SDIO_CLK,
&LPC_CGU->BASE_SSP1_CLK,
};
static void configure_unused_mcu_peripherals(const bool enabled) {
/* Disabling these peripherals reduces "idle" (PortaPack at main
* menu) current by 42mA.
*/
/* Some surprising peripherals in use by PortaPack firmware:
*
* RITIMER: M0 SysTick substitute (because M0 has no SysTick)
* TIMER3: M0 cycle/PCLK counter
* IDIVB: Clock for SPI (set up in bootstrap code)
* IDIVC: I2S audio clock
*/
const uint32_t clock_run_state = enabled ? 1 : 0;
const bool power_down = !enabled;
if( power_down == false ) {
// Power up peripheral clocks *before* enabling run state.
configure_unused_mcu_peripherals_power_down(power_down);
}
LPC_CCU1->CLK_APB3_I2C1_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_APB3_DAC_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_APB3_CAN0_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_APB1_CAN1_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_LCD_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_ETHERNET_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_USB0_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_EMC_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_SCT_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_USB1_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_EMCDIV_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_WWDT_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_USART0_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_UART1_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_SSP0_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_TIMER1_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_USART2_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_USART3_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_TIMER2_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_M4_QEI_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_USB1_CFG.RUN = clock_run_state;
LPC_CCU1->CLK_SPI_CFG.RUN = clock_run_state;
LPC_CCU2->CLK_APB2_USART3_CFG.RUN = clock_run_state;
LPC_CCU2->CLK_APB2_USART2_CFG.RUN = clock_run_state;
LPC_CCU2->CLK_APB0_UART1_CFG.RUN = clock_run_state;
LPC_CCU2->CLK_APB0_USART0_CFG.RUN = clock_run_state;
LPC_CCU2->CLK_APB0_SSP0_CFG.RUN = clock_run_state;
if( power_down == true ) {
// Power down peripheral clocks *after* disabling run state.
configure_unused_mcu_peripherals_power_down(power_down);
static void set_idivc_base_clocks(const cgu::CLK_SEL clock_source) {
for(uint32_t i=0; i<ARRAY_SIZE(base_clocks_idivc); i++) {
base_clocks_idivc[i]->AUTOBLOCK = 1;
base_clocks_idivc[i]->CLK_SEL = toUType(clock_source);
}
}
static void disable_unused_mcu_peripheral_clocks() {
configure_unused_mcu_peripherals(false);
}
static void enable_unused_mcu_peripheral_clocks() {
configure_unused_mcu_peripherals(true);
static void set_clock_config(const clock_config_t& config) {
LPC_CGU->IDIVB_CTRL.word = config.idivb;
LPC_CGU->IDIVC_CTRL.word = config.idivc;
systick_adjust_period(config.systick_count);
halLPCSetSystemClock(config.clock_f);
}
static void shutdown_base() {
i2c0.stop();
set_clock_config(clock_config_irc);
cgu::pll1::disable();
set_idivc_base_clocks(cgu::CLK_SEL::IRC);
cgu::pll1::ctrl({
.pd = 1,
.bypass = 0,
.fbsel = 0,
.direct = 1,
.psel = 0,
.autoblock = 1,
.nsel = 0,
.msel = 23,
.clk_sel = cgu::CLK_SEL::IRC,
});
cgu::pll1::enable();
while( !cgu::pll1::is_locked() );
set_clock_config(clock_config_pll1_boot);
i2c0.start(i2c_config_boot_clock);
clock_manager.shutdown();
chSysDisable();
systick_stop();
enable_unused_mcu_peripheral_clocks();
hackrf::one::reset();
}
bool init() {
clock_manager.init_peripherals();
/* Clock scheme after exiting bootloader in SPIFI mode:
*
* XTAL_OSC = powered down
*
* PLL0USB = powered down
* PLL0AUDIO = powered down
* PLL1 = IRC * 24 = 288 MHz
*
* IDIVA = IRC / 1 = 12 MHz
* IDIVB = PLL1 / 9 = 32 MHz
* IDIVC = PLL1 / 3 = 96 MHz
* IDIVD = IRC / 1 = 12 MHz
* IDIVE = IRC / 1 = 12 MHz
*
* BASE_USB0_CLK = PLL0USB
* BASE_PERIPH_CLK = IRC
* BASE_M4_CLK = IDIVC (96 MHz)
* BASE_SPIFI_CLK = IDIVB (32 MHZ)
*
* everything else = IRC
*/
/* Clock scheme during PortaPack operation:
*
* XTAL_OSC = powered down
*
* PLL0USB = powered down
* PLL0AUDIO = GP_CLKIN, Fcco=491.52 MHz, Fout=12.288 MHz
* PLL1 = GP_CLKIN * 10 = 200 MHz
*
* IDIVA = IRC / 1 = 12 MHz
* IDIVB = PLL1 / 2 = 100 MHz
* IDIVC = PLL1 / 1 = 200 MHz
* IDIVD = PLL0AUDIO / N (where N is varied depending on decimation factor)
* IDIVE = IRC / 1 = 12 MHz
*
* BASE_USB0_CLK = PLL0USB
* BASE_PERIPH_CLK = IRC
* BASE_M4_CLK = IDIVC (200 MHz)
* BASE_SPIFI_CLK = IDIVB (100 MHZ)
* BASE_AUDIO_CLK = IDIVD
*
* everything else = IRC
*/
bool init() {
set_idivc_base_clocks(cgu::CLK_SEL::IDIVC);
i2c0.start(i2c_config_boot_clock);
if( !portapack::cpld::update_if_necessary(portapack_cpld_config()) ) {
shutdown_base();
return false;
}
if( !hackrf::cpld::load_sram() ) {
chSysHalt();
}
portapack::io.init();
clock_manager.init_clock_generator();
i2c0.stop();
set_clock_config(clock_config_irc);
cgu::pll1::disable();
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
* core clock speed to the 110 - 204MHz range.
*/
/* Step into the 90-110MHz M4 clock range */
/* Fclkin = 40M
* /N=2 = 20M = PFDin
* Fcco = PFDin * (M=10) = 200M
* Fclk = Fcco / (2*(P=1)) = 100M
*/
cgu::pll1::ctrl({
.pd = 1,
.bypass = 0,
.fbsel = 0,
.direct = 0,
.psel = 0,
.autoblock = 1,
.nsel = 1,
.msel = 9,
.clk_sel = cgu::CLK_SEL::GP_CLKIN,
});
cgu::pll1::enable();
while( !cgu::pll1::is_locked() );
set_clock_config(clock_config_pll1_step);
/* Delay >50us at 90-110MHz clock speed */
volatile uint32_t delay = 1400;
while(delay--);
set_clock_config(clock_config_pll1);
/* Remove /2P divider from PLL1 output to achieve full speed */
cgu::pll1::direct();
i2c0.start(i2c_config_fast_clock);
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
audio::init(portapack_audio_codec());
@ -294,125 +390,4 @@ void shutdown() {
shutdown_base();
}
/* Bootstrap runs from SPIFI on the M4, immediately after the LPC43xx built-in
* boot ROM runs.
*/
/* After boot ROM executes:
* PLL1 is at 288MHz (IRC * 24)
* IDIVB_CTRL = PLL1 / 9 = 32MHz
* IDIVC_CTRL = PLL1 / 3 = 96MHz
* BASE_SPIFI_CLK.CLK_SEL = IDIVB
* BASE_M4_CLK.CLK_SEL = IDIVC?
*/
static void configure_spifi(void) {
constexpr Pin pins_spifi[] = {
{ 3, 3, PinConfig::spifi_sck(3) }, /* SPIFI_SCK: W25Q80BV.CLK(I), enable input buffer for timing feedback */
{ 3, 4, PinConfig::spifi_inout(3) }, /* SPIFI_SIO3/P82: W25Q80BV.HOLD(IO) */
{ 3, 5, PinConfig::spifi_inout(3) }, /* SPIFI_SIO2/P81: W25Q80BV.WP(IO) */
{ 3, 6, PinConfig::spifi_inout(3) }, /* SPIFI_MISO: W25Q80BV.DO(IO) */
{ 3, 7, PinConfig::spifi_inout(3) }, /* SPIFI_MOSI: W25Q80BV.DI(IO) */
{ 3, 8, PinConfig::spifi_cs(3) }, /* SPIFI_CS/P68: W25Q80BV.CS(I) */
};
for(const auto& pin : pins_spifi) {
pin.init();
}
/* Tweak SPIFI mode */
LPC_SPIFI->CTRL =
(0xffff << 0) /* Timeout */
| (0x1 << 16) /* CS high time in "clocks - 1" */
| (0 << 21) /* 0: Attempt speculative prefetch on data accesses */
| (0 << 22) /* 0: No interrupt on command ended */
| (0 << 23) /* 0: SCK driven low after rising edge at which last bit of command is captured. Stays low while CS# is high. */
| (0 << 27) /* 0: Cache prefetching enabled */
| (0 << 28) /* 0: Quad protocol, IO3:0 */
| (1 << 29) /* 1: Read data sampled on falling edge of clock */
| (1 << 30) /* 1: Read data is sampled using feedback clock from SCK pin */
| (0 << 31) /* 0: DMA request disabled */
;
/* Throttle up the SPIFI interface to 96MHz (IDIVA=PLL1 / 3) */
LPC_CGU->IDIVB_CTRL.word =
( 0 << 0) /* PD */
| ( 2 << 2) /* IDIV (/3) */
| ( 1 << 11) /* AUTOBLOCK */
| ( 9 << 24) /* PLL1 */
;
}
extern "C" {
void __early_init(void) {
/*
* Upon exit from bootloader into SPIFI boot mode:
*
* Enabled:
* PLL1: IRC, M=/24, N=/1, P=/1, autoblock, direct = 288 MHz
* IDIVA: IRC /1 = 12 MHz
* IDIVB: PLL1 /9, autoblock = 32 MHz
* IDIVC: PLL1 /3, autoblock = 96 MHz
* IDIVD: IRC /1 = 12 MHz
* IDIVE: IRC /1 = 12 MHz
* BASE_M4_CLK: IDIVC, autoblock
* BASE_SPIFI_CLK: IDIVB, autoblock
*
* Disabled:
* XTAL_OSC
* PLL0USB
* PLL0AUDIO
*/
/* LPC43xx M4 takes about 500 usec to get to __early_init
* Before __early_init, LPC bootloader runs and starts our code. In user code, the process stack
* is initialized, hardware floating point is initialized, and stacks are zeroed,
*/
const uint32_t CORTEX_M4_CPUID = 0x410fc240;
const uint32_t CORTEX_M4_CPUID_MASK = 0xff0ffff0;
if( (SCB->CPUID & CORTEX_M4_CPUID_MASK) == CORTEX_M4_CPUID ) {
/* Enable unaligned exception handler */
SCB_CCR |= (1 << 3);
/* Enable MemManage, BusFault, UsageFault exception handlers */
SCB_SHCSR |= (1 << 18) | (1 << 17) | (1 << 16);
reset();
// disable_unused_mcu_peripheral_clocks();
configure_spifi();
LPC_CCU1->CLK_M4_M0APP_CFG.RUN = true;
LPC_CREG->M0APPMEMMAP = LPC_SPIFI_DATA_CACHED_BASE + 0x0;
LPC_RGU->RESET_CTRL[1] = 0;
/* Prevent the M4 from doing any more initializing by sleep-waiting forever...
* ...until the M0 resets the M4 with some code to run.
*/
while(1) {
__WFE();
}
}
}
void __late_init(void) {
/*
* 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 */

View File

@ -59,9 +59,6 @@ extern TemperatureLogger temperature_logger;
void set_antenna_bias(const bool v);
bool get_antenna_bias();
void poll_ext_clock();
bool get_ext_clock();
bool init();
void shutdown();

View File

@ -252,12 +252,10 @@ FrequencyOptionsView::FrequencyOptionsView(
&field_step,
});
if( portapack::clock_manager.get_reference_source() == ClockManager::ReferenceSource::External ) {
add_child(&text_ext);
} else {
if( portapack::clock_manager.get_reference().source == ClockManager::ReferenceSource::Xtal ) {
add_child(&field_ppm);
}
add_child(&text_ppm);
}
}
void FrequencyOptionsView::set_step(rf::Frequency f) {

View File

@ -159,7 +159,7 @@ void SystemStatusView::refresh() {
button_bias_tee.set_foreground(ui::Color::light_grey());
}
if (portapack::get_ext_clock()) {
if (portapack::clock_manager.get_reference().source == ClockManager::ReferenceSource::External) {
image_clock_status.set_bitmap(&bitmap_icon_clk_ext);
button_bias_tee.set_foreground(ui::Color::green());
} else {

View File

@ -73,7 +73,7 @@ set(USE_FPU hard)
#
# Imported source files and paths
include(${CHIBIOS_PORTAPACK}/boards/GSG_HACKRF_ONE/board.cmake)
include(${CHIBIOS_PORTAPACK}/boards/PORTAPACK_BASEBAND/board.cmake)
include(${CHIBIOS_PORTAPACK}/os/hal/platforms/LPC43xx_M4/platform.cmake)
include(${CHIBIOS}/os/hal/hal.cmake)
include(${CHIBIOS_PORTAPACK}/os/ports/GCC/ARMCMx/LPC43xx_M4/port.cmake)
@ -470,9 +470,9 @@ DeclareTargets(PWFM wfm_audio)
add_custom_command(
OUTPUT hackrf.bin hackrf.img
COMMAND ${STRIP_DFU} ${HACKRF_FIRMWARE_IMAGE} hackrf.bin
COMMAND ${STRIP_DFU} ${HACKRF_FIRMWARE_DFU_IMAGE} hackrf.bin
COMMAND ${MAKE_IMAGE_CHUNK} hackrf.bin HRF1 hackrf.img
DEPENDS ${HACKRF_FIRMWARE_IMAGE} ${STRIP_DFU} ${MAKE_IMAGE_CHUNK}
DEPENDS hackrf ${STRIP_DFU} ${MAKE_IMAGE_CHUNK}
VERBATIM
)

View File

@ -46,7 +46,3 @@
#if !defined(LPC43XX_M4_CLK) || defined(__DOXYGEN__)
#define LPC43XX_M4_CLK 200000000
#endif
#if !defined(LPC43XX_M4_CLK_SRC) || defined(__DOXYGEN__)
#define LPC43XX_M4_CLK_SRC 0x09
#endif

BIN
firmware/bootstrap/bootstrap.bin Executable file

Binary file not shown.

Binary file not shown.

View File

@ -1,330 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Copyright (C) 2014 Jared Boone, ShareBrained Technology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ch.h"
#include "hal.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
/**
* CoolRunner (HackRF) CPLD:
* CoolRunner-II devices have internal pull-ups on TDI, TMS, and TCK.
* It is not necessary to externally terminate JTAG pins with internal termination; they can be
* left floating. External pull-ups on pins with internal termination is allowed, but not
* necessary. External pull-down termination is not recommended as it would conflict with
* the internal pull-ups
*
* LPC43xx pull-ups come on line when 3V3 supply voltage reaches about 2V.
*
* 3V3 supply:
* Ramps up in about 1ms.
*
* 1V8 supply:
* Ramps up in about 1ms.
* EN1V8 has a 10K pull-down on the HackRF and is pulled up (very gently) by the LPC43xx
* bootloader at boot time. So until the EN1V8 pin is reconfigured as an output, the enable
* pin on the 1V8 supply sits at about 0.55V, which feels untidy...
* 1V8 supply is activated when GPIO is driven high by user code.
*/
const PALConfig pal_default_config = {
.P = {
{ // GPIO0
.data
= (1 << 15) // CS_XCVR
| (1 << 14) // AMP_BYPASS
| (0 << 9) // 10K PD, BOOT1
| (1 << 8) // 10K PU, BOOT0
,
.dir
= (1 << 15) // CS_XCVR
| (1 << 14) // AMP_BYPASS
| (0 << 9) // 10K PD, BOOT1
| (0 << 8) // 10K PU, BOOT0
},
{ // GPIO1
.data
= (1 << 13) // PortaPack P2_13/DIR
| (1 << 12) // !RX_AMP_PWR
| (0 << 11) // RX_AMP
| (1 << 10) // 10K PD, BOOT3, PortaPack P2_9/LCD_WRX
| (1 << 8) // PortaPack CPLD.TDO(O)
| (1 << 1) // PortaPack CPLD.TMS(I)
| (0 << 0) // !MIX_BYPASS
,
.dir
= (1 << 13) // PortaPack P2_13/DIR
| (1 << 12) // !RX_AMP_PWR
| (1 << 11) // RX_AMP
| (1 << 10) // 10K PD, BOOT3, PortaPack P2_9/LCD_WRX
| (0 << 8) // PortaPack CPLD.TDO(O) (input with pull up)
| (0 << 1) // PortaPack CPLD.TMS(I) (output only when needed, pull up internal to CPLD)
| (1 << 0) // !MIX_BYPASS
},
{ // GPIO2
.data
= (0 << 15) // TX_AMP
| (0 << 11) // TX_MIX_BP
| (1 << 14) // MIXER_RESETX, 10K PU
| (1 << 13) // MIXER_ENX, 10K PU
| (1 << 12) // RX_MIX_BP
| (0 << 10) // LP
| (1 << 9) // !VAA_ENABLE
| (0 << 8) // LED3 (TX)
| (1 << 7) // CS_AD
| (0 << 6) // XCVR_EN, 10K PD
| (0 << 5) // RXENABLE
| (0 << 4) // TXENABLE
| (0 << 2) // LED2 (RX)
| (0 << 1) // LED1 (USB)
| (1 << 0) // HP
,
.dir
= (1 << 15) // TX_AMP
| (1 << 14) // MIXER_RESETX, 10K PU
| (1 << 13) // MIXER_ENX, 10K PU
| (1 << 12) // RX_MIX_BP
| (1 << 11) // TX_MIX_BP
| (1 << 10) // LP
| (1 << 9) // !VAA_ENABLE
| (1 << 8) // LED3 (TX)
| (1 << 7) // CS_AD
| (1 << 6) // XCVR_EN, 10K PD
| (1 << 5) // RXENABLE
| (1 << 4) // TXENABLE
| (1 << 2) // LED2 (RX)
| (1 << 1) // LED1 (USB)
| (1 << 0) // HP
},
{ // GPIO3
.data
= (0 << 15) // PortaPack GPIO3_15(IO)
| (0 << 14) // PortaPack GPIO3_14(IO)
| (0 << 13) // PortaPack GPIO3_13(IO)
| (0 << 12) // PortaPack GPIO3_12(IO)
| (0 << 11) // PortaPack GPIO3_11(IO)
| (0 << 10) // PortaPack GPIO3_10(IO)
| (0 << 9) // PortaPack GPIO3_9(IO)
| (0 << 8) // PortaPack GPIO3_8(IO)
| (0 << 7) // VREGMODE
| (1 << 6) // EN1V8, 10K PD
| (1 << 5) // !TX_AMP_PWR, 10K PU
| (1 << 4) // HackRF CPLD.TMS(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
| (1 << 1) // HackRF CPLD.TDI(I), PortaPack I2S0_RX_SDA(O), PortaPack CPLD.TDI(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
| (1 << 0) // HackRF CPLD.TCK(I), PortaPack CPLD.TCK(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
,
.dir
= (0 << 15) // PortaPack GPIO3_15(IO)
| (0 << 14) // PortaPack GPIO3_14(IO)
| (0 << 13) // PortaPack GPIO3_13(IO)
| (0 << 12) // PortaPack GPIO3_12(IO)
| (0 << 11) // PortaPack GPIO3_11(IO)
| (0 << 10) // PortaPack GPIO3_10(IO)
| (0 << 9) // PortaPack GPIO3_9(IO)
| (0 << 8) // PortaPack GPIO3_8(IO)
| (1 << 7) // VREGMODE
| (1 << 6) // EN1V8, 10K PD
| (1 << 5) // !TX_AMP_PWR, 10K PU
| (0 << 4) // HackRF CPLD.TMS(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
| (0 << 1) // HackRF CPLD.TDI(I), PortaPack I2S0_RX_SDA(O), PortaPack CPLD.TDI(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
| (0 << 0) // HackRF CPLD.TCK(I), PortaPack CPLD.TCK(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
},
{ // GPIO4
.data = 0,
.dir = 0
},
{ // GPIO5
.data
= (1 << 18) // HackRF CPLD.TDO(O) (input with pull up)
| (0 << 15) // TX
| (1 << 16) // MIX_BYPASS
| (1 << 5) // RX
| (1 << 4) // PortaPack P2_4/LCD_RDX
| (0 << 3) // PortaPack P2_3/LCD_TE
| (0 << 1) // PortaPack P2_1/ADDR
| (1 << 0) // PortaPack P2_0/IO_STBX
,
.dir
= (0 << 18) // HackRF CPLD.TDO(O) (input with pull up)
| (1 << 16) // MIX_BYPASS
| (1 << 15) // TX
| (1 << 5) // RX
| (1 << 4) // PortaPack P2_4/LCD_RDX
| (0 << 3) // PortaPack P2_3/LCD_TE
| (1 << 1) // PortaPack P2_1/ADDR
| (1 << 0) // PortaPack P2_0/IO_STBX
},
{ // GPIO6
.data = 0,
.dir = 0
},
{ // GPIO7
.data = 0,
.dir = 0
},
},
.SCU = {
/* Configure GP_CLKIN as soon as possible. It's an output at boot time, and the Si5351C doesn't
* reset when the reset button is pressed, so it could still be output enabled.
*/
{ 4, 7, .config={ .MODE=1, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=1 } }, /* GP_CLKIN/P72/MCU_CLK: SI5351C.CLK7(O) */
/* HackRF: LEDs. Configured early so we can use them to indicate boot status. */
{ 4, 1, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* LED1: LED1.A(I) */
{ 4, 2, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* LED2: LED2.A(I) */
{ 6, 12, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* LED3: LED3.A(I) */
/* Power control */
{ 5, 0, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* !VAA_ENABLE: 10K PU, Q3.G(I), power to VAA */
{ 6, 10, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* EN1V8/P70: 10K PD, TPS62410.EN2(I), 1V8LED.A(I) */
{ 6, 11, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* VREGMODE/P69: TPS62410.MODE/DATA(I) */
/* HackRF: I2C0 */
/* Glitch filter operates at 3ns instead of 50ns due to the WM8731
* returning an ACK very fast (170ns) and confusing the I2C state
* machine into thinking there was a bus error. It looks like the
* MCU sees SDA fall before SCL falls, indicating a START at the
* point an ACK is expected. With the glitch filter off or set to
* 3ns, it's probably still a bit tight timing-wise, but improves
* reliability on some problem units.
*/
{ 25, 1,
.config = {
.word = // SFSI2C0
(1U << 0) // SCL: 3ns glitch
| (0U << 2) // SCL: Standard/Fast mode
| (1U << 3) // SCL: Input enabled
| (0U << 7) // SCL: Enable input glitch filter
| (1U << 8) // SDA: 3ns glitch
| (0U << 10) // SDA: Standard/Fast mode
| (1U << 11) // SDA: Input enabled
| (0U << 15) // SDA: Enable input glitch filter
}
},
/* Radio section control */
{ 1, 3, .config={ .MODE=5, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* SSP1_MISO/P41: MAX2837.DOUT(O) */
{ 1, 4, .config={ .MODE=5, .EPD=1, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* SSP1_MOSI/P40: MAX2837.DIN(I), MAX5864.DIN(I) */
{ 1, 7, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* !MIX_BYPASS/P35: U1.VCTL1(I), U11.VCTL2(I), U9.V2(I) */
{ 1, 19, .config={ .MODE=1, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* SSP1_SCK/P39: MAX2837.SCLK(I), MAX5864.SCLK(I) */
{ 1, 20, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* CS_XCVR/P53: MAX2837.CS(I) */
{ 2, 5, .config={ .MODE=4, .EPD=0, .EPUN=0, .EHS=0, .EZI=0, .ZIF=0 } }, /* RX/P43: U7.VCTL1(I), U10.VCTL1(I), U2.VCTL1(I) */
{ 2, 6, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* MIXER_SCLK/P31: 33pF, RFFC5072.SCLK(I) */
{ 2, 10, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* AMP_BYPASS/P50: U14.V2(I), U12.V2(I) */
{ 2, 11, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* RX_AMP/P49: U12.V1(I), U14.V3(I) */
{ 2, 12, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* !RX_AMP_PWR/P52: 10K PU, Q1.G(I), power to U13 (RX amp) */
{ 4, 0, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* HP/P44: U6.VCTL1(I), U5.VCTL2(I) */
{ 4, 4, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* TXENABLE/P55: MAX2837.TXENABLE(I) */
{ 4, 5, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* RXENABLE/P56: MAX2837.RXENABLE(I) */
{ 4, 6, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* XCVR_EN: 10K PD, MAX2837.ENABLE(I) */
{ 5, 1, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* LP/P45: U6.VCTL2(I), U5.VCTL1(I) */
{ 5, 2, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* TX_MIX_BP/P46: U9.V1(I) */
{ 5, 3, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* RX_MIX_BP/P47: U9.V3(I) */
{ 5, 4, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* MIXER_ENX/P32: 10K PU, 33pF, RFFC5072.ENX(I) */
{ 5, 5, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* MIXER_RESETX/P33: 10K PU, 33pF, RFFC5072.RESETX(I) */
{ 5, 6, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* TX_AMP/P48: U12.V3(I), U14.V1(I) */
{ 5, 7, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* CS_AD/P54: MAX5864.CS(I) */
{ 6, 4, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* MIXER_SDATA/P27: 33pF, RFFC5072.SDATA(IO) */
{ 6, 7, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* TX/P42: U7.VCTL2(I), U10.VCTL2(I), U2.VCTL2(I) */
{ 6, 8, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* MIX_BYPASS/P34: U1.VCTL2(I), U11.VCTL1(I) */
{ 6, 9, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* !TX_AMP_PWR/P51: 10K PU, Q2.G(I), power to U25 (TX amp) */
/* SGPIO for sample transfer interface to HackRF CPLD. */
{ 0, 0, .config={ .MODE=3, .EPD=0, .EPUN=1, .EHS=1, .EZI=1, .ZIF=1 } }, /* SGPIO0/P75/BANK2F3M3: CPLD.89/HOST_DATA0(IO) */
{ 0, 1, .config={ .MODE=3, .EPD=0, .EPUN=1, .EHS=1, .EZI=1, .ZIF=1 } }, /* SGPIO1/BANK2F3M5: CPLD.79/HOST_DATA1(IO) */
{ 1, 15, .config={ .MODE=2, .EPD=0, .EPUN=1, .EHS=1, .EZI=1, .ZIF=1 } }, /* SGPIO2/BANK2F3M9: CPLD.74/HOST_DATA2(IO) */
{ 1, 16, .config={ .MODE=2, .EPD=0, .EPUN=1, .EHS=1, .EZI=1, .ZIF=1 } }, /* SGPIO3/BANK2F3M10: CPLD.72/HOST_DATA3(IO) */
{ 6, 3, .config={ .MODE=2, .EPD=0, .EPUN=1, .EHS=1, .EZI=1, .ZIF=1 } }, /* SGPIO4/BANK2F3M14: CPLD.67/HOST_DATA4(IO) */
{ 6, 6, .config={ .MODE=2, .EPD=0, .EPUN=1, .EHS=1, .EZI=1, .ZIF=1 } }, /* SGPIO5/BANK2F3M15: CPLD.64/HOST_DATA5(IO) */
{ 2, 2, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=1, .EZI=1, .ZIF=1 } }, /* SGPIO6/BANK2F3M16: CPLD.61/HOST_DATA6(IO) */
{ 1, 0, .config={ .MODE=6, .EPD=0, .EPUN=1, .EHS=1, .EZI=1, .ZIF=1 } }, /* SGPIO7/P76/BANK2F3M7: CPLD.77/HOST_DATA7(IO) */
{ 9, 6, .config={ .MODE=6, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=1 } }, /* SGPIO8/SGPIO_CLK/P60: SI5351C.CLK2(O) */
{ 4, 3, .config={ .MODE=7, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=1 } }, /* SGPIO9/P77/BANK2F3M1: CPLD.91/HOST_CAPTURE(O) */
{ 1, 14, .config={ .MODE=6, .EPD=0, .EPUN=0, .EHS=1, .EZI=0, .ZIF=0 } }, /* SGPIO10/P78/BANK2F3M8: CPLD.76/HOST_DISABLE(I) */
{ 1, 17, .config={ .MODE=6, .EPD=0, .EPUN=0, .EHS=1, .EZI=0, .ZIF=0 } }, /* SGPIO11/P79/BANK2F3M11: CPLD.71/HOST_DIRECTION(I) */
{ 1, 18, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* SGPIO12/BANK2F3M12: CPLD.70/HOST_INVERT(I) */
{ 4, 8, .config={ .MODE=4, .EPD=0, .EPUN=0, .EHS=0, .EZI=0, .ZIF=0 } }, /* SGPIO13/BANK2F3M2: CPLD.90/HOST_DECIM_SEL0(I) */
{ 4, 9, .config={ .MODE=4, .EPD=0, .EPUN=0, .EHS=0, .EZI=0, .ZIF=0 } }, /* SGPIO14/BANK2F3M4: CPLD.81/HOST_DECIM_SEL1(I) */
{ 4, 10, .config={ .MODE=4, .EPD=0, .EPUN=0, .EHS=0, .EZI=0, .ZIF=0 } }, /* SGPIO15/BANK2F3M6: CPLD.78/HOST_DECIM_SEL2(I) */
/* HackRF: CPLD */
{ 6, 1, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* CPLD_TCK: CPLD.TCK(I), PortaPack CPLD.TCK(I) */
{ 6, 2, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* CPLD_TDI: CPLD.TDI(I), PortaPack I2S0_RX_SDA(O), PortaPack CPLD.TDI(I) */
{ 6, 5, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* CPLD_TMS: CPLD.TMS(I) */
{ 9, 5, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* CPLD_TDO: CPLD.TDO(O) */
/* PortaPack */
{ 1, 5, .config={ .MODE=0, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=0 } }, /* SD_POW: PortaPack CPLD.TDO(O) */
{ 1, 8, .config={ .MODE=0, .EPD=0, .EPUN=0, .EHS=0, .EZI=0, .ZIF=0 } }, /* SD_VOLT0: PortaPack CPLD.TMS(I) */
{ 2, 0, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* U0_TXD: PortaPack P2_0/IO_STBX */
{ 2, 1, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* U0_RXD: PortaPack P2_1/ADDR */
{ 2, 3, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* I2C1_SDA: PortaPack P2_3/LCD_TE */
{ 2, 4, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* I2C1_SCL: PortaPack P2_4/LCD_RDX */
{ 2, 8, .config={ .MODE=4, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* P2_8: 10K PD, BOOT2, DFU switch, PortaPack P2_8/<unused> */
{ 2, 9, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* P2_9: 10K PD, BOOT3, PortaPack P2_9/LCD_WRX */
{ 2, 13, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* P2_13: PortaPack P2_13/DIR */
{ 7, 0, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* GPIO3_8: PortaPack GPIO3_8(IO) */
{ 7, 1, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* GPIO3_9: PortaPack GPIO3_9(IO) */
{ 7, 2, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* GPIO3_10: PortaPack GPIO3_10(IO) */
{ 7, 3, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* GPIO3_11: PortaPack GPIO3_11(IO) */
{ 7, 4, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* GPIO3_12: PortaPack GPIO3_12(IO) */
{ 7, 5, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* GPIO3_13: PortaPack GPIO3_13(IO) */
{ 7, 6, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* GPIO3_14: PortaPack GPIO3_14(IO) */
{ 7, 7, .config={ .MODE=0, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=0 } }, /* GPIO3_15: PortaPack GPIO3_15(IO) */
/* PortaPack: Audio */
{ 3, 0, .config={ .MODE=2, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=0 } }, /* I2S0_TX_SCK: PortaPack I2S0_TX_SCK(I) */
{ 3, 1, .config={ .MODE=0, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=0 } }, /* I2S0_RX_WS: PortaPack I2S0_TX_WS(I). Input enabled to fold back into RX. */
{ 3, 2, .config={ .MODE=0, .EPD=0, .EPUN=0, .EHS=0, .EZI=0, .ZIF=0 } }, /* I2S0_RX_SDA: PortaPack I2S0_TX_SDA(I) */
{ 24, 2, .config={ .MODE=6, .EPD=1, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* I2S0_TX_CLK: PortaPack I2S0_TX_MCLK */
/* PortaPack: SD card socket */
{ 24, 0, .config={ .MODE=4, .EPD=1, .EPUN=1, .EHS=0, .EZI=1, .ZIF=1 } }, /* SD_CLK: PortaPack SD.CLK, enable input buffer for timing feedback? */
{ 1, 6, .config={ .MODE=7, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=1 } }, /* SD_CMD: PortaPack SD.CMD(IO) */
{ 1, 9, .config={ .MODE=7, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=1 } }, /* SD_DAT0: PortaPack SD.DAT0(IO) */
{ 1, 10, .config={ .MODE=7, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=1 } }, /* SD_DAT1: PortaPack SD.DAT1(IO) */
{ 1, 11, .config={ .MODE=7, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=1 } }, /* SD_DAT2: PortaPack SD.DAT2(IO) */
{ 1, 12, .config={ .MODE=7, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=1 } }, /* SD_DAT3: PortaPack SD.DAT3(IO) */
{ 1, 13, .config={ .MODE=7, .EPD=0, .EPUN=0, .EHS=0, .EZI=1, .ZIF=0 } }, /* SD_CD: PortaPack SD.CD(O) */
/* Miscellaneous */
{ 1, 1, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* P1_1/P74: 10K PU, BOOT0 */
{ 1, 2, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* P1_2/P73: 10K PD, BOOT1 */
{ 2, 7, .config={ .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 } }, /* ISP: 10K PU, Unused */
{ 6, 0, .config={ .MODE=0, .EPD=0, .EPUN=0, .EHS=0, .EZI=0, .ZIF=0 } }, /* I2S0_RX_MCLK: Unused */
{ 15, 4, .config={ .MODE=7, .EPD=0, .EPUN=0, .EHS=0, .EZI=0, .ZIF=0 } }, /* I2S0_RX_SCK: Unused */
}
};
#endif
/**
* @brief Early initialization code.
* @details This initialization must be performed just after stack setup
* and before any other initialization.
*/
// void __early_init(void) {
// }
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
void boardInit(void) {
}

View File

@ -1,9 +0,0 @@
# List of all the board related files.
set(BOARDSRC
${CHIBIOS_PORTAPACK}/boards/GSG_HACKRF_ONE/board.c
)
# Required include directories
set(BOARDINC
${CHIBIOS_PORTAPACK}/boards/GSG_HACKRF_ONE
)

View File

@ -1,5 +0,0 @@
# List of all the board related files.
BOARDSRC = ${CHIBIOS_PORTAPACK}/boards/GSG_HACKRF_ONE/board.c
# Required include directories
BOARDINC = ${CHIBIOS_PORTAPACK}/boards/GSG_HACKRF_ONE

View File

@ -0,0 +1,9 @@
# List of all the board related files.
set(BOARDSRC
${CHIBIOS_PORTAPACK}/boards/PORTAPACK_APPLICATION/board.cpp
)
# Required include directories
set(BOARDINC
${CHIBIOS_PORTAPACK}/boards/PORTAPACK_APPLICATION
)

View File

@ -0,0 +1,607 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Copyright (C) 2014 Jared Boone, ShareBrained Technology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ch.h"
#include "hal.h"
#include <array>
#if HAL_USE_PAL || defined(__DOXYGEN__)
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
/**
* CoolRunner (HackRF) CPLD:
* CoolRunner-II devices have internal pull-ups on TDI, TMS, and TCK.
* It is not necessary to externally terminate JTAG pins with internal termination; they can be
* left floating. External pull-ups on pins with internal termination is allowed, but not
* necessary. External pull-down termination is not recommended as it would conflict with
* the internal pull-ups
*
* LPC43xx pull-ups come on line when 3V3 supply voltage reaches about 2V.
*
* 3V3 supply:
* Ramps up in about 1ms.
*
* 1V8 supply:
* Ramps up in about 1ms.
* EN1V8 has a 10K pull-down on the HackRF and is pulled up (very gently) by the LPC43xx
* bootloader at boot time. So until the EN1V8 pin is reconfigured as an output, the enable
* pin on the 1V8 supply sits at about 0.55V, which feels untidy...
* 1V8 supply is activated when GPIO is driven high by user code.
*/
const PALConfig pal_default_config = {
.P = {
{ // GPIO0
.data
= (1 << 15) // CS_XCVR
| (1 << 14) // AMP_BYPASS
| (0 << 9) // 10K PD, BOOT1
| (1 << 8) // 10K PU, BOOT0
,
.dir
= (1 << 15) // CS_XCVR
| (1 << 14) // AMP_BYPASS
| (0 << 9) // 10K PD, BOOT1
| (0 << 8) // 10K PU, BOOT0
},
{ // GPIO1
.data
= (1 << 13) // PortaPack P2_13/DIR
| (1 << 12) // !RX_AMP_PWR
| (0 << 11) // RX_AMP
| (1 << 10) // 10K PD, BOOT3, PortaPack P2_9/LCD_WRX
| (1 << 8) // PortaPack CPLD.TDO(O)
| (1 << 1) // PortaPack CPLD.TMS(I)
| (0 << 0) // !MIX_BYPASS
,
.dir
= (1 << 13) // PortaPack P2_13/DIR
| (1 << 12) // !RX_AMP_PWR
| (1 << 11) // RX_AMP
| (1 << 10) // 10K PD, BOOT3, PortaPack P2_9/LCD_WRX
| (0 << 8) // PortaPack CPLD.TDO(O) (input with pull up)
| (0 << 1) // PortaPack CPLD.TMS(I) (output only when needed, pull up internal to CPLD)
| (1 << 0) // !MIX_BYPASS
},
{ // GPIO2
.data
= (0 << 15) // TX_AMP
| (0 << 11) // TX_MIX_BP
| (1 << 14) // MIXER_RESETX, 10K PU
| (1 << 13) // MIXER_ENX, 10K PU
| (1 << 12) // RX_MIX_BP
| (0 << 10) // LP
| (1 << 9) // !VAA_ENABLE
| (0 << 8) // LED3 (TX)
| (1 << 7) // CS_AD
| (0 << 6) // XCVR_EN, 10K PD
| (0 << 5) // RXENABLE
| (0 << 4) // TXENABLE
| (0 << 2) // LED2 (RX)
| (0 << 1) // LED1 (USB)
| (1 << 0) // HP
,
.dir
= (1 << 15) // TX_AMP
| (1 << 14) // MIXER_RESETX, 10K PU
| (1 << 13) // MIXER_ENX, 10K PU
| (1 << 12) // RX_MIX_BP
| (1 << 11) // TX_MIX_BP
| (1 << 10) // LP
| (1 << 9) // !VAA_ENABLE
| (1 << 8) // LED3 (TX)
| (1 << 7) // CS_AD
| (1 << 6) // XCVR_EN, 10K PD
| (1 << 5) // RXENABLE
| (1 << 4) // TXENABLE
| (1 << 2) // LED2 (RX)
| (1 << 1) // LED1 (USB)
| (1 << 0) // HP
},
{ // GPIO3
.data
= (0 << 15) // PortaPack GPIO3_15(IO)
| (0 << 14) // PortaPack GPIO3_14(IO)
| (0 << 13) // PortaPack GPIO3_13(IO)
| (0 << 12) // PortaPack GPIO3_12(IO)
| (0 << 11) // PortaPack GPIO3_11(IO)
| (0 << 10) // PortaPack GPIO3_10(IO)
| (0 << 9) // PortaPack GPIO3_9(IO)
| (0 << 8) // PortaPack GPIO3_8(IO)
| (0 << 7) // VREGMODE
| (1 << 6) // EN1V8, 10K PD
| (1 << 5) // !TX_AMP_PWR, 10K PU
| (1 << 4) // HackRF CPLD.TMS(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
| (1 << 1) // HackRF CPLD.TDI(I), PortaPack I2S0_RX_SDA(O), PortaPack CPLD.TDI(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
| (1 << 0) // HackRF CPLD.TCK(I), PortaPack CPLD.TCK(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
,
.dir
= (0 << 15) // PortaPack GPIO3_15(IO)
| (0 << 14) // PortaPack GPIO3_14(IO)
| (0 << 13) // PortaPack GPIO3_13(IO)
| (0 << 12) // PortaPack GPIO3_12(IO)
| (0 << 11) // PortaPack GPIO3_11(IO)
| (0 << 10) // PortaPack GPIO3_10(IO)
| (0 << 9) // PortaPack GPIO3_9(IO)
| (0 << 8) // PortaPack GPIO3_8(IO)
| (1 << 7) // VREGMODE
| (1 << 6) // EN1V8, 10K PD
| (1 << 5) // !TX_AMP_PWR, 10K PU
| (0 << 4) // HackRF CPLD.TMS(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
| (0 << 1) // HackRF CPLD.TDI(I), PortaPack I2S0_RX_SDA(O), PortaPack CPLD.TDI(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
| (0 << 0) // HackRF CPLD.TCK(I), PortaPack CPLD.TCK(I) (output only when needed, pull-up internal to CPLD when 1V8 present)
},
{ // GPIO4
.data = 0,
.dir = 0
},
{ // GPIO5
.data
= (1 << 18) // HackRF CPLD.TDO(O) (input with pull up)
| (0 << 15) // TX
| (1 << 16) // MIX_BYPASS
| (1 << 5) // RX
| (1 << 4) // PortaPack P2_4/LCD_RDX
| (0 << 3) // PortaPack P2_3/LCD_TE
| (0 << 1) // PortaPack P2_1/ADDR
| (1 << 0) // PortaPack P2_0/IO_STBX
,
.dir
= (0 << 18) // HackRF CPLD.TDO(O) (input with pull up)
| (1 << 16) // MIX_BYPASS
| (1 << 15) // TX
| (1 << 5) // RX
| (1 << 4) // PortaPack P2_4/LCD_RDX
| (0 << 3) // PortaPack P2_3/LCD_TE
| (1 << 1) // PortaPack P2_1/ADDR
| (1 << 0) // PortaPack P2_0/IO_STBX
},
{ // GPIO6
.data = 0,
.dir = 0
},
{ // GPIO7
.data = 0,
.dir = 0
},
},
.SCU = {
/* Configure GP_CLKIN as soon as possible. It's an output at boot time, and the Si5351C doesn't
* reset when the reset button is pressed, so it could still be output enabled.
*/
{ 4, 7, scu_config_normal_drive_t { .mode=1, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=1 } }, /* GP_CLKIN/P72/MCU_CLK: SI5351C.CLK7(O) */
/* HackRF: LEDs. Configured early so we can use them to indicate boot status. */
{ 4, 1, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* LED1: LED1.A(I) */
{ 4, 2, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* LED2: LED2.A(I) */
{ 6, 12, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* LED3: LED3.A(I) */
/* Power control */
{ 5, 0, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* !VAA_ENABLE: 10K PU, Q3.G(I), power to VAA */
{ 6, 10, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* EN1V8/P70: 10K PD, TPS62410.EN2(I), 1V8LED.A(I) */
{ 6, 11, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* VREGMODE/P69: TPS62410.MODE/DATA(I) */
/* HackRF: I2C0 */
/* Glitch filter operates at 3ns instead of 50ns due to the WM8731
* returning an ACK very fast (170ns) and confusing the I2C state
* machine into thinking there was a bus error. It looks like the
* MCU sees SDA fall before SCL falls, indicating a START at the
* point an ACK is expected. With the glitch filter off or set to
* 3ns, it's probably still a bit tight timing-wise, but improves
* reliability on some problem units.
*/
{ 25, 1,
scu_config_sfsi2c0_t {
.scl_efp=1, // SCL: 3ns glitch
.scl_ehd=0, // SCL: Standard/Fast mode
.scl_ezi=1, // SCL: Input enabled
.scl_zif=0, // SCL: Enable input glitch filter
.sda_efp=1, // SDA: 3ns glitch
.sda_ehd=0, // SDA: Standard/Fast mode
.sda_ezi=1, // SDA: Input enabled
.sda_zif=0 // SDA: Enable input glitch filter
}
},
/* Radio section control */
{ 1, 3, scu_config_normal_drive_t { .mode=5, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* SSP1_MISO/P41: MAX2837.DOUT(O) */
{ 1, 4, scu_config_normal_drive_t { .mode=5, .epd=1, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* SSP1_MOSI/P40: MAX2837.DIN(I), MAX5864.DIN(I) */
{ 1, 7, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* !MIX_BYPASS/P35: U1.VCTL1(I), U11.VCTL2(I), U9.V2(I) */
{ 1, 19, scu_config_normal_drive_t { .mode=1, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* SSP1_SCK/P39: MAX2837.SCLK(I), MAX5864.SCLK(I) */
{ 1, 20, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* CS_XCVR/P53: MAX2837.CS(I) */
{ 2, 5, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=0, .ehs=0, .ezi=0, .zif=0 } }, /* RX/P43: U7.VCTL1(I), U10.VCTL1(I), U2.VCTL1(I) */
{ 2, 6, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* MIXER_SCLK/P31: 33pF, RFFC5072.SCLK(I) */
{ 2, 10, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* AMP_BYPASS/P50: U14.V2(I), U12.V2(I) */
{ 2, 11, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* RX_AMP/P49: U12.V1(I), U14.V3(I) */
{ 2, 12, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* !RX_AMP_PWR/P52: 10K PU, Q1.G(I), power to U13 (RX amp) */
{ 4, 0, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* HP/P44: U6.VCTL1(I), U5.VCTL2(I) */
{ 4, 4, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* TXENABLE/P55: MAX2837.TXENABLE(I) */
{ 4, 5, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* RXENABLE/P56: MAX2837.RXENABLE(I) */
{ 4, 6, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* XCVR_EN: 10K PD, MAX2837.ENABLE(I) */
{ 5, 1, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* LP/P45: U6.VCTL2(I), U5.VCTL1(I) */
{ 5, 2, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* TX_MIX_BP/P46: U9.V1(I) */
{ 5, 3, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* RX_MIX_BP/P47: U9.V3(I) */
{ 5, 4, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* MIXER_ENX/P32: 10K PU, 33pF, RFFC5072.ENX(I) */
{ 5, 5, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* MIXER_RESETX/P33: 10K PU, 33pF, RFFC5072.RESETX(I) */
{ 5, 6, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* TX_AMP/P48: U12.V3(I), U14.V1(I) */
{ 5, 7, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* CS_AD/P54: MAX5864.CS(I) */
{ 6, 4, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* MIXER_SDATA/P27: 33pF, RFFC5072.SDATA(IO) */
{ 6, 7, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* TX/P42: U7.VCTL2(I), U10.VCTL2(I), U2.VCTL2(I) */
{ 6, 8, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* MIX_BYPASS/P34: U1.VCTL2(I), U11.VCTL1(I) */
{ 6, 9, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* !TX_AMP_PWR/P51: 10K PU, Q2.G(I), power to U25 (TX amp) */
/* SGPIO for sample transfer interface to HackRF CPLD. */
{ 0, 0, scu_config_normal_drive_t { .mode=3, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SGPIO0/P75/BANK2F3M3: CPLD.89/HOST_DATA0(IO) */
{ 0, 1, scu_config_normal_drive_t { .mode=3, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SGPIO1/BANK2F3M5: CPLD.79/HOST_DATA1(IO) */
{ 1, 15, scu_config_normal_drive_t { .mode=2, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SGPIO2/BANK2F3M9: CPLD.74/HOST_DATA2(IO) */
{ 1, 16, scu_config_normal_drive_t { .mode=2, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SGPIO3/BANK2F3M10: CPLD.72/HOST_DATA3(IO) */
{ 6, 3, scu_config_normal_drive_t { .mode=2, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SGPIO4/BANK2F3M14: CPLD.67/HOST_DATA4(IO) */
{ 6, 6, scu_config_normal_drive_t { .mode=2, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SGPIO5/BANK2F3M15: CPLD.64/HOST_DATA5(IO) */
{ 2, 2, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SGPIO6/BANK2F3M16: CPLD.61/HOST_DATA6(IO) */
{ 1, 0, scu_config_normal_drive_t { .mode=6, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SGPIO7/P76/BANK2F3M7: CPLD.77/HOST_DATA7(IO) */
{ 9, 6, scu_config_normal_drive_t { .mode=6, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=1 } }, /* SGPIO8/SGPIO_CLK/P60: SI5351C.CLK2(O) */
{ 4, 3, scu_config_normal_drive_t { .mode=7, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=1 } }, /* SGPIO9/P77/BANK2F3M1: CPLD.91/HOST_CAPTURE(O) */
{ 1, 14, scu_config_normal_drive_t { .mode=6, .epd=0, .epun=0, .ehs=1, .ezi=0, .zif=0 } }, /* SGPIO10/P78/BANK2F3M8: CPLD.76/HOST_DISABLE(I) */
{ 1, 17, scu_config_normal_drive_t { .mode=6, .epd=0, .epun=0, .ehs=1, .ezi=0, .zif=0 } }, /* SGPIO11/P79/BANK2F3M11: CPLD.71/HOST_DIRECTION(I) */
{ 1, 18, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* SGPIO12/BANK2F3M12: CPLD.70/HOST_INVERT(I) */
{ 4, 8, scu_config_normal_drive_t { .mode=4, .epd=1, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* SGPIO13/BANK2F3M2: CPLD.90/HOST_SYNC_EN(I) */
{ 4, 9, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=0, .ehs=0, .ezi=0, .zif=0 } }, /* SGPIO14/BANK2F3M4: CPLD.81/CPLD_P81 */
{ 4, 10, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=0, .ehs=0, .ezi=0, .zif=0 } }, /* SGPIO15/BANK2F3M6: CPLD.78/CPLD_P78 */
/* HackRF: CPLD */
{ 6, 1, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* CPLD_TCK: CPLD.TCK(I), PortaPack CPLD.TCK(I) */
{ 6, 2, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* CPLD_TDI: CPLD.TDI(I), PortaPack I2S0_RX_SDA(O), PortaPack CPLD.TDI(I) */
{ 6, 5, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* CPLD_TMS: CPLD.TMS(I) */
{ 9, 5, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* CPLD_TDO: CPLD.TDO(O) */
/* PortaPack */
{ 1, 5, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=0 } }, /* SD_POW: PortaPack CPLD.TDO(O) */
{ 1, 8, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=0, .ehs=0, .ezi=0, .zif=0 } }, /* SD_VOLT0: PortaPack CPLD.TMS(I) */
{ 2, 0, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* U0_TXD: PortaPack P2_0/IO_STBX */
{ 2, 1, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* U0_RXD: PortaPack P2_1/ADDR */
{ 2, 3, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* I2C1_SDA: PortaPack P2_3/LCD_TE */
{ 2, 4, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* I2C1_SCL: PortaPack P2_4/LCD_RDX */
{ 2, 8, scu_config_normal_drive_t { .mode=4, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* P2_8: 10K PD, BOOT2, DFU switch, PortaPack P2_8/<unused> */
{ 2, 9, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* P2_9: 10K PD, BOOT3, PortaPack P2_9/LCD_WRX */
{ 2, 13, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* P2_13: PortaPack P2_13/DIR */
{ 7, 0, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_8: PortaPack GPIO3_8(IO) */
{ 7, 1, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_9: PortaPack GPIO3_9(IO) */
{ 7, 2, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_10: PortaPack GPIO3_10(IO) */
{ 7, 3, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_11: PortaPack GPIO3_11(IO) */
{ 7, 4, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_12: PortaPack GPIO3_12(IO) */
{ 7, 5, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_13: PortaPack GPIO3_13(IO) */
{ 7, 6, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_14: PortaPack GPIO3_14(IO) */
{ 7, 7, scu_config_normal_drive_t { .mode=0, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=0 } }, /* GPIO3_15: PortaPack GPIO3_15(IO) */
/* PortaPack: Audio */
{ 3, 0, scu_config_normal_drive_t { .mode=2, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=0 } }, /* I2S0_TX_SCK: PortaPack I2S0_TX_SCK(I) */
{ 3, 1, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=0 } }, /* I2S0_RX_WS: PortaPack I2S0_TX_WS(I). Input enabled to fold back into RX. */
{ 3, 2, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=0, .ehs=0, .ezi=0, .zif=0 } }, /* I2S0_RX_SDA: PortaPack I2S0_TX_SDA(I) */
{ 24, 2, scu_config_normal_drive_t { .mode=6, .epd=1, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* I2S0_TX_CLK: PortaPack I2S0_TX_MCLK */
/* PortaPack: SD card socket */
{ 24, 0, scu_config_normal_drive_t { .mode=4, .epd=1, .epun=1, .ehs=0, .ezi=1, .zif=1 } }, /* SD_CLK: PortaPack SD.CLK, enable input buffer for timing feedback? */
{ 1, 6, scu_config_normal_drive_t { .mode=7, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=1 } }, /* SD_CMD: PortaPack SD.CMD(IO) */
{ 1, 9, scu_config_normal_drive_t { .mode=7, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=1 } }, /* SD_DAT0: PortaPack SD.DAT0(IO) */
{ 1, 10, scu_config_normal_drive_t { .mode=7, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=1 } }, /* SD_DAT1: PortaPack SD.DAT1(IO) */
{ 1, 11, scu_config_normal_drive_t { .mode=7, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=1 } }, /* SD_DAT2: PortaPack SD.DAT2(IO) */
{ 1, 12, scu_config_normal_drive_t { .mode=7, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=1 } }, /* SD_DAT3: PortaPack SD.DAT3(IO) */
{ 1, 13, scu_config_normal_drive_t { .mode=7, .epd=0, .epun=0, .ehs=0, .ezi=1, .zif=0 } }, /* SD_CD: PortaPack SD.CD(O) */
/* Miscellaneous */
{ 1, 1, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* P1_1/P74: 10K PU, BOOT0 */
{ 1, 2, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* P1_2/P73: 10K PD, BOOT1 */
{ 2, 7, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } }, /* ISP: 10K PU, Unused */
{ 6, 0, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=0, .ehs=0, .ezi=0, .zif=0 } }, /* I2S0_RX_MCLK: Unused */
{ 15, 4, scu_config_normal_drive_t { .mode=7, .epd=0, .epun=0, .ehs=0, .ezi=0, .zif=0 } }, /* I2S0_RX_SCK: Unused */
}
};
#endif
static const std::array<scu_setup_t, 6> pins_setup_spifi { {
{ 3, 3, scu_config_normal_drive_t { .mode=3, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SPIFI_SCK: W25Q80BV.CLK(I), enable input buffer for timing feedback */
{ 3, 4, scu_config_normal_drive_t { .mode=3, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SPIFI_SIO3/P82: W25Q80BV.HOLD(IO) */
{ 3, 5, scu_config_normal_drive_t { .mode=3, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SPIFI_SIO2/P81: W25Q80BV.WP(IO) */
{ 3, 6, scu_config_normal_drive_t { .mode=3, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SPIFI_MISO: W25Q80BV.DO(IO) */
{ 3, 7, scu_config_normal_drive_t { .mode=3, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SPIFI_MOSI: W25Q80BV.DI(IO) */
{ 3, 8, scu_config_normal_drive_t { .mode=3, .epd=0, .epun=1, .ehs=1, .ezi=1, .zif=1 } }, /* SPIFI_CS/P68: W25Q80BV.CS(I) */
} };
static void setup_pin(const scu_setup_t& pin_setup) {
LPC_SCU->SFSP[pin_setup.port][pin_setup.pin] = pin_setup.config;
}
template<size_t N>
void setup_pins(const std::array<scu_setup_t, N>& pins_setup) {
for(const auto& pin_setup : pins_setup) {
setup_pin(pin_setup);
}
}
static void configure_spifi(void) {
setup_pins(pins_setup_spifi);
/* Tweak SPIFI mode */
LPC_SPIFI->CTRL =
(0xffff << 0) /* Timeout */
| (0x1 << 16) /* CS high time in "clocks - 1" */
| (0 << 21) /* 0: Attempt speculative prefetch on data accesses */
| (0 << 22) /* 0: No interrupt on command ended */
| (0 << 23) /* 0: SCK driven low after rising edge at which last bit of command is captured. Stays low while CS# is high. */
| (0 << 27) /* 0: Cache prefetching enabled */
| (0 << 28) /* 0: Quad protocol, IO3:0 */
| (1 << 29) /* 1: Read data sampled on falling edge of clock */
| (1 << 30) /* 1: Read data is sampled using feedback clock from SCK pin */
| (0 << 31) /* 0: DMA request disabled */
;
/* Throttle up the SPIFI interface to 96MHz (IDIVA=PLL1 / 3) */
LPC_CGU->IDIVB_CTRL.word =
( 0 << 0) /* PD */
| ( 2 << 2) /* IDIV (/3) */
| ( 1 << 11) /* AUTOBLOCK */
| ( 9 << 24) /* PLL1 */
;
}
static const motocon_pwm_resources_t motocon_pwm_resources = {
.base = { .clk = &LPC_CGU->BASE_APB1_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 1) },
.branch = { .cfg = &LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG, .stat = &LPC_CCU1->CLK_APB1_MOTOCON_PWM_STAT },
.reset = { .output_index = 38 },
};
static const scu_setup_t pin_setup_vaa_enablex_pwm = { 5, 0, scu_config_normal_drive_t { .mode=1, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } };
static const scu_setup_t pin_setup_vaa_enablex_gpio = { 5, 0, scu_config_normal_drive_t { .mode=0, .epd=0, .epun=1, .ehs=0, .ezi=0, .zif=0 } };
/* 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.
*/
void vaa_power_on(void) {
/* Very twitchy process for powering up VAA without glitching the 3.3V rail, which can send the
* microcontroller into reset.
*
* Controlling timing while running from SPIFI flash is tricky, hence use of a PWM peripheral...
*/
/* Configure and enable MOTOCONPWM peripheral clocks.
* Assume IDIVC is running the post-bootloader configuration, outputting 96MHz derived from PLL1.
*/
base_clock_enable(&motocon_pwm_resources.base);
branch_clock_enable(&motocon_pwm_resources.branch);
peripheral_reset(&motocon_pwm_resources.reset);
/* Combination of pulse duration and duty cycle was arrived at empirically, to keep supply glitching
* to +/- 0.15V.
*/
const uint32_t cycle_period = 128;
const uint32_t enable_period = 10;
LPC_MCPWM->TC2 = 0;
LPC_MCPWM->MAT2 = cycle_period - enable_period;
LPC_MCPWM->LIM2 = cycle_period;
/* Switch !VAA_ENABLE pin from GPIO to MOTOCONPWM peripheral output, now that the peripheral is configured. */
setup_pin(pin_setup_vaa_enablex_pwm); // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
/* Start the PWM operation. */
LPC_MCPWM->CON_SET = (1 << 16);
/* Wait until VAA rises to approximately 90% of final voltage. */
/* Timing assumes we're running immediately after the bootloader: 96 MHz from IRC+PLL1
*/
{ volatile uint32_t delay = 12000; while(delay--); }
/* Hold !VAA_ENABLE active using a GPIO, so we can reclaim and shut down the MOTOCONPWM peripheral. */
LPC_GPIO->CLR[2] = (1 << 9); // !VAA_ENABLE
LPC_GPIO->DIR[2] |= (1 << 9);
setup_pin(pin_setup_vaa_enablex_gpio); // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
peripheral_reset(&motocon_pwm_resources.reset);
branch_clock_disable(&motocon_pwm_resources.branch);
base_clock_disable(&motocon_pwm_resources.base);
}
void vaa_power_off(void) {
// TODO: There's a lot of other stuff that must be done to prevent
// leakage from +3V3 into VAA.
LPC_GPIO->W2[9] = 1;
}
/**
* @brief Early initialization code.
* @details This initialization must be performed just after stack setup
* and before any other initialization.
*/
extern "C" void __early_init(void) {
/*
* Upon exit from bootloader into SPIFI boot mode:
*
* Enabled:
* PLL1: IRC, M=/24, N=/1, P=/1, autoblock, direct = 288 MHz
* IDIVA: IRC /1 = 12 MHz
* IDIVB: PLL1 /9, autoblock = 32 MHz
* IDIVC: PLL1 /3, autoblock = 96 MHz
* IDIVD: IRC /1 = 12 MHz
* IDIVE: IRC /1 = 12 MHz
* BASE_M4_CLK: IDIVC, autoblock
* BASE_SPIFI_CLK: IDIVB, autoblock
*
* Disabled:
* XTAL_OSC
* PLL0USB
* PLL0AUDIO
*/
/* LPC43xx M4 takes about 500 usec to get to __early_init
* Before __early_init, LPC bootloader runs and starts our code. In user code, the process stack
* is initialized, hardware floating point is initialized, and stacks are zeroed,
*/
const uint32_t CORTEX_M4_CPUID = 0x410fc240;
const uint32_t CORTEX_M4_CPUID_MASK = 0xff0ffff0;
if( (SCB->CPUID & CORTEX_M4_CPUID_MASK) == CORTEX_M4_CPUID ) {
/* Enable unaligned exception handler */
SCB_CCR |= (1 << 3);
/* Enable MemManage, BusFault, UsageFault exception handlers */
SCB_SHCSR |= (1 << 18) | (1 << 17) | (1 << 16);
/* "The reset delay is counted in IRC clock cycles. If the core frequency
* CCLK is much higher than the IRC frequency, add a software delay of
* fCCLK/fIRC clock cycles between resetting and accessing any of the
* peripheral blocks."
*/
/* Don't reset these peripherals, as they're operating during initialization:
* WWDT, CREG, SCU, SPIFI
*/
LPC_RGU->RESET_CTRL[0] =
(1U << 16) // LCD_RST
| (1U << 17) // USB0_RST
| (1U << 18) // USB1_RST
| (1U << 19) // DMA_RST
| (1U << 20) // SDIO_RST
| (1U << 21) // EMC_RST
| (1U << 22) // ETHERNET_RST
| (1U << 28) // GPIO_RST
;
LPC_RGU->RESET_CTRL[1] =
(1U << 0) // TIMER0_RST
| (1U << 1) // TIMER1_RST
| (1U << 2) // TIMER2_RST
| (1U << 3) // TIMER3_RST
| (1U << 4) // RITIMER_RST
| (1U << 5) // SCT_RST
| (1U << 6) // MOTOCONPWM_RST
| (1U << 7) // QEI_RST
| (1U << 8) // ADC0_RST
| (1U << 9) // ADC1_RST
| (1U << 10) // DAC_RST
| (1U << 12) // UART0_RST
| (1U << 13) // UART1_RST
| (1U << 14) // UART2_RST
| (1U << 15) // UART3_RST
| (1U << 16) // I2C0_RST
| (1U << 17) // I2C1_RST
| (1U << 18) // SSP0_RST
| (1U << 19) // SSP1_RST
| (1U << 20) // I2S_RST
| (1U << 22) // CAN1_RST
| (1U << 23) // CAN0_RST
| (1U << 24) // M0APP_RST
| (1U << 25) // SGPIO_RST
| (1U << 26) // SPI_RST
| (1U << 28) // ADCHS_RST
;
configure_spifi();
LPC_CCU1->CLK_M4_M0APP_CFG.RUN = true;
LPC_CREG->M0APPMEMMAP = LPC_SPIFI_DATA_CACHED_BASE + 0x0;
LPC_RGU->RESET_CTRL[1] = 0;
/* Prevent the M4 from doing any more initializing by sleep-waiting forever...
* ...until the M0 resets the M4 with some code to run.
*/
while(1) {
__WFE();
}
}
}
extern "C" void __late_init(void) {
/*
* 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();
}
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
extern "C" void boardInit(void) {
vaa_power_on();
}
extern "C" void _default_exit(void) {
vaa_power_off();
chSysDisable();
systick_stop();
/* Don't reset these peripherals, as they're operating during shutdown:
* WWDT, CREG, SCU, SPIFI, GPIO, M0APP
*/
LPC_RGU->RESET_CTRL[0] =
(1U << 16) // LCD_RST
| (1U << 17) // USB0_RST
| (1U << 18) // USB1_RST
| (1U << 19) // DMA_RST
| (1U << 20) // SDIO_RST
| (1U << 21) // EMC_RST
| (1U << 22) // ETHERNET_RST
//| (1U << 28) // GPIO_RST
;
LPC_RGU->RESET_CTRL[1] =
(1U << 0) // TIMER0_RST
| (1U << 1) // TIMER1_RST
| (1U << 2) // TIMER2_RST
| (1U << 3) // TIMER3_RST
| (1U << 4) // RITIMER_RST
| (1U << 5) // SCT_RST
| (1U << 6) // MOTOCONPWM_RST
| (1U << 7) // QEI_RST
| (1U << 8) // ADC0_RST
| (1U << 9) // ADC1_RST
| (1U << 10) // DAC_RST
| (1U << 12) // UART0_RST
| (1U << 13) // UART1_RST
| (1U << 14) // UART2_RST
| (1U << 15) // UART3_RST
| (1U << 16) // I2C0_RST
| (1U << 17) // I2C1_RST
| (1U << 18) // SSP0_RST
| (1U << 19) // SSP1_RST
| (1U << 20) // I2S_RST
| (1U << 22) // CAN1_RST
| (1U << 23) // CAN0_RST
//| (1U << 24) // M0APP_RST
| (1U << 25) // SGPIO_RST
| (1U << 26) // SPI_RST
| (1U << 28) // ADCHS_RST
;
}

View File

@ -0,0 +1,45 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Copyright (C) 2014 Jared Boone, ShareBrained Technology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
/*
* Setup for PortaPack application running on M4, which then bootstaps the M0,
* which then runs the application firmware and user interface.
*/
/*
* Board identifiers.
*/
#define BOARD_PORTAPACK_APPLICATION
#define BOARD_NAME "PortaPack Application"
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
void vaa_power_on(void);
void vaa_power_off(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* _BOARD_H_ */

View File

@ -0,0 +1,5 @@
# List of all the board related files.
BOARDSRC = ${CHIBIOS_PORTAPACK}/boards/PORTAPACK_APPLICATION/board.cpp
# Required include directories
BOARDINC = ${CHIBIOS_PORTAPACK}/boards/PORTAPACK_APPLICATION

View File

@ -0,0 +1,26 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Copyright (C) 2014 Jared Boone, ShareBrained Technology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ch.h"
#include "hal.h"
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
void boardInit(void) {
}

View File

@ -0,0 +1,9 @@
# List of all the board related files.
set(BOARDSRC
${CHIBIOS_PORTAPACK}/boards/PORTAPACK_BASEBAND/board.c
)
# Required include directories
set(BOARDINC
${CHIBIOS_PORTAPACK}/boards/PORTAPACK_BASEBAND
)

View File

@ -1,6 +1,6 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Copyright (C) 2014 Jared Boone, ShareBrained Technology
Copyright (C) 2018 Jared Boone, ShareBrained Technology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -19,14 +19,15 @@
#define _BOARD_H_
/*
* Setup for Great Scott Gadgets HackRF One
* Setup for PortaPack application running on M4, which then bootstaps the M0,
* which then runs the application firmware and user interface.
*/
/*
* Board identifiers.
*/
#define BOARD_GSG_HACKRF_ONE
#define BOARD_NAME "Great Scott Gadgets HackRF One"
#define BOARD_PORTAPACK_BASEBAND
#define BOARD_NAME "PortaPack Baseband"
#if !defined(_FROM_ASM_)
#ifdef __cplusplus

View File

@ -0,0 +1,5 @@
# List of all the board related files.
BOARDSRC = ${CHIBIOS_PORTAPACK}/boards/PORTAPACK_BASEBAND/board.c
# Required include directories
BOARDINC = ${CHIBIOS_PORTAPACK}/boards/PORTAPACK_BASEBAND

View File

@ -98,13 +98,6 @@
/**
* @brief Structure used for ADC configuration.
*/
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
peripheral_reset_t reset;
interrupt_config_t interrupt;
} adc_resources_t;
typedef LPC_ADCx_Type* ADC_TypeDef;
/**

View File

@ -135,15 +135,6 @@
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Structure used for Timer configuration.
*/
typedef struct {
branch_clock_regs_t branch;
peripheral_reset_t reset;
interrupt_config_t interrupt;
} timer_resources_t;
/**
* @brief GPT frequency type.
*/

View File

@ -99,12 +99,6 @@
/**
* @brief Structure used for I2C configuration.
*/
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
peripheral_reset_t reset;
} i2c_resources_t;
typedef LPC_I2Cx_Type* I2C_TypeDef;
/**

View File

@ -37,6 +37,224 @@ typedef struct {
uint32_t priority_mask;
} interrupt_config_t;
typedef struct {
uint32_t data;
uint32_t dir;
} gpio_setup_t;
struct scu_config_normal_drive_t {
uint16_t mode;
uint16_t epd;
uint16_t epun;
uint16_t ehs;
uint16_t ezi;
uint16_t zif;
};
struct scu_config_sfsi2c0_t {
uint16_t scl_efp;
uint16_t scl_ehd;
uint16_t scl_ezi;
uint16_t scl_zif;
uint16_t sda_efp;
uint16_t sda_ehd;
uint16_t sda_ezi;
uint16_t sda_zif;
};
struct scu_config_t {
#ifdef __cplusplus
scu_config_t() = delete;
scu_config_t(const scu_config_t&) = delete;
scu_config_t(scu_config_t&) = delete;
constexpr scu_config_t(
uint16_t value
) :
word(value)
{
}
constexpr scu_config_t(
const scu_config_normal_drive_t config
) :
word(
((config.mode & 7) << 0)
| ((config.epd & 1) << 3)
| ((config.epun & 1) << 4)
| ((config.ehs & 1) << 5)
| ((config.ezi & 1) << 6)
| ((config.zif & 1) << 7)
)
{
}
constexpr scu_config_t(
const scu_config_sfsi2c0_t config
) :
word(
((config.scl_efp & 1) << 0)
| ((config.scl_ehd & 1) << 2)
| ((config.scl_ezi & 1) << 3)
| ((config.scl_zif & 1) << 7)
| ((config.sda_efp & 1) << 8)
| ((config.sda_ehd & 1) << 10)
| ((config.sda_ezi & 1) << 11)
| ((config.sda_zif & 1) << 15)
)
{
}
constexpr operator uint32_t() const {
return word;
}
private:
#endif
uint16_t word;
};
#ifndef __cplusplus
typedef struct scu_config_t scu_config_t;
#endif
typedef struct {
uint8_t port;
uint8_t pin;
scu_config_t config;
} scu_setup_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
peripheral_reset_t reset;
interrupt_config_t interrupt;
} adc_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
} audio_clock_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
peripheral_reset_t reset;
} gpdma_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
peripheral_reset_t reset;
} i2c_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
peripheral_reset_t reset[2];
} i2s_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
peripheral_reset_t reset;
} motocon_pwm_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch_register_if;
branch_clock_regs_t branch_peripheral;
peripheral_reset_t reset;
interrupt_config_t interrupt;
} sdio_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch;
peripheral_reset_t reset;
} sgpio_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch_register_if;
branch_clock_regs_t branch_peripheral;
peripheral_reset_t reset;
} ssp_resources_t;
typedef struct {
branch_clock_regs_t branch;
peripheral_reset_t reset;
interrupt_config_t interrupt;
} timer_resources_t;
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch_register_if;
branch_clock_regs_t branch_peripheral;
peripheral_reset_t reset;
interrupt_config_t interrupt;
} uart_resources_t;
static const base_clock_regs_t base_clock_apb3 = {
.clk = &LPC_CGU->BASE_APB3_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 0),
};
static const base_clock_regs_t base_clock_apb1 = {
.clk = &LPC_CGU->BASE_APB1_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 1),
};
static const base_clock_regs_t base_clock_spifi = {
.clk = &LPC_CGU->BASE_SPIFI_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 2),
};
static const base_clock_regs_t base_clock_m4 = {
.clk = &LPC_CGU->BASE_M4_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 3),
};
static const base_clock_regs_t base_clock_periph = {
.clk = &LPC_CGU->BASE_PERIPH_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 6),
};
static const base_clock_regs_t base_clock_usb0 = {
.clk = &LPC_CGU->BASE_USB0_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 7),
};
static const base_clock_regs_t base_clock_usb1 = {
.clk = &LPC_CGU->BASE_USB1_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 8),
};
static const base_clock_regs_t base_clock_spi = {
.clk = &LPC_CGU->BASE_SPI_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 9),
};
static const base_clock_regs_t base_clock_uart3 = {
.clk = &LPC_CGU->BASE_UART3_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 1),
};
static const base_clock_regs_t base_clock_uart2 = {
.clk = &LPC_CGU->BASE_UART2_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 2),
};
static const base_clock_regs_t base_clock_uart1 = {
.clk = &LPC_CGU->BASE_UART1_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 3),
};
static const base_clock_regs_t base_clock_uart0 = {
.clk = &LPC_CGU->BASE_UART0_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 4),
};
static const base_clock_regs_t base_clock_ssp1 = {
.clk = &LPC_CGU->BASE_SSP1_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 5),
};
static const base_clock_regs_t base_clock_ssp0 = {
.clk = &LPC_CGU->BASE_SSP0_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = (1 << 6),
};
#ifdef __cplusplus
extern "C" {
#endif
void peripheral_reset(const peripheral_reset_t* const reset);
void base_clock_enable(const base_clock_regs_t* const base);
@ -48,4 +266,8 @@ void branch_clock_disable(const branch_clock_regs_t* const branch);
void interrupt_enable(const interrupt_config_t* const interrupt);
void interrupt_disable(const interrupt_config_t* const interrupt);
#ifdef __cplusplus
}
#endif
#endif /* _LPC43XX_H_ */

View File

@ -40,74 +40,10 @@
/* Driver local variables and types. */
/*===========================================================================*/
static const scu_config_t pin_config_vaa_enablex_pwm = { .MODE=1, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 };
static const scu_config_t pin_config_vaa_enablex_gpio = { .MODE=0, .EPD=0, .EPUN=1, .EHS=0, .EZI=0, .ZIF=0 };
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/* 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.
*/
static void vaa_power_on(void) {
/* Very twitchy process for powering up VAA without glitching the 3.3V rail, which can send the
* microcontroller into reset.
*
* Controlling timing while running from SPIFI flash is tricky, hence use of a PWM peripheral...
*/
/* Configure and enable MOTOCONPWM peripheral clocks.
* Assume IDIVC is running the post-bootloader configuration, outputting 96MHz derived from PLL1.
*/
LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG.RUN = true;
/* Combination of pulse duration and duty cycle was arrived at empirically, to keep supply glitching
* to +/- 0.15V.
*/
const uint32_t cycle_period = 128;
const uint32_t enable_period = 10;
LPC_MCPWM->TC2 = 0;
LPC_MCPWM->MAT2 = cycle_period - enable_period;
LPC_MCPWM->LIM2 = cycle_period;
/* Switch !VAA_ENABLE pin from GPIO to MOTOCONPWM peripheral output, now that the peripheral is configured. */
LPC_SCU->SFSP[5][ 0] = pin_config_vaa_enablex_pwm.word; // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
/* Start the PWM operation. */
LPC_MCPWM->CON_SET = (1 << 16);
/* Wait until VAA rises to approximately 90% of final voltage. */
/* Timing assumes we're running immediately after the bootloader: 96 MHz from IRC+PLL1
*/
{ volatile uint32_t delay = 12000; while(delay--); }
/* Hold !VAA_ENABLE active using a GPIO, so we can reclaim and shut down the MOTOCONPWM peripheral. */
LPC_GPIO->CLR[2] = (1 << 9); // !VAA_ENABLE
LPC_GPIO->DIR[2] |= (1 << 9);
LPC_SCU->SFSP[5][ 0] = pin_config_vaa_enablex_gpio.word; // P5_0 /GPIO2[ 9]/MCOB2: !VAA_ENABLE, 10K PU
/* Reset the MOTOCONPWM peripheral. */
LPC_RGU->RESET_CTRL[1] = (1U << 6);
/* Shut down the MOTOCONPWM clocks. */
LPC_CCU1->CLK_APB1_MOTOCON_PWM_CFG.RUN = false;
}
static void vaa_power_off(void) {
// TODO: There's a lot of other stuff that must be done to prevent
// leakage from +3V3 into VAA.
LPC_GPIO->W2[9] = 1;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
@ -135,8 +71,6 @@ void _pal_lld_init(const PALConfig *config) {
for(size_t i=0; i<ARRAY_SIZE(config->SCU); i++) {
LPC_SCU->SFSP[config->SCU[i].port][config->SCU[i].pin] = config->SCU[i].config.word;
}
vaa_power_on();
}
/**

View File

@ -41,37 +41,6 @@
/* I/O Ports Types and constants. */
/*===========================================================================*/
/**
* @brief GPIO port setup info.
*/
typedef struct {
/** Initial value for FIO_PIN register.*/
uint32_t data;
/** Initial value for FIO_DIR register.*/
uint32_t dir;
} gpio_setup_t;
typedef struct {
union {
struct {
uint16_t MODE : 3;
uint16_t EPD : 1;
uint16_t EPUN : 1;
uint16_t EHS : 1;
uint16_t EZI : 1;
uint16_t ZIF : 1;
uint16_t RESERVED0 : 8;
};
uint16_t word;
};
} scu_config_t;
typedef struct {
uint8_t port;
uint8_t pin;
scu_config_t config;
} scu_setup_t;
/**
* @brief Generic I/O ports static initializer.
* @details An instance of this structure must be passed to @p palInit() at

View File

@ -76,17 +76,6 @@
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Structure used for SDIO configuration.
*/
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch_register_if;
branch_clock_regs_t branch_peripheral;
peripheral_reset_t reset;
interrupt_config_t interrupt;
} sdio_resources_t;
/**
* @brief Type of SDIO bus mode.
*/

View File

@ -69,7 +69,7 @@ static const uart_resources_t usart0_resources = {
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_USART0_CFG, .stat = &LPC_CCU1->CLK_M4_USART0_STAT },
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB0_USART0_CFG, .stat = &LPC_CCU2->CLK_APB0_USART0_STAT },
.reset = { .output_index = 44 },
.interrupt = { .irq = USART0_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART0_IRQ_PRIORITY) },
.interrupt = { .irq = USART0_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART0_IRQ_PRIORITY) },
};
#endif
#if LPC_SERIAL_USE_UART1
@ -78,7 +78,7 @@ static const uart_resources_t uart1_resources = {
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_UART1_CFG, .stat = &LPC_CCU1->CLK_M4_UART1_STAT },
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB0_UART1_CFG, .stat = &LPC_CCU2->CLK_APB0_UART1_STAT },
.reset = { .output_index = 45 },
.interrupt = { .irq = UART1_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_UART1_IRQ_PRIORITY) },
.interrupt = { .irq = UART1_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_UART1_IRQ_PRIORITY) },
};
#endif
#if LPC_SERIAL_USE_USART2
@ -88,10 +88,10 @@ static const uart_resources_t usart2_resources = {
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB2_USART2_CFG, .stat = &LPC_CCU2->CLK_APB2_USART2_STAT },
.reset = { .output_index = 46 },
#if defined(LPC43XX_M4)
.interrupt = { .irq = USART2_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART2_IRQ_PRIORITY) },
.interrupt = { .irq = USART2_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART2_IRQ_PRIORITY) },
#endif
#if defined(LPC43XX_M0)
.interrupt = { .irq = USART2_OR_C_CAN1_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART2_IRQ_PRIORITY) },
.interrupt = { .irq = USART2_OR_C_CAN1_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART2_IRQ_PRIORITY) },
#endif
};
#endif
@ -101,7 +101,7 @@ static const uart_resources_t usart3_resources = {
.branch_register_if = { .cfg = &LPC_CCU1->CLK_M4_USART3_CFG, .stat = &LPC_CCU1->CLK_M4_USART3_STAT },
.branch_peripheral = { .cfg = &LPC_CCU2->CLK_APB2_USART3_CFG, .stat = &LPC_CCU2->CLK_APB2_USART3_STAT },
.reset = { .output_index = 47 },
.interrupt = { .irq = USART3_IRQn, priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART3_IRQ_PRIORITY) },
.interrupt = { .irq = USART3_IRQn, .priority_mask = CORTEX_PRIORITY_MASK(LPC_SERIAL_USART3_IRQ_PRIORITY) },
};
#endif
@ -438,7 +438,7 @@ void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
void sd_lld_stop(SerialDriver *sdp) {
if (sdp->state == SD_READY) {
uart_deinit(&sdp->uart);
uart_deinit(sdp->uart);
interrupt_disable(&sdp->resources->interrupt);
peripheral_reset(&sdp->resources->reset);
branch_clock_disable(&sdp->resources->branch_peripheral);

View File

@ -260,14 +260,6 @@
/**
* @brief Structure used for UART configuration.
*/
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch_register_if;
branch_clock_regs_t branch_peripheral;
peripheral_reset_t reset;
interrupt_config_t interrupt;
} uart_resources_t;
/**
* @brief LPC Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
@ -307,7 +299,7 @@ typedef struct {
/* Pointer to the UART registers block.*/ \
LPC_USART_Type *uart; \
/* Pointer to the non-peripheral SSP resources.*/ \
const ssp_resources_t * resources;
const uart_resources_t * resources;
/*===========================================================================*/
/* Driver macros. */

View File

@ -220,16 +220,6 @@
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Structure used for SSP configuration.
*/
typedef struct {
base_clock_regs_t base;
branch_clock_regs_t branch_register_if;
branch_clock_regs_t branch_peripheral;
peripheral_reset_t reset;
} ssp_resources_t;
/**
* @brief Type of a structure representing an SPI driver.
*/

View File

@ -77,8 +77,10 @@ void systick_adjust_period(const uint32_t counts_per_tick) {
* @notapi
*/
void hal_lld_init(void) {
#if defined(LPC43XX_M4_CLK_SRC)
LPC_CGU->BASE_M4_CLK.AUTOBLOCK = 1;
LPC_CGU->BASE_M4_CLK.CLK_SEL = LPC43XX_M4_CLK_SRC;
#endif
/* SysTick initialization using the system clock.*/
systick_adjust_period(halLPCGetSystemClock() / CH_FREQUENCY - 1);

View File

@ -23,8 +23,8 @@ __process_stack_size__ = 0x1000; /* main() stack */
MEMORY
{
flash : org = 0x00000000, len = 512k /* SPIFI flash @ 0x140????? */
ram : org = 0x20000000, len = 64k /* AHB SRAM @ 0x20000000 */
flash (rx) : org = 0x00000000, len = 1024k /* SPIFI flash @ 0x140????? */
ram (rwx) : org = 0x20000000, len = 64k /* AHB SRAM @ 0x20000000 */
}
__ram_start__ = ORIGIN(ram);
@ -127,6 +127,8 @@ SECTIONS
PROVIDE(_edata = .);
} > ram
_textend = LOADADDR(.data) + SIZEOF(.data);
.bss ALIGN(4) : ALIGN(4)
{
. = ALIGN(4);

View File

@ -23,8 +23,8 @@ __process_stack_size__ = 0x1000; /* main() stack */
MEMORY
{
flash : org = 0x00000000, len = 32752 /* Local SRAM @ 0x10080000 */
ram : org = 0x10000000, len = 96k /* Local SRAM @ 0x10000000 */
flash (rx) : org = 0x00000000, len = 32752 /* Local SRAM @ 0x10080000 */
ram (rwx) : org = 0x10000000, len = 96k /* Local SRAM @ 0x10000000 */
}
__ram_start__ = ORIGIN(ram);
@ -127,6 +127,8 @@ SECTIONS
PROVIDE(_edata = .);
} > ram
_textend = LOADADDR(.data) + SIZEOF(.data);
.bss ALIGN(4) : ALIGN(4)
{
. = ALIGN(4);

View File

@ -135,9 +135,9 @@ enum {
PIN_DISABLE = 10,
PIN_DIRECTION = 11,
PIN_INVERT = 12,
PIN_DECIM0 = 13,
PIN_DECIM1 = 14,
PIN_DECIM2 = 15,
PIN_SYNC_EN = 13,
PIN_P81 = 14,
PIN_P78 = 15,
};
enum class Slice : uint8_t {
@ -189,9 +189,9 @@ constexpr uint32_t gpio_outreg(const Direction direction) {
constexpr uint32_t gpio_oenreg(const Direction direction) {
return
(0U << PIN_DECIM2)
| (0U << PIN_DECIM1)
| (0U << PIN_DECIM0)
(0U << PIN_P78)
| (0U << PIN_P81)
| (0U << PIN_SYNC_EN)
| (0U << PIN_INVERT)
| (1U << PIN_DIRECTION)
| (1U << PIN_DISABLE)
@ -295,6 +295,18 @@ constexpr P_OUT_CFG data_p_out_cfg(
;
}
static const sgpio_resources_t sgpio_resources = {
.base = { .clk = &LPC_CGU->BASE_PERIPH_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 6) },
.branch = { .cfg = &LPC_CCU1->CLK_PERIPH_SGPIO_CFG, .stat = &LPC_CCU1->CLK_PERIPH_SGPIO_STAT },
.reset = { .output_index = 57 },
};
void SGPIO::init() {
base_clock_enable(&sgpio_resources.base);
branch_clock_enable(&sgpio_resources.branch);
peripheral_reset(&sgpio_resources.reset);
}
void SGPIO::configure(const Direction direction) {
disable_all_slice_counters();

View File

@ -32,8 +32,7 @@ namespace baseband {
class SGPIO {
public:
void init() {
}
void init();
void configure(const Direction direction);

View File

@ -42,6 +42,17 @@ void CPLD::sample() {
}
}
void CPLD::sample(std::bitset<240>& value) {
shift_ir(instruction_t::SAMPLE);
jtag.runtest_tck(93);
shift_dr(value);
}
void CPLD::extest(std::bitset<240>& value) {
shift_ir(instruction_t::EXTEST);
shift_dr(value);
}
void CPLD::clamp() {
shift_ir(instruction_t::CLAMP);
jtag.runtest_tck(93);

View File

@ -48,6 +48,8 @@ public:
void bypass();
void sample();
void sample(std::bitset<240>& value);
void extest(std::bitset<240>& value);
void clamp();
void reset() {

View File

@ -341,9 +341,18 @@ constexpr std::array<channel::Channel, 8> channels { {
{ 4 }, { 5 }, { 6 }, { 7 },
} };
static const gpdma_resources_t gpdma_resources = {
.base = { .clk = &LPC_CGU->BASE_M4_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 3) },
.branch = { .cfg = &LPC_CCU1->CLK_M4_DMA_CFG, .stat = &LPC_CCU1->CLK_M4_DMA_STAT },
.reset = { .output_index = 19 },
};
class Controller {
public:
void enable() const {
base_clock_enable(&gpdma_resources.base);
branch_clock_enable(&gpdma_resources.branch);
peripheral_reset(&gpdma_resources.reset);
LPC_GPDMA->CONFIG |= (1U << 0);
}
@ -352,6 +361,9 @@ public:
channel.disable();
}
LPC_GPDMA->CONFIG &= ~(1U << 0);
peripheral_reset(&gpdma_resources.reset);
branch_clock_disable(&gpdma_resources.branch);
base_clock_disable(&gpdma_resources.base);
}
};

View File

@ -186,7 +186,7 @@ struct PinConfig {
}
static constexpr PinConfig spifi_cs(const uint32_t mode) {
return { .mode = mode, .pd = 0, .pu = 0, .fast = 1, .input = 0, .ifilt = 0 };
return { .mode = mode, .pd = 0, .pu = 0, .fast = 1, .input = 1, .ifilt = 0 };
}
};

View File

@ -28,54 +28,5 @@ using namespace lpc43xx;
namespace hackrf {
namespace one {
void reset() {
/* "The reset delay is counted in IRC clock cycles. If the core frequency
* CCLK is much higher than the IRC frequency, add a software delay of
* fCCLK/fIRC clock cycles between resetting and accessing any of the
* peripheral blocks."
*/
rgu::reset_mask(
/* Don't reset SCU, may trip up SPIFI pins if running from SPIFI
* memory.
*/
/*rgu::Reset::SCU */
rgu::Reset::LCD
| rgu::Reset::USB0
| rgu::Reset::USB1
| rgu::Reset::DMA
| rgu::Reset::SDIO
| rgu::Reset::EMC
| rgu::Reset::ETHERNET
| rgu::Reset::GPIO
| rgu::Reset::TIMER0
| rgu::Reset::TIMER1
| rgu::Reset::TIMER2
| rgu::Reset::TIMER3
| rgu::Reset::RITIMER
| rgu::Reset::SCT
| rgu::Reset::MOTOCONPWM
| rgu::Reset::QEI
| rgu::Reset::ADC0
| rgu::Reset::ADC1
| rgu::Reset::DAC
| rgu::Reset::UART0
| rgu::Reset::UART1
| rgu::Reset::UART2
| rgu::Reset::UART3
| rgu::Reset::I2C0
| rgu::Reset::I2C1
| rgu::Reset::SSP0
| rgu::Reset::SSP1
| rgu::Reset::I2S
/* Don't reset SPIFI if running from SPIFI memory */
/*| rgu::Reset::SPIFI*/
| rgu::Reset::CAN1
| rgu::Reset::CAN0
| rgu::Reset::M0APP
| rgu::Reset::SGPIO
| rgu::Reset::SPI
);
}
} /* namespace one */
} /* namespace hackrf */

View File

@ -73,8 +73,6 @@ using adc0 = adc::ADC<LPC_ADC0_BASE>;
using adc1 = adc::ADC<LPC_ADC1_BASE>;
void reset();
} /* namespace one */
} /* namespace hackrf */

View File

@ -154,6 +154,17 @@ struct ConfigDMA {
uint32_t dma2;
};
static const audio_clock_resources_t audio_clock_resources = {
.base = { .clk = &LPC_CGU->BASE_AUDIO_CLK, .stat = &LPC_CCU2->BASE_STAT, .stat_mask = 0 },
.branch = { .cfg = &LPC_CCU2->CLK_AUDIO_CFG, .stat = &LPC_CCU2->CLK_AUDIO_STAT },
};
static const i2s_resources_t i2s_resources = {
.base = { .clk = &LPC_CGU->BASE_APB1_CLK, .stat = &LPC_CCU1->BASE_STAT, .stat_mask = (1 << 1) },
.branch = { .cfg = &LPC_CCU1->CLK_APB1_I2S_CFG, .stat = &LPC_CCU1->CLK_APB1_I2S_STAT },
.reset = { { .output_index = 52 }, { .output_index = 53 } },
};
template<uint32_t BaseAddress>
class I2S {
public:
@ -161,6 +172,19 @@ public:
const ConfigTX& config_tx,
const ConfigRX& config_rx
) {
base_clock_enable(&i2s_resources.base);
branch_clock_enable(&i2s_resources.branch);
base_clock_enable(&audio_clock_resources.base);
branch_clock_enable(&audio_clock_resources.branch);
if( &p() == LPC_I2S0 ) {
peripheral_reset(&i2s_resources.reset[0]);
}
if( &p() == LPC_I2S1 ) {
peripheral_reset(&i2s_resources.reset[1]);
}
reset();
if( &p() == LPC_I2S0 ) {
@ -194,6 +218,21 @@ public:
p().DMA2 = config_dma.dma2;
}
static void shutdown() {
if( &p() == LPC_I2S0 ) {
peripheral_reset(&i2s_resources.reset[0]);
}
if( &p() == LPC_I2S1 ) {
peripheral_reset(&i2s_resources.reset[1]);
}
branch_clock_disable(&audio_clock_resources.branch);
base_clock_disable(&audio_clock_resources.base);
branch_clock_disable(&i2s_resources.branch);
base_clock_disable(&i2s_resources.base);
}
static void rx_start() {
p().DAI &= ~(1U << 3);
}

View File

@ -134,7 +134,7 @@ struct IDIV_CTRL {
constexpr operator uint32_t() const {
return
((pd & 1) << 0)
| ((idiv & 3) << 2)
| ((idiv & 255) << 2)
| ((autoblock & 1) << 11)
| ((toUType(clk_sel) & 0x1f) << 24)
;

View File

@ -89,9 +89,9 @@ constexpr Pin pins[] = {
[P4_5] = { 4, 5, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* RXENABLE/P56: MAX2837.RXENABLE(I) */
[P4_6] = { 4, 6, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* XCVR_EN: 10K PD, MAX2837.ENABLE(I) */
[P4_7] = { 4, 7, { .mode=1, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=0 } }, /* GP_CLKIN/P72/MCU_CLK: SI5351C.CLK7(O) */
[P4_8] = { 4, 8, PinConfig::gpio_out_with_pullup(4) }, /* SGPIO13/BANK2F3M2: CPLD.90/HOST_DECIM_SEL0(I) */
[P4_9] = { 4, 9, PinConfig::gpio_out_with_pullup(4) }, /* SGPIO14/BANK2F3M4: CPLD.81/HOST_DECIM_SEL1(I) */
[P4_10] = { 4, 10, PinConfig::gpio_out_with_pullup(4) }, /* SGPIO15/BANK2F3M6: CPLD.78/HOST_DECIM_SEL2(I) */
[P4_8] = { 4, 8, PinConfig::floating_input_with_pull(0, 4) }, /* SGPIO13/BANK2F3M2: CPLD.90/HOST_SYNC_EN(I) */
[P4_9] = { 4, 9, PinConfig::floating_input(4) }, /* SGPIO14/BANK2F3M4: CPLD.81(I) */
[P4_10] = { 4, 10, PinConfig::floating_input(4) }, /* SGPIO15/BANK2F3M6: CPLD.78(I) */
[P5_0] = { 5, 0, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* !VAA_ENABLE: 10K PU, Q3.G(I), power to VAA */
[P5_1] = { 5, 1, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* LP/P45: U6.VCTL2(I), U5.VCTL1(I) */
[P5_2] = { 5, 2, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* TX_MIX_BP/P46: U9.V1(I) */

View File

@ -28,6 +28,8 @@
#include "memory_map.hpp"
extern uint32_t _textend;
namespace portapack {
namespace spi_flash {
@ -114,14 +116,14 @@ struct region_t {
}
};
constexpr region_t images {
.offset = 0x80000,
.size = 0x80000,
const region_t images {
.offset = reinterpret_cast<uint32_t>(&_textend),
.size = portapack::memory::map::spifi_cached.size() - reinterpret_cast<uint32_t>(&_textend),
};
constexpr region_t application {
const region_t application {
.offset = 0x00000,
.size = 0x80000,
.size = reinterpret_cast<uint32_t>(&_textend),
};
} /* namespace spi_flash */

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -55,12 +55,12 @@ images = (
{
'name': 'application',
'data': application_image,
'size': 0x80000, #len(application_image),
'size': len(application_image),
},
{
'name': 'baseband',
'data': baseband_image,
'size': 0x80000,
'size': len(baseband_image),
},
)

View File

@ -6,8 +6,8 @@ $Descr A4 11693 8268
encoding utf-8
Sheet 2 6
Title "PortaPack H1"
Date "2018-08-20"
Rev "20180820"
Date "2018-10-29"
Rev "20181029"
Comp "ShareBrained Technology, Inc."
Comment1 "Copyright © 2014-2018 Jared Boone"
Comment2 "License: GNU General Public License, version 2"

View File

@ -6,8 +6,8 @@ $Descr A4 11693 8268
encoding utf-8
Sheet 6 6
Title "PortaPack H1"
Date "2018-08-20"
Rev "20180820"
Date "2018-10-29"
Rev "20181029"
Comp "ShareBrained Technology, Inc."
Comment1 "Copyright © 2014-2018 Jared Boone"
Comment2 "License: GNU General Public License, version 2"

View File

@ -6,8 +6,8 @@ $Descr A4 11693 8268
encoding utf-8
Sheet 4 6
Title "PortaPack H1"
Date "2018-08-20"
Rev "20180820"
Date "2018-10-29"
Rev "20181029"
Comp "ShareBrained Technology, Inc."
Comment1 "Copyright © 2014-2018 Jared Boone"
Comment2 "License: GNU General Public License, version 2"

View File

@ -6,8 +6,8 @@ $Descr A4 11693 8268
encoding utf-8
Sheet 3 6
Title "PortaPack H1"
Date "2018-08-20"
Rev "20180820"
Date "2018-10-29"
Rev "20181029"
Comp "ShareBrained Technology, Inc."
Comment1 "Copyright © 2014-2018 Jared Boone"
Comment2 "License: GNU General Public License, version 2"

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
(export (version D)
(design
(source /home/jboone/src/portapack-hackrf/hardware/portapack_h1/portapack_h1.sch)
(date "Sun 19 Aug 2018 12:51:43 PM PDT")
(tool "Eeschema 5.0.0-fee4fd1~66~ubuntu18.04.1")
(date "Thu 25 Oct 2018 10:48:17 AM PDT")
(tool "Eeschema 5.0.1-33cea8e~68~ubuntu18.04.1")
(sheet (number 1) (name /) (tstamps /)
(title_block
(title "PortaPack H1")
(company "ShareBrained Technology, Inc.")
(rev 20180819)
(date 2018-08-19)
(rev 20181025)
(date 2018-10-25)
(source portapack_h1.sch)
(comment (number 1) (value "Copyright © 2014-2018 Jared Boone"))
(comment (number 2) (value "License: GNU General Public License, version 2"))
@ -18,8 +18,8 @@
(title_block
(title "PortaPack H1")
(company "ShareBrained Technology, Inc.")
(rev 20180819)
(date 2018-08-19)
(rev 20181025)
(date 2018-10-25)
(source audio.sch)
(comment (number 1) (value "Copyright © 2014-2018 Jared Boone"))
(comment (number 2) (value "License: GNU General Public License, version 2"))
@ -29,8 +29,8 @@
(title_block
(title "PortaPack H1")
(company "ShareBrained Technology, Inc.")
(rev 20180819)
(date 2018-08-19)
(rev 20181025)
(date 2018-10-25)
(source lcd_sw_sd.sch)
(comment (number 1) (value "Copyright © 2014-2018 Jared Boone"))
(comment (number 2) (value "License: GNU General Public License, version 2"))
@ -40,8 +40,8 @@
(title_block
(title "PortaPack H1")
(company "ShareBrained Technology, Inc.")
(rev 20180819)
(date 2018-08-19)
(rev 20181025)
(date 2018-10-25)
(source hackrf_if.sch)
(comment (number 1) (value "Copyright © 2014-2018 Jared Boone"))
(comment (number 2) (value "License: GNU General Public License, version 2"))
@ -51,8 +51,8 @@
(title_block
(title "PortaPack H1")
(company "ShareBrained Technology, Inc.")
(rev 20180819)
(date 2018-08-19)
(rev 20181025)
(date 2018-10-25)
(source power.sch)
(comment (number 1) (value "Copyright © 2014-2018 Jared Boone"))
(comment (number 2) (value "License: GNU General Public License, version 2"))
@ -62,8 +62,8 @@
(title_block
(title "PortaPack H1")
(company "ShareBrained Technology, Inc.")
(rev 20180819)
(date 2018-08-19)
(rev 20181025)
(date 2018-10-25)
(source gps.sch)
(comment (number 1) (value "Copyright © 2014-2018 Jared Boone"))
(comment (number 2) (value "License: GNU General Public License, version 2"))
@ -850,12 +850,10 @@
(tstamp 5B682C91))
(comp (ref R22)
(value 33R)
(footprint ipc_resc:IPC_RESC160X80X55L25N)
(footprint ipc_resc:IPC_RESC100X50X40L25N)
(datasheet ~)
(fields
(field (name DNP) DNP)
(field (name Mfr) Yageo)
(field (name Part) RC0603FR-0733RL))
(field (name DNP) DNP))
(libsource (lib Device) (part R) (description Resistor))
(sheetpath (names /power/) (tstamps /58CFF3E3/))
(tstamp 5B682CA2))
@ -894,12 +892,12 @@
(sheetpath (names /power/) (tstamps /58CFF3E3/))
(tstamp 5B682CCB))
(comp (ref R21)
(value 33R)
(footprint ipc_resc:IPC_RESC160X80X55L25N)
(value 100R)
(footprint ipc_resc:IPC_RESC100X50X40L25N)
(datasheet ~)
(fields
(field (name Mfr) Yageo)
(field (name Part) RC0603FR-0733RL))
(field (name Part) RC0402FR-07100RL))
(libsource (lib Device) (part R) (description Resistor))
(sheetpath (names /power/) (tstamps /58CFF3E3/))
(tstamp 5B682CD3))

View File

@ -6,8 +6,8 @@ $Descr A4 11693 8268
encoding utf-8
Sheet 1 6
Title "PortaPack H1"
Date "2018-08-20"
Rev "20180820"
Date "2018-10-29"
Rev "20181029"
Comp "ShareBrained Technology, Inc."
Comment1 "Copyright © 2014-2018 Jared Boone"
Comment2 "License: GNU General Public License, version 2"

View File

@ -6,8 +6,8 @@ $Descr A4 11693 8268
encoding utf-8
Sheet 5 6
Title "PortaPack H1"
Date "2018-08-20"
Rev "20180820"
Date "2018-10-29"
Rev "20181029"
Comp "ShareBrained Technology, Inc."
Comment1 "Copyright © 2014-2018 Jared Boone"
Comment2 "License: GNU General Public License, version 2"
@ -878,11 +878,9 @@ AR Path="/53A8C780/5B682CA2" Ref="R?" Part="1"
AR Path="/58CFF3E3/5B682CA2" Ref="R22" Part="1"
F 0 "R22" V 4050 6500 50 0000 C CNN
F 1 "33R" V 4034 6500 50 0001 C CNN
F 2 "ipc_resc:IPC_RESC160X80X55L25N" V 4080 6500 50 0001 C CNN
F 2 "ipc_resc:IPC_RESC100X50X40L25N" V 4080 6500 50 0001 C CNN
F 3 "~" H 4150 6500 50 0001 C CNN
F 4 "DNP" V 4150 6500 50 0000 C CNN "DNP"
F 5 "Yageo" V 4150 6500 50 0001 C CNN "Mfr"
F 6 "RC0603FR-0733RL" V 4150 6500 50 0001 C CNN "Part"
1 4150 6500
0 1 1 0
$EndComp
@ -974,11 +972,11 @@ P 3550 7200
AR Path="/53A8C780/5B682CD3" Ref="R?" Part="1"
AR Path="/58CFF3E3/5B682CD3" Ref="R21" Part="1"
F 0 "R21" V 3450 7200 50 0000 C CNN
F 1 "33R" V 3550 7200 50 0000 C CNN
F 2 "ipc_resc:IPC_RESC160X80X55L25N" V 3480 7200 50 0001 C CNN
F 1 "100R" V 3550 7200 50 0000 C CNN
F 2 "ipc_resc:IPC_RESC100X50X40L25N" V 3480 7200 50 0001 C CNN
F 3 "~" H 3550 7200 50 0001 C CNN
F 4 "Yageo" V 3550 7200 50 0001 C CNN "Mfr"
F 5 "RC0603FR-0733RL" V 3550 7200 50 0001 C CNN "Part"
F 5 "RC0402FR-07100RL" V 3550 7200 50 0001 C CNN "Part"
1 3550 7200
0 1 1 0
$EndComp