diff --git a/firmware/common/LPC4330_M4_ROM_to_RAM.ld b/firmware/common/LPC4330_M4_ROM_to_RAM.ld index f2850b91..e3852933 100644 --- a/firmware/common/LPC4330_M4_ROM_to_RAM.ld +++ b/firmware/common/LPC4330_M4_ROM_to_RAM.ld @@ -29,7 +29,8 @@ MEMORY /* rom is really the shadow region that points to SPI flash or elsewhere */ rom (rx) : ORIGIN = 0x00000000, LENGTH = 1M ram (rwx) : ORIGIN = 0x10000000, LENGTH = 128K - /* there are some additional RAM regions */ + /* there are some additional RAM regions for data */ + ram_data (rw) : ORIGIN = 0x10080000, LENGTH = 72K } /* Include the common ld script. */ diff --git a/firmware/common/Makefile_inc.mk b/firmware/common/Makefile_inc.mk index 49b3af2c..384fd9f1 100644 --- a/firmware/common/Makefile_inc.mk +++ b/firmware/common/Makefile_inc.mk @@ -45,7 +45,7 @@ OBJDUMP = $(PREFIX)-objdump GDB = $(PREFIX)-gdb TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX) -CFLAGS += -O2 -g3 -Wall -Wextra -I$(LIBOPENCM3)/include -I../common \ +CFLAGS += -std=c99 -O2 -g3 -Wall -Wextra -I$(LIBOPENCM3)/include -I../common \ -fno-common -mcpu=cortex-m4 -mthumb -MD \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ $(HACKRF_OPTS) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 43626947..ee991b27 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -49,16 +49,22 @@ void cpu_clock_init(void) si5351c_configure_pll1_multisynth(); /* MS0/CLK0 is the source for the MAX2837 clock input. */ - si5351c_configure_multisynth(0, 2048, 0, 1, 0); /* 40MHz */ + si5351c_configure_multisynth(0, 2048, 0, 1, 0); /* 40MHz */ - /* MS1/CLK1 is the source for the MAX5864 codec. */ - si5351c_configure_multisynth(1, 4608, 0, 1, 1); /* 20MHz derived from MS0 */ + /* MS0/CLK1 is the source for the MAX5864 codec. */ + si5351c_configure_multisynth(1, 4608, 0, 1, 2); /* 10MHz */ + + /* MS0/CLK2 is the source for the CPLD clock. */ + si5351c_configure_multisynth(2, 4608, 0, 1, 1); /* 20MHz */ + + /* MS0/CLK3 is the source for the CPLD clock (inverted). */ + si5351c_configure_multisynth(3, 4608, 0, 1, 1); /* 20MHz */ /* MS4/CLK4 is the source for the LPC43xx microcontroller. */ - si5351c_configure_multisynth(4, 8021, 1, 3, 0); /* 12MHz */ + si5351c_configure_multisynth(4, 8021, 1, 3, 0); /* 12MHz */ /* MS5/CLK5 is the source for the RFFC5071 mixer. */ - si5351c_configure_multisynth(5, 1536, 1, 1, 0); /* 50MHz */ + si5351c_configure_multisynth(5, 1536, 1, 1, 0); /* 50MHz */ si5351c_configure_clock_control(); si5351c_enable_clock_outputs(); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index e9ad07b3..d300416a 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -1,6 +1,7 @@ /* * Copyright 2012 Michael Ossmann * Copyright 2012 Benjamin Vernoux + * Copyright (C) 2012 Jared Boone * * This file is part of HackRF. * @@ -59,6 +60,30 @@ extern "C" #define SCU_SSP1_SCK (P1_19) /* P1_19 */ #define SCU_SSP1_SSEL (P1_20) /* P1_20 */ +/* CPLD JTAG interface */ +#define SCU_PINMUX_CPLD_TDO (P9_5) /* GPIO5[18] */ +#define SCU_PINMUX_CPLD_TCK (P6_1) /* GPIO3[ 0] */ +#define SCU_PINMUX_CPLD_TMS (P6_2) /* GPIO3[ 1] */ +#define SCU_PINMUX_CPLD_TDI (P6_5) /* GPIO3[ 4] */ + +/* CPLD SGPIO interface */ +#define SCU_PINMUX_SGPIO0 (P0_0) +#define SCU_PINMUX_SGPIO1 (P0_1) +#define SCU_PINMUX_SGPIO2 (P1_15) +#define SCU_PINMUX_SGPIO3 (P1_16) +#define SCU_PINMUX_SGPIO4 (P6_3) +#define SCU_PINMUX_SGPIO5 (P6_6) +#define SCU_PINMUX_SGPIO6 (P2_2) +#define SCU_PINMUX_SGPIO7 (P1_0) +#define SCU_PINMUX_SGPIO8 (P9_6) +#define SCU_PINMUX_SGPIO9 (P4_3) +#define SCU_PINMUX_SGPIO10 (P1_14) +#define SCU_PINMUX_SGPIO11 (P1_17) +#define SCU_PINMUX_SGPIO12 (P1_18) +#define SCU_PINMUX_SGPIO13 (P4_8) +#define SCU_PINMUX_SGPIO14 (P4_9) +#define SCU_PINMUX_SGPIO15 (P4_10) + /* MAX2837 GPIO (XCVR_CTL) PinMux */ #define SCU_XCVR_ENABLE (P4_6) /* GPIO2[6] on P4_6 */ #define SCU_XCVR_RXENABLE (P4_5) /* GPIO2[5] on P4_5 */ @@ -106,6 +131,16 @@ extern "C" #define PIN_BOOT2 (BIT7) /* GPIO5[7] on P2_8 */ #define PIN_BOOT3 (BIT10) /* GPIO1[10] on P2_9 */ +/* CPLD JTAG interface GPIO pins */ +#define PIN_CPLD_TDO (GPIOPIN18) +#define PORT_CPLD_TDO (GPIO5) +#define PIN_CPLD_TCK (GPIOPIN0) +#define PORT_CPLD_TCK (GPIO3) +#define PIN_CPLD_TMS (GPIOPIN1) +#define PORT_CPLD_TMS (GPIO3) +#define PIN_CPLD_TDI (GPIOPIN4) +#define PORT_CPLD_TDI (GPIO3) + /* Read GPIO Pin */ #define BOOT0_STATE ((GPIO0_PIN & PIN_BOOT0)==PIN_BOOT0) #define BOOT1_STATE ((GPIO0_PIN & PIN_BOOT1)==PIN_BOOT1) diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index eb91bee0..6708f748 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -133,7 +133,7 @@ void si5351c_configure_pll1_multisynth() void si5351c_configure_multisynth(const uint_fast8_t ms_number, const uint32_t p1, const uint32_t p2, const uint32_t p3, - const uint_fast8_t r) + const uint_fast8_t r_div) { /* * TODO: Check for p3 > 0? 0 has no meaning in fractional mode? @@ -152,7 +152,7 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number, register_number, (p3 >> 8) & 0xFF, (p3 >> 0) & 0xFF, - (r << 4) | (0 << 2) | ((p1 >> 16) & 0x3), + (r_div << 4) | (0 << 2) | ((p1 >> 16) & 0x3), (p1 >> 8) & 0xFF, (p1 >> 0) & 0xFF, (((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0), @@ -175,21 +175,21 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number, * MS1_INT=1 (integer mode) * MS1_SRC=0 (PLLA as source for MultiSynth 1) * CLK1_INV=0 (not inverted) - * CLK1_SRC=3 (MS0 as input source) + * CLK1_SRC=2 (MS0 as input source) * CLK1_IDRV=3 (8mA) * CLK2: * CLK2_PDN=0 (powered up) * MS2_INT=1 (integer mode) * MS2_SRC=0 (PLLA as source for MultiSynth 2) * CLK2_INV=0 (not inverted) - * CLK2_SRC=3 (MS0 as input source) + * CLK2_SRC=2 (MS0 as input source) * CLK2_IDRV=3 (8mA) * CLK3: * CLK3_PDN=0 (powered up) * MS3_INT=1 (integer mode) * MS3_SRC=0 (PLLA as source for MultiSynth 3) - * CLK3_INV=0 (not inverted) - * CLK3_SRC=3 (MS0 as input source) + * CLK3_INV=1 (inverted) + * CLK3_SRC=2 (MS0 as input source) * CLK3_IDRV=3 (8mA) * CLK4: * CLK4_PDN=0 (powered up) @@ -208,13 +208,13 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number, */ void si5351c_configure_clock_control() { - uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x0F, 0x4F, 0xC0, 0xC0 }; + uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x5B, 0x0F, 0x4F, 0xC0, 0xC0 }; si5351c_write(data, sizeof(data)); } -/* Enable CLK outputs 0, 1, 4, 5 only. */ +/* Enable CLK outputs 0, 1, 2, 3, 4, 5 only. */ void si5351c_enable_clock_outputs() { - uint8_t data[] = { 3, 0xCC }; + uint8_t data[] = { 3, 0xC0 }; si5351c_write(data, sizeof(data)); } diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 6ef76be4..729619af 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -41,7 +41,7 @@ void si5351c_configure_pll_sources_for_xtal(); void si5351c_configure_pll1_multisynth(); void si5351c_configure_multisynth(const uint_fast8_t ms_number, const uint32_t p1, const uint32_t p2, const uint32_t p3, - const uint_fast8_t r); + const uint_fast8_t r_div); void si5351c_configure_clock_control(); void si5351c_enable_clock_outputs(); diff --git a/firmware/sgpio/Makefile b/firmware/sgpio/Makefile new file mode 100644 index 00000000..7eefb0de --- /dev/null +++ b/firmware/sgpio/Makefile @@ -0,0 +1,9 @@ +# Hey Emacs, this is a -*- makefile -*- + +BINARY = sgpio + +SRC = $(BINARY).c \ + ../common/hackrf_core.c \ + ../common/si5351c.c + +include ../common/Makefile_inc.mk diff --git a/firmware/sgpio/README b/firmware/sgpio/README new file mode 100644 index 00000000..8c7856fc --- /dev/null +++ b/firmware/sgpio/README @@ -0,0 +1,2 @@ +A program to demonstrate TX control of the MAX5864 DAC, via the +SGPIO CPLD interface. \ No newline at end of file diff --git a/firmware/sgpio/sgpio.c b/firmware/sgpio/sgpio.c new file mode 100644 index 00000000..26552828 --- /dev/null +++ b/firmware/sgpio/sgpio.c @@ -0,0 +1,245 @@ +/* + * Copyright 2012 Michael Ossmann + * Copyright (C) 2012 Jared Boone + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +#include + +void pin_setup(void) { + /* Configure SCU Pin Mux as GPIO */ + scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_FAST); + scu_pinmux(SCU_PINMUX_LED2, SCU_GPIO_FAST); + scu_pinmux(SCU_PINMUX_LED3, SCU_GPIO_FAST); + + scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_FAST); + + /* Configure all GPIO as Input (safe state) */GPIO0_DIR = 0; + GPIO1_DIR = 0; + GPIO2_DIR = 0; + GPIO3_DIR = 0; + GPIO4_DIR = 0; + GPIO5_DIR = 0; + GPIO6_DIR = 0; + GPIO7_DIR = 0; + + /* Configure GPIO2[1/2/8] (P4_1/2 P6_12) as output. */GPIO2_DIR |= (PIN_LED1 + | PIN_LED2 | PIN_LED3); + + /* GPIO3[6] on P6_10 as output. */GPIO3_DIR |= PIN_EN1V8; + + /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ + scu_pinmux(SCU_SSP1_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(SCU_SSP1_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); + scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); +} + +void enable_1v8_power() { + gpio_set(PORT_EN1V8, PIN_EN1V8); +} + +void release_cpld_jtag_pins() { + scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4); + scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + + GPIO_CLR(PORT_CPLD_TDO) = PIN_CPLD_TDO; + GPIO_CLR(PORT_CPLD_TCK) = PIN_CPLD_TCK; + GPIO_CLR(PORT_CPLD_TMS) = PIN_CPLD_TMS; + GPIO_CLR(PORT_CPLD_TDI) = PIN_CPLD_TDI; +} + +void configure_sgpio_pin_functions() { + scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu_pinmux(SCU_PINMUX_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3); + scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu_pinmux(SCU_PINMUX_SGPIO3, SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu_pinmux(SCU_PINMUX_SGPIO4, SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu_pinmux(SCU_PINMUX_SGPIO5, SCU_GPIO_FAST | SCU_CONF_FUNCTION2); + scu_pinmux(SCU_PINMUX_SGPIO6, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_PINMUX_SGPIO7, SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu_pinmux(SCU_PINMUX_SGPIO8, SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu_pinmux(SCU_PINMUX_SGPIO9, SCU_GPIO_FAST | SCU_CONF_FUNCTION7); + scu_pinmux(SCU_PINMUX_SGPIO10, SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu_pinmux(SCU_PINMUX_SGPIO11, SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu_pinmux(SCU_PINMUX_SGPIO12, SCU_GPIO_FAST | SCU_CONF_FUNCTION6); + scu_pinmux(SCU_PINMUX_SGPIO13, SCU_GPIO_FAST | SCU_CONF_FUNCTION7); + scu_pinmux(SCU_PINMUX_SGPIO14, SCU_GPIO_FAST | SCU_CONF_FUNCTION7); + scu_pinmux(SCU_PINMUX_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION7); +} + +void test_sgpio_interface() { + const uint_fast8_t host_clock_sgpio_pin = 8; // Input + const uint_fast8_t host_capture_sgpio_pin = 9; // Input + const uint_fast8_t host_disable_sgpio_pin = 10; // Output + const uint_fast8_t host_direction_sgpio_pin = 11; // Output + + SGPIO_GPIO_OENREG = 0; // All inputs for the moment. + + // Disable all counters during configuration + SGPIO_CTRL_ENABLE = 0; + + configure_sgpio_pin_functions(); + + // Make all SGPIO controlled by SGPIO's "GPIO" registers + for (uint_fast8_t i = 0; i < 16; i++) { + SGPIO_OUT_MUX_CFG(i) = (0L << 4) | (4L << 0); + } + + // Set SGPIO output values. + SGPIO_GPIO_OUTREG = (1L << host_direction_sgpio_pin) + | (1L << host_disable_sgpio_pin); + + // Enable SGPIO pin outputs. + SGPIO_GPIO_OENREG = (1L << host_direction_sgpio_pin) + | (1L << host_disable_sgpio_pin) | (0L << host_capture_sgpio_pin) + | (0L << host_clock_sgpio_pin) | (0xFF << 0); + + // Configure SGPIO slices. + + // Enable codec data stream. + SGPIO_GPIO_OUTREG &= ~(1L << host_disable_sgpio_pin); + + while (1) { + for (uint_fast8_t i = 0; i < 8; i++) { + SGPIO_GPIO_OUTREG ^= (1L << i); + } + } +} + +void configure_sgpio() { + // Disable all counters during configuration + SGPIO_CTRL_ENABLE = 0; + + configure_sgpio_pin_functions(); + + // Set SGPIO output values. + SGPIO_GPIO_OUTREG = + (1L << 11) | // direction + (1L << 10); // disable + + // Enable SGPIO pin outputs. + SGPIO_GPIO_OENREG = + (1L << 11) | // direction + (1L << 10) | // disable + 0xFF; + + SGPIO_OUT_MUX_CFG( 8) = 0; // SGPIO: Input: clock + SGPIO_OUT_MUX_CFG( 9) = 0; // SGPIO: Input: qualifier + SGPIO_OUT_MUX_CFG(10) = (0L << 4) | (4L << 0); // GPIO: Output: disable + SGPIO_OUT_MUX_CFG(11) = (0L << 4) | (4L << 0); // GPIO: Output: direction + + for(uint_fast8_t i=0; i<8; i++) { + // SGPIO pin 0 outputs slice A bit "i". + SGPIO_OUT_MUX_CFG(i) = + (0L << 4) | // P_OE_CFG = 0 + (9L << 0); // P_OUT_CFG = 9, dout_doutm8a (8-bit mode 8a) + } + + // Slice A + SGPIO_MUX_CFG(SGPIO_SLICE_A) = + (0L << 12) | // CONCAT_ORDER = 0 (self-loop) + (1L << 11) | // CONCAT_ENABLE = 1 (concatenate data) + (0L << 9) | // QUALIFIER_SLICE_MODE = X + (1L << 7) | // QUALIFIER_PIN_MODE = 1 (SGPIO9) + (3L << 5) | // QUALIFIER_MODE = 3 (external SGPIO pin) + (0L << 3) | // CLK_SOURCE_SLICE_MODE = X + (0L << 1) | // CLK_SOURCE_PIN_MODE = 0 (SGPIO8) + (1L << 0); // EXT_CLK_ENABLE = 1, external clock signal (slice) + + SGPIO_SLICE_MUX_CFG(SGPIO_SLICE_A) = + (0L << 8) | // INV_QUALIFIER = 0 (use normal qualifier) + (3L << 6) | // PARALLEL_MODE = 3 (shift 8 bits per clock) + (0L << 4) | // DATA_CAPTURE_MODE = 0 (detect rising edge) + (0L << 3) | // INV_OUT_CLK = 0 (normal clock) + (1L << 2) | // CLKGEN_MODE = 1 (use external pin clock) + (0L << 1) | // CLK_CAPTURE_MODE = 0 (use rising clock edge) + (0L << 0); // MATCH_MODE = 0 (do not match data) + + SGPIO_PRESET(SGPIO_SLICE_A) = 0; + SGPIO_COUNT(SGPIO_SLICE_A) = 0; + SGPIO_POS(SGPIO_SLICE_A) = (0x3L << 8) | (0x3L << 0); + SGPIO_REG(SGPIO_SLICE_A) = 0xFF00FF00; // Primary output data register + SGPIO_REG_SS(SGPIO_SLICE_A) = 0xFF00FF00; // Shadow output data register + /* + // Slice D (clock for Slice A) + LPC_SGPIO->SGPIO_MUX_CFG[3] = + (0L << 12) | // CONCAT_ORDER = 0 (self-loop) + (1L << 11) | // CONCAT_ENABLE = 1 (concatenate data) + (0L << 9) | // QUALIFIER_SLICE_MODE = X + (0L << 7) | // QUALIFIER_PIN_MODE = X + (0L << 5) | // QUALIFIER_MODE = 0 (enable) + (0L << 3) | // CLK_SOURCE_SLICE_MODE = 0, slice D + (0L << 1) | // CLK_SOURCE_PIN_MODE = X + (0L << 0); // EXT_CLK_ENABLE = 0, internal clock signal (slice) + + LPC_SGPIO->SLICE_MUX_CFG[3] = + (0L << 8) | // INV_QUALIFIER = 0 (use normal qualifier) + (0L << 6) | // PARALLEL_MODE = 0 (shift 1 bit per clock) + (0L << 4) | // DATA_CAPTURE_MODE = 0 (detect rising edge) + (0L << 3) | // INV_OUT_CLK = 0 (normal clock) + (0L << 2) | // CLKGEN_MODE = 0 (use clock from COUNTER) + (0L << 1) | // CLK_CAPTURE_MODE = 0 (use rising clock edge) + (0L << 0); // MATCH_MODE = 0 (do not match data) + + LPC_SGPIO->PRESET[3] = 0; + LPC_SGPIO->COUNT[3] = 0; + LPC_SGPIO->POS[3] = (0x1FL << 8) | (0x1FL << 0); + LPC_SGPIO->REG[0] = 0xAAAAAAAA; // Primary output data register + LPC_SGPIO->REG_SS[0] = 0xAAAAAAAA; // Shadow output data register + */ + // Start SGPIO operation by enabling slice clocks. + SGPIO_CTRL_ENABLE = + (1L << 0) // Slice A + ; + + // Enable codec data stream. + SGPIO_GPIO_OUTREG &= ~(1L << 10); +} + +int main(void) { + pin_setup(); + enable_1v8_power(); + cpu_clock_init(); + + CGU_BASE_PERIPH_CLK = (CGU_BASE_CLK_AUTOBLOCK + | (CGU_SRC_PLL1 << CGU_BASE_CLK_SEL_SHIFT)); + + CGU_BASE_APB1_CLK = (CGU_BASE_CLK_AUTOBLOCK + | (CGU_SRC_PLL1 << CGU_BASE_CLK_SEL_SHIFT)); + + gpio_set(PORT_LED1_3, (PIN_LED1 | PIN_LED2 | PIN_LED3)); /* LEDs on */ + + //test_sgpio_interface(); + configure_sgpio(); + + while (1) { + + } + + return 0; +}