KSFoundation  [April-2021]
A platform for simpler EPIC programming on GE MR systems
KSFoundation_tgt.c File Reference
#include <RtpPsd.h>
#include <PromoCommon.h>
#include "stddef_ep.h"
#include "pulsegen.h"
#include "epic.global.h"
#include "epicfuns.h"
#include "epicmsg.h"
#include "epicconf.h"
#include "ca_filt.h"
#include "psdutil.h"

Data Structures

union  Indices
 

Functions

STATUS scale (FLOAT(*inrotmat)[9], long(*outrotmat)[9], INT slquant, LOG_GRAD *lgrad, PHYS_GRAD *pgrad, INT contdebug)
 
void ks_scan_omegawave_hz (KS_WAVE *wave, int instanceno, float Hz)
 
void ks_scan_omegatrap_hz (KS_TRAP *trp, int instanceno, float Hz)
 
void ks_scan_wait (KS_WAIT *wait, int waitperiod)
 
void ks_scan_trap_ampscale (KS_TRAP *trp, int instanceno, float ampscale)
 
void ks_scan_trap_ampscale_slice (KS_TRAP *trp, int start, int skip, int count, float ampscale)
 
void ks_scan_phaser_kmove (KS_PHASER *phaser, int instanceno, double pixelunits)
 
void ks_scan_phaser_toline (KS_PHASER *phaser, int instanceno, int view)
 
void ks_scan_phaser_fromline (KS_PHASER *phaser, int instanceno, int view)
 
void ks_scan_rf_ampscale (KS_RF *rf, int instanceno, float ampscale)
 
void ks_scan_rf_on (KS_RF *rf, int instanceno)
 
void ks_scan_rf_on_chop (KS_RF *rf, int instanceno)
 
void ks_scan_rf_off (KS_RF *rf, int instanceno)
 
unsigned int ks_cycles_to_iphase (double cycles)
 
unsigned int ks_degrees_to_iphase (double degrees)
 
unsigned int ks_radians_to_iphase (double radians)
 
void ks_scan_selrf_setfreqphase_pins (KS_SELRF *selrf, int instanceno, SCAN_INFO sliceinfo, int sms_multiband_factor, float sms_slice_gap, float rfphase)
 
void ks_scan_selrf_setfreqphase (KS_SELRF *selrf, int instanceno, SCAN_INFO sliceinfo, float rfphase)
 
void ks_scan_rf_setphase (KS_RF *rf, int instanceno, float rfphase)
 
void ks_scan_wave2hardware (KS_WAVE *wave, const KS_WAVEFORM newwave)
 
void ks_scan_offsetfov_iso (KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, double ky, double kz, double rcvphase)
 
void ks_scan_offsetfov_iso_readwave (KS_READWAVE *readwave, int instanceno, SCAN_INFO sliceinfo, double ky, double kz, double rcvphase)
 
void ks_scan_offsetfov (KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, float ky, float phasefovratio, float rcvphase)
 
void ks_scan_offsetfov3D (KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, float ky, float phasefovratio, float kz, float zphasefovratio, float rcvphase)
 
void ks_scan_offsetfov_readwave (KS_READWAVE *readwave, int instanceno, SCAN_INFO sliceinfo, float ky, float phasefovratio, float rcvphase)
 
void ks_scan_rotate (SCAN_INFO slice_info)
 
void ks_scan_isirotate (KS_ISIROT *isirot)
 
int ks_scan_getsliceloc (const KS_SLICE_PLAN *slice_plan, int passindx, int sltimeinpass)
 
int ks_scan_getslicetime (const KS_SLICE_PLAN *slice_plan, int passindx, int slloc)
 
ks_enum_epiblipsign ks_scan_epi_verify_phaseenc_plan (KS_EPI *epi, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
 
void ks_scan_epi_shotcontrol (KS_EPI *epi, int echo, SCAN_INFO sliceinfo, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, int exc, float rcvphase)
 
void ks_scan_epi_loadecho_with_tag (KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, KSEPI_DATATAG *datatag, KS_DATASTORETAG *datastoretag)
 
void ks_scan_epi_loadecho_with_datastoretag (KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, KS_DATASTORETAG *datastoretag)
 
void ks_scan_epi_loadecho_with_epidatatag (KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, KSEPI_DATATAG *datatag)
 
void ks_scan_epi_loadecho (KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
 
void ks_loaddab (WF_PULSE_ADDR echo, char *custom_dab_array)
 
void ks_loaddab_datastoretag (WF_PULSE_ADDR echo, KS_DATASTORETAG *datastoretag)
 
void ks_scan_acq_to_rtp (KS_READ *acq, TYPDAB_PACKETS dabacqctrl, float fatoffset)
 
STATUS boffset (long *offsets)
 
void ks_scan_switch_to_sequence (KS_SEQ_CONTROL *ctrl)
 
STATUS setssitime (long)
 
STATUS startseq (s16, s16)
 
int ks_scan_playsequence (KS_SEQ_CONTROL *ctrl)
 
STATUS ks_scan_loaddabwithindices_nex (WF_PULSE_ADDR pulse, LONG slice, LONG echo, LONG view, uint8_t acq, uint8_t vol, LONG operation, TYPDAB_PACKETS acqon_flag)
 
STATUS ks_scan_loaddabwithindices (WF_PULSE_ADDR pulse, LONG slice, LONG echo, LONG view, uint8_t acq, uint8_t vol, TYPDAB_PACKETS acqon_flag)
 
int ks_scan_wait_for_rtp (void *rtpmsg, int maxmsgsize, int maxwait, KS_SEQ_CONTROL *waitctrl)
 
void ks_copy_and_reset_obj (void *pobj)
 
void ks_tgt_reset_gradrfctrl (KS_GRADRFCTRL *gradrfctrl)
 
void ks_show_clock (FLOAT scantime)
 
STATUS acqq_longdab (WF_PULSE_ADDR pulse, LONG pos_ref, LONG dab_ref, LONG xtr_ref, LONG fslot_value)
 

Variables

float GAM
 
int cfreceiveroffsetfreq
 
int rspent
 
int pscR1
 
int cfcoilswitchmethod
 
int cfswgut
 
int cfswrfut
 
int rhasset
 
int cfhwgut
 
int piviews
 
int opslicecnt
 

Detailed Description

This file contains functions only accessible on TGT.

Function Documentation

◆ scale()

STATUS scale ( FLOAT(*)  inrotmat[9],
long(*)  outrotmat[9],
INT  slquant,
LOG_GRAD *  lgrad,
PHYS_GRAD *  pgrad,
INT  contdebug 
)

◆ ks_scan_omegawave_hz()

void ks_scan_omegawave_hz ( KS_WAVE wave,
int  instanceno,
float  Hz 
)

Updates a KS_WAVE object on the OMEGA board to produce a frequency offset

A KS_WAVE object on OMEGA can be used to perform a dynamic frequency offset

  1. while an RF pulse is played out. One example is Spectral-Spatial RF pulses
  2. during data acquisition
Parameters
[in,out]wavePointer to KS_WAVE
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]HzDesired frequency offset in [Hz] for the point in the KS_WAVE with the largest absolute amplitude
Return values
STATUSSUCCESS or FAILURE
57  {
58  int iamp;
59  float omega_scale = 256.0;
60 
61  iamp = (int) (Hz / (TARDIS_FREQ_RES * omega_scale));
62 
63  if (abs(iamp) > 32768) {
64  ks_error("ks_scan_omegawave_hz(%s): the integer amplitude is too large (%d) for instance %d", wave->description, iamp, instanceno);
65  return;
66  }
67 
68 #ifdef IPG
69 
70  if (wave->wfi[instanceno].loc.board != OMEGA) {
71  ks_error("ks_scan_omegawave_hz(%s): Only omega board is supported", wave->description);
72  return;
73  }
74 
75  /* input validation */
76  if (instanceno < 0 || instanceno >= wave->base.ngenerated) {
77  ks_error("ks_scan_omegawave_hz(%s): instanceno (%d) out of range [0,%d)", wave->description, instanceno, wave->base.ngenerated);
78  return;
79  }
80 
81  if (setiamp((short) iamp, wave->wfi[instanceno].wf, wave->wfi[instanceno].boardinstance) != SUCCESS) {
82  ks_error("ks_scan_omegawave_hz(%s): An error occurred calling 'setiampt()'", wave->description);
83  return;
84  }
85 
86 #else
87  int numplaced = wave->base.ninst;
88  if (!numplaced) {
89  return;
90  }
91  float* tmp = (float*)realloc(wave->rtscale, numplaced * sizeof(float));
92  if (!tmp) {
93  ks_error("%s: rtscale realloc failed", __FUNCTION__);
94  return;
95  }
96  wave->rtscale = tmp;
97  wave->rtscale[instanceno] = Hz;
98 
99 #endif
100 
101 } /* ks_scan_omegawave_hz */
float * rtscale
Definition: KSFoundation.h:675
int boardinstance
Definition: KSFoundation.h:399
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
int board
Definition: KSFoundation.h:388
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:674
KS_SEQLOC loc
Definition: KSFoundation.h:401
KS_DESCRIPTION description
Definition: KSFoundation.h:666
KS_BASE base
Definition: KSFoundation.h:665
WF_PULSE * wf
Definition: KSFoundation.h:400
int ngenerated
Definition: KSFoundation.h:410

◆ ks_scan_omegatrap_hz()

void ks_scan_omegatrap_hz ( KS_TRAP trap,
int  instanceno,
float  Hz 
)

Updates a KS_TRAP object on the OMEGA board to produce a frequency offset

A KS_TRAP object on OMEGA is used for rampsampled acquisitions and is placed out using ks_pg_readtrap() for a KS_READTRAP object if the field .rampsampling = 1. This will cause a trapezoidal frequency shift during the readout instead of a fixed frequency offset when rampsampling is not used. An error is returned if the current instance of the KS_TRAP is on another board than OMEGA

For Cartesian applications, there is no need to call this function directly, since ks_scan_offsetfov() already calls this function

Special note for OMEGA: Neither the .amp field nor the .ampscale field passed in to ks_pg_trap() has an effect. Only the Hz argument controls the frequency shift

Parameters
[in,out]trapPointer to KS_TRAP
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]HzDesired frequency offset in [Hz] at the plateau of the trapezoid
Return values
STATUSSUCCESS or FAILURE
105  {
106  int iamp;
107  float omega_scale = 256.0;
108 
109  iamp = (int) (Hz / (TARDIS_FREQ_RES * omega_scale));
110  if (abs(iamp) > 32768) {
111  ks_error("ks_scan_omegatrap_hz(%s): the integer amplitude is too large (%d) for instance %d", trp->description, iamp, instanceno);
112  return;
113  }
114 
115 #ifdef IPG
116 
117  if (trp->wfi[instanceno].loc.board != OMEGA) {
118  ks_error("ks_scan_omegatrap_hz(%s): Wrong function - use ks_scan_trap_ampscale() KS_TRAPs on XGRAD, YGRAD, ZGRAD", trp->description);
119  return;
120  }
121 
122  /* input validation */
123  if (instanceno < 0 || instanceno >= trp->base.ngenerated) {
124  ks_error("ks_scan_omegatrap_hz(%s): instanceno (%d) out of range [0,%d)", trp->description, instanceno, trp->base.ngenerated);
125  return;
126  }
127 
128  if (setiampt((short) iamp, trp->wfi[instanceno].wf, trp->wfi[instanceno].boardinstance) != SUCCESS) {
129  ks_error("ks_scan_omegatrap_hz(%s): An error occurred calling 'setiampt()'", trp->description);
130  return;
131  }
132 
133 #else
134  int numplaced = trp->base.ninst;
135  if (!numplaced) {
136  return;
137  }
138  float* tmp = (float*)realloc(trp->rtscale, numplaced * sizeof(float));
139  if (!tmp) {
140  ks_error("%s: rtscale realloc failed", __FUNCTION__);
141  return;
142  }
143  trp->rtscale = tmp;
144  trp->rtscale[instanceno] = Hz;
145 #endif
146 
147 } /* ks_scan_omegatrap_hz */
int boardinstance
Definition: KSFoundation.h:399
KS_BASE base
Definition: KSFoundation.h:579
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
int board
Definition: KSFoundation.h:388
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:591
KS_SEQLOC loc
Definition: KSFoundation.h:401
WF_PULSE * wf
Definition: KSFoundation.h:400
KS_DESCRIPTION description
Definition: KSFoundation.h:580
int ngenerated
Definition: KSFoundation.h:410
float * rtscale
Definition: KSFoundation.h:592

◆ ks_scan_wait()

void ks_scan_wait ( KS_WAIT wait,
int  waitperiod 
)

Updates the wait period of all instances of a KS_WAIT sequence object. The value of waitperiod must not exceed

.duration.

Parameters
[in,out]waitPointer to KS_WAIT
[in]waitperiodTime in [us] to wait
Return values
STATUSSUCCESS or FAILURE
151  {
152 
153 #ifdef IPG
154  int i;
155  int numplaced = wait->base.ngenerated;
156 #else
157  int numplaced = wait->base.ninst;
158 #endif
159 
160  if (numplaced == 0) {
161  return;
162  }
163 
164  /* input validation */
165  if (waitperiod < 0) {
166  ks_error("ks_scan_wait(%s): wait period %d is negative", wait->description, waitperiod);
167  return;
168  }
169  if (waitperiod < GRAD_UPDATE_TIME) {
170  waitperiod = GRAD_UPDATE_TIME;
171  }
172  if (waitperiod % GRAD_UPDATE_TIME) {
173  ks_error("ks_scan_wait(%s): waitperiod (3rd arg) on gradient boards must be divisible by 4", wait->description);
174  return;
175  }
176 
177 #ifdef IPG
178 
179  if (wait->wfi == NULL) {
180  ks_error("ks_scan_wait(%s): WF_INSTANCE of trap is NULL", wait->description);
181  }
182 
183  /* set amplitude(s) */
184  for (i = 0; i < numplaced; i++) {
185 
186  if (setperiod(waitperiod, wait->wfi[i].wf, wait->wfi[i].boardinstance) != SUCCESS) {
187  ks_error("ks_scan_wait(%s): An error occurred calling 'setperiod()'", wait->description);
188  return;
189  }
190  }
191 
192 #endif
193 
194 } /* ks_scan_wait */
int boardinstance
Definition: KSFoundation.h:399
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
KS_DESCRIPTION description
Definition: KSFoundation.h:458
KS_BASE base
Definition: KSFoundation.h:457
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:462
WF_PULSE * wf
Definition: KSFoundation.h:400
int ngenerated
Definition: KSFoundation.h:410

◆ ks_scan_trap_ampscale()

void ks_scan_trap_ampscale ( KS_TRAP trap,
int  instanceno,
float  ampscale 
)

Updates the amplitude of one or all instances of a KS_TRAP sequence object

This function multiplies one instance of a KS_TRAP object with an amplitude scale factor (3rd arg) that should be in range [-1.0,1.0] to avoid slewrate issues. To change all instances of a KS_TRAP object, use INSTRALL as the 2nd argument.

The actual amplitude for an instance of a KS_TRAP object is the multiplication of the three factors:

  1. The designed amplitude [G/cm]
  2. The per-instance .ampscale in the KS_SEQLOC struct passed to ks_pg_trap()
  3. The ampscale value passed in as 3rd argument to this function.
