Commit 29d46cfd authored by John Gill's avatar John Gill

Merge remote-tracking branch 'origin/master'

parents 5fb6c286 507f927e
......@@ -3,8 +3,8 @@ VMEBRIDGE=/acc/local/L867/drv/vmebus/1.0.1
PREFIX=/usr/local
CC=gcc
CFLAGS=-g -O -Wall --std=c99 -I$(VMEBRIDGE)/include/vmebus -I../include
LDFLAGS=$(VMEBRIDGE)/lib/libvmebus.a -lrt
CFLAGS=-g -O -Wall --std=gnu99 -I$(VMEBRIDGE)/include/vmebus -I../include
LDFLAGS=$(VMEBRIDGE)/lib/libvmebus.a -lrt -lm
OBJS_LIB=init.o board.o oc_spi16.o ad9910_init.o dac_timing.o
OBJS_HOST=host.o
......
......@@ -130,7 +130,8 @@ libwr2rf_dds_init(struct libwr2rf_dev *dev, unsigned io_update)
}
int
libwr2rf_dds_freq_init(struct libwr2rf_dev *dev, uint64_t freq, unsigned io_update)
libwr2rf_dds_freq_init(struct libwr2rf_dev *dev,
uint64_t freq, unsigned io_update)
{
int res;
......
......@@ -2,6 +2,8 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "libwr2rf/board.h"
#include "libwr2rf/api.h"
#include "regs.h"
......@@ -196,27 +198,139 @@ void libwr2rf_dac_write(struct libwr2rf_dev *dev, unsigned ch, unsigned reg, uin
NULL);
}
int libwr2rf_dac_iqsetpoint(struct libwr2rf_dev *dev, unsigned ch, unsigned igain, unsigned qgain)
#define DAC_IQGAIN_MAX 0x7fff
#define DAC_IQGAIN_MIN 0x8000
/* Convert to short.
The dynamic is asymetric. */
static int dac_convert(float gain)
{
unsigned igain_addr = 0;
unsigned qgain_addr = 0;
if (gain >= 0.0)
return gain * DAC_IQGAIN_MAX;
else
return gain * DAC_IQGAIN_MIN;
}
static int dac_check_range(int gain)
{
if (gain > DAC_IQGAIN_MAX
|| gain < -DAC_IQGAIN_MIN)
return 0;
return 1;
}
int libwr2rf_dac_set_phase_amp(struct libwr2rf_dev *dev, unsigned ch,
float amplitude, float phase, unsigned verbose)
{
if (!(amplitude >= 0.0 && amplitude <= 1.0))
return LIBWR2RF_ERROR_BAD_PARAM;
if (!(phase >= -360.0 && phase <= 360.0))
return LIBWR2RF_ERROR_BAD_PARAM;
float phase_rad = phase * M_PI / 180.0;
float igainf = amplitude * cosf (phase_rad);
float qgainf = amplitude * sinf (phase_rad);
int igain = dac_convert(igainf);
int qgain = dac_convert(qgainf);
switch (ch) {
if (!dac_check_range(igain) || !dac_check_range(qgain))
return LIBWR2RF_ERROR_BAD_PARAM;
if (verbose)
fprintf(stderr,
"DAC IQ %u: ampl=%3.1f, phase=%3.1f, igain=%04x qgain=%04x\n",
ch, amplitude, phase,
(unsigned short)igain, (unsigned short)qgain);
unsigned igain_addr;
unsigned qgain_addr;
unsigned phase_addr;
unsigned updat_addr;
switch (ch) {
case 1:
igain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_IGAIN;
qgain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_QGAIN;
igain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_IGAIN_ARM;
qgain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_QGAIN_ARM;
phase_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_PHASE;
updat_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_PHASE_UPDATE;
break;
case 2:
igain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_IGAIN;
qgain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_QGAIN;
igain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_IGAIN_ARM;
qgain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_QGAIN_ARM;
phase_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_PHASE;
updat_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_PHASE_UPDATE;
break;
default:
return LIBWR2RF_ERROR_BAD_ID;
}
libwr2rf_write16(dev, igain_addr, igain);
libwr2rf_write16(dev, qgain_addr, qgain);
return 0;
libwr2rf_write16(dev, igain_addr, igain);
libwr2rf_write16(dev, qgain_addr, qgain);
libwr2rf_write16(dev, phase_addr, (short)phase);
libwr2rf_write16(dev, updat_addr,
WR2RF_CTRL_REGS_RF1_IQDAC_PHASE_UPDATE_VALID);
return 0;
}
int libwr2rf_dac_reset_phase_amp(struct libwr2rf_dev *dev, unsigned ch,
float amplitude, float phase)
{
return libwr2rf_dac_set_phase_amp(dev, ch, amplitude, phase, 0);
}
int libwr2rf_dac_phase_amp_ext(struct libwr2rf_dev *dev, unsigned ch,
float amplitude, float phase, unsigned verbose)
{
const int phase_step = 15;
int iphase = (int)phase;
unsigned phase_addr;
int last_phase;
int res;
if (!(phase >= -360.0 && phase <= 360.0))
return LIBWR2RF_ERROR_BAD_PARAM;
/* Current phase. */
switch (ch) {
case 1:
phase_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_PHASE;
break;
case 2:
phase_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_PHASE;
break;
default:
return LIBWR2RF_ERROR_BAD_ID;
}
last_phase = (short)libwr2rf_read16(dev, phase_addr);
while (1) {
int dph = iphase - last_phase;
if (dph >= -phase_step && dph <= phase_step) {
/* Smooth enough, apply directly. */
return libwr2rf_dac_set_phase_amp(dev, ch, amplitude, phase, verbose);
}
if (dph >= 0)
last_phase += phase_step;
else
last_phase -= phase_step;
res = libwr2rf_dac_set_phase_amp(dev, ch, amplitude, last_phase, verbose);
if (res != 0)
return res;
/* A delay is implicit through the slow VME access (about 300ns per
access). */
}
}
int libwr2rf_dac_phase_amp(struct libwr2rf_dev *dev, unsigned ch,
float amplitude, float phase)
{
return libwr2rf_dac_phase_amp_ext(dev, ch, amplitude, phase, 0);
}
unsigned libwr2rf_read_fwversion(struct libwr2rf_dev *dev)
......@@ -1014,9 +1128,9 @@ uint32_t libwr2rf_rfnco_read32 (struct libwr2rf_dev *dev, unsigned id, unsigned
{
unsigned addr = 0;
if (id == LIBWR2RF_RF1_CHANNEL_ID)
if (id == LIBWR2RF_RF1_CHANNEL_ID)
addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_RFNCO;
else
else
addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_RFNCO;
addr = addr + off;
......@@ -1027,9 +1141,9 @@ void libwr2rf_rfnco_write32 (struct libwr2rf_dev *dev, unsigned id, unsigned off
{
unsigned addr = 0;
if (id == LIBWR2RF_RF1_CHANNEL_ID)
if (id == LIBWR2RF_RF1_CHANNEL_ID)
addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_RFNCO;
else
else
addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_RFNCO;
addr = addr + off;
......@@ -1037,21 +1151,21 @@ void libwr2rf_rfnco_write32 (struct libwr2rf_dev *dev, unsigned id, unsigned off
}
int libwr2rf_nco_lcfg (struct libwr2rf_dev *dev, unsigned lcfg, unsigned long long ftw_rfnco1,
int libwr2rf_nco_lcfg (struct libwr2rf_dev *dev, unsigned lcfg, unsigned long long ftw_rfnco1,
unsigned long long ftw_rfnco2)
{
unsigned control_lcfg = RFNCO_CONTROL_SOFTLOAD;
unsigned control_wrcfg = RFNCO_CONTROL_SELFTWH1 | RFNCO_CONTROL_EXTRESETENABLE | RFNCO_CONTROL_SELLOAD | RFNCO_CONTROL_SELWRFTWH1;
unsigned control_wrcfg = RFNCO_CONTROL_SELFTWH1 | RFNCO_CONTROL_EXTRESETENABLE | RFNCO_CONTROL_SELLOAD | RFNCO_CONTROL_SELWRFTWH1;
unsigned nco1_ftw_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_RFNCO + RFNCO_FTW_H1;
unsigned nco2_ftw_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_RFNCO + RFNCO_FTW_H1;
unsigned nco1_control_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_RFNCO + RFNCO_CONTROL;
unsigned nco2_control_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_RFNCO + RFNCO_CONTROL;
printf("nco_ftw_addr=%lx nco_ctrl_addr=%lx\n", RFNCO_FTW_H1, RFNCO_CONTROL);
printf("nco_ftw_addr=%lx nco_ctrl_addr=%lx\n", RFNCO_FTW_H1, RFNCO_CONTROL);
if (lcfg == 0) {
/* Use network as RFNCO source. */
libwr2rf_write16(dev, WR2RF_VME_REGS_INIT + WR2RF_INIT_REGS_NCO_LOC_OR_WRS, 0);
libwr2rf_write16(dev, WR2RF_VME_REGS_INIT + WR2RF_INIT_REGS_NCO_LOC_OR_WRS, 0);
libwr2rf_16x32_write32(dev, nco1_control_addr, control_wrcfg);
libwr2rf_16x32_write32(dev, nco2_control_addr, control_wrcfg);
......
......@@ -117,7 +117,7 @@ libwr2rf_clock_init (struct libwr2rf_dev *dev)
/* we have to check if the PLL has already been initialised and the clock select set */
ctrl = libwr2rf_read16(dev, WR2RF_VME_REGS_INIT + WR2RF_INIT_REGS_CLOCK_CTRL);
if ((ctrl & WR2RF_INIT_REGS_CLOCK_CTRL_CLK_SEL) == 0)
if ((ctrl & WR2RF_INIT_REGS_CLOCK_CTRL_CLK_SEL) == 0)
{
/* 1. the PLL (ltc6950). */
/* 1.1 the SPI control for the PLL. */
......@@ -127,13 +127,13 @@ libwr2rf_clock_init (struct libwr2rf_dev *dev)
libwr2rf_ltc6950_init (dev);
/* 1.3 sync the PLL */
libwr2rf_ltc6950_sync (dev);
/* 2. FPGA clock. */
libwr2rf_clock_select_dds (dev);
/* 5. WR-Core */
libwr2rf_wrcore_init(dev);
/* 6. IOdelays */
libwr2rf_iodelay_init(dev);
}
......@@ -239,8 +239,8 @@ libwr2rf_api_init (struct libwr2rf_dev *dev)
libwr2rf_iodelay_init(dev);
/* Command dac-iqsetpoint */
libwr2rf_dac_iqsetpoint(dev, 1, 0x4000, 0);
libwr2rf_dac_iqsetpoint(dev, 2, 0x4000, 0);
libwr2rf_dac_reset_phase_amp(dev, 1, 0.5, 0.0);
libwr2rf_dac_reset_phase_amp(dev, 2, 0.5, 0.0);
/* Commands:
dds-init (TODO: io_update)
......
......@@ -64,8 +64,16 @@ int libwr2rf_check_link_time(struct libwr2rf_dev *dev);
/* Read the mac address (6 bytes). Can be used as unique id. */
int libwr2rf_get_mac(struct libwr2rf_dev *dev, unsigned char *mac);
/* DAC IQ set points. */
int libwr2rf_dac_iqsetpoint(struct libwr2rf_dev *dev, unsigned ch, unsigned igain, unsigned qgain);
/* Set DAC amplitude and phase. Amplitude must be between 0.0 and 1.0,
phase must be between -360.0 and 360.0
Do a smooth transition in case of phase jump. */
int libwr2rf_dac_phase_amp(struct libwr2rf_dev *dev, unsigned ch,
float amplitude, float phase);
/* Like the previous function but apply immediately. Can only be used
when the trigger units are not enabled. */
int libwr2rf_dac_reset_phase_amp(struct libwr2rf_dev *dev, unsigned ch,
float amplitude, float phase);
/* Mask (or not mask) NCO resets. */
int libwr2rf_nco_reset(struct libwr2rf_dev *dev, unsigned ch, unsigned en);
......
......@@ -25,6 +25,9 @@ void libwr2rf_dds_write(struct libwr2rf_dev *dev, unsigned reg,
uint64_t value, unsigned nbits);
uint64_t libwr2rf_dds_read(struct libwr2rf_dev *dev, unsigned reg, unsigned nbits);
int libwr2rf_dds_freq_init(struct libwr2rf_dev *dev,
uint64_t freq, unsigned io_update);
/* Trigger ioupdate. */
void libwr2rf_dds_ioupdate(struct libwr2rf_dev *dev);
......@@ -42,6 +45,10 @@ int libwr2rf_dac_port_timing(struct libwr2rf_dev *dev, unsigned ch);
int libwr2rf_dac_validate_timing(struct libwr2rf_dev *dev, unsigned ch);
void libwr2rf_dac_set_timing_delay(struct libwr2rf_dev *dev, unsigned ch, unsigned v);
/* Adjust phase and amplitude of DAC CH. */
int libwr2rf_dac_phase_amp_ext(struct libwr2rf_dev *dev, unsigned ch,
float amplitude, float phase, unsigned verbose);
/* Raw 32bit IOs through the wb16 to wb32 bridge. */
uint32_t libwr2rf_16x32_read32(struct libwr2rf_dev *dev, unsigned off);
void libwr2rf_16x32_write32(struct libwr2rf_dev *dev, unsigned off,
......
......@@ -8,6 +8,7 @@
#include <termios.h>
#include <errno.h>
#include <ctype.h>
#include <math.h>
#include <arpa/inet.h>
#include "libwr2rf/io.h"
#include "libwr2rf/host.h"
......@@ -473,7 +474,7 @@ rf_reset_offset (struct libwr2rf_dev *dev, int argc, char **argv)
ch = 2;
addr += WR2RF_INIT_RF_REGS_RF2;
}
if (ch != 1 && ch != 2)
goto usage;
else if (argc == 3)
......@@ -484,7 +485,7 @@ rf_reset_offset (struct libwr2rf_dev *dev, int argc, char **argv)
if (argc == 3) {
libwr2rf_write16(dev, addr, delay);
}
}
delay = libwr2rf_read16(dev, addr);
printf ("RF%d Reset Delay Offset = %02d cycles (16ns)\n", ch, delay);
......@@ -639,7 +640,7 @@ nco_lcfg (struct libwr2rf_dev *dev, int argc, char **argv)
libwr2rf_16x32_write32(dev, nco_harmonic_addr, harmonic);
libwr2rf_16x32_write32(dev, nco_control_addr, control);
printf("nco_ftw_addr=%x nco_L00_addr=%x nco_LO1_addr=%x nco_harmonic_addr=%x nco_control_addr=%x\n",
printf("nco_ftw_addr=%x nco_L00_addr=%x nco_LO1_addr=%x nco_harmonic_addr=%x nco_control_addr=%x\n",
nco_ftw_addr, nco_LO0_addr, nco_LO1_addr, nco_harmonic_addr, nco_control_addr );
printf("ftw=%08x.%08x LO=%08x.%08x L1=%08x.%08x harmonic=%08x control=%08x \n",
......@@ -702,7 +703,7 @@ nco_wrcfg (struct libwr2rf_dev *dev, int argc, char **argv)
unsigned long long LO1 = 0x1C9BA5E300000;//223.5 MHz
unsigned off = 0;
unsigned harmonic = 4620;
unsigned control = RFNCO_CONTROL_SELFTWH1 | RFNCO_CONTROL_EXTRESETENABLE | RFNCO_CONTROL_SELLOAD |
unsigned control = RFNCO_CONTROL_SELFTWH1 | RFNCO_CONTROL_EXTRESETENABLE | RFNCO_CONTROL_SELLOAD |
RFNCO_CONTROL_SELWRFTWH1;
unsigned nco_harmonic_addr = RFNCO_FTW_H;
unsigned nco_LO0_addr = RFNCO_FTW_LO0;
......@@ -1779,6 +1780,8 @@ static void
dac_iqsetpoint (struct libwr2rf_dev *dev, int argc, char **argv)
{
int ch;
unsigned igain_addr;
unsigned qgain_addr;
if (argc != 2 && argc != 4) {
printf ("usage: %s 1|2 [i_setpoint q_setpoint]\n", argv[0]);
......@@ -1786,39 +1789,90 @@ dac_iqsetpoint (struct libwr2rf_dev *dev, int argc, char **argv)
}
ch = parse_dac_channel(argv[1]);
if (ch < 0)
if (ch < 1 || ch > 2)
return;
if (argc == 4) {
unsigned igain = 0;
unsigned qgain = 0;
unsigned update_addr;
unsigned igain;
unsigned qgain;
if (ch == DAC1_CS) {
igain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_IGAIN_ARM;
qgain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_QGAIN_ARM;
update_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_PHASE_UPDATE;
} else {
igain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_IGAIN_ARM;
qgain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_QGAIN_ARM;
update_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_PHASE_UPDATE;
}
igain = strtoul(argv[2], NULL, 0);
qgain = strtoul(argv[3], NULL, 0);
if (libwr2rf_dac_iqsetpoint(dev, ch, igain, qgain) != 0) {
printf("error\n");
return;
}
libwr2rf_write16(dev, igain_addr, igain);
libwr2rf_write16(dev, qgain_addr, qgain);
libwr2rf_write16(dev, update_addr, WR2RF_CTRL_REGS_RF2_IQDAC_PHASE_UPDATE_VALID);
printf("Setting RF Channel %d i_setpoint=%04x q_setpoint=%04x\n", ch, igain, qgain);
} else {
unsigned igain_addr = 0;
unsigned qgain_addr = 0;
unsigned igain;
unsigned qgain;
unsigned phase;
unsigned phase_addr;
if (ch == DAC1_CS) {
igain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_IGAIN;
qgain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_QGAIN;
phase_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF1_IQDAC_PHASE;
} else {
igain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_IGAIN;
qgain_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_QGAIN;
phase_addr = WR2RF_VME_REGS_CTRL + WR2RF_CTRL_REGS_RF2_IQDAC_PHASE;
}
igain = libwr2rf_read16(dev, igain_addr);
qgain = libwr2rf_read16(dev, qgain_addr);
printf("RF Channel %d i_setpoint=%04x q_setpoint=%04x\n", ch, igain, qgain);
phase = libwr2rf_read16(dev, phase_addr);
printf("RF Channel %d i_setpoint=%04x q_setpoint=%04x, phase=%u\n", ch, igain, qgain, phase);
float igainf = (short)igain;
float qgainf = (short)qgain;
float rad = atan2f (qgainf, igainf);
float amp = hypotf(igainf, qgainf);
printf ("Real phase=%3.1f gain=%04x\n",
rad * 180.0 / M_PI, (unsigned short)amp);
}
}
static void
dac_iq_phase (struct libwr2rf_dev *dev, int argc, char **argv)
{
int ch;
float phase;
float amp;
int err;
if (argc != 3 && argc != 4) {
printf ("usage: %s 1|2 phase [amp]\n", argv[0]);
return;
}
ch = parse_dac_channel(argv[1]);
if (ch < 1 || ch > 2)
return;
phase = strtof(argv[2], NULL);
if (argc > 3)
amp = strtof(argv[3], NULL);
else
amp = 0.5;
err = libwr2rf_dac_phase_amp_ext(dev, ch, amp, phase, 1);
if (err != 0)
printf("error while setting phase+amp\n");
}
static void
dac_iqctrl (struct libwr2rf_dev *dev, int argc, char **argv)
{
......@@ -3788,7 +3842,7 @@ api_rfnco_read32 (struct libwr2rf_dev *dev, int argc, char **argv)
unsigned addr_off = 0; // bytes
unsigned max_off = 4096; // max address space for rfnco
if (argc != 3)
if (argc != 3)
goto usage;
rfnco_idx = strtoul(argv[1], NULL, 0);
......@@ -3817,7 +3871,7 @@ api_rfnco_write32 (struct libwr2rf_dev *dev, int argc, char **argv)
unsigned max_off = 4096;
unsigned val = 0;
if (argc != 4)
if (argc != 4)
goto usage;
rfnco_idx = strtoul(argv[1], NULL, 0);
......@@ -3828,10 +3882,10 @@ api_rfnco_write32 (struct libwr2rf_dev *dev, int argc, char **argv)
goto usage;
if (addr_off >= max_off)
goto usage;
libwr2rf_rfnco_write32 (dev, rfnco_idx, addr_off, val);
return;
usage:
printf ("usage: %s rfnco rfnco_addr_in_bytes val\n", argv[0]);
}
......@@ -4111,6 +4165,7 @@ static struct cmds cmds[] =
{ "dds-freq", dds_freq, "control the DDS output frequency - useful for standalone DDS rf signal output"},
{ "dac-xdds", dac_xdds, "control the xilinx DDS for testing the IQdac"},
{ "dac-iqsetpoint", dac_iqsetpoint, "configures the amplitude and phase for the IQdacs"},
{ "dac-iq-phase", dac_iq_phase, "change phase and amplitude of IQdacs"},
{ "dac-iqctrl", dac_iqctrl, "Selects the IQdata lines between RFNCO+IQMod or debug DDS"},
{ "dac-tman", dac_tman, "Forces the dac timing"},
{ "dac-power", dac_power, "Set dac power-down register"},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment