dac, adc switch and documentation
This commit is contained in:
parent
b7ca97695a
commit
e19a626945
2
creole
2
creole
|
@ -1 +1 @@
|
|||
Subproject commit c7fc965fcfa72f26456f5221a6480de52f7d776a
|
||||
Subproject commit 0ead095044c93825c7db8cec0a6b92769bac7a7d
|
|
@ -2,9 +2,22 @@ m4_changequote(`⟨', `⟩')
|
|||
m4_changecom(⟨/*⟩, ⟨*/⟩)
|
||||
m4_define(generate_macro, ⟨m4_define(M4_$1, $2)⟩)
|
||||
m4_include(../control_loop/control_loop_cmds.m4)
|
||||
|
||||
/* Since yosys only allows for standard Verilog (no system verilog),
|
||||
* arrays (which would make everything much cleaner) cannot be used.
|
||||
* A preprocessor is used instead, and M4 is used because it is much
|
||||
* cleaner than the Verilog preprocessor (which is bad).
|
||||
*/
|
||||
|
||||
/*********************************************************/
|
||||
/********************** M4 macros ************************/
|
||||
/*********************************************************/
|
||||
|
||||
/* This macro is used in the module declaration.
|
||||
* The first argument is the number of wires the select switch must
|
||||
* support (2 for most DACs, 3 for the control loop DAC).
|
||||
* The second argument is the DAC number.
|
||||
*/
|
||||
m4_define(m4_dac_wires, ⟨
|
||||
input [$1-1:0] dac_sel_$2,
|
||||
output dac_finished_$2,
|
||||
|
@ -27,12 +40,20 @@ m4_define(m4_dac_wires, ⟨
|
|||
input wf_ram_valid_$2
|
||||
⟩)
|
||||
|
||||
/* Same thing but for ADCs */
|
||||
|
||||
m4_define(m4_adc_wires, ⟨
|
||||
output adc_finished_$2,
|
||||
input adc_arm_$2,
|
||||
output [$1-1:0] from_adc_$2
|
||||
⟩)
|
||||
|
||||
/* This is used in the body of the module. It declares the interconnect
|
||||
* for each DAC. The first argument is the amount of switch ports the
|
||||
* DAC requires (2 for most DACs, 3 for the control loop DAC). The
|
||||
* second argument is the DAC number.
|
||||
*/
|
||||
|
||||
m4_define(m4_dac_switch, ⟨
|
||||
wire [$1-1:0] mosi_port_$2;
|
||||
wire [$1-1:0] miso_port_$2;
|
||||
|
@ -111,6 +132,8 @@ m4_define(m4_dac_switch, ⟨
|
|||
)
|
||||
⟩)
|
||||
|
||||
/* Same thing but for ADCs */
|
||||
|
||||
m4_define(m4_adc_switch, ⟨
|
||||
spi_master_ss_no_write #(
|
||||
.WID($1),
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
LOG_MODULE_REGISTER(access);
|
||||
|
||||
/* The values from converters are not aligned to an 8-bit byte.
|
||||
* These values are still in twos compliment and have to be
|
||||
* manually sign-extended.
|
||||
*/
|
||||
static inline uint32_t
|
||||
sign_extend(uint32_t in, unsigned len)
|
||||
{
|
||||
|
@ -74,6 +78,7 @@ dac_read_write(int dac, creole_word send, k_timeout_t timeout,
|
|||
int e = dac_take(dac, timeout);
|
||||
if (e != 0)
|
||||
return e;
|
||||
dac_switch(dac, DAC_SPI_PORT, K_NO_WAIT);
|
||||
|
||||
*to_dac[dac] = send;
|
||||
*dac_arm[dac] = 1;
|
||||
|
@ -94,6 +99,19 @@ dac_read_write(int dac, creole_word send, k_timeout_t timeout,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dac_switch(int dac, int setting, k_timeout_t timeout)
|
||||
{
|
||||
int e = dac_take(dac, timeout);
|
||||
if (e != 0)
|
||||
return e;
|
||||
|
||||
*dac_sel[dac] = setting;
|
||||
|
||||
dac_release(dac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* adc read
|
||||
*********************/
|
||||
|
@ -132,6 +150,25 @@ adc_release(int adc)
|
|||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
adc_switch(int adc, int setting, k_timeout_t timeout)
|
||||
{
|
||||
/* As of now, only one ADC (the CLOOP adc) is used
|
||||
* by two modules at the same time.
|
||||
*/
|
||||
if (adc != 0)
|
||||
return -ENOENT;
|
||||
|
||||
int e = adc_take(adc, timeout);
|
||||
if (e != 0)
|
||||
return e;
|
||||
|
||||
*adc_sel_0 = setting;
|
||||
|
||||
adc_release(adc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
adc_read(int adc, k_timeout_t timeout, creole_word *wrd)
|
||||
{
|
||||
|
@ -139,6 +176,7 @@ adc_read(int adc, k_timeout_t timeout, creole_word *wrd)
|
|||
if ((e = adc_take(adc, timeout)) != 0)
|
||||
return e;
|
||||
|
||||
adc_switch(adc, ADC_SPI_PORT, K_NO_WAIT);
|
||||
*adc_arm[adc] = 1;
|
||||
|
||||
/* Recursive locks should busy wait. */
|
||||
|
@ -173,15 +211,10 @@ cloop_take(k_timeout_t timeout)
|
|||
int
|
||||
cloop_release(void)
|
||||
{
|
||||
/* If being unlocked for the last time. */
|
||||
if (cloop_locked == 1) {
|
||||
*cl_cmd = CONTROL_LOOP_WRITE_BIT | CONTROL_LOOP_STATUS;
|
||||
cl_word_out[0] = 0;
|
||||
cl_word_out[1] = 0;
|
||||
*cl_start_cmd = 1;
|
||||
while (!*cl_finish_cmd);
|
||||
*cl_start_cmd = 0;
|
||||
}
|
||||
/* Do not attempt to reset the CLOOP interface.
|
||||
* Other scripts will fight to modify the CLOOP constants
|
||||
* while the loop is still running.
|
||||
*/
|
||||
int e = k_mutex_unlock(&cloop_mutex);
|
||||
if (e == 0) {
|
||||
cloop_locked--;
|
||||
|
@ -320,6 +353,8 @@ waveform_arm(int slot, bool halt_on_finish, uint32_t wait, k_timeout_t timeout)
|
|||
return 0;
|
||||
}
|
||||
|
||||
dac_switch(slot, DAC_WF_PORT, K_NO_WAIT);
|
||||
|
||||
*wf_halt_on_finish[slot] = halt_on_finish;
|
||||
*wf_time_to_wait[slot] = wait;
|
||||
*wf_arm[slot] = 1;
|
||||
|
|
|
@ -7,10 +7,20 @@ int dac_release(int dac);
|
|||
int dac_read_write(int dac, creole_word send, k_timeout_t timeout,
|
||||
creole_word *recv);
|
||||
|
||||
/* These ports are defined in firmware/rtl/base/base.v.m4 */
|
||||
#define DAC_SPI_PORT 0
|
||||
#define DAC_WF_PORT 1
|
||||
#define DAC_CLOOP_PORT 2
|
||||
int dac_switch(int dac, int setting, k_timeout_t timeout);
|
||||
|
||||
int adc_take(int adc, k_timeout_t timeout);
|
||||
int adc_release(int adc);
|
||||
int adc_read(int adc, k_timeout_t timeout, creole_word *wrd);
|
||||
|
||||
#define ADC_SPI_PORT 0
|
||||
#define ADC_CLOOP_PORT 1
|
||||
int adc_switch(int adc, int setting, k_timeout_t timeout);
|
||||
|
||||
int cloop_take(k_timeout_t timeout);
|
||||
int cloop_read(int code, uint32_t *high_reg, uint32_t *low_reg,
|
||||
k_timeout_t timeout);
|
||||
|
|
Loading…
Reference in New Issue