Parameters
[in,out]trapPointer to KS_TRAP
[in]instancenoInstance of KS_TRAP to change (INSTRALL changes all instances)
[in]ampscaleGradient amplitude scale factor, normally in range [-1.0,1.0], but the range [-1.2, 1.2] is allowed to allow certain run-time gradient corrections
Return values
STATUSSUCCESS or FAILURE
199  {
200  int firstinstance, lastinstance, i;
201 #ifdef IPG
202  int iamp;
203  float gradmax;
204  int numplaced = trp->base.ngenerated;
205 #else
206  int numplaced = trp->base.ninst;
207  if (!numplaced) {
208  return;
209  }
210  float* tmp = (float*)realloc(trp->rtscale, numplaced * sizeof(float));
211  if (!tmp) {
212  ks_error("%s: rtscale realloc failed", __FUNCTION__);
213  return;
214  }
215  trp->rtscale = tmp;
216 #endif
217 
218  if (instanceno == INSTRALL) {
219  firstinstance = 0;
220  lastinstance = numplaced - 1;
221  } else {
222  firstinstance = instanceno;
223  lastinstance = instanceno;
224  }
225 
226  /* input validation */
227  if (numplaced == 0) {
228  return;
229  }
230  if (firstinstance < 0 || lastinstance >= numplaced) {
231  ks_error("ks_scan_trap_ampscale(%s): instanceno (%d) out of range [0,%d]", trp->description, instanceno, numplaced - 1);
232  return;
233  }
234 
235  /* Allow ampscale to be 20% larger than 1. This, to allow future minor runtime changes of trapezoid amplitudes
236  for e.g. (future possible implementations):
237  - oblique ghost correction for EPI, where odd/even blip amps need to be made smaller/larger depending on slice angle and delays
238  - eddy current correction for DW-EPI, where readout lobe amp needs to be changed per diffusion direction etc.
239  If 'ampscale' is larger than 1.0 (i.e. between 1.0 and 1.2), the trapezoid must have been designed with a slewrate that is slightly
240  under the very limit of the system (and the dB/dt limits for PNS). Use with caution. */
241 
242  if (fabs(ampscale) > sqrt(3)) {
243  ks_error("ks_scan_trap_ampscale(%s): ampscale too large (%f)", trp->description, ampscale);
244  return;
245  }
246 
247  /*
248  - trp->amp: The amplitude that was initially designed for the KS_TRAP. Should never be exceeded, or slew rate issues will occur
249  - trp->wfi[i].loc.ampscale: -1.0 -> +1.0. Amp scale factor for each instance of the KS_TRAP placed in the sequence.
250  - ampscale (3rd input arg): -1.0 -> +1.0 (in normal cases). The dynamic amp scale (i.e. over time, or TRs).
251  The product [trp->wfi[i].loc.ampscale * ampscale] should be in range [-1, 1] to avoid slew rate issues.
252  */
253 
254 #ifdef IPG
255 
256  if (trp->wfi == NULL) {
257  ks_error("ks_scan_trap_ampscale(%s): WF_INSTANCE of trap is NULL", trp->description);
258  return;
259  }
260 
261  /* set amplitude(s) */
262  for (i = firstinstance; i <= lastinstance; i++) {
263  gradmax = ks_syslimits_gradtarget(loggrd, trp->wfi[i].loc.board);
264  iamp = (int)((ampscale * trp->wfi[i].loc.ampscale * trp->amp / gradmax) * MAX_PG_IAMP);
265 
266  if (abs(iamp) > 32768) {
267  ks_error("ks_scan_trap_ampscale(%s): the integer amplitude is too large (%d) for instance %d", trp->description, iamp, i);
268  return;
269  }
270  if (trp->wfi[i].loc.board == OMEGA) {
271  ks_error("ks_scan_trap_ampscale(%s): Instance %d on board OMEGA. Please use ks_scan_omegatrap_hz() instead", trp->description, i);
272  return;
273  }
274  if (setiampt((short) iamp, trp->wfi[i].wf, trp->wfi[i].boardinstance) != SUCCESS) {
275  ks_error("ks_scan_trap_ampscale(%s): An error occurred calling 'setiampt()'", trp->description);
276  return;
277  }
278 
279  }
280 
281 #else
282  for (i = firstinstance; i <= lastinstance; i++) {
283  trp->rtscale[i] = ampscale;
284  }
285 #endif
286 } /* ks_scan_trap_ampscale */
int boardinstance
Definition: KSFoundation.h:399
KS_BASE base
Definition: KSFoundation.h:579
float ks_syslimits_gradtarget(LOG_GRAD loggrd, int board)
Returns the maximum target amplitude for a board (internal use)
Definition: KSFoundation_common.c:220
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
int board
Definition: KSFoundation.h:388
float ampscale
Definition: KSFoundation.h:390
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:591
KS_SEQLOC loc
Definition: KSFoundation.h:401
LOG_GRAD loggrd
float amp
Definition: KSFoundation.h:581
WF_PULSE * wf
Definition: KSFoundation.h:400
KS_DESCRIPTION description
Definition: KSFoundation.h:580
int ngenerated
Definition: KSFoundation.h:410
float * rtscale
Definition: KSFoundation.h:592

◆ ks_scan_trap_ampscale_slice()

void ks_scan_trap_ampscale_slice ( KS_TRAP trap,
int  start,
int  skip,
int  count,
float  ampscale 
)

Updates the amplitude of a selection of instances of a KS_TRAP sequence object

This function multiplies some instances of a KS_TRAP object with an amplitude scale factor (5th arg) that should be in range [-1.0,1.0] to avoid slewrate issues.

The instances to change are start + i * skip, where i goes from 0 to count. FAILURE is returned if either start or start + count * skip out of range or count is negative

Parameters
[in,out]trapPointer to KS_TRAP
[in]startFirst instance number of the KS_TRAP
[in]skipDifference in instance number between consecutive instances
[in]countNumber of instances to change in total
[in]ampscaleGradient amplitude scale factor, normally in range [-1.0,1.0], but the range [-1.2, 1.2] is allowed to allow certain run-time gradient corrections
Return values
STATUSSUCCESS or FAILURE
290  {
291  int i;
292 #ifdef IPG
293  int numplaced = trp->base.ngenerated;
294 #else
295  int numplaced = trp->base.ninst;
296 #endif
297 
298  if (numplaced == 0) {
299  return;
300  }
301 
302  /* check range */
303  const int end = start + (count - 1) * skip;
304 
305  if (start < 0 || start >= numplaced || end < 0 || end >= numplaced || count < 0) {
306  ks_error("ks_scan_trap_ampscale_slice(%s): slice with start = %d, skip = %d and count = %d has endpoints outside [0,%d)", trp->description, start, skip, count, numplaced);
307  return;
308  }
309 
310  for (i = 0; i < count; ++i) {
311  ks_scan_trap_ampscale(trp, start + i * skip, ampscale);
312  }
313 
314 } /* ks_scan_trap_ampscale_slice */
KS_BASE base
Definition: KSFoundation.h:579
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
KS_DESCRIPTION description
Definition: KSFoundation.h:580
void ks_scan_trap_ampscale(KS_TRAP *trp, int instanceno, float ampscale)
Updates the amplitude of one or all instances of a KS_TRAP sequence object
Definition: KSFoundation_tgt.c:199
int ngenerated
Definition: KSFoundation.h:410

◆ ks_scan_phaser_kmove()

void ks_scan_phaser_kmove ( KS_PHASER phaser,
int  instanceno,
double  pixelunits 
)

Updates the amplitude of a KS_PHASER sequence object to move some arbitrary distance in k-space

This function sets the amplitude of the gradient for a KS_PHASER object so that a shift in k-space of pixelunits number of pixels is produced. If pixelunits is 1.0, the gradient area corresponds to one pixel shift in a fully sampled k-space (no parallel imaging) along the board the KS_PHASER object is placed on. pixelunits is of type float and any non-integer value is accepted, and the sign of pixelunits determines the direction of k-space shift

Parameters
[in,out]phaserPointer to KS_PHASER
[in]instancenoInstance of KS_TRAP to change (INSTRALL changes all instances)
[in]pixelunitsNon-integer pixel units in a fully sampled k-space to move
Return values
STATUSSUCCESS or FAILURE
318  {
319  double phasepixelarea = (double) ks_calc_fov2gradareapixel(phaser->fov);
320  double newarea = pixelunits * phasepixelarea + (double) phaser->areaoffset;
321  double ampscale = newarea / phaser->grad.area;
322 
323  if (phaser == NULL)
324  return;
325 
326  if (fabs(ampscale) > 1.00003) { /* 1.00003 corresponds to 32768 / 32767, i.e. excess of one short int */
327 #ifndef IPG
328  ks_error("ks_scan_phaser_kmove(%s): Too large value (%g) in 3rd arg", phaser->grad.description, pixelunits);
329 #endif
330  } else if (fabs(ampscale) > 1.0) {
331  /* small round-off fix when ampscale is in range [1.0, 1.00003] */
332  ampscale = ampscale < 0 ? -1.0 : 1.0;
333  }
334 
335  ks_scan_trap_ampscale(&phaser->grad, instanceno, ampscale);
336 
337 } /* ks_scan_phaser_kmove */
KS_TRAP grad
Definition: KSFoundation.h:1676
float ks_calc_fov2gradareapixel(float fov)
Calculates the gradient area needed to move one pixel in k-space
Definition: KSFoundation_common.c:346
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
float areaoffset
Definition: KSFoundation.h:1683
float area
Definition: KSFoundation.h:582
KS_DESCRIPTION description
Definition: KSFoundation.h:580
void ks_scan_trap_ampscale(KS_TRAP *trp, int instanceno, float ampscale)
Updates the amplitude of one or all instances of a KS_TRAP sequence object
Definition: KSFoundation_tgt.c:199
float fov
Definition: KSFoundation.h:1677

◆ ks_scan_phaser_toline()

void ks_scan_phaser_toline ( KS_PHASER phaser,
int  instanceno,
int  view 
)

Updates the amplitude of a KS_PHASER sequence object to move from the k-space center to a desired k-space line

This function sets the amplitude of the gradient for a KS_PHASER object to produce a k-space shift from the center of k-space to the view number (3rd arg). The view number must be an integer in range [0, .res-1], and the number refers to a fully sampled k-space (without parallel imaging)

Parameters
[in,out]phaserPointer to KS_PHASER
[in]instancenoInstance of KS_TRAP to change (INSTRALL changes all instances)
[in]viewPhase encoding line to acquire with index corresponding to a fully sampled k-space [0, res-1]
Return values
STATUSSUCCESS or FAILURE
340  {
341  double kmax;
342 
343  if (phaser == NULL)
344  return;
345 
346  if (view < 0 || view >= phaser->res) {
347  ks_scan_phaser_kmove(phaser, instanceno, 0.0);
348  return;
349  }
350 
351  /* KSFoundation 'view' is always 0-based: e.g. res = 256: view = 0->255. */
352  kmax = ((phaser->res - 1.0) / 2.0);
353  ks_scan_phaser_kmove(phaser, instanceno, kmax - view);
354 
355 } /* ks_scan_phaser_toline */
int res
Definition: KSFoundation.h:1678
void ks_scan_phaser_kmove(KS_PHASER *phaser, int instanceno, double pixelunits)
Updates the amplitude of a KS_PHASER sequence object to move some arbitrary distance in k-space...
Definition: KSFoundation_tgt.c:318
int view
Definition: GERequired.e:2642

◆ ks_scan_phaser_fromline()

void ks_scan_phaser_fromline ( KS_PHASER phaser,
int  instanceno,
int  view 
)

Updates the amplitude of a KS_PHASER sequence object to move from a k-space line to the k-space center

This function sets the amplitude of the gradient for a KS_PHASER object to produce a k-space shift from the view number (3rd arg) to the k-space center. The view number must be an integer in range [0, .res-1], and the number refers to a fully sampled k-space (without parallel imaging)

Parameters
[in,out]phaserPointer to KS_PHASER
[in]instancenoInstance of KS_TRAP to change (INSTRALL changes all instances)
[in]viewPhase encoding line to acquire with index corresponding to a fully sampled k-space [0, res-1]
Return values
STATUSSUCCESS or FAILURE
359  {
360  double kmax;
361 
362  if (phaser == NULL)
363  return;
364 
365  if (view < 0 || view >= phaser->res) {
366  ks_scan_phaser_kmove(phaser, instanceno, 0.0);
367  return;
368  }
369 
370  /* KSFoundation 'view' is always 0-based: e.g. res = 256: view = 0->255. */
371  kmax = ((phaser->res - 1.0) / 2.0);
372  ks_scan_phaser_kmove(phaser, instanceno, view - kmax);
373 
374 } /* ks_scan_phaser_fromline */
int res
Definition: KSFoundation.h:1678
void ks_scan_phaser_kmove(KS_PHASER *phaser, int instanceno, double pixelunits)
Updates the amplitude of a KS_PHASER sequence object to move some arbitrary distance in k-space...
Definition: KSFoundation_tgt.c:318
int view
Definition: GERequired.e:2642

◆ ks_scan_rf_ampscale()

void ks_scan_rf_ampscale ( KS_RF rf,
int  instanceno,
float  ampscale 
)

Changes the amplitude of one or all instances of an RF pulse (KS_RF)

This function multiplies one instance of a KS_RF object with an amplitude scale factor (3rd arg) that must be in range [-1.0,1.0]. To change all instances of a KS_RF object, use INSTRALL as the 2nd argument.

The actual flip angle for an instance of a KS_RF object is the multiplication of the three factors:

  1. The designed flip angle
  2. The per-instance .ampscale in the KS_SEQLOC struct passed to ks_pg_rf()
  3. The ampscale value passed in as 3rd argument to this function. Since both ampscale factors are forced to be in range [-1.0,1.0], it is not possible to increase the flip angle beyond the designed value (.flip)
Parameters
[in,out]rfPointer to KS_RF
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]ampscaleRF amplitude scale factor in range [-1.0,1.0]
379  {
380  int firstinstance, lastinstance, i;
381 #ifdef IPG
382  int instramp;
383  KS_WFINSTANCE *wfi;
384  int numplaced = rf->rfwave.base.ngenerated;
385 #else
386  int numplaced = rf->rfwave.base.ninst;
387  if (!numplaced) {
388  return;
389  }
390  float* tmp = (float*)realloc(rf->rfwave.rtscale, numplaced * sizeof(float));
391  if (!tmp) {
392  ks_error("%s: rtscale realloc failed", __FUNCTION__);
393  return;
394  }
395  rf->rfwave.rtscale = tmp;
396 #endif
397 
398  if (instanceno == INSTRALL) {
399  firstinstance = 0;
400  lastinstance = numplaced - 1;
401  } else {
402  firstinstance = instanceno;
403  lastinstance = instanceno;
404  }
405 
406  /* input validation */
407  if (numplaced == 0) {
408  return;
409  }
410 
411  if (firstinstance < 0 || lastinstance >= numplaced) {
412  ks_error("ks_scan_rf_ampscale(%s): instanceno (%d) out of range [0,%d]", rf->rfwave.description, instanceno, numplaced - 1);
413  return;
414  }
415 
416  if (fabs(ampscale) > 1.0) {
417  ks_error("ks_scan_rf_ampscale(%s): ampscale too large (%f)", rf->rfwave.description, ampscale);
418  return;
419  }
420 
421 #ifdef IPG
422 
423  /* set amplitude(s) */
424  for (i = firstinstance; i <= lastinstance; i++) {
425  wfi = &rf->rfwave.wfi[i];
426  instramp = (int)(rf->amp * wfi->loc.ampscale * ampscale * MAX_PG_IAMP);
427  setiamp(instramp, wfi->wf, wfi->boardinstance);
428  } /* for */
429 
430 #else
431  for (i = firstinstance; i <= lastinstance; i++) {
432  rf->rfwave.rtscale[i] = ampscale;
433  }
434 #endif
435 
436 } /* ks_scan_rf_ampscale */
float * rtscale
Definition: KSFoundation.h:675
int boardinstance
Definition: KSFoundation.h:399
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
(Internal use) Structure being a part of various sequence objects to sort them in time across boards...
Definition: KSFoundation.h:398
int ninst
Definition: KSFoundation.h:409
float ampscale
Definition: KSFoundation.h:390
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:674
KS_SEQLOC loc
Definition: KSFoundation.h:401
KS_DESCRIPTION description
Definition: KSFoundation.h:666
KS_WAVE rfwave
Definition: KSFoundation.h:949
KS_BASE base
Definition: KSFoundation.h:665
float amp
Definition: KSFoundation.h:943
WF_PULSE * wf
Definition: KSFoundation.h:400
int ngenerated
Definition: KSFoundation.h:410

◆ ks_scan_rf_on()

void ks_scan_rf_on ( KS_RF rf,
int  instanceno 
)

Resets the amplitude of one or all instances of an RF pulse (KS_RF)

This function (re)sets the RF amplitude to the state given by ks_pg_rf()

