Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
wr2rf-vme
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
5
Issues
5
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
wr2rf-vme
Commits
f2323010
Commit
f2323010
authored
Sep 01, 2021
by
Tristan Gingold
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
software: change API to support smooth phase changes.
parent
08d1bc0b
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
219 additions
and
24 deletions
+219
-24
Makefile
software/libwr2rf/Makefile
+2
-2
ad9910_init.c
software/libwr2rf/ad9910_init.c
+2
-1
board.c
software/libwr2rf/board.c
+131
-7
init.c
software/libwr2rf/init.c
+2
-2
api.h
software/libwr2rf/libwr2rf/api.h
+10
-2
board.h
software/libwr2rf/libwr2rf/board.h
+7
-0
wr2rf.c
software/libwr2rf/wr2rf.c
+65
-10
No files found.
software/libwr2rf/Makefile
View file @
f2323010
...
...
@@ -3,8 +3,8 @@ VMEBRIDGE=/acc/local/L867/drv/vmebus/1.0.1
PREFIX
=
/usr/local
CC
=
gcc
CFLAGS
=
-g
-O
-Wall
--std
=
c
99
-I
$(VMEBRIDGE)
/include/vmebus
-I
../include
LDFLAGS
=
$(VMEBRIDGE)
/lib/libvmebus.a
-lrt
CFLAGS
=
-g
-O
-Wall
--std
=
gnu
99
-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
...
...
software/libwr2rf/ad9910_init.c
View file @
f2323010
...
...
@@ -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
;
...
...
software/libwr2rf/board.c
View file @
f2323010
...
...
@@ -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,149 @@ 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
)
{
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
)
{
unsigned
igain_addr
=
0
;
unsigned
qgain_addr
=
0
;
if
(
!
(
amplitude
>=
0
.
0
&&
amplitude
<=
1
.
0
))
return
-
1
;
if
(
!
(
phase
>=
0
.
0
&&
phase
<=
360
.
0
))
return
-
1
;
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
);
if
(
!
dac_check_range
(
igain
)
||
!
dac_check_range
(
qgain
))
return
-
1
;
switch
(
ch
)
{
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
;
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
;
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
;
unsigned
phase_addr
;
int
last_phase
;
int
res
;
/* According to fmod:
the returned value has the same sign as x and a magnitude
less than the magnitude of y. */
phase
=
fmodf
(
phase
,
360
.
0
);
if
(
phase
<
0
.
0
)
phase
+=
360
.
0
;
/* IPHASE is in 0 .. 360. */
iphase
=
(
int
)
phase
;
/* 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
=
libwr2rf_read16
(
dev
,
phase_addr
);
while
(
1
)
{
int
dph
=
iphase
-
last_phase
;
if
((
dph
>=
0
&&
dph
<
phase_step
)
||
(
dph
<
0
&&
dph
>
-
phase_step
)
||
(
dph
>=
0
&&
dph
>=
360
-
phase_step
)
||
(
dph
<=
0
&&
dph
<=
-
360
+
phase_step
))
{
/* Smooth enough, apply directly. */
return
libwr2rf_dac_set_phase_amp
(
dev
,
ch
,
amplitude
,
phase
,
verbose
);
}
if
((
dph
>=
0
&&
dph
<=
180
)
||
(
dph
<
0
&&
dph
<
-
180
))
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
)
...
...
software/libwr2rf/init.c
View file @
f2323010
...
...
@@ -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)
...
...
software/libwr2rf/libwr2rf/api.h
View file @
f2323010
...
...
@@ -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
);
...
...
software/libwr2rf/libwr2rf/board.h
View file @
f2323010
...
...
@@ -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
,
...
...
software/libwr2rf/wr2rf.c
View file @
f2323010
...
...
@@ -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"
...
...
@@ -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,37 +1789,88 @@ 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
(
igainf
,
qgainf
);
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
...
...
@@ -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"
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment