Merge pull request #66 from Hoernchen/siclock

si clock for the lpc
This commit is contained in:
Michael Ossmann
2013-06-05 09:14:40 -07:00
6 changed files with 159 additions and 126 deletions

View File

@ -88,26 +88,26 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
#ifdef JAWBREAKER #ifdef JAWBREAKER
uint32_t p1 = 4608; uint32_t p1 = 4608;
switch(sample_rate_hz) { switch(sample_rate_hz) {
case 5000000: case 8000000:
p1 = 9728; // 800MHz / 80 = 10 MHz (SGPIO), 5 MHz (codec) p1 = SI_INTDIV(50); // 800MHz / 50 = 16 MHz (SGPIO), 8 MHz (codec)
break;
case 10000000:
p1 = 4608; // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec)
break;
case 12500000:
p1 = 3584; // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec)
break;
case 16000000:
p1 = 2688; // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec)
break;
case 20000000:
p1 = 2048; // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec)
break; break;
case 10000000:
p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec)
break;
case 12500000:
p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec)
break;
case 16000000:
p1 = SI_INTDIV(25); // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec)
break;
case 20000000:
p1 = SI_INTDIV(20); // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec)
break;
default: default:
return false; return false;
@ -117,13 +117,13 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
si5351c_configure_multisynth(0, p1, 0, 1, 1); si5351c_configure_multisynth(0, p1, 0, 1, 1);
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
si5351c_configure_multisynth(1, p1, 0, 1, 0); si5351c_configure_multisynth(1, p1, 0, 1, 0);//p1 doesn't matter
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(2, p1, 0, 1, 0); si5351c_configure_multisynth(2, p1, 0, 1, 0);//p1 doesn't matter
/* MS0/CLK3 is the source for the external clock output. */ /* MS0/CLK3 is the source for the external clock output. */
si5351c_configure_multisynth(3, p1, 0, 1, 0); //si5351c_configure_multisynth(3, p1, 0, 1, 0); // no clk out
return true; return true;
#endif #endif
@ -186,19 +186,23 @@ void cpu_clock_init(void)
*/ */
/* MS4/CLK4 is the source for the RFFC5071 mixer. */ /* MS4/CLK4 is the source for the RFFC5071 mixer. */
si5351c_configure_multisynth(4, 1536, 0, 1, 0); /* 50MHz */ si5351c_configure_multisynth(4, 16*128-512, 0, 1, 0); /* 800/16 = 50MHz */
/* MS5/CLK5 is the source for the MAX2837 clock input. */ /* MS5/CLK5 is the source for the MAX2837 clock input. */
si5351c_configure_multisynth(5, 2048, 0, 1, 0); /* 40MHz */ si5351c_configure_multisynth(5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */
/* MS7/CLK7 is the source for the LPC43xx microcontroller. */ /* MS7/CLK7 is the source for the LPC43xx microcontroller. */
//si5351c_configure_multisynth(7, 8021, 0, 3, 0); /* 12MHz */ //uint8_t ms7data[] = { 91, 40, 0x0 };
//si5351c_write(ms7data, sizeof(ms7data));
#endif #endif
/* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */ /* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */
sample_rate_set(10000000); sample_rate_set(10000000);
si5351c_configure_clock_control(); si5351c_configure_clock_control();
// soft reset
uint8_t resetdata[] = { 177, 0xac };
si5351c_write(resetdata, sizeof(resetdata));
si5351c_enable_clock_outputs(); si5351c_enable_clock_outputs();
//FIXME disable I2C //FIXME disable I2C
@ -405,6 +409,9 @@ void pin_setup(void) {
scu_pinmux(SCU_SSP1_MOSI, (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_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
/* Configure external clock in */
//scu_pinmux(P4_7, SCU_CLK_IN | SCU_CONF_FUNCTION1);
} }
void enable_1v8_power(void) { void enable_1v8_power(void) {

View File

@ -87,7 +87,16 @@ void si5351c_disable_oeb_pin_control()
/* Power down all CLKx */ /* Power down all CLKx */
void si5351c_power_down_all_clocks() void si5351c_power_down_all_clocks()
{ {
uint8_t data[] = { 16, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0 }; uint8_t data[] = { 16
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
};
si5351c_write(data, sizeof(data)); si5351c_write(data, sizeof(data));
} }
@ -127,8 +136,11 @@ void si5351c_configure_pll_sources_for_xtal()
/* MultiSynth NA (PLL1) */ /* MultiSynth NA (PLL1) */
void si5351c_configure_pll1_multisynth() void si5351c_configure_pll1_multisynth()
{ {
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 }; //init plla and pllb to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode
si5351c_write(data, sizeof(data)); uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };
si5351c_write(data, sizeof(data));
//~ data[0] =34;// pllb
//~ si5351c_write(data, sizeof(data));
} }
void si5351c_configure_multisynth(const uint_fast8_t ms_number, void si5351c_configure_multisynth(const uint_fast8_t ms_number,
@ -215,67 +227,25 @@ void si5351c_configure_clock_control()
#endif #endif
#ifdef JAWBREAKER #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() void si5351c_configure_clock_control()
{ {
uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x4F, 0x4F, 0xC0, 0x80 }; uint8_t data[] = {16
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
,SI5351C_CLK_POWERDOWN /*not connected, clock out*/
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
,SI5351C_CLK_POWERDOWN/* pllb int mode*/| SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
};
si5351c_write(data, sizeof(data)); si5351c_write(data, sizeof(data));
} }
#endif #endif
/* Enable CLK outputs 0, 1, 2, 3, 4, 5 only. */ /* Enable CLK outputs 0, 1, 2, 4, 5, 7 only. */
void si5351c_enable_clock_outputs() void si5351c_enable_clock_outputs()
{ {
uint8_t data[] = { 3, 0xC0 }; uint8_t data[] = { 3, 0xC8 };
si5351c_write(data, sizeof(data)); si5351c_write(data, sizeof(data));
} }

View File

@ -30,8 +30,30 @@ extern "C"
#include <stdint.h> #include <stdint.h>
#define SI_INTDIV(x) (x*128-512)
#define SI5351C_I2C_ADDR (0x60 << 1) #define SI5351C_I2C_ADDR (0x60 << 1)
#define SI5351C_CLK_POWERDOWN (1<<7)
#define SI5351C_CLK_INT_MODE (1<<6)
#define SI5351C_CLK_PLL_SRC(x) (x<<5)
#define SI5351C_CLK_PLL_SRC_A 0
#define SI5351C_CLK_PLL_SRC_B 1
#define SI5351C_CLK_INV (1<<4)
#define SI5351C_CLK_SRC(x) (x<<2)
#define SI5351C_CLK_SRC_XTAL 0
#define SI5351C_CLK_SRC_CLKIN 1
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
#define SI5351C_CLK_IDRV(x) (x<<0)
#define SI5351C_CLK_IDRV_2MA 0
#define SI5351C_CLK_IDRV_4MA 1
#define SI5351C_CLK_IDRV_6MA 2
#define SI5351C_CLK_IDRV_8MA 3
void si5351c_disable_all_outputs(); void si5351c_disable_all_outputs();
void si5351c_disable_oeb_pin_control(); void si5351c_disable_oeb_pin_control();
void si5351c_power_down_all_clocks(); void si5351c_power_down_all_clocks();

View File

@ -107,40 +107,56 @@ int dump_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number)
uint_fast8_t reg_base; uint_fast8_t reg_base;
uint16_t parameters[8]; uint16_t parameters[8];
uint32_t p1,p2,p3,r_div; uint32_t p1,p2,p3,r_div;
uint_fast8_t div_lut[] = {1,2,4,8,16,32,64,128};
reg_base = 42 + (ms_number * 8); printf("MS%d:", ms_number);
for(i=0; i<8; i++) { if(ms_number <6){
uint_fast8_t reg_number = reg_base + i; reg_base = 42 + (ms_number * 8);
int result = hackrf_si5351c_read(device, reg_number, &parameters[i]); for(i=0; i<8; i++) {
if( result != HACKRF_SUCCESS ) { uint_fast8_t reg_number = reg_base + i;
return result; int result = hackrf_si5351c_read(device, reg_number, &parameters[i]);
} if( result != HACKRF_SUCCESS ) {
} return result;
}
p1 = }
(parameters[2] & 0x03 << 16)
| (parameters[3] << 8) p1 =
| parameters[4] (parameters[2] & 0x03 << 16)
; | (parameters[3] << 8)
p2 = | parameters[4]
(parameters[5] & 0x0F << 16) ;
| (parameters[6] << 8) p2 =
| parameters[7] (parameters[5] & 0x0F << 16)
; | (parameters[6] << 8)
p3 = | parameters[7]
(parameters[5] & 0xF0 << 12) ;
| (parameters[0] << 8) p3 =
| parameters[1] (parameters[5] & 0xF0 << 12)
; | (parameters[0] << 8)
r_div = | parameters[1]
(parameters[2] >> 4) & 0x7 ;
; r_div =
(parameters[2] >> 4) & 0x7
printf("MS%d:", ms_number); ;
printf("\tp1 = %u\n", p1);
printf("\tp2 = %u\n", p2); printf("\tp1 = %u\n", p1);
printf("\tp3 = %u\n", p3); printf("\tp2 = %u\n", p2);
printf("\toutput divider = %u\n", 1 << r_div); printf("\tp3 = %u\n", p3);
} else {
// MS6 and 7 are integer only
reg_base = 90;
for(i=0; i<3; i++) {
uint_fast8_t reg_number = reg_base + i;
int result = hackrf_si5351c_read(device, reg_number, &parameters[i]);
if( result != HACKRF_SUCCESS ) {
return result;
}
}
r_div = (ms_number == 6) ? parameters[2] & 0x7 : parameters[2] & 0x70 >> 4 ;
printf("\tp1_int = %u\n", (ms_number == 6) ? parameters[0] : parameters[1]);
}
printf("\toutput divider = %u\n", div_lut[r_div]);
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} }