Parameters
[in,out]rfPointer to KS_RF
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
442  {
443 
444  ks_scan_rf_ampscale(rf, instanceno, 1.0);
445 
446 }
void ks_scan_rf_ampscale(KS_RF *rf, int instanceno, float ampscale)
Changes the amplitude of one or all instances of an RF pulse (KS_RF)
Definition: KSFoundation_tgt.c:379

◆ ks_scan_rf_on_chop()

void ks_scan_rf_on_chop ( KS_RF rf,
int  instanceno 
)

Resets the amplitude of one or all instances of an RF pulse (KS_RF) and toggles the sign (chopping)

Everytime this function is called, the magnitude of the RF amplitude will be (re)set the RF amplitude to the state given by ks_pg_rf() and the polarity of the RF amplitude will be changed. If this function is called each TR (RF chopping) for a linear single-line k-space acquisition, a FOV/2 shift will occur in the image with any DC component shifted out to the edges of the image FOV.

Parameters
[in,out]rfPointer to KS_RF
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
457  {
458  static float chopsign = 1.0;
459 
460  ks_scan_rf_ampscale(rf, instanceno, chopsign);
461 
462  chopsign *= -1.0;
463 
464 }
void ks_scan_rf_ampscale(KS_RF *rf, int instanceno, float ampscale)
Changes the amplitude of one or all instances of an RF pulse (KS_RF)
Definition: KSFoundation_tgt.c:379

◆ ks_scan_rf_off()

void ks_scan_rf_off ( KS_RF rf,
int  instanceno 
)

Sets the amplitude of one or all instances of an RF pulse (KS_RF) to zero

This can be undone by calling ks_scan_rf_on(), ks_scan_rf_on_chop(), or ks_scan_rf_ampscale()

Parameters
[in,out]rfPointer to KS_RF
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
469  {
470 
471  ks_scan_rf_ampscale(rf, instanceno, 0.0);
472 
473 }
void ks_scan_rf_ampscale(KS_RF *rf, int instanceno, float ampscale)
Changes the amplitude of one or all instances of an RF pulse (KS_RF)
Definition: KSFoundation_tgt.c:379

◆ ks_cycles_to_iphase()

unsigned int ks_cycles_to_iphase ( double  cycles)
483  {
484  /* Actual period for u14 */
485  static const unsigned int FS_2PI_u14 = (1<<14);
486  /* Want the fractional part */
487  cycles -= (long)cycles;
488  /* Force positive */
489  cycles++;
490  /* Scale to u14 domain then shift two bits to the
491  left for compatibility with FS_2PI [u16] period. */
492  return (unsigned int)(cycles * (double)FS_2PI_u14 + 0.5) % FS_2PI_u14 << 2;
493 } /* ks_cycles_to_iphase */

◆ ks_degrees_to_iphase()

unsigned int ks_degrees_to_iphase ( double  degrees)
495  {
496  return ks_cycles_to_iphase(degrees / 360.0);
497 } /* wrapper for ks_cycles_to_iphase */
unsigned int ks_cycles_to_iphase(double cycles)
Definition: KSFoundation_tgt.c:483

◆ ks_radians_to_iphase()

unsigned int ks_radians_to_iphase ( double  radians)
499  {
500  return ks_cycles_to_iphase(radians / (2.0 * PI));
501 } /* wrapper for ks_cycles_to_iphase */
unsigned int ks_cycles_to_iphase(double cycles)
Definition: KSFoundation_tgt.c:483

◆ ks_scan_selrf_setfreqphase_pins()

void ks_scan_selrf_setfreqphase_pins ( KS_SELRF selrf,
int  instanceno,
SCAN_INFO  sliceinfo,
int  sms_multiband_factor,
float  sms_slice_gap,
float  rfphase 
)

Updates the off-center phase-modulation of one or all instances of a PINS RF pulse (KS_SELRF)

This function alters the phase of the PINS RF pulse in a KS_SELRF object to excite spatial locations corresponding to the information in sliceinfo.tloc.

Parameters
[in,out]selrfPointer to KS_SELRF
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]sliceinfoSCAN_INFO struct for the current slice to be played out
[in]sms_multiband_factor
[in]sms_slice_gapin [mm]
[in]rfphasePhase of the RF pulse in [degrees]
Return values
STATUSSUCCESS or FAILURE
509  {
510 
511  int firstinstance, lastinstance, j;
512  int phaseIndex = 1;
513  KS_WAVE newwave = KS_INIT_WAVE;
514  float locOffset;
515  float phaseIncrement;
516 #ifdef IPG
517  int i;
518  int numplaced = selrf->rf.rfwave.base.ngenerated;
519 #else
520  int numplaced = selrf->rf.rfwave.base.ninst;
521 #endif
522 
523  if (instanceno == INSTRALL) {
524  firstinstance = 0;
525  lastinstance = numplaced - 1;
526  } else {
527  firstinstance = instanceno;
528  lastinstance = instanceno;
529  }
530 
531  if (numplaced == 0) {
532  return;
533  }
534 
535  if (firstinstance < 0 || lastinstance >= numplaced) {
536  ks_error("ks_scan_selrf_setfreqphase_pins(%s): instanceno (%d) out of range [0,%d]", selrf->rf.rfwave.description, instanceno, numplaced - 1);
537  return;
538  }
539 
540  newwave = selrf->rf.thetawave;
541 
542  locOffset = sliceinfo.optloc;
543  phaseIncrement = (360.0 / sms_slice_gap) * locOffset;
544 
545  /* If the MB-factor is even, center the slice group */
546  if (sms_multiband_factor % 2 == 0) {
547  phaseIncrement += 180.0;
548  }
549 
550  for (j = 0; j < selrf->rf.thetawave.res; j++) {
551 
552  if (!areSame(selrf->rf.rfwave.waveform[j], 0.0)) {
553  newwave.waveform[j] = selrf->rf.thetawave.waveform[j] + ((float)phaseIndex * phaseIncrement) + rfphase;
554  }
555 
556  if (j < selrf->rf.thetawave.res - 1) {
557  if (!areSame(selrf->rf.rfwave.waveform[j], 0.0) && areSame(selrf->rf.rfwave.waveform[j + 1], 0.0)) {
558  phaseIndex++;
559  }
560  }
561  }
562 
563 #ifdef IPG
564 
565  for (i = firstinstance; i <= lastinstance; i++) {
566  /* set RF frequency & phase offset to zero */
567  setfrequency(0, selrf->rf.rfwave.wfi[i].wf, selrf->rf.rfwave.wfi[i].boardinstance);
568  setphase(0.0, selrf->rf.rfwave.wfi[i].wf, selrf->rf.rfwave.wfi[i].boardinstance);
569 
570  /* move modified thetawave to hardware */
571  ks_scan_wave2hardware(&selrf->rf.thetawave, newwave.waveform);
572  }
573 
574 #endif
575 
576 } /* ks_scan_selrf_setfreqphase_pins */
void ks_scan_wave2hardware(KS_WAVE *wave, const KS_WAVEFORM newwave)
Moves a waveform belonging to a KS_WAVE sequence object to hardware
Definition: KSFoundation_tgt.c:743
int boardinstance
Definition: KSFoundation.h:399
#define areSame(a, b)
Definition: KSFoundation.h:119
Core sequence object making arbitrary waveforms on any board (using float data format)
Definition: KSFoundation.h:664
#define KS_INIT_WAVE
Definition: KSFoundation.h:227
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:674
KS_WAVE thetawave
Definition: KSFoundation.h:951
KS_RF rf
Definition: KSFoundation.h:1485
KS_DESCRIPTION description
Definition: KSFoundation.h:666
KS_WAVE rfwave
Definition: KSFoundation.h:949
KS_BASE base
Definition: KSFoundation.h:665
WF_PULSE * wf
Definition: KSFoundation.h:400
int ngenerated
Definition: KSFoundation.h:410
int res
Definition: KSFoundation.h:667
KS_WAVEFORM waveform
Definition: KSFoundation.h:669

◆ ks_scan_selrf_setfreqphase()

void ks_scan_selrf_setfreqphase ( KS_SELRF selrf,
int  instanceno,
SCAN_INFO  sliceinfo,
float  rfphase 
)

Updates the frequency and phase of one or all instances of a slice selective RF pulse (KS_SELRF)

This function alters the frequency of the RF pulse in a KS_SELRF object to excite a spatial location corresponding to the information in sliceinfo.tloc. The phase of the RF pulse is also updated

Parameters
[in,out]selrfPointer to KS_SELRF
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]sliceinfoSCAN_INFO struct for the current slice to be played out
[in]rfphasePhase of the RF pulse in [degrees]
Return values
STATUSSUCCESS or FAILURE
581  {
582  int firstinstance, lastinstance;
583  int i;
584  float freqoffHz, hertzPerMm, ampscale;
585 #ifdef IPG
586  float tloc = sliceinfo.optloc;
587  int numplaced = selrf->rf.rfwave.base.ngenerated;
588 #else
589  float tloc = 1.0; /* Simulate offset of 1 mm for plotting in units of [Hz/mm] */
590  int numplaced = selrf->rf.rfwave.base.ninst;
591 #endif
592 
593  if (instanceno == INSTRALL) {
594  firstinstance = 0;
595  lastinstance = numplaced - 1;
596  } else {
597  firstinstance = instanceno;
598  lastinstance = instanceno;
599  }
600 
601  if (numplaced == 0) {
602  return;
603  }
604  if (firstinstance < 0 || lastinstance >= numplaced) {
605  ks_error("ks_scan_selrf_setfreqphase(%s): instanceno (%d) out of range [0,%d]", selrf->rf.rfwave.description, instanceno, numplaced - 1);
606  return;
607  }
608 
609  /* set frequency */
610  for (i = firstinstance; i <= lastinstance; i++) {
611 #ifdef IPG
612  if (!(i < selrf->rf.rfwave.base.ngenerated &&
613  selrf->rf.rfwave.wfi[i].wf->wavegen_type == TYPRHO1 &&
614  selrf->rf.rfwave.wfi[i].wf->assoc_pulse->tag == SSPFREQ)) { /* make sure it has been set up properly */
615  ks_error("ks_scan_rf_setfreqphase(%s): RF pulse not properly set up or instance # too high", selrf->rf.rfwave.description);
616  return;
617  }
618  if (selrf->gradwave.res > 0) {
619  /* gradwave */
620  if (selrf->gradwave.wfi != NULL) {
621  ampscale = selrf->gradwave.wfi[i].loc.ampscale;
622  } else {
623  ks_error("ks_scan_rf_setfreqphase(%s): no gradwave has been set up, setting ampscale = 0", selrf->rf.rfwave.description);
624  ampscale = 0;
625  }
626  } else {
627  /* trapezoid */
628  if (selrf->grad.wfi != NULL) {
629  ampscale = selrf->grad.wfi[i].loc.ampscale;
630  } else {
631  ks_error("ks_scan_rf_setfreqphase(%s): no grad has been set up, setting ampscale = 0", selrf->rf.rfwave.description);
632  ampscale = 0; /* protect against wfi[i] = NULL, then return 0 amp */
633  }
634  }
635 #else
636  ampscale = (selrf->gradwave.res > 0) ? selrf->gradwave.locs[i].ampscale
637  : selrf->grad.locs[i].ampscale;
638 #endif
639 
640  /* ampscale (a.u.) * GAM [Hz/G] / 10.0 [cm->mm] * gradamp [G/cm] = [Hz/mm] */
641  hertzPerMm = ampscale * GAM / 10.0 *
642  ((selrf->gradwave.res > 0) ? ks_calc_selgradamp(selrf->rf.bw, selrf->slthick) /* gradwave slice selection */
643  : selrf->grad.amp); /* trapezoid slice selection */
644  freqoffHz = selrf->rf.cf_offset; /* [Hz] */
645 
646  /* optloc-dependent freq offset */
647  if (selrf->rf.omegawave.res > 0) {
648  ks_scan_omegawave_hz(&selrf->rf.omegawave, i, hertzPerMm * tloc /* [Hz] */);
649  } else {
650  freqoffHz += hertzPerMm * tloc; /* [Hz] */
651  }
652 
653 #ifdef IPG
654  /* set RF frequency offset */
655  setfrequency((int)(freqoffHz / TARDIS_FREQ_RES), selrf->rf.rfwave.wfi[i].wf, selrf->rf.rfwave.wfi[i].boardinstance);
656 
657  /* calculate phase */
658  {
659  double ftime_delay; /* floating point time delay in seconds */
660  double temp_freq; /* frequency offset */
661  long tmpphase;
662  int syncpos, rfstartpos, time_delay;
663 
664  /* start of RF pulse wave form (for 1st boardinstance) */
665  rfstartpos = selrf->rf.rfwave.wfi[i].wf->inst_hdr_tail->start;
666  /* start of RF SSP frq pulse (for 1st boardinstance) */
667  syncpos = selrf->rf.rfwave.wfi[i].wf->assoc_pulse->inst_hdr_tail->start;
668 
669  /* time difference between SSP frq and isocenter of RF pulse */
670  time_delay = rfstartpos - syncpos - 9 /* frq2sync_dly */ + RUP_FACTOR(selrf->rf.rfwave.duration - selrf->rf.iso2end, 2);
671 
672  /*** Modified from GE's setupphases() ***/
673  ftime_delay = ((double)time_delay) / ((double) 1.0e6);
674  temp_freq = (double) freqoffHz;
675  tmpphase = (ks_degrees_to_iphase(rfphase) /* deg->iphase */ + ks_cycles_to_iphase( - temp_freq * ftime_delay )) % FS_2PI; /* radians */
676  setiphase(tmpphase, selrf->rf.rfwave.wfi[i].wf, selrf->rf.rfwave.wfi[i].boardinstance);
677  }
678 #endif
679  } /* for each instance */
680 } /* ks_scan_selrf_setfreqphase */
KS_TRAP grad
Definition: KSFoundation.h:1491
int boardinstance
Definition: KSFoundation.h:399
float cf_offset
Definition: KSFoundation.h:942
unsigned int ks_degrees_to_iphase(double degrees)
Definition: KSFoundation_tgt.c:495
KS_WAVE gradwave
Definition: KSFoundation.h:1493
KS_SEQLOC locs[KS_MAXINSTANCES]
Definition: KSFoundation.h:672
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
float ampscale
Definition: KSFoundation.h:390
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:591
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:674
KS_SEQLOC loc
Definition: KSFoundation.h:401
KS_RF rf
Definition: KSFoundation.h:1485
KS_DESCRIPTION description
Definition: KSFoundation.h:666
void ks_scan_omegawave_hz(KS_WAVE *wave, int instanceno, float Hz)
Updates a KS_WAVE object on the OMEGA board to produce a frequency offset
Definition: KSFoundation_tgt.c:57
KS_WAVE rfwave
Definition: KSFoundation.h:949
KS_BASE base
Definition: KSFoundation.h:665
int iso2end
Definition: KSFoundation.h:945
KS_SEQLOC locs[KS_MAXINSTANCES]
Definition: KSFoundation.h:589
WF_PULSE * wf
Definition: KSFoundation.h:400
float ks_calc_selgradamp(float rfbw, float slthick)
Returns the gradient amplitude in [G/cm] necessary for slice selection (internal use)
Definition: KSFoundation_common.c:309
unsigned int ks_cycles_to_iphase(double cycles)
Definition: KSFoundation_tgt.c:483
KS_WAVE omegawave
Definition: KSFoundation.h:950
int ngenerated
Definition: KSFoundation.h:410
float GAM
int res
Definition: KSFoundation.h:667
int duration
Definition: KSFoundation.h:668
float slthick
Definition: KSFoundation.h:1487
float bw
Definition: KSFoundation.h:941

◆ ks_scan_rf_setphase()

void ks_scan_rf_setphase ( KS_RF rf,
int  instanceno,
float  rfphase 
)

Updates the phase of one or all instances of an RF pulse (KS_RF)

This function sets the phase of an RF pulse object (KS_RF). Can be used for RF spoiling

