artiq/soc/runtime/dds.c

83 lines
2.2 KiB
C
Raw Normal View History

2014-09-12 15:34:11 +08:00
#include <generated/csr.h>
2014-08-28 16:56:48 +08:00
#include <hw/common.h>
2014-09-12 15:34:11 +08:00
#include <stdio.h>
2014-08-28 16:56:48 +08:00
#include "rtio.h"
2014-08-28 16:56:48 +08:00
#include "dds.h"
#define DDS_FTW0 0x0a
#define DDS_FTW1 0x0b
#define DDS_FTW2 0x0c
#define DDS_FTW3 0x0d
2014-11-21 04:32:56 +08:00
#define DDS_POW0 0x0e
#define DDS_POW1 0x0f
2014-08-28 16:56:48 +08:00
#define DDS_GPIO 0x41
#define DDS_READ(addr) \
2014-09-05 12:03:22 +08:00
MMPTR(0xb0000000 + (addr)*4)
2014-08-28 16:56:48 +08:00
#define DDS_WRITE(addr, data) \
2014-09-05 12:03:22 +08:00
MMPTR(0xb0000000 + (addr)*4) = data
2014-08-28 16:56:48 +08:00
void dds_init(void)
{
2014-09-05 12:03:22 +08:00
int i;
for(i=0;i<8;i++) {
2014-11-16 02:23:23 +08:00
DDS_WRITE(DDS_GPIO, i);
2014-09-11 19:25:55 +08:00
DDS_WRITE(DDS_GPIO, i | (1 << 7));
2014-09-05 12:03:22 +08:00
DDS_WRITE(DDS_GPIO, i);
2014-11-21 04:32:56 +08:00
dds_phase_clear_en(i, 0);
2014-09-05 12:03:22 +08:00
}
2014-08-28 16:56:48 +08:00
}
2014-11-21 04:32:56 +08:00
void dds_phase_clear_en(int channel, int phase_clear_en)
2014-08-28 16:56:48 +08:00
{
2014-11-21 04:32:56 +08:00
DDS_WRITE(0x00, 0x78);
DDS_WRITE(0x01, 0x00);
DDS_WRITE(0x02, phase_clear_en ? 0x40 : 0x00);
DDS_WRITE(0x03, 0x00);
}
/*
* DDS phase modes:
2014-12-09 13:50:33 +08:00
* - continuous: Set sysclk_per_microcycle=0 to disable POW alteration.
2014-11-21 04:32:56 +08:00
* phase_tracking is ignored, set to 0.
* Disable phase accumulator clearing prior to programming.
2014-12-09 13:50:33 +08:00
* - absolute: Set sysclk_per_microcycle to its nominal value
2014-11-21 04:32:56 +08:00
* and phase_tracking=0.
* Enable phase accumulator clearing prior to programming.
2014-12-09 13:50:33 +08:00
* - tracking: Set sysclk_per_microcycle to its nominal value
2014-11-21 04:32:56 +08:00
* and phase_tracking=1.
* Enable phase accumulator clearing prior to programming.
*/
void dds_program(long long int timestamp, int channel,
2014-12-09 13:50:33 +08:00
unsigned int ftw, unsigned int pow, unsigned int sysclk_per_microcycle,
2014-11-21 04:32:56 +08:00
int rt_fud, int phase_tracking)
{
long long int fud_time;
2014-12-09 13:50:33 +08:00
unsigned int phase_time_offset;
2014-11-21 04:32:56 +08:00
rtio_fud_sync();
2014-09-05 12:03:22 +08:00
DDS_WRITE(DDS_GPIO, channel);
2014-11-21 04:32:56 +08:00
2014-09-05 12:03:22 +08:00
DDS_WRITE(DDS_FTW0, ftw & 0xff);
DDS_WRITE(DDS_FTW1, (ftw >> 8) & 0xff);
DDS_WRITE(DDS_FTW2, (ftw >> 16) & 0xff);
DDS_WRITE(DDS_FTW3, (ftw >> 24) & 0xff);
2014-11-21 04:32:56 +08:00
phase_time_offset = phase_tracking ? timestamp : 0;
if(rt_fud)
fud_time = timestamp;
else {
fud_time = rtio_get_counter() + 8000;
2014-12-09 13:50:33 +08:00
/* POW is mod 2**14, so wraparound on negative values is OK */
2014-11-21 04:32:56 +08:00
phase_time_offset -= timestamp - fud_time;
}
2014-12-09 13:50:33 +08:00
pow += phase_time_offset*ftw*sysclk_per_microcycle >> 18;
2014-11-21 04:32:56 +08:00
DDS_WRITE(DDS_POW0, pow & 0xff);
DDS_WRITE(DDS_POW1, (pow >> 8) & 0x3f);
rtio_fud(fud_time);
2014-08-28 16:56:48 +08:00
}