mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-23 14:29:23 -05:00
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 commit262c030224
. 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 commit920b98f7c9
. 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:
parent
262c030224
commit
e7c0fa394b
10
.travis.yml
10
.travis.yml
@ -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" ":")
|
||||
|
@ -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)
|
||||
|
250
README.md
250
README.md
@ -1,125 +1,125 @@
|
||||
![HAVOC banner](doc/banner.png)
|
||||
|
||||
HAVOC is a fork of the PortaPack H1 firmware, a portability add-on for the [HackRF One software-defined radio](http://greatscottgadgets.com/hackrf/).
|
||||
|
||||
Hardware is available at [ShareBrained Technology](http://sharebrained.com/portapack).
|
||||
|
||||
It is build on top of [ShareBrained's firmware](https://github.com/sharebrained/portapack-hackrf/), meaning that the original functionalities are kept (except when I don't sync for 2 months).
|
||||
|
||||
# Documentation
|
||||
|
||||
[READ THE WIKI](https://github.com/furrtek/portapack-havoc/wiki/Home/)
|
||||
|
||||
If you want to submit a bug report, suggest something... Don't hesitate, use this page: https://github.com/furrtek/portapack-havoc/issues (Check the progress list below first).
|
||||
|
||||
# Summary
|
||||
|
||||
As its name implies, HAVOC's functionalities can be fun, mean and even useful sometimes. You shouldn't use them. No ! Bad ! Put it down.
|
||||
|
||||
**In most countries, radio transmissions are tightly regulated. Transmitting outside of free/public bands without a licence or authorization, even at very low power, is certainly forbidden where you live. Always bear that in mind. You're the ONLY ONE responsible for what you do with this software.**
|
||||
|
||||
# Fork features
|
||||
|
||||
* IQ file replay
|
||||
* Microphone FM transmit with CTCSS
|
||||
* CTCSS decoder
|
||||
* Frequency manager (save & load from SD card, with categories and notes)
|
||||
* File manager
|
||||
* "Soundboard" wave file player (put 8-bit mono files in SD card /wav directory)
|
||||
* ADS-B receiver with map view
|
||||
* ADS-B transmitter (aircraft spoof)
|
||||
* SSTV transmitter
|
||||
* Fully configurable jammer
|
||||
* POCSAG transmitter
|
||||
* POCSAG receiver/decoder
|
||||
* Morse transmitter (FM tone and CW)
|
||||
* OOK transmitter for common remote encoders (PT2262, doorbells, remote outlets, some garage doors, ...)
|
||||
* RDS (Radio Data System) PSN, RadioText and Time groups transmitter
|
||||
* Meteorological radiosonde receiver for M10 and M2K2...
|
||||
* AFSK receiver
|
||||
* AFSK transmitter (Bell202...)
|
||||
* Nuoptix DTMF sync transmitter (quite specific but can be useful in some theme parks :) )
|
||||
* TouchTunes jukebox universal remote (by Notpike)
|
||||
* LCR (Language de Commande Routier) message generator
|
||||
* Street lighting control transmitter (CCIR tones)
|
||||
* "Play Dead" in case of emergency
|
||||
* Fully configurable RF signal generator
|
||||
* RSSI audio output as pitch (for direction finding)
|
||||
|
||||
# Progress
|
||||
|
||||
Feature | Progress | Notes
|
||||
------- | -------- | -----
|
||||
POCSAG RX | 95% | Needs support for numeric messages
|
||||
Morse TX | 95% | Needs fox hunt scheduler and live keying mode
|
||||
Mic. TX | 95% | Carrier leak bug, need to find guard tones for various brands of wireless mics
|
||||
ADS-B RX | 90% | Needs angle and speed decoding
|
||||
Close-Call™ | 85% | Needs adjustments and optimization for wider frequency range
|
||||
ADS-B TX | 85% | Works but baseband module needs cleaning
|
||||
SSTV TX | 80% | Needs better bitmap file handling, support for other modes (ROBOT ?) and callsign FSK ID
|
||||
Radiosondes | 75% | Needs support for other models
|
||||
Wave visualizer | 70% | Needs cleaning and handling of other sample formats, high priority
|
||||
AFSK RX | 70% | Needs work regarding flexibility
|
||||
Sigfox RX | 40% | Tuning basics done, needs decoding code and testing
|
||||
Generic TXs | 30% | Raw AX.25, AFSK, FSK, CCIR, DTMF... Tonesets are ready
|
||||
CC1101 TRX | 10% | And other sub-GHz transceiver chips like SI4032...
|
||||
SSTV RX | 0% |
|
||||
Scanner | 0% | Easy, could be used with POCSAG RX to catch jumping channels
|
||||
SSB TX | 0% | Requested but math is hard :(
|
||||
OOK RX | 0% | See if rtl_433's author is fine with using protocol defs
|
||||
Analog TV TX| 0% | Enough CPU ? B&W and no sound ?
|
||||
LoJack RX | 0% | Basically AFSK RX
|
||||
DMR info RX | 0% | Retrieve DMR channel info. **No voice** because of vocoder complexity and possible legal issue
|
||||
Tetra info? | 0% | Same
|
||||
|
||||
# Screenshots
|
||||
|
||||
![HAVOC screenshots](doc/screenshots.png)
|
||||
|
||||
# Thanks
|
||||
|
||||
* Sig and cLx for research on AFSK LCR, Xylos, and for lending remote-controlled outlets
|
||||
* Pyr3x, Rainer Matla and DC1RDB for the donations :)
|
||||
* Keld Norman and Giorgio Campiotti for ideas and suggestions
|
||||
|
||||
# License
|
||||
|
||||
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) 2015-2016 Furrtek
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA.
|
||||
|
||||
# Contact
|
||||
|
||||
## Original firmware and hardware
|
||||
|
||||
Jared Boone <jared@sharebrained.com>
|
||||
|
||||
ShareBrained Technology, Inc.
|
||||
|
||||
<http://www.sharebrained.com/>
|
||||
|
||||
The latest version of this repository can be found at
|
||||
https://github.com/sharebrained/portapack-hackrf/
|
||||
|
||||
## HAVOC specific things
|
||||
|
||||
Furrtek <furrtek@gmail.com>
|
||||
|
||||
<http://www.furrtek.org>
|
||||
![HAVOC banner](doc/banner.png)
|
||||
|
||||
HAVOC is a fork of the PortaPack H1 firmware, a portability add-on for the [HackRF One software-defined radio](http://greatscottgadgets.com/hackrf/).
|
||||
|
||||
Hardware is available at [ShareBrained Technology](http://sharebrained.com/portapack).
|
||||
|
||||
It is build on top of [ShareBrained's firmware](https://github.com/sharebrained/portapack-hackrf/), meaning that the original functionalities are kept (except when I don't sync for 2 months).
|
||||
|
||||
# Documentation
|
||||
|
||||
[READ THE WIKI](https://github.com/furrtek/portapack-havoc/wiki/Home/)
|
||||
|
||||
If you want to submit a bug report, suggest something... Don't hesitate, use this page: https://github.com/furrtek/portapack-havoc/issues (Check the progress list below first).
|
||||
|
||||
# Summary
|
||||
|
||||
As its name implies, HAVOC's functionalities can be fun, mean and even useful sometimes. You shouldn't use them. No ! Bad ! Put it down.
|
||||
|
||||
**In most countries, radio transmissions are tightly regulated. Transmitting outside of free/public bands without a licence or authorization, even at very low power, is certainly forbidden where you live. Always bear that in mind. You're the ONLY ONE responsible for what you do with this software.**
|
||||
|
||||
# Fork features
|
||||
|
||||
* IQ file replay
|
||||
* Microphone FM transmit with CTCSS
|
||||
* CTCSS decoder
|
||||
* Frequency manager (save & load from SD card, with categories and notes)
|
||||
* File manager
|
||||
* "Soundboard" wave file player (put 8-bit mono files in SD card /wav directory)
|
||||
* ADS-B receiver with map view
|
||||
* ADS-B transmitter (aircraft spoof)
|
||||
* SSTV transmitter
|
||||
* Fully configurable jammer
|
||||
* POCSAG transmitter
|
||||
* POCSAG receiver/decoder
|
||||
* Morse transmitter (FM tone and CW)
|
||||
* OOK transmitter for common remote encoders (PT2262, doorbells, remote outlets, some garage doors, ...)
|
||||
* RDS (Radio Data System) PSN, RadioText and Time groups transmitter
|
||||
* Meteorological radiosonde receiver for M10 and M2K2...
|
||||
* AFSK receiver
|
||||
* AFSK transmitter (Bell202...)
|
||||
* Nuoptix DTMF sync transmitter (quite specific but can be useful in some theme parks :) )
|
||||
* TouchTunes jukebox universal remote (by Notpike)
|
||||
* LCR (Language de Commande Routier) message generator
|
||||
* Street lighting control transmitter (CCIR tones)
|
||||
* "Play Dead" in case of emergency
|
||||
* Fully configurable RF signal generator
|
||||
* RSSI audio output as pitch (for direction finding)
|
||||
|
||||
# Progress
|
||||
|
||||
Feature | Progress | Notes
|
||||
------- | -------- | -----
|
||||
POCSAG RX | 95% | Needs support for numeric messages
|
||||
Morse TX | 95% | Needs fox hunt scheduler and live keying mode
|
||||
Mic. TX | 95% | Carrier leak bug, need to find guard tones for various brands of wireless mics
|
||||
ADS-B RX | 90% | Needs angle and speed decoding
|
||||
Close-Call™ | 85% | Needs adjustments and optimization for wider frequency range
|
||||
ADS-B TX | 85% | Works but baseband module needs cleaning
|
||||
SSTV TX | 80% | Needs better bitmap file handling, support for other modes (ROBOT ?) and callsign FSK ID
|
||||
Radiosondes | 75% | Needs support for other models
|
||||
Wave visualizer | 70% | Needs cleaning and handling of other sample formats, high priority
|
||||
AFSK RX | 70% | Needs work regarding flexibility
|
||||
Sigfox RX | 40% | Tuning basics done, needs decoding code and testing
|
||||
Generic TXs | 30% | Raw AX.25, AFSK, FSK, CCIR, DTMF... Tonesets are ready
|
||||
CC1101 TRX | 10% | And other sub-GHz transceiver chips like SI4032...
|
||||
SSTV RX | 0% |
|
||||
Scanner | 0% | Easy, could be used with POCSAG RX to catch jumping channels
|
||||
SSB TX | 0% | Requested but math is hard :(
|
||||
OOK RX | 0% | See if rtl_433's author is fine with using protocol defs
|
||||
Analog TV TX| 0% | Enough CPU ? B&W and no sound ?
|
||||
LoJack RX | 0% | Basically AFSK RX
|
||||
DMR info RX | 0% | Retrieve DMR channel info. **No voice** because of vocoder complexity and possible legal issue
|
||||
Tetra info? | 0% | Same
|
||||
|
||||
# Screenshots
|
||||
|
||||
![HAVOC screenshots](doc/screenshots.png)
|
||||
|
||||
# Thanks
|
||||
|
||||
* Sig and cLx for research on AFSK LCR, Xylos, and for lending remote-controlled outlets
|
||||
* Pyr3x, Rainer Matla and DC1RDB for the donations :)
|
||||
* Keld Norman and Giorgio Campiotti for ideas and suggestions
|
||||
|
||||
# License
|
||||
|
||||
Except where specified in subdirectories of this project, all work is offered under the following license:
|
||||
|
||||
Copyright (C) 2013-2019 Jared Boone, ShareBrained Technology, Inc.
|
||||
|
||||
Copyright (C) 2015-2016 Furrtek
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA.
|
||||
|
||||
# Contact
|
||||
|
||||
## Original firmware and hardware
|
||||
|
||||
Jared Boone <jared@sharebrained.com>
|
||||
|
||||
ShareBrained Technology, Inc.
|
||||
|
||||
<http://www.sharebrained.com/>
|
||||
|
||||
The latest version of this repository can be found at
|
||||
https://github.com/sharebrained/portapack-hackrf/
|
||||
|
||||
## HAVOC specific things
|
||||
|
||||
Furrtek <furrtek@gmail.com>
|
||||
|
||||
<http://www.furrtek.org>
|
||||
|
BIN
doc/images/hardware/portapack_h1_operating.jpg
Normal file
BIN
doc/images/hardware/portapack_h1_operating.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
BIN
doc/images/hardware/portapack_h1_parts.jpg
Normal file
BIN
doc/images/hardware/portapack_h1_parts.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 137 KiB |
@ -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
|
||||
)
|
||||
|
||||
|
@ -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})
|
||||
|
@ -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(); };
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
&field_ppm,
|
||||
&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
|
||||
|
@ -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"
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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__*/
|
||||
|
@ -223,8 +223,6 @@ void EventDispatcher::handle_local_queue() {
|
||||
|
||||
void EventDispatcher::handle_rtc_tick() {
|
||||
sd_card::poll_inserted();
|
||||
|
||||
portapack::poll_ext_clock();
|
||||
|
||||
portapack::temperature_logger.second_tick();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 });
|
||||
|
||||
|
@ -454,11 +454,7 @@ public:
|
||||
_clock_control[n].CLK_PDN = ClockControl::ClockPowerDown::Power_Off;
|
||||
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;
|
||||
@ -472,7 +468,7 @@ private:
|
||||
I2C& _bus;
|
||||
const I2C::address_t _address;
|
||||
uint8_t _output_enable;
|
||||
|
||||
|
||||
void update_output_enable_control() {
|
||||
write_register(Register::OutputEnableControl, ~_output_enable);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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__*/
|
||||
|
@ -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 */
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
add_child(&text_ppm);
|
||||
}
|
||||
|
||||
void FrequencyOptionsView::set_step(rf::Frequency f) {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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
BIN
firmware/bootstrap/bootstrap.bin
Executable file
Binary file not shown.
BIN
firmware/bootstrap/bootstrap_pad.bin
Executable file
BIN
firmware/bootstrap/bootstrap_pad.bin
Executable file
Binary file not shown.
@ -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) {
|
||||
}
|
@ -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
|
||||
)
|
@ -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
|
@ -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
|
||||
)
|
607
firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp
Executable file
607
firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.cpp
Executable 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
|
||||
;
|
||||
}
|
45
firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.h
Executable file
45
firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.h
Executable 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_ */
|
5
firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.mk
Executable file
5
firmware/chibios-portapack/boards/PORTAPACK_APPLICATION/board.mk
Executable 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
|
26
firmware/chibios-portapack/boards/PORTAPACK_BASEBAND/board.c
Normal file
26
firmware/chibios-portapack/boards/PORTAPACK_BASEBAND/board.c
Normal 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) {
|
||||
}
|
@ -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
|
||||
)
|
83
firmware/chibios-portapack/boards/GSG_HACKRF_ONE/board.h → firmware/chibios-portapack/boards/PORTAPACK_BASEBAND/board.h
Executable file → Normal file
83
firmware/chibios-portapack/boards/GSG_HACKRF_ONE/board.h → firmware/chibios-portapack/boards/PORTAPACK_BASEBAND/board.h
Executable file → Normal file
@ -1,41 +1,42 @@
|
||||
/*
|
||||
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 Great Scott Gadgets HackRF One
|
||||
*/
|
||||
|
||||
/*
|
||||
* Board identifiers.
|
||||
*/
|
||||
#define BOARD_GSG_HACKRF_ONE
|
||||
#define BOARD_NAME "Great Scott Gadgets HackRF One"
|
||||
|
||||
#if !defined(_FROM_ASM_)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void boardInit(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _FROM_ASM_ */
|
||||
|
||||
#endif /* _BOARD_H_ */
|
||||
/*
|
||||
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
|
||||
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.
|
||||
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_BASEBAND
|
||||
#define BOARD_NAME "PortaPack Baseband"
|
||||
|
||||
#if !defined(_FROM_ASM_)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void boardInit(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _FROM_ASM_ */
|
||||
|
||||
#endif /* _BOARD_H_ */
|
@ -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
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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_ */
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -32,8 +32,7 @@ namespace baseband {
|
||||
|
||||
class SGPIO {
|
||||
public:
|
||||
void init() {
|
||||
}
|
||||
void init();
|
||||
|
||||
void configure(const Direction direction);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 };
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -73,8 +73,6 @@ using adc0 = adc::ADC<LPC_ADC0_BASE>;
|
||||
|
||||
using adc1 = adc::ADC<LPC_ADC1_BASE>;
|
||||
|
||||
void reset();
|
||||
|
||||
} /* namespace one */
|
||||
} /* namespace hackrf */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
;
|
||||
|
@ -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) */
|
||||
|
@ -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.
@ -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),
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
@ -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))
|
||||
|
Binary file not shown.
@ -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"
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user