libpruio  0.2
Input/Output driver for digital/analog lines on Beagleboard hardware
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pruio_adc.bas
Go to the documentation of this file.
1 /'* \file pruio_adc.bas
2 \brief The ADC component source code.
3 
4 Source code file containing the function bodies of the ADC component.
5 
6 '/
7 
8 
9 /'* \brief The constructor for the ADC features.
10 \param T A pointer of the calling PruIo structure.
11 
12 The constructor prepares the DRam parameters to run the pasm_init.p
13 instructions. The adress of the subsystem and the adress of the clock
14 registers get prepared, and the index of the last parameter gets stored
15 to compute the offset in the Init and Conf data blocks.
16 
17 \since 0.2
18 '/
19 CONSTRUCTOR AdcUdt(BYVAL T AS Pruio_ PTR)
20  Top = T
21  WITH *Top
22  VAR i = .ParOffs
23  InitParA = i
24  i += 1 : .DRam[i] = &h44E0D000uL
25  i += 1 : .DRam[i] = IIF(.DevAct AND PRUIO_ACT_ADC, &h44E004BCuL, 0)
26  .ParOffs = i
27  END WITH
28 END CONSTRUCTOR
29 
30 
31 /'* \brief Initialize the register context after running the pasm_init.p instructions (private).
32 \param Av The avaraging for default step configuration.
33 \param OpD The open delay for default step configuration.
34 \param SaD The sample delay for default step configuration.
35 \returns Zero on success (otherwise a string with an error message).
36 
37 This is a private function, designed to be called from the main
38 constructor PruIo::PruIo(). It sets the pointers to the Init and
39 Conf structures in the data blocks. And it initializes some register
40 context, if the subsystem woke up and is enabled.
41 
42 '/
43 FUNCTION AdcUdt.initialize CDECL( _
44  BYVAL Av AS UInt8 = PRUIO_DEF_AVRAGE _
45  , BYVAL OpD AS UInt32 = PRUIO_DEF_ODELAY _
46  , BYVAL SaD AS UInt8 = PRUIO_DEF_SDELAY) AS ZSTRING PTR
47 
48  WITH *Top
49  var p = .MOffs + .DRam[InitParA]
50  Init = p
51  Conf = p + .DSize
52  END WITH
53 
54  WITH *Conf
55  IF .ClAd = 0 ORELSE _
56  .REVISION = 0 THEN _ ' subsystem not enabled
57  .DeAd = 0 : .ClVa = 0 : RETURN 0
58  .ClVa = 2
59  .SYSCONFIG = 0
60  .CTRL = &b11
61 
62  VAR a = ABS((Av > 1) + (Av > 2) + (Av > 4) + (Av > 8)) SHL 2 _
63  , d = OpD AND &h3FFFF
64  FOR i AS LONG = 1 TO 8 ' set default ADC steps
65  WITH .St_p(i)
66  .Confg = a + ((i - 1) SHL 19)
67  .Delay = d + SaD SHL 24
68  END WITH
69  NEXT
70  END WITH : RETURN 0
71 END FUNCTION
72 
73 
74 /'* \brief Configuration of ADC parameters for PRU (private).
75 \param Samp The number of samples to fetch (or 1 for IO mode).
76 \param Mask The step mask to use.
77 \param Tmr The timer value in ns (ignored in IO mode).
78 \param Mds The bit encoding modus (0 = 12 bit, ... 4 = 16 bit).
79 \returns Zero on success (otherwise a string with an error message).
80 
81 This is a private function, designed to be called from PruIo::config().
82 It checks if the ADC subsystem is enabled and prepares parameters in
83 PruIo::DRam. Don't call it directly.
84 
85 '/
86 FUNCTION AdcUdt.configure CDECL( _
87  BYVAL Samp AS UInt32 = PRUIO_DEF_SAMPLS _
88  , BYVAL Mask AS UInt32 = PRUIO_DEF_STPMSK _
89  , BYVAL Tmr AS UInt32 = PRUIO_DEF_TIMERV _
90  , BYVAL Mds AS UInt16 = PRUIO_DEF_LSLMOD) AS ZSTRING PTR
91 
92  WITH *Top
93  Value = CAST(ANY PTR, .DRam) + PRUIO_DAT_ADC + 4
94 
95  IF 2 <> Conf->ClVa THEN ' subsystem not enabled
96  IF Samp < 2 ANDALSO _
97  Mask = 0 THEN .DRam[2] = Samp _
98  ELSE .DRam[2] = 0 : .Errr = E5 ' ADC not enabled
99  .DRam[3] = 0
100  .DRam[4] = 0
101  .DRam[5] = 0 : RETURN .Errr
102  END IF
103 
104  ChAz = 0
105  VAR c = UBOUND(Conf->St_p) _
106  , r = 0 _ ' first active step
107  , d = 0 ' duration of all steps
108  FOR i AS LONG = c - 1 TO 0 STEP -1
109  IF 0 = BIT(Mask, i) THEN CONTINUE FOR
110  r = i ' find right-most bit
111  ChAz += 1 ' count steps
112  WITH Conf->St_p(r) ' calculate clock cycles (delay)
113  VAR opd = .Delay AND &h3FFFF _
114  , smd = .Delay SHR 24 _
115  , avr = (.Confg SHR 2) AND &b111
116  d += opd + 1 + (14 + smd) * IIF(avr, 1 SHL avr, 1)
117  END WITH
118  NEXT
119 
120  IF Samp < 2 THEN ' IO mode
121  Samples = 1
122  TimerVal = 0
123  ELSE
124  IF r < 1 THEN .Errr = @"no step active" : RETURN .Errr
125  Samples = Samp * ChAz
126  IF (Samples SHL 1) > .ESize THEN _
127  .Errr = @"out of memory" : RETURN .Errr
128  d *= (Conf->ADC_CLKDIV + 1) * 417 '417 ≈ 1000000 / 2400 (= 1 GHz / 2.4 MHz)
129  d += 30 ' PRU cycles for restart [GHz]
130  IF Tmr <= d THEN .Errr = @"sample rate too big" : RETURN .Errr
131  TimerVal = Tmr
132  Value = .ERam
133  END IF
134  WITH *Conf
135  IF BIT(Mask, 31) THEN _ ' adapt idle step config
136  .IDLECONFIG = .St_p(r).Confg AND &b1111111111111111111100000
137 
138  Mask AND= (1 SHL c) - 1
139  .STEPENABLE = Mask
140  END WITH
141  LslMode = IIF(Mds < 4, Mds, CAST(UInt16, 4))
142 
143  .DRam[2] = Samples
144  .DRam[3] = Mask
145  .DRam[4] = LslMode
146  .DRam[5] = TimerVal
147  END WITH : RETURN 0
148 END FUNCTION
149 
150 
151 /'* \brief Customize a single configuration step.
152 \param Stp Step index (0 = step 0 => charge step, 1 = step 1 (=> AIN-0 by default), ..., 17 = idle step)-
153 \param ChN Channel number to scan (0 = AIN-0, 1 = AIN-1, ...)-
154 \param Av New value for avaraging (defaults to 4)-
155 \param SaD New value for sample delay (defaults to 0)-
156 \param OpD New value for open delay (defaults to 0x98)-
157 \returns Zero on success (otherwise a string with an error message).
158 
159 This function is used to adapt a step configuration. In the
160 constructor, steps 1 to 8 get configured for AIN-0 to AIN-7 (other
161 steps stay un-configured). By this function you can customize the
162 default settings and / or configure further steps (input channel
163 number, avaraging and delay values).
164 
165 | Stp | Description |
166 | -------: | :---------- |
167 | 0 | charge step |
168 | 1 | step 1 |
169 | 2 | step 2 |
170 | ... | ... |
171 | 16 | step 16 |
172 
173 \note This sets the local data on the host system (ARM). The setup gets
174  uploaded to the PRU and activated when calling function
175  PruIo::config().
176 
177 It's also possible to directly write to the step configuration in
178 member variables AdcSet::St_p `(i).Confg` and
179 AdcSet::St_p `(i).Delay`. See \ArmRef{12} for details on ADC
180 configurations.
181 
182 '/
183 FUNCTION AdcUdt.setStep CDECL( _
184  BYVAL Stp AS UInt8 _
185  , BYVAL ChN AS UInt8 _
186  , BYVAL Av AS UInt8 = PRUIO_DEF_AVRAGE _
187  , BYVAL SaD AS UInt8 = PRUIO_DEF_SDELAY _
188  , BYVAL OpD AS UInt32 = PRUIO_DEF_ODELAY) AS ZSTRING PTR
189 
190  WITH *Top
191  IF 2 <> Conf->ClVa THEN .Errr = E5 : RETURN .Errr ' ADC not enabled
192  IF Stp > UBOUND(Conf->St_p) THEN .Errr = E0 : RETURN .Errr ' step number too big
193  IF ChN > 7 THEN .Errr = E1 : RETURN .Errr ' channel number too big
194  END WITH
195 
196  WITH *Conf.St_p(Stp)
197  VAR a = ABS((Av > 1) + (Av > 2) + (Av > 4) + (Av > 8))
198  .Confg = (a SHL 2) + (ChN SHL 19)
199  .Delay = (OpD AND &h3FFFF) + (SaD SHL 24)
200  END WITH : RETURN 0
201 END FUNCTION
202 
203 
204 /'* \brief Create a trigger configuration for a digital trigger (GPIO).
205 \param Ball The CPU ball number to test.
206 \param GpioV The state to check (defaults to high = 1).
207 \param Skip The number of samples to skip (defaults to 0 = zero, max. 1023).
208 \returns The trigger configuration (or zero in case of an error, check PruIo::Errr).
209 
210 This function is used to create a configuration for a digital (= GPIO)
211 trigger. Pass the returned value as parameter to function
212 PruIo::mm_start(). The measurement (or the next trigger) will start
213 when the specified GPIO gets in to the declared state.
214 
215 The parameter Skip can be used to hold up the start for a certain
216 time (previously defined by the Tmr parameter in the last call to
217 function PruIo::config() ).
218 
219 This trigger is a fast trigger. The ADC subsystem is waiting in idle
220 mode while the GPIO gets checked.
221 
222 \note When the CPU ball number (parameter *Ball*) is on a GPIO
223  subsystem that is not enabled, an error gets reported (return
224  value = zero). When you switch off the subsystem after creating
225  the trigger specification, the trigger has no effect (it gets
226  skipped).
227 
228 '/
229 FUNCTION AdcUdt.mm_trg_pin CDECL( _
230  BYVAL Ball AS UInt8 _
231  , BYVAL GpioV AS UInt8 = 0 _
232  , BYVAL Skip AS UInt16 = 0) AS UInt32
233 
234  WITH *Top
235  IF 2 <> Conf->ClVa THEN .Errr = E5 : RETURN 0 ' ADC not enabled
236  IF Skip > 1023 THEN .Errr = E2 : RETURN 0 'too much values 2 skip
237  BallCheck(" trigger", 0)
238  VAR g = .BallGpio(Ball) _ ' resulting GPIO (index and bit number)
239  , i = g SHR 5 ' index of GPIO
240 
241  IF 2 <> .Gpio->Conf(i)->ClVa THEN _
242  .Errr = @"GPIO subsystem not enabled" : RETURN 0
243  IF 7 <> (.BallConf[Ball] AND &b111) THEN _
244  .Errr = @"pin must be in GPIO mode (mode 7)" : RETURN 0
245  END WITH
246 
247  DIM AS UInt32 r = (Skip SHL 22) _ ' number of samples to skip
248  + (1 SHL 21) _ ' GPIO bit
249  + (Ball SHL 8) _ ' Ball number
250  + IIF(GpioV = 0, 1 SHL 7, 0) ' negative bit
251  RETURN r
252 END FUNCTION
253 
254 
255 /'* \brief Create a trigger configuration for an analog input trigger.
256 \param Stp The step number to use for trigger input (or 0 for all active steps).
257 \param AdcV The sample value to match (positive checks greater than, negative checks less than).
258 \param Rela Not zero means AdcV is relative to the sample at start (ignored when Stp = 0).
259 \param Skip The number of samples to skip (defaults to 0 = zero, max. 1023).
260 \returns The trigger configuration (or zero in case of an error, check PruIo::Errr).
261 
262 This function is used to create a configuration for an analog (= AIN)
263 trigger. Pass the returned value as parameter to function
264 PruIo::mm_start(). The measurement (or the next trigger) will start
265 when the specified analog input (AIN) gets in to the declared state.
266 
267 The parameter *Stp* specifies the step number to use for the trigger.
268 This may be an active step (enabled in the PruIo::config() call).
269 Or it can be a further step with customized settings only for trigger
270 purposes (see trigger.bas for an example).
271 
272 The parameter *AdcV* specifies the value to compare with. A positive
273 value starts when the input is greater than AdcV. A negative value
274 starts when the input is less than AdcV.
275 
276 AdcV is scalled like the samples, so when the previuos call to function
277 PruIo::config() requires 16 bit samples (Mds = 4), AdcV has to be
278 specified as 16 bit value as well.
279 
280 AdcV can either be an absolute value or a relative value. For the later
281 case set parameter *Rela* to any value <> zero. The driver will
282 fetch the current analog input value when the trigger gets active and
283 adds AdcV to calculate the absolute trigger value.
284 
285 This trigger value gets auto-limited to a certain range (ie &hF0 to
286 &hFF00, in case of default 16 bit setting), to avoid trigger values
287 that never can be reached.
288 
289 The parameter *Skip* can be used to hold up the start for a certain
290 time (previously defined by the Tmr parameter in the last call to
291 function PruIo::config() ). Example:
292 
293 ~~~{.bas}
294  Tmr = 1e8 ' 10 Hz
295 Skip = 500 ' skip 500 samples
296 time = Skip / Tmr * 1e9 ' delay time = 5 seconds (1e9 = Hz / GHz)
297 ~~~
298 
299 This trigger is a fast trigger. Only the specified step is active while
300 waiting for the event. The trigger step can be inactive in the Mask of
301 the previous call to function PruIo::config() and only be used for
302 trigger purposes. (Ie. a short open delay can get specified for the
303 trigger step since there is no channel muxing.)
304 
305 \note All error checks in this function are related to the parameters
306  of the previuos call to function PruIo::config(). The
307  created specification may get invalid by changing the ADC
308  settings by a further call to function PruIo::config() with
309  different parameters (ie. when the trigger step gets cleared). To
310  be on the save side, re-create your trigger specifications after
311  each call to function PruIo::config().
312 
313 '/
314 FUNCTION AdcUdt.mm_trg_ain CDECL( _
315  BYVAL Stp AS UInt8 _
316  , BYVAL AdcV AS Int32 _
317  , BYVAL Rela AS UInt8 = 0 _
318  , BYVAL Skip AS UInt16 = 0) AS UInt32
319 
320  WITH *Top
321  IF 2 <> Conf->ClVa THEN .Errr = E5 : RETURN 0 ' ADC not enabled
322  IF Stp > 16 THEN .Errr = E4 : RETURN 0 ' invalid step number
323  IF Stp ANDALSO 0 = Conf->St_p(Stp).Confg THEN .Errr = E3 : RETURN 0 ' trigger step not configured
324  IF Skip > 1023 THEN .Errr = E2 : RETURN 0 ' too much values to skip
325  END WITH
326 
327  VAR v = ABS(AdcV) SHR LslMode
328  IF v < &hF THEN v = &hF ELSE IF v > &hFF0 THEN v = &hFF0
329 
330  DIM AS UInt32 r = (Skip SHL 22) _ ' number of samples to skip
331  + (v SHL 8) _ ' sample AdcV to check
332  + IIF(AdcV < 0, 1 SHL 7, 0) ' negative bit
333  IF 0 = Stp THEN r += (1 SHL 5) _ ' all step bit,
334  ELSE r += Stp - 1 _ ' or step number
335  + IIF(Rela, 1 SHL 6, 0) ' and relative bit
336  RETURN r
337 END FUNCTION
338 
339 
340 /'* \brief Create a trigger configuration for an analog input trigger.
341 \param Stp The step number to use for trigger input.
342 \param AdcV The sample value to match (positive check greater than, negative check less than).
343 \param Samp The number of samples for the pre-trigger.
344 \param Rela If AdcV is relative to the current input.
345 \returns The trigger configuration (or zero in case of an error, check PruIo::Errr).
346 
347 This function is used to create a configuration for an analog (= AIN)
348 pre-trigger. Pass the returned value as parameter to function
349 PruIo::mm_start(). The measurement on all active steps will start
350 immediately and collect the input values in a ring buffer. Normal
351 measurement starts when the specified analog input (AIN) gets in to the
352 declared state.
353 
354 Either a certain step (that must be activated in the previous call to
355 function PruIo::config() ) can be checked. Or all active inputs
356 get checked against the specified AdcV. In the later case AdcV is
357 allways an absolute value (parameter Rela gets ignored).
358 
359 The parameter AdcV specifies the value to compare with. A positive
360 value starts when the input is greater than AdcV. A negative value
361 starts when the input is less than AdcV.
362 
363 AdcV is scalled like the samples, so when the previuos call to function
364 PruIo::config() requires 16 bit samples (Mds = 4), AdcV has to be
365 specified as 16 bit value as well.
366 
367 AdcV can either be an absolute value or a relative value. For the later
368 case set parameter Rela to any value <> zero. The driver will
369 fetch the current analog input value when the trigger gets active and
370 add AdcV to calculate the absolute trigger value.
371 
372 The trigger value gets auto-limited to a certain range (ie &hF0 to
373 &hFF00, in case of default 16 bit setting), to avoid trigger values
374 that never can be reached.
375 
376 Parameter Samp is used to specify the number of samples to fetch
377 before the trigger event occurs. It specifies the number of sampling
378 sets for all active channels. Its maximum value is limited to 1023 and
379 also by the amount of memory available (approx. 7000 samples in DRam0
380 and DRam1) to sort the ring buffer.
381 
382 The pre-trigger is a slow trigger. The ADC subsystem goes through all
383 activated steps while waiting for the trigger event.
384 
385 \note All error checks in this function are related to the parameters
386  of the previuos call to function PruIo::config(). The
387  created specification may get invalid by changing the ADC
388  settings by a further call to function PruIo::config() with
389  different parameters (ie. when the trigger step gets cleared). To
390  be on the save side, re-create your trigger specifications after
391  each call to function PruIo::config().
392 
393 \note A pre-trigger is always the last trigger specification in the
394  call to function PruIo::mm_start() (all further
395  specifications get ignored).
396 
397 '/
398 FUNCTION AdcUdt.mm_trg_pre CDECL( _
399  BYVAL Stp AS UInt8 _
400  , BYVAL AdcV AS Int32 _
401  , BYVAL Samp AS UInt16 = 0 _
402  , BYVAL Rela AS UInt8 = 0) AS UInt32
403 
404  WITH *Top
405  IF 2 <> Conf->ClVa THEN .Errr = E5 : RETURN 0 ' ADC not enabled
406  IF Stp > 16 THEN .Errr = E4 : RETURN 0 ' invalid step number
407  IF Stp ANDALSO 0 = Conf->St_p(Stp).Confg THEN .Errr = E3 : RETURN 0 ' trigger step not configured
408  IF Stp ANDALSO 0 = (Conf->STEPENABLE AND (1 SHL Stp)) THEN _
409  .Errr = @"trigger step not activated" : RETURN 0
410  VAR t = (Samp + 1) * ChAz
411  IF t > ((16384 - PRUIO_DAT_ADC - 32) SHR 1) THEN _
412  .Errr = @"too much pre-samples" : RETURN 0
413  IF t > Samples THEN _
414  .Errr = @"more pre-samples than samples" : RETURN 0
415  END WITH
416 
417  VAR v = ABS(AdcV) SHR LslMode
418  IF v < &hF THEN v = &hF ELSE IF v > &hFF0 THEN v = &hFF0
419 
420  DIM AS UInt32 r = (Samp SHL 22) _ ' number of pre-samples
421  + (v SHL 8) _ ' sample AdcV to check
422  + IIF(AdcV < 0, 1 SHL 7, 0) _ ' negative bit
423  + (1 SHL 4) ' pre-trigger bit
424  IF 0 = Stp THEN r += (1 SHL 5) _ ' all step bit,
425  ELSE r += Stp - 1 _ ' or step number
426  + IIF(Rela, 1 SHL 6, 0) ' and relative bit
427  RETURN r
428 END FUNCTION
429