Parameters
[in,out]rfPointer to KS_SEL
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]rfphasePhase of the RF pulse in [degrees]
685  {
686  int firstinstance, lastinstance;
687  #ifdef IPG
688  int i;
689  int numplaced = rf->rfwave.base.ngenerated;
690  #else
691  int numplaced = rf->rfwave.base.ninst;
692  #endif
693 
694  if (instanceno == INSTRALL) {
695  firstinstance = 0;
696  lastinstance = numplaced - 1;
697  } else {
698  firstinstance = instanceno;
699  lastinstance = instanceno;
700  }
701 
702  if (numplaced == 0) {
703  return;
704  }
705  if (firstinstance < 0 || lastinstance >= numplaced) {
706  ks_error("%s(%s): instanceno (%d) out of range [0,%d]", __FUNCTION__, rf->rfwave.description, instanceno, numplaced - 1);
707  return;
708  }
709 
710  #ifdef IPG
711  /* set frequency */
712  for (i = firstinstance; i <= lastinstance; i++) {
713  /* calculate phase */
714  {
715  double ftime_delay; /* floating point time delay in seconds */
716  double cf_offset = (double) rf->cf_offset; /* frequency offset */
717  long tmpphase;
718  int syncpos, rfstartpos, time_delay;
719 
720  /* start of RF pulse wave form (for 1st boardinstance) */
721  rfstartpos = rf->rfwave.wfi[i].wf->inst_hdr_tail->start;
722  /* start of RF SSP frq pulse (for 1st boardinstance) */
723  syncpos = rf->rfwave.wfi[i].wf->assoc_pulse->inst_hdr_tail->start;
724 
725  /* time difference between SSP frq and isocenter of RF pulse */
726  time_delay = rfstartpos - syncpos - 9 /* frq2sync_dly */ + RUP_FACTOR(rf->rfwave.duration - rf->iso2end, 2);
727 
728  /*** Modified from GE's setupphases() ***/
729  ftime_delay = ((double)time_delay) / ((double) 1.0e6);
730  tmpphase = (ks_degrees_to_iphase(rfphase) /* deg->iphase */ + ks_cycles_to_iphase( - cf_offset * ftime_delay )) % FS_2PI; /* radians */
731  setiphase(tmpphase, rf->rfwave.wfi[i].wf, rf->rfwave.wfi[i].boardinstance);
732  }
733 
734  } /* for each instance */
735 
736  #endif
737 
738 
739 } /* ks_scan_rf_setphase */
int boardinstance
Definition: KSFoundation.h:399
float cf_offset
Definition: KSFoundation.h:942
unsigned int ks_degrees_to_iphase(double degrees)
Definition: KSFoundation_tgt.c:495
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:674
KS_DESCRIPTION description
Definition: KSFoundation.h:666
KS_WAVE rfwave
Definition: KSFoundation.h:949
KS_BASE base
Definition: KSFoundation.h:665
int iso2end
Definition: KSFoundation.h:945
WF_PULSE * wf
Definition: KSFoundation.h:400
unsigned int ks_cycles_to_iphase(double cycles)
Definition: KSFoundation_tgt.c:483
int ngenerated
Definition: KSFoundation.h:410
int duration
Definition: KSFoundation.h:668

◆ ks_scan_wave2hardware()

void ks_scan_wave2hardware ( KS_WAVE wave,
const KS_WAVEFORM  newwave 
)

Moves a waveform belonging to a KS_WAVE sequence object to hardware

This function copies a waveform to one of the two hardware waveform buffers (belonging to the KS_WAVE object) that is currently not in use for the current sequence playout. The selection of which buffer to update is handled automatically by the function, which will also change the waveform pointer to the updated buffer so it will be used for the next sequence playout

If the 2nd argument (newwave, of type KS_WAVEFORM (float array)) is

  1. not NULL, the content of newwave is used
  2. NULL, it is assumed that the .waveform field of KS_WAVE has been updated with new contents and is copied to hardware instead of newwave
Parameters
[in,out]wavePointer to KS_WAVE
[in]newwaveKS_WAVEFORM to copy to hardware (if NULL, the .waveform field in KS_WAVE will be used instead)
743  {
744 #ifdef IPG
745  KS_IWAVE iwave;
746  WF_PULSE *wfpulse;
747  LONG current_wave_ptrs[KS_WF_SIZE];
748  LONG wave_ptr;
749  int i,j;
750  STATUS status;
751  int numplaced = wave->base.ngenerated;
752 #else
753  int numplaced = wave->base.ninst;
754 #endif
755 
756  if (numplaced == 0) {
757  return;
758  }
759 
760 #ifdef IPG
761 
762  for (i = 0; i < 7; i++) {
763 
764  wfpulse = wave->wfpulse[i];
765 
766  if (!wfpulse) {
767  continue;
768  }
769 
770  if (newwave != NULL) {
771  /* use the new float array passed in as 3rd argument */
772  status = ks_waveform2iwave(iwave, newwave, wave->res, i);
773  } else {
774  /* use the data in the `.waveform` field of the KS_WAVE (1st arg) */
775  status = ks_wave2iwave(iwave, wave, i); /* iwave is waveform memory */
776  }
777 
778  /* Extract current wave pointers */
779  for (j = KS_WF_MAIN; j < KS_WF_SIZE; j++) {
780  getwave(&current_wave_ptrs[j], &wfpulse[j]);
781  }
782 
783  /* Compare the main pointer with the buffers and find wich buffer was used
784  last time, then move the new waveform to the other one. Also, get the new pointer.
785  movewaveimm might take some time to compute if the wave is long, consider increasing
786  the SSI-time if you expericence any problems */
787  if (current_wave_ptrs[KS_WF_MAIN] == current_wave_ptrs[KS_WF_BUF2]) {
788  movewaveimm(iwave, &wfpulse[KS_WF_BUF1], (int) 0, wave->res, TOHARDWARE);
789  getwave(&wave_ptr, &wfpulse[KS_WF_BUF1]);
790  } else {
791  movewaveimm(iwave, &wfpulse[KS_WF_BUF2], (int) 0, wave->res, TOHARDWARE);
792  getwave(&wave_ptr, &wfpulse[KS_WF_BUF2]);
793  }
794 
795  /* Make the new pointer the main one */
796  setwave(wave_ptr, &wfpulse[KS_WF_MAIN], -1);
797 
798  } /* for */
799 
800 #endif
801 
802 } /* ks_scan_wave2hardware */
short KS_IWAVE[KS_MAXWAVELEN]
Definition: KSFoundation.h:263
Definition: KSFoundation.h:1957
int ninst
Definition: KSFoundation.h:409
WF_PULSE ** wfpulse
Definition: KSFoundation.h:673
KS_BASE base
Definition: KSFoundation.h:665
STATUS ks_waveform2iwave(KS_IWAVE iwave, const KS_WAVEFORM waveform, int res, int board) WARN_UNUSED_RESULT
(Internal use) Conversion of a KS_WAVEFORM to a short int array for use on hardware
Definition: KSFoundation_common.c:1418
Definition: KSFoundation.h:1957
int ngenerated
Definition: KSFoundation.h:410
Definition: KSFoundation.h:1957
STATUS ks_wave2iwave(KS_IWAVE iwave, const KS_WAVE *wave, int board) WARN_UNUSED_RESULT
(Internal use) Conversion of waveform content in a KS_WAVE sequence object to a short int array for u...
Definition: KSFoundation_common.c:1440
int res
Definition: KSFoundation.h:667
Definition: KSFoundation.h:1957

◆ ks_scan_offsetfov_iso()

void ks_scan_offsetfov_iso ( KS_READTRAP readtrap,
int  instanceno,
SCAN_INFO  sliceinfo,
double  ky,
double  kz,
double  rcvphase 
)

Updates the frequency and phase to create a FOV shift assuming that the k-space voxels/pixels are isometric

Parameters
[in,out]readtrapPointer to KS_READTRAP
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]sliceinfoSCAN_INFO struct for the current slice to be played out
[in]kyphase offset in k-space measured in voxels/pixels
[in]kzphase offset in k-space measured in voxels/pixels
[in]rcvphaseReceiver phase in [degrees] of the acquisition window corresponding to the KS_READTRAP and instanceno
806  {
807  /* Warning: We never have more than one instance (i.e. instruction) per readtrap.echo[i] (see ks_pg_readtrap())
808  unlike KS_TRAP and KS_RF. This means that the 2nd input arg here ('instanceno') means the instanceno'th echo. */
809 
810 #ifdef IPG
811  const int numplaced = readtrap->acq.base.ngenerated;
812 #else
813  const int numplaced = readtrap->acq.base.ninst;
814 #endif
815 
816  int firstreadout, lastreadout;
817  if (instanceno == INSTRALL) {
818  firstreadout = 0;
819  lastreadout = numplaced - 1;
820  } else {
821  firstreadout = instanceno;
822  lastreadout = instanceno;
823  }
824 
825  if (numplaced == 0) {
826  return;
827  }
828 
829  if (firstreadout < 0 || lastreadout >= numplaced) {
830  ks_error("ks_scan_offsetfov(%s): readout instance (%d) out of range [0,%d]", readtrap->grad.description, instanceno, numplaced - 1);
831  return;
832  }
833 
834  int i;
835  for (i = firstreadout; i <= lastreadout; i++) {
836 #ifdef IPG
837  /* gradient amplitude for this instance -> Hz */
838  const double mmtoHz = readtrap->grad.amp * readtrap->grad.wfi[i].loc.ampscale * GAM / 10.0; /* [Hz/mm]. designed amp [G/cm] * instance amp * GAM [Hz/G] / 10.0 [cm->mm] */
839  float rloc = sliceinfo.oprloc;
840 #else
841  const double mmtoHz = readtrap->grad.amp * readtrap->grad.locs[i].ampscale * GAM / 10.0;
842  float rloc = 1;
843 #endif
844 
845 
846  /* omega offset for rampsampled cases */
847  if (readtrap->omega.duration > 0) {
848  ks_scan_omegatrap_hz(&readtrap->omega, i, mmtoHz * rloc /* [Hz] */);
849  }
850 
851 #ifdef IPG
852 
853  const int gradsign = (mmtoHz >= 0) ? 1 : -1;
854  /* Frequency offsets [Hz]:
855  - cfreceiveroffsetfreq: GE's standard frequency offset
856  - readtrap->freqoffHz: Additional frequency offset for current KS_READTRAP. This value is multiplied with the gradient polarity sign
857  - mmtoHz * sliceinfo.oprloc: Slice-dependent and gradient polarity dependent frequency offset (when omega is off) */
858  const double freqoffHz = cfreceiveroffsetfreq + readtrap->freqoffHz * gradsign + (readtrap->omega.duration == 0) * (mmtoHz * rloc); /* [Hz] */
859 
860  /* set readout frequency offset */
861  if (i < readtrap->acq.base.ngenerated && readtrap->acq.echo[i].tag == SSPDAB) { /* make sure it has been set up properly */
862  setfrequency((int)(freqoffHz / TARDIS_FREQ_RES), &readtrap->acq.echo[i], 0);
863  }
864  /* set phase offset */
865  if (i < readtrap->acq.base.ngenerated && readtrap->acq.echo[i].tag == SSPDAB) {
866 
867  const double time2echo = (double)(readtrap->time2center - readtrap->acqdelay);
868  /* The clock source at setfrequency() starts before the first readout of the ADC, we need to account for the phase that accunmulates during this time.
869  acqq.cpp - the RBA packet [ADC sync time?] has a fixed delay of RBA_length[PSD_XCVR2] which is set in EpicConf.cpp to RBA_LENGTH (= 4)
870  It seems that all known hardware uses PSD_XCVR2 as the index and RBA_length isn't included in the scope of this file.*/
871  int adcstartpos = readtrap->acq.echo[i].assoc_pulse->assoc_pulse->inst_hdr_tail->start + RBA_LENGTH;
872  /* start of ADC SSP frq pulse (for 1st boardinstance) */
873  int syncpos = readtrap->acq.echo[i].assoc_pulse->inst_hdr_tail->start;
874  /* time difference between SSP frq and start of the ADC readout */
875  int time_delay = adcstartpos - syncpos - 10;
876 
877  const unsigned int iphase_due_to_freqoffset = ks_cycles_to_iphase(- freqoffHz * ((double)time_delay + time2echo) * 1e-6);
878  const unsigned int iphase_ky = ks_cycles_to_iphase(- ky * sliceinfo.opphasoff / readtrap->fov);
879  const unsigned int iphase_kz = ks_cycles_to_iphase(- kz * sliceinfo.optloc / readtrap->fov);
880  const unsigned int ircvphase = ks_degrees_to_iphase(rcvphase);
881  long iphase = (iphase_ky + iphase_kz + ircvphase + iphase_due_to_freqoffset) % FS_2PI;
882  setiphase(iphase, &readtrap->acq.echo[i], 0);
883 
884  }
885 #endif
886 
887  } /* for */
888 } /* ks_scan_offsetfov_iso */
WF_PULSE * echo
Definition: KSFoundation.h:738
void ks_scan_omegatrap_hz(KS_TRAP *trp, int instanceno, float Hz)
Updates a KS_TRAP object on the OMEGA board to produce a frequency offset
Definition: KSFoundation_tgt.c:105
unsigned int ks_degrees_to_iphase(double degrees)
Definition: KSFoundation_tgt.c:495
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
float fov
Definition: KSFoundation.h:1576
int cfreceiveroffsetfreq
KS_TRAP grad
Definition: KSFoundation.h:1586
float ampscale
Definition: KSFoundation.h:390
KS_BASE base
Definition: KSFoundation.h:731
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:591
KS_SEQLOC loc
Definition: KSFoundation.h:401
KS_TRAP omega
Definition: KSFoundation.h:1587
float amp
Definition: KSFoundation.h:581
KS_SEQLOC locs[KS_MAXINSTANCES]
Definition: KSFoundation.h:589
KS_DESCRIPTION description
Definition: KSFoundation.h:580
unsigned int ks_cycles_to_iphase(double cycles)
Definition: KSFoundation_tgt.c:483
float freqoffHz
Definition: KSFoundation.h:1582
int ngenerated
Definition: KSFoundation.h:410
KS_READ acq
Definition: KSFoundation.h:1574
int duration
Definition: KSFoundation.h:585
float GAM
int time2center
Definition: KSFoundation.h:1585
int acqdelay
Definition: KSFoundation.h:1580

◆ ks_scan_offsetfov_iso_readwave()

