dac, adc switch and documentation

This commit is contained in:
Peter McGoron 2023-04-04 15:10:32 -04:00
parent b7ca97695a
commit e19a626945
4 changed files with 78 additions and 10 deletions

2
creole

@ -1 +1 @@
Subproject commit c7fc965fcfa72f26456f5221a6480de52f7d776a Subproject commit 0ead095044c93825c7db8cec0a6b92769bac7a7d

View File

@ -2,9 +2,22 @@ m4_changequote(`⟨', `⟩')
m4_changecom(⟨/*⟩, ⟨*/⟩) m4_changecom(⟨/*⟩, ⟨*/⟩)
m4_define(generate_macro, ⟨m4_define(M4_$1, $2)⟩) m4_define(generate_macro, ⟨m4_define(M4_$1, $2)⟩)
m4_include(../control_loop/control_loop_cmds.m4) 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 ************************/ /********************** 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, ⟨ m4_define(m4_dac_wires, ⟨
input [$1-1:0] dac_sel_$2, input [$1-1:0] dac_sel_$2,
output dac_finished_$2, output dac_finished_$2,
@ -27,12 +40,20 @@ m4_define(m4_dac_wires, ⟨
input wf_ram_valid_$2 input wf_ram_valid_$2
⟩) ⟩)
/* Same thing but for ADCs */
m4_define(m4_adc_wires, ⟨ m4_define(m4_adc_wires, ⟨
output adc_finished_$2, output adc_finished_$2,
input adc_arm_$2, input adc_arm_$2,
output [$1-1:0] from_adc_$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, ⟨ m4_define(m4_dac_switch, ⟨
wire [$1-1:0] mosi_port_$2; wire [$1-1:0] mosi_port_$2;
wire [$1-1:0] miso_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, ⟨ m4_define(m4_adc_switch, ⟨
spi_master_ss_no_write #( spi_master_ss_no_write #(
.WID($1), .WID($1),

View File

@ -18,6 +18,10 @@
LOG_MODULE_REGISTER(access); 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 static inline uint32_t
sign_extend(uint32_t in, unsigned len) 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); int e = dac_take(dac, timeout);
if (e != 0) if (e != 0)
return e; return e;
dac_switch(dac, DAC_SPI_PORT, K_NO_WAIT);
*to_dac[dac] = send; *to_dac[dac] = send;
*dac_arm[dac] = 1; *dac_arm[dac] = 1;
@ -94,6 +99,19 @@ dac_read_write(int dac, creole_word send, k_timeout_t timeout,
return 0; 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 * adc read
*********************/ *********************/
@ -132,6 +150,25 @@ adc_release(int adc)
return e; 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 int
adc_read(int adc, k_timeout_t timeout, creole_word *wrd) 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) if ((e = adc_take(adc, timeout)) != 0)
return e; return e;
adc_switch(adc, ADC_SPI_PORT, K_NO_WAIT);
*adc_arm[adc] = 1; *adc_arm[adc] = 1;
/* Recursive locks should busy wait. */ /* Recursive locks should busy wait. */
@ -173,15 +211,10 @@ cloop_take(k_timeout_t timeout)
int int
cloop_release(void) cloop_release(void)
{ {
/* If being unlocked for the last time. */ /* Do not attempt to reset the CLOOP interface.
if (cloop_locked == 1) { * Other scripts will fight to modify the CLOOP constants
*cl_cmd = CONTROL_LOOP_WRITE_BIT | CONTROL_LOOP_STATUS; * while the loop is still running.
cl_word_out[0] = 0; */
cl_word_out[1] = 0;
*cl_start_cmd = 1;
while (!*cl_finish_cmd);
*cl_start_cmd = 0;
}
int e = k_mutex_unlock(&cloop_mutex); int e = k_mutex_unlock(&cloop_mutex);
if (e == 0) { if (e == 0) {
cloop_locked--; cloop_locked--;
@ -320,6 +353,8 @@ waveform_arm(int slot, bool halt_on_finish, uint32_t wait, k_timeout_t timeout)
return 0; return 0;
} }
dac_switch(slot, DAC_WF_PORT, K_NO_WAIT);
*wf_halt_on_finish[slot] = halt_on_finish; *wf_halt_on_finish[slot] = halt_on_finish;
*wf_time_to_wait[slot] = wait; *wf_time_to_wait[slot] = wait;
*wf_arm[slot] = 1; *wf_arm[slot] = 1;

View File

@ -7,10 +7,20 @@ int dac_release(int dac);
int dac_read_write(int dac, creole_word send, k_timeout_t timeout, int dac_read_write(int dac, creole_word send, k_timeout_t timeout,
creole_word *recv); 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_take(int adc, k_timeout_t timeout);
int adc_release(int adc); int adc_release(int adc);
int adc_read(int adc, k_timeout_t timeout, creole_word *wrd); 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_take(k_timeout_t timeout);
int cloop_read(int code, uint32_t *high_reg, uint32_t *low_reg, int cloop_read(int code, uint32_t *high_reg, uint32_t *low_reg,
k_timeout_t timeout); k_timeout_t timeout);