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
|
|
|
|
2014-10-14 12:47:04 +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
|
|
|
|
2014-10-14 12:47:04 +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);
|
|
|
|
|
2014-10-14 12:47:04 +08:00
|
|
|
rtio_fud(fud_time);
|
2014-08-28 16:56:48 +08:00
|
|
|
}
|