void ks_scan_offsetfov_iso_readwave ( KS_READWAVE readwave,
int  instanceno,
SCAN_INFO  sliceinfo,
double  ky,
double  kz,
double  rcvphase 
)
891  {
892 
893  /* Warning: We never have more than one instance (i.e. instruction) per readwave.acq.echo[i] (see ks_pg_readwave())
894  unlike KS_TRAP and KS_RF. This means that the 2nd input arg here ('instanceno') means the instanceno'th echo. */
895 #ifdef IPG
896  const int numplaced = readwave->acq.base.ngenerated;
897  const double halfreadoutdur = ((readwave->acq.filt.outputs - 1) * readwave->acq.filt.tsp / 2.0) * 1e-6; /* [s] */
898 #else
899  const int numplaced = readwave->acq.base.ninst;
900 #endif
901  if (numplaced == 0) {
902  return;
903  }
904 
905  int firstreadout, lastreadout;
906  if (instanceno == INSTRALL) {
907  firstreadout = 0;
908  lastreadout = numplaced - 1;
909  } else {
910  firstreadout = instanceno;
911  lastreadout = instanceno;
912  }
913 
914  if (firstreadout < 0 || lastreadout >= numplaced) {
915  ks_error("%s: readout instance (%d) out of range [0,%d]", __FUNCTION__, instanceno, numplaced - 1);
916  return;
917  }
918 
919  const float read_max = ks_wave_max(&readwave->grads[0]);
920  const float read_min = ks_wave_min(&readwave->grads[0]);
921  const float read_amp = read_max > -read_min ? read_max : read_min; /* Contains sign */
922 
923  int i;
924  for (i = firstreadout; i <= lastreadout; i++) {
925 #ifdef IPG
926  /* gradient amplitude for this instance -> Hz */
927  const double hertzPerMm = read_amp * readwave->grads[0].wfi[i].loc.ampscale * GAM / 10.0; /* [Hz/mm]. designed amp [G/cm] * instance amp * GAM [Hz/G] / 10.0 [cm->mm] */
928  float rloc = sliceinfo.oprloc;
929 #else
930  const double hertzPerMm = read_amp * readwave->grads[0].locs[i].ampscale * GAM / 10.0;
931  float rloc = 1;
932 #endif
933 
934 #ifdef IPG
935  const int gradsign = (hertzPerMm >= 0) ? 1 : -1;
936  /* Frequency offsets [Hz]:
937  - cfreceiveroffsetfreq: GE's standard frequency offset
938  - readwave->freqoffHz: Additional frequency offset for current KS_WAVE. This value is multiplied with the gradient polarity sign
939  - hertzPerMm * rloc: Slice-dependent and gradient polarity dependent frequency offset (when omega is off) */
940  const double freqoffHz = cfreceiveroffsetfreq + readwave->freqoffHz * gradsign + (readwave->omega.duration == 0) * (hertzPerMm * rloc); /* [Hz] */
941 
942  /* set readout frequency offset */
943  if (i < readwave->acq.base.ngenerated && readwave->acq.echo[i].tag == SSPDAB) {/* make sure it has been set up properly */
944  setfrequency((int)(freqoffHz / TARDIS_FREQ_RES), &readwave->acq.echo[i], 0);
945  }
946 #endif
947 
948  /* omega offset for rampsampled cases */
949  if (readwave->omega.duration > 0) {
950  ks_scan_omegawave_hz(&readwave->omega, i, hertzPerMm * rloc /* [Hz] */);
951  }
952 
953 #ifdef IPG
954  /* set phase offset */
955  if (i < readwave->acq.base.ngenerated && readwave->acq.echo[i].tag == SSPDAB) {
956  const unsigned int iphase_due_to_freqoffset = ks_cycles_to_iphase(- hertzPerMm * rloc * halfreadoutdur);
957  const unsigned int iphase_ky = ks_cycles_to_iphase(- ky * sliceinfo.opphasoff / readwave->fov);
958  const unsigned int iphase_kz = ks_cycles_to_iphase(- kz * sliceinfo.optloc / readwave->fov);
959  const unsigned int ircvphase = ks_degrees_to_iphase(rcvphase);
960  long iphase = (iphase_ky + iphase_kz + ircvphase + iphase_due_to_freqoffset) % FS_2PI;
961  setiphase(iphase, &readwave->acq.echo[i], 0);
962  }
963 #endif
964 
965  } /* for */
966 } /* ks_scan_offsetfov_iso_readwave */
KS_WAVE grads[3]
Definition: KSFoundation.h:1592
float fov
Definition: KSFoundation.h:1599
WF_PULSE * echo
Definition: KSFoundation.h:738
unsigned int ks_degrees_to_iphase(double degrees)
Definition: KSFoundation_tgt.c:495
KS_SEQLOC locs[KS_MAXINSTANCES]
Definition: KSFoundation.h:672
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
KS_WAVE omega
Definition: KSFoundation.h:1593
int cfreceiveroffsetfreq
float freqoffHz
Definition: KSFoundation.h:1598
float ampscale
Definition: KSFoundation.h:390
KS_BASE base
Definition: KSFoundation.h:731
KS_WFINSTANCE * wfi
Definition: KSFoundation.h:674
KS_SEQLOC loc
Definition: KSFoundation.h:401
void ks_scan_omegawave_hz(KS_WAVE *wave, int instanceno, float Hz)
Updates a KS_WAVE object on the OMEGA board to produce a frequency offset
Definition: KSFoundation_tgt.c:57
FILTER_INFO filt
Definition: KSFoundation.h:735
unsigned int ks_cycles_to_iphase(double cycles)
Definition: KSFoundation_tgt.c:483
float ks_wave_max(const KS_WAVE *wave)
Returns the maximum value in a KS_WAVE sequence object
Definition: KSFoundation_common.c:1151
int ngenerated
Definition: KSFoundation.h:410
KS_READ acq
Definition: KSFoundation.h:1595
float ks_wave_min(const KS_WAVE *wave)
Returns the minimum value in a KS_WAVE sequence object
Definition: KSFoundation_common.c:1177
float GAM
int duration
Definition: KSFoundation.h:668

◆ ks_scan_offsetfov()

void ks_scan_offsetfov ( KS_READTRAP readtrap,
int  instanceno,
SCAN_INFO  sliceinfo,
float  view,
float  phasefovratio,
float  rcvphase 
)

Updates the frequency and phase of one or all instances of a KS_READTRAP to create a FOV shift

This function can be used by 2D Cartesian pulse sequences to build up the phase ramp in k-space necessary to shift the image FOV. The desired image FOV shift is given by the SCAN_INFO struct passed in as 3rd argument. The view field and the phasefovratio arguments are necessary to know where in the physical k-space the acquired data is placed. Knowing this and the FOV offset in the phase encoding direction, the necessary receiver phase for the current view can be set. After this function has been called for all view numbers, the necessary phase ramp has been set up in k-space to perform the phase FOV shift in the image domain. The rcvphase is added to the receive phase required for the FOV shift. In general, the rcvphase should be the same as the phase of the RF excitation pulse.

For rampsampled acquisitions (.rampsampling = 1 in KS_READTRAP), the ks_scan_offsetfov_iso() function called will internally call ks_scan_omegatrap_hz() for FOV shifts in the readout direction. Both ks_scan_offsetfov() and ks_scan_offsetfov3D() calls the same ks_scan_offsetfov_iso() function after performing unit conversions of the input arguments.

Parameters
[in,out]readtrapPointer to KS_READTRAP
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]sliceinfoSCAN_INFO struct for the current slice to be played out
[in]viewPhase encoding line to acquire with index corresponding to a fully sampled k-space [0, res-1]
[in]phasefovratioThe ratio of FOVphase/FOVfreq (as opphasefov)
[in]rcvphaseReceiver phase in [degrees] of the acquisition window corresponding to the KS_READTRAP and instanceno
968  {
969  const double koffset = (double)(ky) / phasefovratio;
970  ks_scan_offsetfov_iso(readtrap, instanceno, sliceinfo, koffset, 0, rcvphase);
971 }
void ks_scan_offsetfov_iso(KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, double ky, double kz, double rcvphase)
Updates the frequency and phase to create a FOV shift assuming that the k-space voxels/pixels are iso...
Definition: KSFoundation_tgt.c:806

◆ ks_scan_offsetfov3D()

void ks_scan_offsetfov3D ( KS_READTRAP readtrap,
int  instanceno,
SCAN_INFO  sliceinfo,
float  kyview,
float  phasefovratio,
float  kzview,
float  zphasefovratio,
float  rcvphase 
)

Updates the frequency and phase of one or all instances of a KS_READTRAP to create a FOV shift

This function can be used by 3D Cartesian pulse sequences to build up the phase ramp in k-space necessary to shift the image FOV. The desired image FOV shift is given by the SCAN_INFO struct passed in as 3rd argument. The kyview/kzview field and the phasefovratio/zphasefovratio arguments are necessary to know where in the physical k-space the acquired data is placed. Knowing this and the FOV offset in both phase encoding directions, the necessary receiver phase for the current kyview/kzview can be set. After this function has been called for all kyview/kzview numbers, the necessary phase ramp has been set up in k-space to perform the phase FOV shift in the image domain. The rcvphase is added to the receive phase required for the FOV shift. In general, the rcvphase should be the same as the phase of the RF excitation pulse.

For rampsampled acquisitions (.rampsampling = 1 in KS_READTRAP), the ks_scan_offsetfov_iso() function called will internally call ks_scan_omegatrap_hz() for FOV shifts in the readout direction. Both ks_scan_offsetfov() and ks_scan_offsetfov3D() calls the same ks_scan_offsetfov_iso() function after performing unit conversions of the input arguments.

Parameters
[in,out]readtrapPointer to KS_READTRAP
[in]instancenoInstance of KS_RF to change (INSTRALL changes all instances)
[in]sliceinfoSCAN_INFO struct for the current slice to be played out
[in]kyviewPhase encoding line to acquire with index corresponding to a fully sampled k-space [0, res-1] (YGRAD)
[in]phasefovratioThe ratio of FOVphase/FOVfreq (as opphasefov)
[in]kzviewZ Phase encoding line to acquire with index corresponding to a fully sampled k-space [0, res-1] (ZGRAD)
[in]zphasefovratioThe ratio of FOVslice/FOVfreq (as (opslquant * opslthick) / opfov)
[in]rcvphaseReceiver phase in [degrees] of the acquisition window corresponding to the KS_READTRAP and instanceno
974  {
975  const double kyoffset = (double)(ky) / phasefovratio;
976  const double kzoffset = (double)(kz) / zphasefovratio;
977  ks_scan_offsetfov_iso(readtrap, instanceno, sliceinfo, kyoffset, kzoffset, rcvphase);
978 }
void ks_scan_offsetfov_iso(KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, double ky, double kz, double rcvphase)
Updates the frequency and phase to create a FOV shift assuming that the k-space voxels/pixels are iso...
Definition: KSFoundation_tgt.c:806

◆ ks_scan_offsetfov_readwave()

void ks_scan_offsetfov_readwave ( KS_READWAVE readwave,
int  instanceno,
SCAN_INFO  sliceinfo,
float  ky,
float  phasefovratio,
float  rcvphase 
)
981  {
982  const double koffset = (double)(ky) / phasefovratio;
983  ks_scan_offsetfov_iso_readwave(readwave, instanceno, sliceinfo, koffset, 0, rcvphase);
984 }
void ks_scan_offsetfov_iso_readwave(KS_READWAVE *readwave, int instanceno, SCAN_INFO sliceinfo, double ky, double kz, double rcvphase)
Definition: KSFoundation_tgt.c:891

◆ ks_scan_rotate()

void ks_scan_rotate ( SCAN_INFO  slice_info)

Performs a rotation of the logical system on hardware (WARP)

The field .oprot (9-element array) in the SCAN_INFO struct holds the rotation matrix that should be played out

This function performs the necessary scaling of the rotation matrix using loggrd and phygrd and then calls setrotatearray(), which performs the actual rotation on hardware during the next SSI time.

See ks_scan_update_slice_location() for detail on how to create new SCAN_INFO structs in run-time

Parameters
[in]slice_infoSCAN_INFO struct holding new slice information
Returns
void
989  {
990 #ifdef IPG
991 
992  /* scale to long int rotation matrix (accounting for gradient scaling) */
993  scale(&slice_info.oprot, &rsprot[0], 1, &loggrd, &phygrd, 0);
994 
995  setrotatearray(1, rsprot[0]);
996 
997 #endif
998 }
PHYS_GRAD phygrd
LOG_GRAD loggrd
STATUS scale(FLOAT(*inrotmat)[9], long(*outrotmat)[9], INT slquant, LOG_GRAD *lgrad, PHYS_GRAD *pgrad, INT contdebug)

◆ ks_scan_isirotate()

void ks_scan_isirotate ( KS_ISIROT isirot)

Performs an immediate rotation of the logical system on hardware (WARP)

This function needs a psd-specific wrapper function to execute (see ks_pg_isirot()) since the ISI interupt routine is calling a void function without input arguments. This psd-specific wrapper function should only contain the call to ks_scan_isirotate() with the psd-specific KS_ISIROT set up in pulsegen().

For N number of calls to ks_pg_isirot() in the sequence module's pg-function, the field isirot.numinstances will be set to N, and this many ISI interrupt with a corresponding isirot.isinumber exist in the sequence module. Valid ISI numbers are 4-7, and one available number should be linked to one specific wrapper function using ks_eval_isirot() and ks_pg_isirot().

In real-time, ks_scan_isirotate() will increment the isirot.counter field by 1 and restart at 0 after isirot->numinstances. isirot.counter is set to 0 in ks_pg_isirot(). Based on the value of the .counter field, it will assign a pre-stored SCAN_INFO struct corresponding to this counter value. Again, this connection is done by ks_pg_isirot().

ks_scan_isirotate() takes the current SCAN_INFO and converts it to long int, and then calls setrotateimm(..., WARP_UPDATE_ON_SSP_INT);

Parameters
[in]isirotPointer to the KS_ISIROT struct set up by ks_pg_isirot()
Returns
void
1002  {
1003 #ifdef IPG
1004 
1005  if (isirot == NULL || isirot->numinstances < 1)
1006  return;
1007 
1008  /* wrap around after numinstances interupts */
1009  isirot->counter = isirot->counter % isirot->numinstances;
1010 
1011  /* scale to long int rotation matrix (accounting for gradient scaling) */
1012  scale(&isirot->scan_info[isirot->counter++].oprot, &rsprot[0], 1, &loggrd, &phygrd, 0);
1013 
1014  /* rotate on SSP interrupt */
1015  setrotateimm(rsprot[0], WARP_UPDATE_ON_SSP_INT);
1016 
1017 #endif
1018 }
SCAN_INFO * scan_info
Definition: KSFoundation.h:472
PHYS_GRAD phygrd
LOG_GRAD loggrd
int counter
Definition: KSFoundation.h:475
STATUS scale(FLOAT(*inrotmat)[9], long(*outrotmat)[9], INT slquant, LOG_GRAD *lgrad, PHYS_GRAD *pgrad, INT contdebug)
int numinstances
Definition: KSFoundation.h:476

◆ ks_scan_getsliceloc()

int ks_scan_getsliceloc ( const KS_SLICE_PLAN slice_plan,
int  passindx,
int  sltimeinpass 
)

Returns the spatially sorted slice index from a DATA_ACQ_ORDER struct array

This function finds the spatially sorted slice index (.slloc) in range [0, nslices-1] given the sequence's DATA_ACQ_ORDER struct array (in slice_plan.acq_order)

Parameters
[in]slice_planPointer to the slice plan (KS_SLICE_PLAN) for the sequence
[in]passindxCurrent pass index ([0, acqs-1])
[in]sltimeinpassTemporal index of the n slices acquired in each pass ([0, n-1])
Return values
sllocSpatially sorted slice index
1023  {
1024  int i;
1025  for (i = 0; i < slice_plan->nslices; i++) {
1026  if (slice_plan->acq_order[i].slpass == passindx && slice_plan->acq_order[i].sltime == sltimeinpass) {
1027  return slice_plan->acq_order[i].slloc;
1028  }
1029  }
1030 
1031  return KS_NOTSET;
1032 
1033 }
DATA_ACQ_ORDER acq_order[SLICE_FACTOR *DATA_ACQ_MAX]
Definition: KSFoundation.h:1354
#define KS_NOTSET
Definition: KSFoundation.h:103
int passindx
Definition: ksfse_implementation.e:2849
int nslices
Definition: KSFoundation.h:1351

◆ ks_scan_getslicetime()

int ks_scan_getslicetime ( const KS_SLICE_PLAN slice_plan,
int  passindx,
int  slloc 
)

Returns the temporally sorted slice index from a DATA_ACQ_ORDER struct array

This function finds the temporally sorted slice index (.sltime) in range [0, nslices-1] given the sequence's DATA_ACQ_ORDER struct array (in slice_plan.acq_order)

Parameters
[in]slice_planPointer to the slice plan (KS_SLICE_PLAN) for the sequence
[in]passindxCurrent pass index ([0, acqs-1])
[in]sllocSpatially sorted slice index [0, nslices-1]
Return values
sltimeinpassTemporal index of the n slices acquired in each pass ([0, n-1])
1036  {
1037  int i;
1038  for (i = 0; i < slice_plan->nslices; i++) {
1039  if (slice_plan->acq_order[i].slpass == passindx && slice_plan->acq_order[i].slloc == slloc) {
1040  return slice_plan->acq_order[i].sltime;
1041  }
1042  }
1043 
1044  return KS_NOTSET;
1045 
1046 }
DATA_ACQ_ORDER acq_order[SLICE_FACTOR *DATA_ACQ_MAX]
Definition: KSFoundation.h:1354
#define KS_NOTSET
Definition: KSFoundation.h:103
int passindx
Definition: ksfse_implementation.e:2849
int nslices
Definition: KSFoundation.h:1351

◆ ks_scan_epi_verify_phaseenc_plan()