View File

@ -318,6 +318,9 @@ static void usage() {
printf("\t-t <filename> # Transmit data from file.\n"); printf("\t-t <filename> # Transmit data from file.\n");
printf("\t[-f set_freq_hz] # Set Freq in Hz between [%lluMHz, %lluMHz[.\n", FREQ_MIN_HZ/FREQ_ONE_MHZ, FREQ_MAX_HZ/FREQ_ONE_MHZ); printf("\t[-f set_freq_hz] # Set Freq in Hz between [%lluMHz, %lluMHz[.\n", FREQ_MIN_HZ/FREQ_ONE_MHZ, FREQ_MAX_HZ/FREQ_ONE_MHZ);
printf("\t[-a set_amp] # Set Amp 1=Enable, 0=Disable.\n"); printf("\t[-a set_amp] # Set Amp 1=Enable, 0=Disable.\n");
printf("\t[-l gain_db] # Set lna gain, 0-40dB, 8dB steps\n");
printf("\t[-i gain_db] # Set vga(if) gain, 0-62dB, 2dB steps\n");
printf("\t[-x gain_db] # Set TX vga gain, 0-47dB, 1dB steps\n");
printf("\t[-s sample_rate_hz] # Set sample rate in Hz (5/10/12.5/16/20MHz, default %lldMHz).\n", DEFAULT_SAMPLE_RATE_HZ/FREQ_ONE_MHZ); printf("\t[-s sample_rate_hz] # Set sample rate in Hz (5/10/12.5/16/20MHz, default %lldMHz).\n", DEFAULT_SAMPLE_RATE_HZ/FREQ_ONE_MHZ);
printf("\t[-n num_samples] # Number of samples to transfer (default is unlimited).\n"); printf("\t[-n num_samples] # Number of samples to transfer (default is unlimited).\n");
printf("\t[-b baseband_filter_bw_hz] # Set baseband filter bandwidth in MHz.\n\tPossible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz, default < sample_rate_hz.\n" ); printf("\t[-b baseband_filter_bw_hz] # Set baseband filter bandwidth in MHz.\n\tPossible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz, default < sample_rate_hz.\n" );
@ -359,8 +362,9 @@ int main(int argc, char** argv) {
int exit_code = EXIT_SUCCESS; int exit_code = EXIT_SUCCESS;
struct timeval t_end; struct timeval t_end;
float time_diff; float time_diff;
unsigned int lna_gain=8, vga_gain=20, txvga_gain=0;
while( (opt = getopt(argc, argv, "wr:t:f:a:s:n:b:")) != EOF ) while( (opt = getopt(argc, argv, "wr:t:f:a:s:n:b:l:i:x:")) != EOF )
{ {
result = HACKRF_SUCCESS; result = HACKRF_SUCCESS;
switch( opt ) switch( opt )
@ -389,6 +393,18 @@ int main(int argc, char** argv) {
result = parse_u32(optarg, &amp_enable); result = parse_u32(optarg, &amp_enable);
break; break;
case 'l':
result = parse_u32(optarg, &lna_gain);
break;
case 'i':
result = parse_u32(optarg, &vga_gain);
break;
case 'x':
result = parse_u32(optarg, &txvga_gain);
break;
case 's': case 's':
sample_rate = true; sample_rate = true;
result = parse_u32(optarg, &sample_rate_hz); result = parse_u32(optarg, &sample_rate_hz);
@ -592,9 +608,12 @@ int main(int argc, char** argv) {
} }
if( transceiver_mode == TRANSCEIVER_MODE_RX ) { if( transceiver_mode == TRANSCEIVER_MODE_RX ) {
result = hackrf_start_rx(device, rx_callback, NULL); result = hackrf_set_vga_gain(device, vga_gain);
result |= hackrf_set_lna_gain(device, lna_gain);
result |= hackrf_start_rx(device, rx_callback, NULL);
} else { } else {
result = hackrf_start_tx(device, tx_callback, NULL); result = hackrf_set_txvga_gain(device, txvga_gain);
result |= hackrf_start_tx(device, tx_callback, NULL);
} }
if( result != HACKRF_SUCCESS ) { if( result != HACKRF_SUCCESS ) {
printf("hackrf_start_?x() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_start_?x() failed: %s (%d)\n", hackrf_error_name(result), result);

View File

@ -32,13 +32,12 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../cmake/modules)
if(MSVC) if(MSVC)
set(THREADS_USE_PTHREADS_WIN32 true) set(THREADS_USE_PTHREADS_WIN32 true)
find_package(Threads REQUIRED)
else() else()
add_definitions(-Wall) add_definitions(-Wall)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90")
endif() endif()
find_package(USB1 REQUIRED) find_package(USB1 REQUIRED)
find_package(Threads REQUIRED)
include_directories(${LIBUSB_INCLUDE_DIR} ${THREADS_PTHREADS_INCLUDE_DIR}) include_directories(${LIBUSB_INCLUDE_DIR} ${THREADS_PTHREADS_INCLUDE_DIR})