forked from M-Labs/artiq
runtime/rt2wb: use input/output terminology and add (async) input
This commit is contained in:
parent
764795a8fe
commit
7d7a710a56
|
@ -3,12 +3,16 @@ from artiq.language.types import *
|
|||
|
||||
|
||||
@syscall
|
||||
def rt2wb_write(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32
|
||||
def rt2wb_output(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32
|
||||
) -> TNone:
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
|
||||
@syscall
|
||||
def rt2wb_read_sync(time_mu: TInt64, channel: TInt32, addr: TInt32,
|
||||
duration_mu: TInt32) -> TInt32:
|
||||
def rt2wb_input(channel: TInt32) -> TInt32:
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
|
||||
@syscall
|
||||
def rt2wb_input_sync(timeout_mu: TInt64, channel: TInt32) -> TInt32:
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from artiq.language.core import (kernel, portable, seconds_to_mu, now_mu,
|
||||
delay_mu)
|
||||
delay_mu, int)
|
||||
from artiq.language.units import MHz
|
||||
from artiq.coredevice.rt2wb import rt2wb_write, rt2wb_read_sync
|
||||
from artiq.coredevice.rt2wb import rt2wb_output, rt2wb_input, rt2wb_input_sync
|
||||
|
||||
|
||||
SPI_DATA_ADDR, SPI_XFER_ADDR, SPI_CONFIG_ADDR = range(3)
|
||||
|
@ -28,11 +28,11 @@ class SPIMaster:
|
|||
def __init__(self, dmgr, ref_period, channel):
|
||||
self.core = dmgr.get("core")
|
||||
self.ref_period = ref_period
|
||||
self.ref_period_mu = seconds_to_mu(ref_period, self.core)
|
||||
self.ref_period_mu = int(seconds_to_mu(ref_period, self.core))
|
||||
self.channel = channel
|
||||
self.write_period_mu = 0
|
||||
self.read_period_mu = 0
|
||||
self.xfer_period_mu = 0
|
||||
self.write_period_mu = int(0)
|
||||
self.read_period_mu = int(0)
|
||||
self.xfer_period_mu = int(0)
|
||||
# A full transfer takes write_period_mu + xfer_period_mu.
|
||||
# Chained transfers can happen every xfer_period_mu.
|
||||
# The second transfer of a chain can be written 2*ref_period_mu
|
||||
|
@ -49,11 +49,11 @@ class SPIMaster:
|
|||
|
||||
@kernel
|
||||
def set_config_mu(self, flags=0, write_div=6, read_div=6):
|
||||
rt2wb_write(now_mu(), self.channel, SPI_CONFIG_ADDR, flags |
|
||||
rt2wb_output(now_mu(), self.channel, SPI_CONFIG_ADDR, flags |
|
||||
((write_div - 2) << 16) | ((read_div - 2) << 24))
|
||||
self.write_period_mu = int(write_div*self.ref_period_mu)
|
||||
self.read_period_mu = int(read_div*self.ref_period_mu)
|
||||
delay_mu(2*self.ref_period_mu)
|
||||
delay_mu(3*self.ref_period_mu)
|
||||
|
||||
@portable
|
||||
def get_xfer_period_mu(self, write_length, read_length):
|
||||
|
@ -62,33 +62,40 @@ class SPIMaster:
|
|||
|
||||
@kernel
|
||||
def set_xfer(self, chip_select=0, write_length=0, read_length=0):
|
||||
rt2wb_write(now_mu(), self.channel, SPI_XFER_ADDR,
|
||||
rt2wb_output(now_mu(), self.channel, SPI_XFER_ADDR,
|
||||
chip_select | (write_length << 16) | (read_length << 24))
|
||||
self.xfer_period_mu = self.get_xfer_period_mu(
|
||||
write_length, read_length)
|
||||
delay_mu(int(2*self.ref_period_mu))
|
||||
self.xfer_period_mu = self.get_xfer_period_mu(write_length,
|
||||
read_length)
|
||||
delay_mu(3*self.ref_period_mu)
|
||||
|
||||
@kernel
|
||||
def write(self, data):
|
||||
rt2wb_write(now_mu(), self.channel, SPI_DATA_ADDR, data)
|
||||
delay_mu(int(self.write_period_mu + self.xfer_period_mu))
|
||||
rt2wb_output(now_mu(), self.channel, SPI_DATA_ADDR, data)
|
||||
delay_mu(3*self.ref_period_mu)
|
||||
|
||||
@kernel
|
||||
def read_async(self):
|
||||
rt2wb_write(now_mu(), self.channel, SPI_DATA_ADDR | SPI_RT2WB_READ, 0)
|
||||
delay_mu(int(2*self.ref_period_mu))
|
||||
def read(self):
|
||||
rt2wb_output(now_mu(), self.channel, SPI_DATA_ADDR | SPI_RT2WB_READ, 0)
|
||||
delay_mu(3*self.ref_period_mu)
|
||||
|
||||
@kernel
|
||||
def input(self):
|
||||
return rt2wb_input(self.channel)
|
||||
|
||||
@kernel
|
||||
def _rt2wb_read_sync(self, addr=0):
|
||||
t = now_mu()
|
||||
rt2wb_output(t, self.channel, addr | SPI_RT2WB_READ, 0)
|
||||
return rt2wb_input_sync(t + 3*self.ref_period_mu, self.channel)
|
||||
|
||||
@kernel
|
||||
def read_sync(self):
|
||||
return rt2wb_read_sync(now_mu(), self.channel, SPI_DATA_ADDR |
|
||||
SPI_RT2WB_READ, int(2*self.ref_period_mu))
|
||||
return self._rt2wb_read_sync(SPI_DATA_ADDR)
|
||||
|
||||
@kernel
|
||||
def _get_config_sync(self):
|
||||
return rt2wb_read_sync(now_mu(), self.channel, SPI_CONFIG_ADDR |
|
||||
SPI_RT2WB_READ, int(2*self.ref_period_mu))
|
||||
return self._rt2wb_read_sync(SPI_CONFIG_ADDR)
|
||||
|
||||
@kernel
|
||||
def _get_xfer_sync(self):
|
||||
return rt2wb_read_sync(now_mu(), self.channel, SPI_XFER_ADDR |
|
||||
SPI_RT2WB_READ, int(2*self.ref_period_mu))
|
||||
return self._rt2wb_read_sync(SPI_XFER_ADDR)
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#endif
|
||||
|
||||
#define DDS_WRITE(addr, data) do { \
|
||||
rt2wb_write(now, CONFIG_RTIO_DDS_CHANNEL, addr, data); \
|
||||
rt2wb_output(now, CONFIG_RTIO_DDS_CHANNEL, addr, data); \
|
||||
now += DURATION_WRITE; \
|
||||
} while(0)
|
||||
|
||||
|
|
|
@ -122,8 +122,9 @@ static const struct symbol runtime_exports[] = {
|
|||
{"dds_batch_exit", &dds_batch_exit},
|
||||
{"dds_set", &dds_set},
|
||||
|
||||
{"rt2wb_write", &rt2wb_write},
|
||||
{"rt2wb_read_sync", &rt2wb_read_sync},
|
||||
{"rt2wb_output", &rt2wb_output},
|
||||
{"rt2wb_input", &rt2wb_input},
|
||||
{"rt2wb_input_sync", &rt2wb_input_sync},
|
||||
|
||||
{"cache_get", &cache_get},
|
||||
{"cache_put", &cache_put},
|
||||
|
|
|
@ -5,29 +5,50 @@
|
|||
#include "rt2wb.h"
|
||||
|
||||
|
||||
void rt2wb_write(long long int timestamp, int channel, int addr,
|
||||
void rt2wb_output(long long int timestamp, int channel, int addr,
|
||||
unsigned int data)
|
||||
{
|
||||
rtio_output(timestamp, channel, addr, data);
|
||||
}
|
||||
|
||||
|
||||
unsigned int rt2wb_read_sync(long long int timestamp, int channel, int addr,
|
||||
int duration)
|
||||
unsigned int rt2wb_input(int channel)
|
||||
{
|
||||
unsigned int data;
|
||||
int status;
|
||||
|
||||
rtio_output(timestamp, channel, addr, 0);
|
||||
|
||||
status = rtio_input_wait(timestamp + duration, channel);
|
||||
if (status & RTIO_I_STATUS_OVERFLOW)
|
||||
rtio_chan_sel_write(channel);
|
||||
status = rtio_i_status_read();
|
||||
if (status & RTIO_I_STATUS_OVERFLOW) {
|
||||
rtio_i_overflow_reset_write(1);
|
||||
artiq_raise_from_c("RTIOOverflow",
|
||||
"RT2WB read overflow on channel {0}",
|
||||
"RT2WB input overflow on channel {0}",
|
||||
channel, 0, 0);
|
||||
}
|
||||
if (status & RTIO_I_STATUS_EMPTY)
|
||||
artiq_raise_from_c("RTIOTimeout",
|
||||
"RT2WB read timeout on channel {0}",
|
||||
"RT2WB input timeout on channel {0}",
|
||||
channel, 0, 0);
|
||||
|
||||
data = rtio_i_data_read();
|
||||
rtio_i_re_write(1);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
unsigned int rt2wb_input_sync(long long int timeout, int channel)
|
||||
{
|
||||
unsigned int data;
|
||||
int status;
|
||||
|
||||
status = rtio_input_wait(timeout, channel);
|
||||
if (status & RTIO_I_STATUS_OVERFLOW)
|
||||
artiq_raise_from_c("RTIOOverflow",
|
||||
"RT2WB input overflow on channel {0}",
|
||||
channel, 0, 0);
|
||||
if (status & RTIO_I_STATUS_EMPTY)
|
||||
artiq_raise_from_c("RTIOTimeout",
|
||||
"RT2WB input timeout on channel {0}",
|
||||
channel, 0, 0);
|
||||
|
||||
data = rtio_i_data_read();
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include "rtio.h"
|
||||
|
||||
void rt2wb_write(long long int timestamp, int channel, int address,
|
||||
void rt2wb_output(long long int timestamp, int channel, int addr,
|
||||
unsigned int data);
|
||||
unsigned int rt2wb_read_sync(long long int timestamp, int channel, int address,
|
||||
int duration);
|
||||
unsigned int rt2wb_input(int channel);
|
||||
unsigned int rt2wb_input_sync(long long int timeout, int channel);
|
||||
|
||||
#endif /* __RT2WB_H */
|
||||
|
||||
|
|
Loading…
Reference in New Issue