ks_enum_epiblipsign ks_scan_epi_verify_phaseenc_plan ( KS_EPI epi,
KS_PHASEENCODING_PLAN phaseenc_plan,
int  shot 
)
1050  {
1051  int i;
1052  int kystep[epi->etl];
1055 
1056  if (phaseenc_plan == NULL) {
1057  return blipsign;
1058  }
1059 
1060  /* verify phase encoding plan has equidistant ky step size */
1061  /* first store ky coords */
1062  for (i = 0; i < epi->etl; i++) {
1063  coord = ks_phaseencoding_get(phaseenc_plan, i, shot);
1064  kystep[i] = coord.ky;
1065  }
1066 
1067  for (i = 0; i < epi->etl-1; i++) {
1068  kystep[i] = kystep[i+1] - kystep[i]; /* calculate ky step */
1069  if (i > 0) {
1070  /* check that kystep is consistent */
1071  if (kystep[i] != kystep[0]) {
1072  ks_error("%s(%s): KS_EPI does not support varying ky step size", __FUNCTION__, phaseenc_plan->description);
1073  return KS_EPI_NOBLIPS;
1074  }
1075  }
1076  }
1077 
1078  if (kystep[0] < 0) {
1079  blipsign = KS_EPI_POSBLIPS;
1080  } else if (kystep[0] > 0) {
1081  blipsign = KS_EPI_NEGBLIPS;
1082  }
1083 
1084  return blipsign;
1085 }
#define KS_INIT_PHASEENCODING_COORD
Definition: KSFoundation.h:219
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ky
Definition: KSFoundation.h:1705
int etl
Definition: KSFoundation.h:1843
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1704
KS_PHASEENCODING_COORD ks_phaseencoding_get(const KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, int echo, int shot)
Get [ky,kz] coordinate from KS_PHASEENCODING_PLAN for given echo and shot
Definition: KSFoundation_common.c:375
KS_DESCRIPTION description
Definition: KSFoundation.h:1741
Definition: KSFoundation.h:1929
ks_enum_epiblipsign
Definition: KSFoundation.h:1929
Definition: KSFoundation.h:1929
Definition: KSFoundation.h:1929

◆ ks_scan_epi_shotcontrol()

void ks_scan_epi_shotcontrol ( KS_EPI epi,
int  echo,
SCAN_INFO  sliceinfo,
KS_PHASEENCODING_PLAN phaseenc_plan,
int  shot,
int  exc,
float  rcvphase 
)

Changes the gradient state of a KS_EPI object for the given slice information

