diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 05f86627..9cb6ec63 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -28,8 +28,6 @@ #include #include -#ifdef JELLYBEAN - void delay(uint32_t duration) { uint32_t i; @@ -51,6 +49,19 @@ void cpu_clock_init(void) si5351c_configure_pll_sources_for_xtal(); si5351c_configure_pll1_multisynth(); +#ifdef JELLYBEAN + /* + * Jellybean/Lemondrop clocks: + * CLK0 -> MAX2837 + * CLK1 -> MAX5864/CPLD + * CLK2 -> CPLD + * CLK3 -> CPLD + * CLK4 -> LPC4330 + * CLK5 -> RFFC5072 + * CLK6 -> extra + * CLK7 -> extra + */ + /* MS0/CLK0 is the source for the MAX2837 clock input. */ si5351c_configure_multisynth(0, 2048, 0, 1, 0); /* 40MHz */ @@ -68,6 +79,42 @@ void cpu_clock_init(void) /* MS5/CLK5 is the source for the RFFC5071 mixer. */ si5351c_configure_multisynth(5, 1536, 0, 1, 0); /* 50MHz */ +#endif + +#ifdef JAWBREAKER + /* + * Jawbreaker clocks: + * CLK0 -> MAX5864/CPLD + * CLK1 -> CPLD + * CLK2 -> SGPIO + * CLK3 -> external clock output + * CLK4 -> RFFC5072 + * CLK5 -> MAX2837 + * CLK6 -> none + * CLK7 -> LPC4330 (but LPC4330 starts up on its own crystal) + */ + + /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ + si5351c_configure_multisynth(0, 4608, 0, 1, 1); /* 10MHz */ + + /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ + si5351c_configure_multisynth(1, 4608, 0, 1, 0); /* 20MHz */ + + /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ + si5351c_configure_multisynth(2, 4608, 0, 1, 0); /* 20MHz */ + + /* MS0/CLK3 is the source for the external clock output. */ + si5351c_configure_multisynth(3, 4608, 0, 1, 0); /* 20MHz */ + + /* MS4/CLK4 is the source for the RFFC5071 mixer. */ + si5351c_configure_multisynth(4, 1536, 0, 1, 0); /* 50MHz */ + + /* MS5/CLK5 is the source for the MAX2837 clock input. */ + si5351c_configure_multisynth(5, 2048, 0, 1, 0); /* 40MHz */ + + /* MS7/CLK7 is the source for the LPC43xx microcontroller. */ + //si5351c_configure_multisynth(7, 8021, 0, 3, 0); /* 12MHz */ +#endif si5351c_configure_clock_control(); si5351c_enable_clock_outputs(); @@ -203,5 +250,3 @@ void ssp1_set_mode_max5864(void) SSP_MASTER, SSP_SLAVE_OUT_ENABLE); } - -#endif diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 8121ff71..6ba54ab0 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -30,15 +30,19 @@ extern "C" #endif /* hardware identification number */ -#define BOARD_ID_JELLYBEAN 0 +#define BOARD_ID_JELLYBEAN 0 +#define BOARD_ID_JAWBREAKER 1 #ifdef JELLYBEAN #define BOARD_ID BOARD_ID_JELLYBEAN #endif -#ifdef JELLYBEAN +#ifdef JAWBREAKER +#define BOARD_ID BOARD_ID_JAWBREAKER +#endif + /* - * Jellybean SCU PinMux + * SCU PinMux */ /* GPIO Output PinMux */ @@ -94,14 +98,28 @@ extern "C" #define SCU_AD_CS (P5_7) /* GPIO2[7] on P5_7 */ /* RFFC5071 GPIO serial interface PinMux */ +#ifdef JELLYBEAN #define SCU_MIXER_ENX (P7_0) /* GPIO3[8] on P7_0 */ #define SCU_MIXER_SCLK (P7_1) /* GPIO3[9] on P7_1 */ #define SCU_MIXER_SDATA (P7_2) /* GPIO3[10] on P7_2 */ +#define SCU_MIXER_RESETX (P7_3) /* GPIO3[11] on P7_3 */ +#endif +#ifdef JAWBREAKER +#define SCU_MIXER_ENX (P5_4) /* GPIO2[13] on P5_4 */ +#define SCU_MIXER_SCLK (P2_6) /* GPIO5[6] on P2_6 */ +#define SCU_MIXER_SDATA (P6_4) /* GPIO3[3] on P6_4 */ +#define SCU_MIXER_RESETX (P5_5) /* GPIO2[14] on P5_5 */ +#endif + +/* RF LDO control */ +#ifdef JAWBREAKER +#define RF_LDO_ENABLE (P5_0) /* GPIO2[9] on P5_0 */ +#endif /* TODO add other Pins */ /* - * Jellybean GPIO Pins + * GPIO Pins */ /* GPIO Output */ @@ -123,10 +141,31 @@ extern "C" #define PIN_AD_CS (BIT7) /* GPIO2[7] on P5_7 */ #define PORT_AD_CS (GPIO2) /* PORT for AD_CS */ -#define PIN_MIXER_ENX (BIT8) /* GPIO3[8] on P7_0 */ -#define PIN_MIXER_SCLK (BIT9) /* GPIO3[9] on P7_1 */ -#define PIN_MIXER_SDATA (BIT10) /* GPIO3[10] on P7_2 */ -#define PORT_MIXER (GPIO3) /* PORT for mixer serial interface */ +#ifdef JELLYBEAN +#define PIN_MIXER_ENX (BIT8) /* GPIO3[8] on P7_0 */ +#define PORT_MIXER_ENX (GPIO3) +#define PIN_MIXER_SCLK (BIT9) /* GPIO3[9] on P7_1 */ +#define PORT_MIXER_SCLK (GPIO3) +#define PIN_MIXER_SDATA (BIT10) /* GPIO3[10] on P7_2 */ +#define PORT_MIXER_SDATA (GPIO3) +#define PIN_MIXER_RESETX (BIT11) /* GPIO3[11] on P7_3 */ +#define PORT_MIXER_RESETX (GPIO3) +#endif +#ifdef JAWBREAKER +#define PIN_MIXER_ENX (BIT13) /* GPIO2[13] on P5_4 */ +#define PORT_MIXER_ENX (GPIO2) +#define PIN_MIXER_SCLK (BIT6) /* GPIO5[6] on P2_6 */ +#define PORT_MIXER_SCLK (GPIO5) +#define PIN_MIXER_SDATA (BIT3) /* GPIO3[3] on P6_4 */ +#define PORT_MIXER_SDATA (GPIO3) +#define PIN_MIXER_RESETX (BIT14) /* GPIO2[14] on P5_5 */ +#define PORT_MIXER_RESETX (GPIO2) +#endif + +#ifdef JAWBREAKER +#define PIN_RF_LDO_ENABLE (BIT9) /* GPIO2[9] on P5_0 */ +#define PORT_RF_LDO_ENABLE (GPIO2) /* PORT for RF_LDO_ENABLE */ +#endif /* GPIO Input */ #define PIN_BOOT0 (BIT8) /* GPIO0[8] on P1_1 */ @@ -145,14 +184,14 @@ extern "C" #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) -#define BOOT2_STATE ((GPIO5_PIN & PIN_BOOT2)==PIN_BOOT2) -#define BOOT3_STATE ((GPIO1_PIN & PIN_BOOT3)==PIN_BOOT3) -#define MIXER_SDATA_STATE ((GPIO3_PIN & PIN_MIXER_SDATA)==PIN_MIXER_SDATA) +#define GPIO_STATE(port, pin) ((GPIO_PIN(port) & (pin)) == (pin)) +#define BOOT0_STATE GPIO_STATE(GPIO0, PIN_BOOT0) +#define BOOT1_STATE GPIO_STATE(GPIO0, PIN_BOOT1) +#define BOOT2_STATE GPIO_STATE(GPIO5, PIN_BOOT2) +#define BOOT3_STATE GPIO_STATE(GPIO1, PIN_BOOT3) +#define MIXER_SDATA_STATE GPIO_STATE(PORT_MIXER_SDATA, PIN_MIXER_SDATA) /* TODO add other Pins */ -#endif void cpu_clock_init(void); void ssp1_init(void); diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 3bc678bf..c0e2cd80 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -103,13 +103,19 @@ void rffc5071_setup(void) scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST); scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST); + scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST); /* Set GPIO pins as outputs. */ - GPIO3_DIR |= (PIN_MIXER_ENX | PIN_MIXER_SCLK | PIN_MIXER_SDATA); + GPIO_DIR(PORT_MIXER_ENX) |= PIN_MIXER_ENX; + GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK; + GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; + GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX; /* set to known state */ - gpio_set(PORT_MIXER, PIN_MIXER_ENX); /* active low */ - gpio_clear(PORT_MIXER, (PIN_MIXER_SCLK | PIN_MIXER_SDATA)); + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); /* active low */ + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ #endif /* initial setup */ @@ -185,69 +191,70 @@ uint16_t rffc5071_spi_read(uint8_t r) { return 0; #else /* make sure everything is starting in the correct state */ - gpio_set(PORT_MIXER, PIN_MIXER_ENX); - gpio_clear(PORT_MIXER, (PIN_MIXER_SCLK | PIN_MIXER_SDATA)); + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); /* * The device requires two clocks while ENX is high before a serial * transaction. This is not clearly documented. */ serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_SCLK); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_clear(PORT_MIXER, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_SCLK); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_clear(PORT_MIXER, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); /* start transaction by bringing ENX low */ - gpio_clear(PORT_MIXER, PIN_MIXER_ENX); + gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); while (bits--) { if (data & msb) - gpio_set(PORT_MIXER, PIN_MIXER_SDATA); + gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); else - gpio_clear(PORT_MIXER, PIN_MIXER_SDATA); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); data <<= 1; serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_SCLK); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_clear(PORT_MIXER, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); } serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_SCLK); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_clear(PORT_MIXER, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); bits = 16; data = 0; /* set SDATA line as input */ - GPIO3_DIR &= ~PIN_MIXER_SDATA; + GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA; while (bits--) { data <<= 1; serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_SCLK); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_clear(PORT_MIXER, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); if (MIXER_SDATA_STATE) data |= 1; } /* set SDATA line as output */ - GPIO3_DIR |= PIN_MIXER_SDATA; + GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_ENX); + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); return data; #endif /* DEBUG */ @@ -272,44 +279,45 @@ void rffc5071_spi_write(uint8_t r, uint16_t v) { uint32_t data = ((r & 0x7f) << 16) | v; /* make sure everything is starting in the correct state */ - gpio_set(PORT_MIXER, PIN_MIXER_ENX); - gpio_clear(PORT_MIXER, (PIN_MIXER_SCLK | PIN_MIXER_SDATA)); + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); /* * The device requires two clocks while ENX is high before a serial * transaction. This is not clearly documented. */ serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_SCLK); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_clear(PORT_MIXER, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_SCLK); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_clear(PORT_MIXER, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); /* start transaction by bringing ENX low */ - gpio_clear(PORT_MIXER, PIN_MIXER_ENX); + gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); while (bits--) { if (data & msb) - gpio_set(PORT_MIXER, PIN_MIXER_SDATA); + gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); else - gpio_clear(PORT_MIXER, PIN_MIXER_SDATA); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); data <<= 1; serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_SCLK); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); serial_delay(); - gpio_clear(PORT_MIXER, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); } serial_delay(); - gpio_set(PORT_MIXER, PIN_MIXER_ENX); + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); #endif } diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 5d7adf06..fa506150 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -161,6 +161,7 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number, si5351c_write(data, sizeof(data)); } +#ifdef JELLYBEAN /* * Registers 16 through 23: CLKx Control * CLK0: @@ -211,6 +212,66 @@ void si5351c_configure_clock_control() uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x0F, 0x4F, 0xC0, 0xC0 }; si5351c_write(data, sizeof(data)); } +#endif + +#ifdef JAWBREAKER +/* + * Registers 16 through 23: CLKx Control + * CLK0: + * CLK0_PDN=0 (powered up) + * MS0_INT=1 (integer mode) + * MS0_SRC=0 (PLLA as source for MultiSynth 0) + * CLK0_INV=0 (not inverted) + * CLK0_SRC=3 (MS0 as input source) + * CLK0_IDRV=3 (8mA) + * CLK1: + * CLK1_PDN=0 (powered up) + * MS1_INT=1 (integer mode) + * MS1_SRC=0 (PLLA as source for MultiSynth 1) + * CLK1_INV=0 (not inverted) + * 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=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 (inverted) + * CLK3_SRC=2 (MS0 as input source) + * CLK3_IDRV=3 (8mA) + * CLK4: + * CLK4_PDN=0 (powered up) + * MS4_INT=1 (integer mode) + * MS4_SRC=0 (PLLA as source for MultiSynth 4) + * CLK4_INV=0 (not inverted) + * CLK4_SRC=3 (MS4 as input source) + * CLK4_IDRV=3 (8mA) + * CLK5: + * CLK5_PDN=0 (powered up) + * MS5_INT=1 (integer mode) + * MS5_SRC=0 (PLLA as source for MultiSynth 5) + * CLK5_INV=0 (not inverted) + * CLK5_SRC=3 (MS5 as input source) + * CLK5_IDRV=3 (8mA) + * CLK6: (not connected) + * CLK5_PDN=1 (powered down) + * MS5_INT=1 (integer mode) + * CLK7: (not connected) + * CLK7_PDN=1 (powered down) + * MS7_INT=0 (fractional mode -- to support 12MHz to LPC) + */ +void si5351c_configure_clock_control() +{ + uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x4F, 0x4F, 0xC0, 0x80 }; + si5351c_write(data, sizeof(data)); +} +#endif /* Enable CLK outputs 0, 1, 2, 3, 4, 5 only. */ void si5351c_enable_clock_outputs()