Updated HackRF firmware
This commit is contained in:
@ -0,0 +1,236 @@
|
||||
#include "max2871.h"
|
||||
#include "max2871_regs.h"
|
||||
|
||||
#if (defined DEBUG)
|
||||
#include <stdio.h>
|
||||
#define LOG printf
|
||||
#else
|
||||
#define LOG(x,...)
|
||||
#include <libopencm3/lpc43xx/ssp.h>
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include "hackrf_core.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v);
|
||||
static void max2871_write_registers(max2871_driver_t* const drv);
|
||||
static void delay_ms(int ms);
|
||||
|
||||
void max2871_setup(max2871_driver_t* const drv)
|
||||
{
|
||||
/* Configure GPIO pins. */
|
||||
scu_pinmux(SCU_VCO_CE, SCU_GPIO_FAST);
|
||||
scu_pinmux(SCU_VCO_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
/* Only used for the debug pin config: scu_pinmux(SCU_VCO_SCLK, SCU_GPIO_FAST); */
|
||||
scu_pinmux(SCU_VCO_SDATA, SCU_GPIO_FAST);
|
||||
scu_pinmux(SCU_VCO_LE, SCU_GPIO_FAST);
|
||||
scu_pinmux(SCU_VCO_MUX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
scu_pinmux(SCU_SYNT_RFOUT_EN, SCU_GPIO_FAST);
|
||||
|
||||
/* Set GPIO pins as outputs. */
|
||||
gpio_output(drv->gpio_vco_ce);
|
||||
gpio_output(drv->gpio_vco_sclk);
|
||||
gpio_output(drv->gpio_vco_sdata);
|
||||
gpio_output(drv->gpio_vco_le);
|
||||
gpio_output(drv->gpio_synt_rfout_en);
|
||||
|
||||
/* MUX is an input */
|
||||
gpio_input(drv->gpio_vco_mux);
|
||||
|
||||
/* set to known state */
|
||||
gpio_set(drv->gpio_vco_ce); /* active high */
|
||||
gpio_clear(drv->gpio_vco_sclk);
|
||||
gpio_clear(drv->gpio_vco_sdata);
|
||||
gpio_set(drv->gpio_vco_le); /* active low */
|
||||
gpio_set(drv->gpio_synt_rfout_en); /* active high */
|
||||
|
||||
max2871_regs_init();
|
||||
int i;
|
||||
for(i = 5; i >= 0; i--) {
|
||||
max2871_spi_write(drv, i, max2871_get_register(i));
|
||||
delay_ms(20);
|
||||
}
|
||||
|
||||
max2871_set_INT(1);
|
||||
max2871_set_N(4500);
|
||||
max2871_set_FRAC(0);
|
||||
max2871_set_CPL(0);
|
||||
max2871_set_CPT(0);
|
||||
max2871_set_P(1);
|
||||
max2871_set_M(0);
|
||||
max2871_set_LDS(0);
|
||||
max2871_set_SDN(0);
|
||||
max2871_set_MUX(0x0C); /* Register 6 readback */
|
||||
max2871_set_DBR(0);
|
||||
max2871_set_RDIV2(0);
|
||||
max2871_set_R(1); /* 40 MHz f_PFD */
|
||||
max2871_set_REG4DB(1);
|
||||
max2871_set_CP(15); /* ?: CP charge pump current 0-15 */
|
||||
max2871_set_LDF(1); /* INT-N */
|
||||
max2871_set_LDP(0); /* ?: Lock-Detect Precision */
|
||||
max2871_set_PDP(1);
|
||||
max2871_set_SHDN(0);
|
||||
max2871_set_TRI(0);
|
||||
max2871_set_RST(0);
|
||||
max2871_set_VCO(0);
|
||||
max2871_set_VAS_SHDN(0);
|
||||
max2871_set_VAS_TEMP(1);
|
||||
max2871_set_CSM(0);
|
||||
max2871_set_MUTEDEL(1);
|
||||
max2871_set_CDM(0);
|
||||
max2871_set_CDIV(0);
|
||||
max2871_set_SDLDO(0);
|
||||
max2871_set_SDDIV(0);
|
||||
max2871_set_SDREF(0);
|
||||
max2871_set_BS(20*40); /* For 40 MHz f_PFD */
|
||||
max2871_set_FB(1); /* Do not put DIVA into the feedback loop */
|
||||
max2871_set_DIVA(0);
|
||||
max2871_set_SDVCO(0);
|
||||
max2871_set_MTLD(1);
|
||||
max2871_set_BDIV(0);
|
||||
max2871_set_RFB_EN(0);
|
||||
max2871_set_BPWR(0);
|
||||
max2871_set_RFA_EN(0);
|
||||
max2871_set_APWR(3);
|
||||
max2871_set_SDPLL(0);
|
||||
max2871_set_F01(1);
|
||||
max2871_set_LD(1);
|
||||
max2871_set_ADCS(0);
|
||||
max2871_set_ADCM(0);
|
||||
|
||||
max2871_write_registers(drv);
|
||||
|
||||
max2871_set_frequency(drv, 3500);
|
||||
}
|
||||
|
||||
static void delay_ms(int ms)
|
||||
{
|
||||
uint32_t i;
|
||||
while(ms--) {
|
||||
for (i = 0; i < 20000; i++) {
|
||||
__asm__("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void serial_delay(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
__asm__("nop");
|
||||
}
|
||||
|
||||
|
||||
/* SPI register write
|
||||
*
|
||||
* Send 32 bits:
|
||||
* First 29 bits are data
|
||||
* Last 3 bits are register number */
|
||||
static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v) {
|
||||
#if DEBUG
|
||||
LOG("0x%04x -> reg%d\n", v, r);
|
||||
#else
|
||||
|
||||
uint32_t bits = 32;
|
||||
uint32_t msb = 1 << (bits -1);
|
||||
uint32_t data = v | r;
|
||||
|
||||
/* make sure everything is starting in the correct state */
|
||||
gpio_set(drv->gpio_vco_le);
|
||||
gpio_clear(drv->gpio_vco_sclk);
|
||||
gpio_clear(drv->gpio_vco_sdata);
|
||||
|
||||
/* start transaction by bringing LE low */
|
||||
gpio_clear(drv->gpio_vco_le);
|
||||
|
||||
while (bits--) {
|
||||
if (data & msb)
|
||||
gpio_set(drv->gpio_vco_sdata);
|
||||
else
|
||||
gpio_clear(drv->gpio_vco_sdata);
|
||||
data <<= 1;
|
||||
|
||||
serial_delay();
|
||||
gpio_set(drv->gpio_vco_sclk);
|
||||
|
||||
serial_delay();
|
||||
gpio_clear(drv->gpio_vco_sclk);
|
||||
}
|
||||
|
||||
gpio_set(drv->gpio_vco_le);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t max2871_spi_read(max2871_driver_t* const drv)
|
||||
{
|
||||
uint32_t bits = 32;
|
||||
uint32_t data = 0;
|
||||
|
||||
max2871_spi_write(drv, 0x06, 0x0);
|
||||
|
||||
serial_delay();
|
||||
gpio_set(drv->gpio_vco_sclk);
|
||||
serial_delay();
|
||||
gpio_clear(drv->gpio_vco_sclk);
|
||||
serial_delay();
|
||||
|
||||
while (bits--) {
|
||||
gpio_set(drv->gpio_vco_sclk);
|
||||
serial_delay();
|
||||
|
||||
gpio_clear(drv->gpio_vco_sclk);
|
||||
serial_delay();
|
||||
|
||||
data <<= 1;
|
||||
data |= gpio_read(drv->gpio_vco_mux) ? 1 : 0;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static void max2871_write_registers(max2871_driver_t* const drv)
|
||||
{
|
||||
int i;
|
||||
for(i = 5; i >= 0; i--) {
|
||||
max2871_spi_write(drv, i, max2871_get_register(i));
|
||||
}
|
||||
}
|
||||
|
||||
/* Set frequency (MHz). */
|
||||
uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz)
|
||||
{
|
||||
int n = mhz / 40;
|
||||
int diva = 0;
|
||||
|
||||
while(n * 40 < 3000) {
|
||||
n *= 2;
|
||||
diva += 1;
|
||||
}
|
||||
|
||||
max2871_set_RFA_EN(0);
|
||||
max2871_write_registers(drv);
|
||||
|
||||
max2871_set_N(n);
|
||||
max2871_set_DIVA(diva);
|
||||
max2871_write_registers(drv);
|
||||
|
||||
while(max2871_spi_read(drv) & MAX2871_VASA);
|
||||
|
||||
max2871_set_RFA_EN(1);
|
||||
max2871_write_registers(drv);
|
||||
|
||||
return (mhz/40)*40 * 1000000;
|
||||
}
|
||||
|
||||
void max2871_enable(max2871_driver_t* const drv)
|
||||
{
|
||||
gpio_set(drv->gpio_vco_ce);
|
||||
}
|
||||
void max2871_disable(max2871_driver_t* const drv)
|
||||
{
|
||||
gpio_clear(drv->gpio_vco_ce);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user