This function has two different tasks. First, it controls the EPI blips and sets the EPI dephaser and rephaser amplitude given the current phaseshot and blipsign. If phaseshot is outside the valid range ([0, .blipphaser.R-1], all gradient amplitudes on the blip (phase encoding) axis will be zero. This can be useful to acquire a refscan for Nyquist ghost correction. Second, it sets up the proper frequency and phase modulation per readout lobe to produce the desired FOV offset in both the frequency and phase encoding directions

Parameters
[in,out]epiPointer to KS_EPI
[in]echoEPI echo index (up to 16 EPI trains supported)
[in]sliceinfoSCAN_INFO struct for the current slice to be played out
[in]phaseenc_planPointer to the phase encoding plan
[in]shotLinear ky kz shot index in range [0, (phaseenc_plan.num_shots-1)]
[in]excZero-based NEX index
[in]rcvphaseReceiver phase in degrees, for RF spoiling.
Return values
STATUSSUCCESS or FAILURE
1089  {
1090  float blipampscale = 1.0;
1091  float yfovratio, zfovratio;
1092  int i, readindx, blipindx, kyview, kzview;
1093  int numblips = (epi->etl - 1);
1094  int isrefscan = (exc < 0); /* exc < 0 => data acquisition ON, EPI blips OFF (to make RefScan for Nyquist ghost correction) */
1096 
1097  ks_enum_epiblipsign blipsign = ks_scan_epi_verify_phaseenc_plan(epi, phaseenc_plan, shot);
1098 
1099  if (phaseenc_plan != NULL && (epi->etl != phaseenc_plan->etl)) {
1100  ks_error("%s(%s): ETL of KS_EPI (%d) and KS_PHASEENCODING_PLAN (%d) do not match", __FUNCTION__, phaseenc_plan->description, epi->etl, phaseenc_plan->etl);
1101  blipsign = KS_EPI_NOBLIPS;
1102  }
1103 
1104  if (isrefscan) {
1105  blipsign = KS_EPI_NOBLIPS;
1106  }
1107 
1108  /* EPI read & blips for current 'echo' = EPI train. */
1109  for (i = 0; i < epi->etl; i++) {
1110  coord = ks_phaseencoding_get(phaseenc_plan, i, shot);
1111  kyview = (blipsign != KS_EPI_NOBLIPS) ? coord.ky : KS_NOTSET;
1112  kzview = (blipsign != KS_EPI_NOBLIPS) ? coord.kz : KS_NOTSET;
1113 
1114  if (i == 0) { /* EPI dephaser. From k-space center to this line */
1115  ks_scan_phaser_toline(&epi->blipphaser, 0 + 2 * echo, kyview); /* KS_NOTSET => zero amplitude */
1116  if (epi->zphaser.grad.duration > 0) {
1117  /* 3D epi z dephaser(s) for even instances '2*echo' */
1118  ks_scan_phaser_toline(&epi->zphaser, 0 + 2 * echo, kzview);
1119  }
1120  }
1121 
1122  if (i == epi->etl-1) { /* EPI rephaser. From this line to k-space center */
1123  ks_scan_phaser_fromline(&epi->blipphaser, 1 + 2 * echo, kyview); /* KS_NOTSET => zero amplitude */
1124  if (epi->zphaser.grad.duration > 0) {
1125  /* 3D epi z rephaser(s) for odd instances '1+2*echo' */
1126  ks_scan_phaser_fromline(&epi->zphaser, 1 + 2 * echo, kzview);
1127  }
1128  }
1129 
1130  readindx = i + echo * epi->etl; /* ETL# of readouts */
1131  blipindx = i + echo * numblips; /* (ETL-1)# of blips */
1132 
1133  if (i < numblips) {
1134  /* FUTURE: at this point, we could increase/decrease blipampscale for odd/even blips for oblique ghost correction */
1135  blipampscale = blipsign / epi->blipoversize;
1136  ks_scan_trap_ampscale(&epi->blip, blipindx, blipampscale);
1137  }
1138 
1139  /* FOV offsets (by changing freq/phase of epi.read) */
1140  float ky_centred, kz_centred;
1141  if (kyview < 0) {
1142  ky_centred = 0.0f;
1143  } else {
1144  ky_centred = (float)kyview - ((epi->blipphaser.res - 1) / 2.0f);
1145  }
1146  yfovratio = epi->blipphaser.fov / epi->read.fov;
1147  if (epi->zphaser.grad.duration > 0) {
1148  if (kzview < 0) {
1149  kz_centred = 0.0f;
1150  } else {
1151  kz_centred = (float)kzview - ((epi->zphaser.res - 1) / 2.0f);
1152  }
1153  zfovratio = epi->zphaser.fov / epi->read.fov;
1154  ks_scan_offsetfov3D(&epi->read, readindx, sliceinfo, ky_centred, yfovratio, kz_centred, zfovratio, rcvphase);
1155  } else {
1156  ks_scan_offsetfov(&epi->read, readindx, sliceinfo, ky_centred, yfovratio, rcvphase);
1157  }
1158 
1159  } /* for etl */
1160 
1161 } /* ks_scan_epi_shotcontrol */
float blipoversize
Definition: KSFoundation.h:1847
KS_TRAP blip
Definition: KSFoundation.h:1839
#define KS_INIT_PHASEENCODING_COORD
Definition: KSFoundation.h:219
void ks_scan_phaser_toline(KS_PHASER *phaser, int instanceno, int view)
Updates the amplitude of a KS_PHASER sequence object to move from the k-space center to a desired k-s...
Definition: KSFoundation_tgt.c:340
int res
Definition: KSFoundation.h:1678
void ks_scan_offsetfov3D(KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, float ky, float phasefovratio, float kz, float zphasefovratio, float rcvphase)
Updates the frequency and phase of one or all instances of a KS_READTRAP to create a FOV shift...
Definition: KSFoundation_tgt.c:974
KS_TRAP grad
Definition: KSFoundation.h:1676
#define KS_NOTSET
Definition: KSFoundation.h:103
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
float fov
Definition: KSFoundation.h:1576
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
int ky
Definition: KSFoundation.h:1705
KS_PHASER zphaser
Definition: KSFoundation.h:1841
ks_enum_epiblipsign ks_scan_epi_verify_phaseenc_plan(KS_EPI *epi, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
Definition: KSFoundation_tgt.c:1050
int kz
Definition: KSFoundation.h:1706
int etl
Definition: KSFoundation.h:1843
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1704
KS_PHASEENCODING_COORD ks_phaseencoding_get(const KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, int echo, int shot)
Get [ky,kz] coordinate from KS_PHASEENCODING_PLAN for given echo and shot
Definition: KSFoundation_common.c:375
void ks_scan_offsetfov(KS_READTRAP *readtrap, int instanceno, SCAN_INFO sliceinfo, float ky, float phasefovratio, float rcvphase)
Updates the frequency and phase of one or all instances of a KS_READTRAP to create a FOV shift...
Definition: KSFoundation_tgt.c:968
KS_DESCRIPTION description
Definition: KSFoundation.h:1741
int etl
Definition: KSFoundation.h:1740
KS_READTRAP read
Definition: KSFoundation.h:1837
ks_enum_epiblipsign
Definition: KSFoundation.h:1929
void ks_scan_trap_ampscale(KS_TRAP *trp, int instanceno, float ampscale)
Updates the amplitude of one or all instances of a KS_TRAP sequence object
Definition: KSFoundation_tgt.c:199
void ks_scan_phaser_fromline(KS_PHASER *phaser, int instanceno, int view)
Updates the amplitude of a KS_PHASER sequence object to move from a k-space line to the k-space cente...
Definition: KSFoundation_tgt.c:359
int duration
Definition: KSFoundation.h:585
Definition: KSFoundation.h:1929
float fov
Definition: KSFoundation.h:1677

◆ ks_scan_epi_loadecho_with_tag()

void ks_scan_epi_loadecho_with_tag ( KS_EPI epi,
int  echo,
int  storeecho,
int  slice,
KS_PHASEENCODING_PLAN phaseenc_plan,
int  shot,
KSEPI_DATATAG datatag,
KS_DATASTORETAG datastoretag 
)

Loads the data storage information to hardware for the acquisition windows in a KS_EPI sequence object

This function specifies where to store the data acquired for each readout lobe in the KS_EPI train given current:

  • echo: First instance of the KS_EPI train is 0
  • slice: Slice index, 0-based
  • shot: Linear ky kz shot index in range [0, (phaseenc_plan.num_shots-1)]
  • phaseenc_plan: phaseenc_plan Pointer to the phase encoding plan

If shot is outside the valid range, a baseline view (view 0 in loaddab()) will be acquired.

If slice is < 0, data acquisition is turned off in loaddab()

Parameters
[in,out]epiPointer to KS_EPI
[in]echoEPI echo index to work on (up to 16 EPI trains supported)
[in]storeechoEPI echo index for storing (usually the same as echo)
[in]sliceSlice index where to store the data (0-based)
[in]phaseenc_planPointer to the phase encoding plan
[in]shotLinear ky kz shot index in range [0, (phaseenc_plan.num_shots-1)]
[in]datastoretagTag (unsigned int) passed to loaddabwithangle(). This can be filled with whatever content to inform recon. Will be a part of each control packet on the recon side.
Return values
STATUSSUCCESS or FAILURE
1165  {
1166  if ((datastoretag != NULL) && (datatag != NULL)) {
1167  ks_error("%s: either datastoretag or custom_dab_array must be NULL, but both were supplied.", __FUNCTION__);
1168  return;
1169  }
1170 
1171  int i, readindx;
1172 #ifdef IPG
1173  int validsliceindx = (slice >= 0 && slice < 2048);
1174  int validshotindx = (shot >= 0 && (phaseenc_plan == NULL || shot < phaseenc_plan->num_shots));
1176  ks_enum_epiblipsign blipsign = ks_scan_epi_verify_phaseenc_plan(epi, phaseenc_plan, shot);
1177  int centerecho = epi->time2center / epi->read.grad.duration; /* etl index corresponding to k-space center */
1178  int numplaced = epi->read.acq.base.ngenerated;
1179 
1180  /* 'pscR1' is the R1 receive gain made by prescan */
1181  int currentR1 = (epi->read.acq.override_R1 > 0 && epi->read.acq.override_R1 <= 11) ? epi->read.acq.override_R1 : pscR1;
1182 
1183  TYPDAB_PACKETS dabacqctrl;
1184  if (validsliceindx && validshotindx) {
1185  dabacqctrl = DABON; /* turn receiver on */
1186  } else {
1187  dabacqctrl = DABOFF; /* turn receiver off */
1188  slice = 0; /* necessary? */
1189  }
1190 #else
1191  int numplaced = epi->read.acq.base.ninst;
1192 #endif
1193 
1194  if (numplaced == 0) {
1195  return;
1196  }
1197  if (storeecho < 0 || storeecho > 15) {
1198  ks_error("%s: storeecho must be in range [0:15]", __FUNCTION__);
1199  return;
1200  }
1201  if (echo < 0 || (echo + 1) * epi->etl > numplaced) {
1202  ks_error("%s: echo (%d) must be in range [0:%d]", __FUNCTION__, echo, numplaced/epi->etl-1);
1203  return;
1204  }
1205 
1206  for (i = 0; i < epi->etl; i++) {
1207 
1208  readindx = i + echo * epi->etl; /* N.B.: 'echo' is # of EPI trains, not EPI readout lobes (up to 16 possible, set by opnecho) */
1209 
1210  if (readindx >= numplaced) {
1211  ks_error("%s(%s): Readout lobe index %d has not been placed in PG", __FUNCTION__, epi->read.grad.description, readindx);
1212  return;
1213  }
1214 
1215 #ifdef IPG
1216  int kyview = KS_NOTSET;
1217  if (validshotindx && (blipsign != KS_EPI_NOBLIPS)) {
1218  coord = ks_phaseencoding_get(phaseenc_plan, i, shot);
1219  kyview = coord.ky;
1220  if (rhasset == ASSET_SCAN && epi->blipphaser.R > 1 && epi->blipphaser.nacslines == 0) {
1221  /* Auto-detect ASSET scan, which uses compressed storage of accelerated data, i.e. only
1222  storing the acquired lines, without inteleaving with blank unacquired lines */
1223  if (blipsign == KS_EPI_POSBLIPS) {
1224  kyview = epi->etl-1 - i;
1225  } else if (blipsign == KS_EPI_NEGBLIPS) {
1226  kyview = i;
1227  }
1228  }
1229  }
1230 
1231  if (rspent == L_APS2 || rspent == L_MPS2) {
1232  /* Prescan (R1 & R2) */
1233  if (readindx == centerecho && echo == 0) {
1234  loaddab(&epi->read.acq.echo[readindx], slice, storeecho, DABSTORE, 0, dabacqctrl, PSD_LOAD_DAB_ALL); /* turn on acquisition for center echo of 1st EPI train */
1235  } else {
1236  loaddab(&epi->read.acq.echo[readindx], slice, storeecho, DABSTORE, 0, DABOFF, PSD_LOAD_DAB_ALL); /* turn off acquisition for all other lobes (and all later EPI trains) */
1237  }
1238  } else {
1239  if (datastoretag != NULL) {
1240  /* Storing additional data in the dab pulse, in datastoretag.dab_array is space for up to KS_CUSTOM_DATASTORE_LENGTH byte */
1241  ks_loaddab_datastoretag(&epi->read.acq.echo[readindx], datastoretag);
1242  }
1243  if (datatag != NULL) {
1244  datatag->readout = i;
1245  ks_loaddab(&epi->read.acq.echo[readindx], (char*) datatag);
1246  }
1247  /* N.B.: kyview = KS_NOTSET (-1) if shot = KS_NOTSET. Hence kyview + 1 = dabview = 0 without phase encodes */
1248  loaddab_hub_r1(&epi->read.acq.echo[readindx], slice, storeecho, DABSTORE, kyview + 1 /* GE's views are 1-based */, 0, currentR1, dabacqctrl, PSD_LOAD_DAB_ALL_WITH_HUB_R1);
1249  }
1250 #endif
1251 
1252  } /* per acq window (readout lobe) */
1253 
1254 } /* ks_scan_epi_loadecho_with_tag */
#define KS_INIT_PHASEENCODING_COORD
Definition: KSFoundation.h:219
int R
Definition: KSFoundation.h:1680
WF_PULSE * echo
Definition: KSFoundation.h:738
int num_shots
Definition: KSFoundation.h:1739
int nacslines
Definition: KSFoundation.h:1681
#define KS_NOTSET
Definition: KSFoundation.h:103
LONG override_R1
Definition: KSFoundation.h:737
uint16_t readout
Definition: KSFoundation.h:280
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ninst
Definition: KSFoundation.h:409
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
int ky
Definition: KSFoundation.h:1705
int rspent
Definition: GERequired.e:2626
ks_enum_epiblipsign ks_scan_epi_verify_phaseenc_plan(KS_EPI *epi, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
Definition: KSFoundation_tgt.c:1050
KS_TRAP grad
Definition: KSFoundation.h:1586
KS_BASE base
Definition: KSFoundation.h:731
int etl
Definition: KSFoundation.h:1843
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1704
KS_PHASEENCODING_COORD ks_phaseencoding_get(const KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, int echo, int shot)
Get [ky,kz] coordinate from KS_PHASEENCODING_PLAN for given echo and shot
Definition: KSFoundation_common.c:375
int pscR1
KS_READTRAP read
Definition: KSFoundation.h:1837
void ks_loaddab_datastoretag(WF_PULSE_ADDR echo, KS_DATASTORETAG *datastoretag)
Definition: KSFoundation_tgt.c:1293
int rhasset
void ks_loaddab(WF_PULSE_ADDR echo, char *custom_dab_array)
Definition: KSFoundation_tgt.c:1276
Definition: KSFoundation.h:1929
KS_DESCRIPTION description
Definition: KSFoundation.h:580
ks_enum_epiblipsign
Definition: KSFoundation.h:1929
int time2center
Definition: KSFoundation.h:1846
int ngenerated
Definition: KSFoundation.h:410
KS_READ acq
Definition: KSFoundation.h:1574
int duration
Definition: KSFoundation.h:585
Definition: KSFoundation.h:1929
Definition: KSFoundation.h:1929

◆ ks_scan_epi_loadecho_with_datastoretag()

void ks_scan_epi_loadecho_with_datastoretag ( KS_EPI epi,
int  echo,
int  storeecho,
int  slice,
KS_PHASEENCODING_PLAN phaseenc_plan,
int  shot,
KS_DATASTORETAG datastoretag 
)

Wrappers around ks_scan_epi_loadecho_withtag_or_dabarray.

1258  {
1259  ks_scan_epi_loadecho_with_tag(epi, echo, storeecho, slice, phaseenc_plan, shot, NULL, datastoretag);
1260 }
void ks_scan_epi_loadecho_with_tag(KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, KSEPI_DATATAG *datatag, KS_DATASTORETAG *datastoretag)
Loads the data storage information to hardware for the acquisition windows in a KS_EPI sequence objec...
Definition: KSFoundation_tgt.c:1165

◆ ks_scan_epi_loadecho_with_epidatatag()

void ks_scan_epi_loadecho_with_epidatatag ( KS_EPI epi,
int  echo,
int  storeecho,
int  slice,
KS_PHASEENCODING_PLAN phaseenc_plan,
int  shot,
KSEPI_DATATAG datatag 
)
1264  {
1265  ks_scan_epi_loadecho_with_tag(epi, echo, storeecho, slice, phaseenc_plan, shot, datatag, NULL);
1266 }
void ks_scan_epi_loadecho_with_tag(KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, KSEPI_DATATAG *datatag, KS_DATASTORETAG *datastoretag)
Loads the data storage information to hardware for the acquisition windows in a KS_EPI sequence objec...
Definition: KSFoundation_tgt.c:1165

◆ ks_scan_epi_loadecho()

void ks_scan_epi_loadecho ( KS_EPI epi,
int  echo,
int  storeecho,
int  slice,
KS_PHASEENCODING_PLAN phaseenc_plan,
int  shot 
)
1270  {
1271  ks_scan_epi_loadecho_with_tag(epi, echo, storeecho, slice, phaseenc_plan, shot, NULL, NULL);
1272 }
void ks_scan_epi_loadecho_with_tag(KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, KSEPI_DATATAG *datatag, KS_DATASTORETAG *datastoretag)
Loads the data storage information to hardware for the acquisition windows in a KS_EPI sequence objec...
Definition: KSFoundation_tgt.c:1165

◆ ks_loaddab()

void ks_loaddab ( WF_PULSE_ADDR  echo,
char *  custom_dab_array 
)
1276  {
1277  int i;
1278  static const int dab_indices[KS_CUSTOM_DATASTORE_LENGTH] = {2,3,4,5,6,7,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29};
1279 
1280  for (i=0; i<KS_CUSTOM_DATASTORE_LENGTH; i++){
1281  short dabbyte = custom_dab_array[i];
1282 #ifdef IPG
1283  sspload(&dabbyte, echo, dab_indices[i], 1, (HW_DIRECTION)TOHARDWARE, (SSP_S_ATTRIB)SSPS1);
1284 #else
1285  (void) dabbyte;
1286  (void) dab_indices;
1287 #endif
1288  }
1289 }
#define KS_CUSTOM_DATASTORE_LENGTH
Definition: KSFoundation.h:267

◆ ks_loaddab_datastoretag()

void ks_loaddab_datastoretag ( WF_PULSE_ADDR  echo,
KS_DATASTORETAG datastoretag 
)
1293  {
1294  if (datastoretag == NULL) {
1295  return;
1296  }
1297 
1298  if (datastoretag->info.load_custom_dab_array == TRUE) {
1299  /* if the psd provides */
1300  if (datastoretag->fill_dab_array_fct != NULL){
1301  datastoretag->fill_dab_array_fct(datastoretag);
1302  }
1303  ks_loaddab(echo, datastoretag->dab_array);
1304  }
1305 }
char dab_array[KS_CUSTOM_DATASTORE_LENGTH]
Definition: KSFoundation.h:316
void ks_loaddab(WF_PULSE_ADDR echo, char *custom_dab_array)
Definition: KSFoundation_tgt.c:1276
KS_DATASTORE_STRUCT_INFO info
Definition: KSFoundation.h:315
void(* fill_dab_array_fct)(struct _KS_DATASTORETAG *datastoretag)
Definition: KSFoundation.h:318
int load_custom_dab_array
Definition: KSFoundation.h:306

◆ ks_scan_acq_to_rtp()

void ks_scan_acq_to_rtp ( KS_READ read,
TYPDAB_PACKETS  dabacqctrl,
float  fatoffset 
)

Data routing control for RTP

Parameters
[in,out]readPointer to KS_READ
[in]dabacqctrlDABON or DABOFF
[in]fatoffsetFrequency offset in [Hz] for the current data acquisition window
Returns
void
1314  {
1315 #ifdef IPG
1316 
1317  WF_PULSE *echo_ptr;
1318  WF_PULSE *xtr_ptr;
1319  WF_PULSE *rba_ptr;
1320 
1321  int i;
1322  for (i = 0; i < acq->base.ngenerated; ++i) {
1323  echo_ptr = &acq->echo[i];
1324  setrfltrs((int) acq->filt.fslot, echo_ptr);
1325 
1326  getssppulse(&rba_ptr, echo_ptr, "rba", 0);
1327  getssppulse(&xtr_ptr, echo_ptr, "xtr", 0);
1328  acqctrl(dabacqctrl, (RECEIVER_SPEED_E)0, rba_ptr);
1329 
1330  setfreqphase((int)(fatoffset / TARDIS_FREQ_RES), /* freq ctrl */
1331  0, /* phase ctrl */
1332  xtr_ptr);
1333 
1334  /* TODO: Add r1 scaling here! */
1335  /*if (r1_scale != 1.0 && (rspent==L_SCAN)) {
1336  newR1 = ceil(pscR1 * r1_scale);
1337  if (newR1 > 13)
1338  newR1 = 13;
1339  else if (newR1 < 1)
1340  newR1 = 1;
1341 
1342  loaddab_hub_r1(echo_ptr, dabslice, dabecho, DABSTORE, dabview, 0, newR1, dabacqctrl, PSD_LOAD_DAB_ALL | PSD_LOAD_DAB_R1);
1343  }*/ /* if R1 change */
1344  routeDataFrameDab(echo_ptr, ROUTE_TO_RTP, cfcoilswitchmethod);
1345  }
1346 
1347 #endif
1348 
1349 }
WF_PULSE * echo
Definition: KSFoundation.h:738
KS_BASE base
Definition: KSFoundation.h:731
int cfcoilswitchmethod
FILTER_INFO filt
Definition: KSFoundation.h:735
int ngenerated
Definition: KSFoundation.h:410

◆ boffset()

STATUS boffset ( long *  offsets)

◆ ks_scan_switch_to_sequence()

void ks_scan_switch_to_sequence ( KS_SEQ_CONTROL ctrl)
1356  {
1357 #ifdef IPG
1358  if (ctrl->duration > 0) {
1359  boffset(ctrl->handle.offset);
1360  }
1361 #endif
1362 }
STATUS boffset(long *offsets)
long * offset
Definition: KSFoundation.h:986
int duration
Definition: KSFoundation.h:1135
KS_SEQ_HANDLE handle
Definition: KSFoundation.h:1142

◆ setssitime()

STATUS setssitime ( long  )

◆ startseq()

STATUS startseq ( s16  ,
s16   
)

◆ ks_scan_playsequence()

int ks_scan_playsequence ( KS_SEQ_CONTROL ctrl)
1368  {
1369 
1370  if (ctrl->duration > 0) {
1371 
1372 #ifdef IPG
1373  {
1375  setssitime(ctrl->ssi_time / cfhwgut);
1376  startseq(0, (short) MAY_PAUSE); /* play out the sequence in real time */
1377  }
1378 #else
1379  /* HOST */
1380  ctrl->nseqinstances++;
1381 #endif
1382  } /* ctrl->duration > 0 */
1383 
1384  return ctrl->duration;
1385 }
STATUS startseq(s16, s16)
STATUS setssitime(long)
int cfhwgut
int duration
Definition: KSFoundation.h:1135
int nseqinstances
Definition: KSFoundation.h:1133
void ks_scan_switch_to_sequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1356
int ssi_time
Definition: KSFoundation.h:1134

◆ ks_scan_loaddabwithindices_nex()

STATUS ks_scan_loaddabwithindices_nex ( WF_PULSE_ADDR  pulse,
LONG  slice,
LONG  echo,
LONG  view,
uint8_t  acq,
uint8_t  vol,
LONG  operation,
TYPDAB_PACKETS  acqon_flag 
)

loaddab() with extra arguments for current acquisition and image volume and current excitation (NEX)

Parameters
[in]pulsePointer to WF_PULSE in a KS_READ
[in]slice0-based temporal slice index (2D) or kz encoding step typically (3D)
[in]echo0-based echo in the echo train
[in]view1-based ky view number
[in]acq0-based acquisition index (always 0 if all slices fit in one TR)
[in]vol0-based volume index (always 0 if only one volume)
[in]operationDABSTORE, DABADD (for 2nd to last excitation)
[in]acqon_flagDABON or DABOFF
Return values
STATUSSUCCESS or FAILURE
1399  {
1400 
1401  union Indices idx;
1402  idx.c[0] = acq;
1403  idx.c[1] = vol;
1404  return loaddabwithangle(pulse, idx.i, slice, echo, operation, view, acqon_flag, PSD_LOAD_DAB_ALL);
1405 }
Definition: KSFoundation_tgt.c:1387
int view
Definition: GERequired.e:2642
uint8_t c[4]
Definition: KSFoundation_tgt.c:1388

◆ ks_scan_loaddabwithindices()

STATUS ks_scan_loaddabwithindices ( WF_PULSE_ADDR  pulse,
LONG  slice,
LONG  echo,
LONG  view,
uint8_t  acq,
uint8_t  vol,
TYPDAB_PACKETS  acqon_flag 
)

loaddab() with extra arguments for current acquisition and image volume

Parameters
[in]pulsePointer to WF_PULSE in a KS_READ
[in]slice0-based temporal slice index (2D) or kz encoding step typically (3D)
[in]echo0-based echo in the echo train
[in]view1-based ky view number
[in]acq0-based acquisition index (always 0 if all slices fit in one TR)
[in]vol0-based volume index (always 0 if only one volume)
[in]acqon_flagDABON or DABOFF
Return values
STATUSSUCCESS or FAILURE
1413  {
1414  return ks_scan_loaddabwithindices_nex(pulse, slice, echo, view, acq, vol, DABSTORE, acqon_flag);
1415 }
STATUS ks_scan_loaddabwithindices_nex(WF_PULSE_ADDR pulse, LONG slice, LONG echo, LONG view, uint8_t acq, uint8_t vol, LONG operation, TYPDAB_PACKETS acqon_flag)
loaddab() with extra arguments for current acquisition and image volume and current excitation (NEX)...
Definition: KSFoundation_tgt.c:1392
int view
Definition: GERequired.e:2642

◆ ks_scan_wait_for_rtp()

int ks_scan_wait_for_rtp ( void *  rtpmsg,
int  maxmsgsize,
int  maxwait,
KS_SEQ_CONTROL waitctrl 
)

play a wait sequence in a loop untill a RTP message is received.

Parameters
[out]rtpmsgpointer to memory that will be filled by the RTP message
[in]maxmsgsizesize in bytes of the memory pointed by rtpmsg
[in]maxwaittiming out period in [ms]
[in]waitctrlpointer to the KS_SEQ_CONTROL of a wait sequence. If NULL, the provided maxwait is ignored and a value of zero used instead.
Return values
sizeof the received message, zero if timed out
1417  {
1418  int maxplayouts;
1419  int nBytes = 0;
1420  int i;
1421  n32 packed = 1;
1422 #ifdef IPG
1423  setscantimestop();
1424 #endif
1425 
1426  maxplayouts = waitctrl ? maxwait / waitctrl->duration : 0;
1427  if (maxplayouts < 1) {
1428  waitctrl = NULL;
1429  maxplayouts = 0;
1430  }
1431 
1432  for (i = 0; i <= maxplayouts; i++) {
1433 
1434 #ifdef IPG
1435  if (i != 0 && waitctrl) {
1436  ks_scan_playsequence(waitctrl);
1437  }
1438 #endif
1439 
1440  nBytes = 0;
1441 
1442 #if defined(MGD_TGT) && defined(PSD_HW)
1443 
1444 
1445  nBytes = rtp_get_feedback_data(rtpmsg, maxmsgsize, &packed, 2, RTP_QUEUE_NEWEST); /*according to RTP_RESULT_PROMO=2, defined in lx/include/PromoCommon.h*/
1446 
1447 
1448 #endif
1449 
1450  if (nBytes>0 && !packed) {
1451  break;
1452  }
1453  }
1454 
1455 #ifdef IPG
1456  setscantimestart();
1457 #endif
1458 
1459  return nBytes;
1460 }
int32_t i
Definition: KSFoundation_tgt.c:1389
int duration
Definition: KSFoundation.h:1135
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1368

◆ ks_copy_and_reset_obj()

void ks_copy_and_reset_obj ( void *  pobj)

Create a copy of any sequence object with a KS_BASE as first member

Create a copy of the object pointed by pobj and insert it into the linked list in second position. finally reset the (base part of) original object.

It is required that pobj can be casted to (KS_BASE *), which is the pointed object should have a KS_BASE as first member. Note that other, object-specific, actions may need to be performed to finalize the reset. This includes calls to ks_instancereset_***() functions on each member of the current pobj

Parameters
[in]pobjPointer to a sequence object of some kind
Returns
void
1463  {
1464 
1465  KS_BASE *head = (KS_BASE*) pobj;
1466 
1467  /* create a copy */
1468  KS_BASE *copy = (KS_BASE*) AllocNode(head->size);
1469  memcpy(copy, head, head->size);
1470 
1471  /* link to the copy */
1472  head->next = copy;
1473 
1474  /* reset the count of generated instances */
1475  head->ngenerated = 0;
1476 }
void * next
Definition: KSFoundation.h:411
(Internal use) Structure being a part of various sequence object to keep count of instances on HOST a...
Definition: KSFoundation.h:408
int ngenerated
Definition: KSFoundation.h:410
int size
Definition: KSFoundation.h:412

◆ ks_tgt_reset_gradrfctrl()

void ks_tgt_reset_gradrfctrl ( KS_GRADRFCTRL gradrfctrl)

Clears KS_GRADRFCTRL on TGT. Called in ks_pg_trap, ks_pg_wave, and ks_pg_rf if the field is_cleared_on_tgt is false.

Parameters
gradrfctrl[pointer to KS_GRADRFCTRL]
1481  {
1482  int i = 0;
1483  for (i = 0; i < gradrfctrl->numrf; ++i) {
1484  gradrfctrl->rfptr[i] = NULL;
1485  }
1486  for (i = 0; i < gradrfctrl->numtrap; ++i) {
1487  gradrfctrl->trapptr[i] = NULL;
1488  }
1489  for (i = 0; i < gradrfctrl->numwave; ++i) {
1490  gradrfctrl->waveptr[i] = NULL;
1491  }
1492  for (i = 0; i < gradrfctrl->numacq; ++i) {
1493  gradrfctrl->readptr[i] = NULL;
1494  }
1495  gradrfctrl->numrf = 0;
1496  gradrfctrl->numtrap = 0;
1497  gradrfctrl->numwave = 0;
1498  gradrfctrl->numacq = 0;
1499  gradrfctrl->is_cleared_on_tgt = TRUE;
1500 }
KS_RF * rfptr[KS_MAXUNIQUE_RF]
Definition: KSFoundation.h:966
int numtrap
Definition: KSFoundation.h:969
int32_t i
Definition: KSFoundation_tgt.c:1389
int numrf
Definition: KSFoundation.h:967
KS_WAVE * waveptr[KS_MAXUNIQUE_WAVE]
Definition: KSFoundation.h:970
int is_cleared_on_tgt
Definition: KSFoundation.h:974
KS_TRAP * trapptr[KS_MAXUNIQUE_TRAP]
Definition: KSFoundation.h:968
int numwave
Definition: KSFoundation.h:971
KS_READ * readptr[KS_MAXUNIQUE_READ]
Definition: KSFoundation.h:972
int numacq
Definition: KSFoundation.h:973

◆ ks_show_clock()

void ks_show_clock ( FLOAT  scantime)

Show the clock in the UI with the remaining scan time

1502  {
1503 #ifdef IPG
1504  setscantimestop();
1505  setscantimeimm(PSD_CLOCK_NORM, (float)scantime, piviews, (float)pitslice, opslicecnt);
1506  setscantimestart();
1507 #endif
1508 }
int piviews
int opslicecnt

◆ acqq_longdab()

STATUS acqq_longdab ( WF_PULSE_ADDR  pulse,
LONG  pos_ref,
LONG  dab_ref,
LONG  xtr_ref,
LONG  fslot_value 
)
1511 {
1512  static const CHAR *routine = "acqq_longdab";
1513  CHAR *basename = NULL;
1514  INT start; /* Start of the pulse */
1515  WF_PULSE_ADDR newpulse; /* Pointer to new pulse */
1516  INT pack_ix = 0; /* CERD change */
1517  INT LONG_DAB_length = 31; /* Maximum is 31, hardware limitation */
1518  SHORT LONG_DAB_bits[31]; /* Maximum is 31, hardware limitation */
1519 #ifdef PGEN_TIMING
1520  extern INT time_pgen;
1521  if (time_pgen == 1) {
1522  start_timer(&_PGEN_start_time);
1523  }
1524 #endif
1525 
1526  pack_ix = PSD_XCVR2;
1527 
1528 #ifdef SIM_IO
1529  if (psdtrace3)
1530  {
1531  CHAR tmpname[50];
1532  if (pulse->pulsename == NULL)
1533  strcpy(tmpname,"");
1534  else
1535  strcpy(tmpname,pulse->pulsename);
1536 
1537  fprintf(stderr,"%s pulse: %s posref %d xtrref %d dabref %d fslot %d\n",
1538  routine,
1539  tmpname,
1540  pos_ref,
1541  xtr_ref,
1542  dab_ref,
1543  fslot_value);
1544  fflush(stderr);
1545  }
1546 #endif
1547 
1548  LONG_DAB_bits[0] = SSPDS + DABDC; /* CAPM , CERD change: new opcode */
1549  LONG_DAB_bits[1] = SSPOC + DXCT; /* Excitation , CERD change: ew opcode */
1550  LONG_DAB_bits[2] = SSPD;
1551  LONG_DAB_bits[3] = SSPD;
1552  LONG_DAB_bits[4] = SSPD;
1553  LONG_DAB_bits[5] = SSPD;
1554  LONG_DAB_bits[6] = SSPD;
1555  LONG_DAB_bits[7] = SSPD + DABIS; /* if DABIS is really needed is unclear, we leave it for the moment */
1556  LONG_DAB_bits[8] = SSPD;
1557  LONG_DAB_bits[9] = SSPD;
1558  LONG_DAB_bits[10] = SSPD;
1559  LONG_DAB_bits[11] = SSPD;
1560  LONG_DAB_bits[12] = SSPD;
1561  LONG_DAB_bits[13] = SSPD;
1562  LONG_DAB_bits[14] = SSPD;
1563  LONG_DAB_bits[15] = SSPD;
1564  LONG_DAB_bits[16] = SSPD;
1565  LONG_DAB_bits[17] = SSPD;
1566  LONG_DAB_bits[18] = SSPD;
1567  LONG_DAB_bits[19] = SSPD;
1568  LONG_DAB_bits[20] = SSPD;
1569  LONG_DAB_bits[21] = SSPD;
1570  LONG_DAB_bits[22] = SSPD;
1571  LONG_DAB_bits[23] = SSPD;
1572  LONG_DAB_bits[24] = SSPD;
1573  LONG_DAB_bits[25] = SSPD;
1574  LONG_DAB_bits[26] = SSPD;
1575  LONG_DAB_bits[27] = SSPD;
1576  LONG_DAB_bits[28] = SSPD;
1577  LONG_DAB_bits[29] = SSPD;
1578  LONG_DAB_bits[30] = SSPDS; /* Last field must be SSPDS, max number of fields = 31 */
1579 
1580  /* Make sure packets are ordered properly (dab->xtr->rba) and that
1581  the dab packet doesn't collide with xtr packet. */
1582  if ((dab_ref != DEFAULTPOS) && (xtr_ref != DEFAULTPOS) &&
1583  (dab_ref + LONG_DAB_length > xtr_ref))
1584  MsgHndlr(routine,
1585  MSG_PULSE, pulse,
1586  MSG_FORMAT,
1587  CODING_PBM,
1588  EMT_INVLD_INSTR_START,
1589  dab_ref);
1590 
1591  /* Make sure there is enough room for xtr packet */
1592  if ((xtr_ref != DEFAULTPOS) &&
1593  (pos_ref - xtr_ref < (XTR_length[pack_ix] + RBA_length[pack_ix])))
1594  MsgHndlr(routine,
1595  MSG_PULSE, pulse,
1596  MSG_FORMAT,
1597  CODING_PBM,
1598  EMT_INVLD_INSTR_START,
1599  xtr_ref);
1600 
1601  if ((xtr_ref == DEFAULTPOS) && (RBA_length[pack_ix] > XTRSETLNG))
1602  MsgHndlr(routine,
1603  MSG_PULSE, pulse,
1604  MSG_FORMAT,
1605  CODING_PBM,
1606  EMT_INVLD_INSTR_START,
1607  pos_ref);
1608 
1609  /* This routine assumes that the user has created the
1610  * the pulse passed into this routine with the pre-processor
1611  */
1612 
1613  /***** The bits will be created first ****/
1614  /* The first thing this routine will do will be to verify if
1615  * any bits have been created or no.
1616  */
1617 
1618  if (pulse-> ninsts == 0)
1619  {
1620 
1621  /***************************************/
1622  /**** Create DAB 'bits' Pulse **********/
1623  /***************************************/
1624 
1625  if (!(basename = (CHAR *)AllocNode(strlen(pulse-> pulsename)+1)))
1626  {
1627  MsgHndlr(routine, MSG_FORMAT, HARDWARE_PBM,
1628  EMT_ALLOC, pulse-> pulsename);
1629  }
1630  strcpy(basename, pulse-> pulsename);
1631 
1632  char* dabname = (char *)AllocNode(strlen(basename)+4);
1633  /* Create Name For Pulse */
1634  if (!dabname)
1635  {
1636  MsgHndlr(routine, MSG_PULSE, pulse,
1637  MSG_FORMAT, HARDWARE_PBM,
1638  EMT_ALLOC, "DAB Bits Pulse Name");
1639  }
1640 
1641  /* Append "dab" suffix for loaddab... routines */
1642  sprintf(dabname,"%sdab",basename);
1643  pulse-> pulsename = dabname;
1644 
1645  createbits(pulse, (WF_PROCESSOR)TYPSSP,
1646  LONG_DAB_length,
1647  LONG_DAB_bits);
1648 
1649  /***************************************/
1650  /**** Create XTR 'bits' Pulse **********/
1651  /***************************************/
1652 
1653  if (!(newpulse = (WF_PULSE *)AllocNode(sizeof(WF_PULSE))))
1654  {
1655 
1656  MsgHndlr(routine, MSG_FORMAT,
1657  HARDWARE_PBM, EMT_ALLOC, "Receive Bits");
1658 
1659  }
1660 
1661  char* xtrname = (char *)AllocNode(strlen(basename)+4);
1662  /* Create Name For Pulse */
1663  if (!xtrname)
1664  {
1665  MsgHndlr(routine, MSG_PULSE, pulse,
1666  MSG_FORMAT,
1667  HARDWARE_PBM,
1668  EMT_ALLOC,
1669  "Xtr Bits Pulse Name");
1670  }
1671 
1672  /* Attach to dab pulse */
1673  pulse-> assoc_pulse = newpulse;
1674 
1675  /* Append xtr for use by other routines */
1676  sprintf(xtrname,"%sxtr",basename);
1677  newpulse-> pulsename = xtrname;
1678 
1679  /* Verify the parameters for the pulse */
1680 
1681  /* Begin LxMGD - RJF 12/6/00 */
1682 
1683  /* For MGD, there is a maximum of 8 filters with slot numbers 0 thru 7.
1684  The filter block is terminated with a slot number of -1.
1685  So the valid filter slots are from 0 to 7 - RJF */
1686 
1687  if ((fslot_value < MIN_FILTER_SLOT) || (fslot_value > MAX_FILTER_SLOT) )
1688  {
1689  MsgHndlr(routine,
1690  MSG_PULSE, newpulse,
1691  MSG_FORMAT,
1692  CODING_PBM,
1693  EMT_DAB_SLOT_NO,
1694  fslot_value);
1695  }
1696 
1697  /* Begin LxMGD - RJF, 12/6/00 */
1698  /* The way XTR bits was set up for CERD was wrong
1699  (see sspinit.c, which initializes the
1700  packet.) The receiver values should have been at offset 10
1701  and the filter slot value should be at offset 11. */
1702 
1703  XTR_bits[pack_ix][10] = SSPOC + RFLTRS;
1704  XTR_bits[pack_ix][11] = SSPD + fslot_value;
1705 
1706  /* End CERD change */
1707 
1708  /* Insert EOS */
1709  XTR_bits[pack_ix][XTR_length[pack_ix]-1] = SSPDS;
1710 
1711  createbits(newpulse,
1712  (WF_PROCESSOR)TYPSSP,
1713  XTR_length[pack_ix],
1714  XTR_bits[pack_ix]);
1715 
1716 
1717  /*************************************/
1718  /**** Create Receive 'bits' Pulse ****/
1719  /*************************************/
1720 
1721  if (!(newpulse = (WF_PULSE *)AllocNode(sizeof(WF_PULSE))))
1722  {
1723 
1724  MsgHndlr(routine, MSG_FORMAT,
1725  HARDWARE_PBM, EMT_ALLOC, "Receive Bits");
1726 
1727  }
1728 
1729  char* rbaname = (char *)AllocNode(strlen(basename)+4);
1730  /* Create Name For Pulse */
1731  if (!rbaname)
1732  {
1733  MsgHndlr(routine, MSG_PULSE, pulse,
1734  MSG_FORMAT,
1735  HARDWARE_PBM,
1736  EMT_ALLOC,
1737  "Receive Bits Pulse Name");
1738  }
1739  sprintf(rbaname,"%srba",basename);
1740  newpulse-> pulsename = rbaname;
1741 
1742  /* Attach to exciter pulse */
1743  pulse-> assoc_pulse -> assoc_pulse = newpulse;
1744 
1745 
1746  createbits(newpulse,
1747  (WF_PROCESSOR)TYPSSP,
1748  RBA_length[pack_ix],
1749  RBA_bits[pack_ix]);
1750  /* End CERD change */
1751 
1752  }
1753 
1754  /********** End of creating bits *******************/
1755 
1756  /***************************************/
1757  /**** Create XTR Instruction ***********/
1758  /***************************************/
1759 
1760  /* Back off for settling time of exciter */
1761  if (xtr_ref == DEFAULTPOS) {
1762  start = pos_ref - (XTRSETLNG + XTR_length[pack_ix]);
1763  } else {
1764  start = xtr_ref;
1765  }
1766  createinstr(pulse -> assoc_pulse,
1767  start,
1768  XTR_length[pack_ix],
1769  0);
1770 
1771  pulse->assoc_pulse-> tag = SSPXTR;
1772 
1773  /***************************************/
1774  /**** Create DAB Instruction ***********/
1775  /***************************************/
1776  /* The DAB needs at least DABSETUP set-up time. */
1777  if (dab_ref == DEFAULTPOS) {
1778  if (xtr_ref == DEFAULTPOS) {
1779  start = pos_ref - IMax(2, DABSETUP,
1780  XTRSETLNG + XTR_length[pack_ix] + LONG_DAB_length);
1781  } else {
1782  start = IMin(2, pos_ref-DABSETUP,xtr_ref-LONG_DAB_length);
1783  }
1784 
1785  } else {
1786  start = dab_ref;
1787  }
1788 
1789  /* For DAB packet */
1790  createinstr(pulse, start, LONG_DAB_length, 0);
1791 
1792  pulse->tag = SSPDAB;
1793 
1794  /***************************************/
1795  /**** Create RBA Instruction ***********/
1796  /***************************************/
1797  /* Back off by length of RBA packet */
1798 
1799  start = pos_ref - RBA_length[pack_ix];
1800 
1801  createinstr(pulse -> assoc_pulse -> assoc_pulse,
1802  start + RBA_start,
1803  RBA_length[pack_ix],
1804  0);
1805 
1806  pulse-> assoc_pulse-> assoc_pulse-> tag = SSPRBA;
1807  /* End of CERD change */
1808  FreeNode(basename); /* Arg must be a LONG : pradeep */
1809 #ifdef PGEN_TIMING
1810  if (time_pgen == 1) {
1811 
1812  end_timer(_PGEN_start_time,acqq_ix,"acqq");
1813 
1814  }
1815 #endif
1816 
1817  return SUCCESS;
1818 }

Variable Documentation

◆ GAM

float GAM

◆ cfreceiveroffsetfreq

int cfreceiveroffsetfreq

◆ rspent

int rspent

◆ pscR1

int pscR1

◆ cfcoilswitchmethod

int cfcoilswitchmethod

◆ cfswgut

int cfswgut

◆ cfswrfut

int cfswrfut

◆ rhasset

int rhasset

◆ cfhwgut

int cfhwgut

◆ piviews

int piviews

◆ opslicecnt

int opslicecnt