libpruio  0.0
AM33xx-PRU driver for digital input / output and analog input
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pruio.bas
Go to the documentation of this file.
1 /'* \file pruio.bas
2 \brief The main source code of the library.
3 
4 This is the main source code of the library. You may compile it by `fbc
5 -dylib pruio.bas` to get a small library file (small, because the C
6 wrapper functions are not included as in the original version).
7 
8 '/
9 
10 
11 /'* \mainpage libpruio
12 
13 Welcome to library libpruio,
14 
15 - a driver for ARM33xx micro processors,
16 - developed on [Beaglebone hardware](http://www.beaglebone.org) for
17 - analog input and
18 - digital input and output.
19 
20 It's designed to support easy configuration and data handling at high
21 speed. *libpruio* controls the subsystems
22 
23 - Programmable Realtime Unit SubSystem (= PRUSS or just PRU),
24 - Touch Screen Controler and Analog-to-Digital Convertor SubSystem (= TSC_ADC_SS or just ADC),
25 - Control Module
26 - General Purpose Input / Outputs (= GPIO)
27 
28 by software running at the real time unit (PRU). Once installed, this
29 library can configure and control the devices from single source (no
30 need for further overlays or the device tree compiler). The driver
31 supports two run modi
32 
33 - digital and analog lines conrolled by the host (IO mode) and
34 - analog measurements with accurate timing controlled by the PRU (MM mode).
35 
36 \em libpruio is developed and tested on a Beaglebone Black under Ubuntu
37 13.10 and should run on all Beaglebone platforms with Debian based
38 LINUX operating system. It's compiled by the
39 [FreeBasic compiler](http://www.freebasic.net). A wrapper for C
40 programming language is included.
41 
42 Find more information in the Description pages
43 
44 - \subpage ChaFeatures
45 - \subpage ChaMemory
46 - \subpage ChaPreparation
47 - \subpage ChaExamples
48 - \subpage ChaMessages
49 - \subpage ChaFE
50 
51 or at the world wide web:
52 
53  - [en: libpruio (BB D/A - I/O fast and easy)](http://www.freebasic.net/forum/viewtopic.php?f=14&t=22501)
54  - [de: libpruio (D/A - I/O schnell und einfach)](http://www.freebasic-portal.de/downloads/fb-on-arm/libpruio-325.html)
55 
56 
57 \section SecLicence Licence:
58 
59 \subsection SubLicLib libpruio (LGPLv2):
60 
61 Copyright © 2014 by \Email
62 
63 This program is free software; you can redistribute it and/or modify it
64 under the terms of the Lesser GNU General Public License version 2 as
65 published by the Free Software Foundation.
66 
67 This program is distributed in the hope that it will be useful, but
68 WITHOUT ANY WARRANTY; without even the implied warranty of
69 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
70 General Public License for more details.
71 
72 You should have received a copy of the GNU General Public License
73 along with this program; if not, write to the Free Software
74 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-
75 1301, USA. For further details please refer to:
76 http://www.gnu.org/licenses/lgpl-2.0.html
77 
78 \subsection SubLicExa Examples (GPLv3):
79 
80 Copyright © 2014 by \Email
81 
82 The examples of this bundle are free software as well; you can
83 redistribute them and/or modify them under the terms of the GNU
84 General Public License version 3 as published by the Free Software
85 Foundation.
86 
87 The programs are distributed in the hope that they will be useful, but
88 WITHOUT ANY WARRANTY; without even the implied warranty of
89 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
90 General Public License for more details.
91 
92 You should have received a copy of the GNU General Public License
93 along with this program; if not, write to the Free Software
94 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-
95 1301, USA. For further details please refer to:
96 http://www.gnu.org/licenses/gpl-3.0.html
97 
98 '/
99 
100 '' compile by
101 '' ./build
102 
103 #DEFINE __PRUIO_COMPILING__
104 
105 '* Driver header file.
106 #INCLUDE ONCE "pruio.bi"
107 '* Header file with convenience macros.
108 #INCLUDE ONCE "pruio_pins.bi"
109 '* Header file with PRU initialisation instructions.
110 #INCLUDE ONCE "pruio_init.bi"
111 '* Header file with PRU driver instructions.
112 #INCLUDE ONCE "pruio_run.bi"
113 '* Header file with PRU destructor instructions.
114 #INCLUDE ONCE "pruio_exit.bi"
115 
116 '* Macro to calculate the total size of an array in bytes.
117 #DEFINE ArrayBytes(_A_) (UBOUND(_A_) + 1) * SIZEOF(_A_)
118 
119 '* Declaration for C runtime function memcpy().
120 DECLARE FUNCTION memcpy CDECL ALIAS "memcpy"(BYVAL AS ANY PTR, BYVAL AS ANY PTR, BYVAL AS size_t) AS ANY PTR
121 
122 
123 /'* \brief Constructor, initialize devices, create default configuration.
124 \param Av avaraging for default steps (0 to 16, defaults to 0)
125 \param OpD open delay for default steps (0 to 0x3FFFF, defaults to 0x98)
126 \param SaD sample delay for default steps (0 to 255, defaults to 0)
127 \param Pru number of PRU subsystem to use (0 or 1, defaults to 1)
128 
129 The constructor tries to open the PRUSS interrupt and reports an error
130 in case of a failure (the structure should be freed in that case and in
131 case of any other error).
132 
133 Otherwise the constructor generates valid steps configuration data for
134 all channels (AIN0 to AIN 7 in steps 1 to 8). For these steps, the
135 default values can get customized using the (optional) parameter list:
136 
137 - avaraging may get done in a certain number of steps, options are 1,
138  2, 4, 8 or 16. (A non-matching parameter get increased either to the
139  next higher or to the last option.)
140 - open delay is the number of clock cycles the ADC waits between
141  setting the step configuration and sending the start of conversion
142  signal.
143 - sample delay is the number of clock cycles the ADC waits before
144  starting (the width of the start of conversion signal). It specifies
145  the number of clock cycles between the single conversion processes.
146 
147 See \ArmRef{12} for details on step configuration.
148 
149 Also, and after executing the constructor, the step configuration can
150 get customized by function \ref PruIo::adc_step().
151 
152 '/
153 CONSTRUCTOR PruIo( _
154  BYVAL Av AS uint8 = PRUIO_DEF_AVRAGE _
155  , BYVAL OpD AS uint32 = PRUIO_DEF_ODELAY _
156  , BYVAL SaD AS uint8 = PRUIO_DEF_SDELAY _
157  , BYVAL Pru AS uint8 = PRUIO_DEF_PRUSS)
158 
159  SELECT CASE AS CONST Pru
160  CASE 0
161  PruEvtout = PRU_EVTOUT_0
162  PruIRam = PRUSS0_PRU0_IRAM
163  PruDRam = PRUSS0_PRU0_DATARAM
164  ArmPruInt = ARM_PRU0_INTERRUPT
165  CASE 1
166  PruEvtout = PRU_EVTOUT_1
167  PruIRam = PRUSS0_PRU1_IRAM
168  PruDRam = PRUSS0_PRU1_DATARAM
169  ArmPruInt = ARM_PRU1_INTERRUPT
170  CASE ELSE : Errr = @"unknown PRUSS - select 0 or 1" : EXIT CONSTRUCTOR
171  END SELECT
172  PruNo = Pru
173  prussdrv_init()
174 
175  IF prussdrv_open(PRUIO_EVNT) THEN _ ' open PRU Interrupt
176  Errr = @"failed opening uio5 interrupt" : EXIT CONSTRUCTOR
177 
178  prussdrv_map_prumem(PruDRam, CAST(ANY PTR, @DRam))
179  prussdrv_map_extmem(@ERam)
180  ESize = prussdrv_extmem_size()
181  EOffs = prussdrv_get_phys_addr(ERam)
182 
183  VAR o = PRUIO_GPIO_OFFS SHR 2 _
184  , l = SIZEOF(GpioSet) * (PRUIO_GPIO_AZ + 1)
185  Gpio = CAST(GpioSet PTR, DRam + o)
186  IF 0 >= prussdrv_pru_write_memory(PruDRam, o, CAST(uint32 PTR, @GpioInit(0)), l) THEN _
187  Errr = @"failed loading GPIO initialisation" : EXIT CONSTRUCTOR
188 
189  prussdrv_pru_disable(PruNo) ' disable PRU
190  l = ArrayBytes(Pru_Init)
191  IF 0 >= prussdrv_pru_write_memory(PruIRam, 0, @Pru_Init(0), l) THEN _
192  Errr = @"failed loading Pru_Init instructions" : EXIT CONSTRUCTOR
193  prussdrv_pruintc_init(@IntcInit) ' get interrupt initialized
194  prussdrv_pru_enable(PruNo)
195 
196  VAR a = ABS((Av > 1) + (Av > 2) + (Av > 4) + (Av > 8)) SHL 2 _
197  , d = OpD AND &h3FFFF
198  FOR i AS INTEGER = 1 TO 8
199  WITH St_p(i)
200  .Confg = a + ((i - 1) SHL 19)
201  .Delay = d + SaD SHL 24
202  END WITH
203  NEXT
204 
205  prussdrv_pru_wait_event(PRUIO_EVNT)
206  IF DRam[0] <> PRUIO_MSG_INIT_OK THEN _
207  Errr = @"failed executing Pru_Init instructions" : EXIT CONSTRUCTOR
208 
209  BallConf = CAST(uint8 PTR, DRam) + PRUIO_BALL_OFFS
210  VAR p1 = DRam[1] - PRUIO_BALL_OFFS _
211  , p2 = p1 + (PRUIO_GPIO_AZ + 1) * PRUIO_GPIO_DATA _
212  , adc = DRam + p1 + p2
213  CSize = p2 + iif(adc[0], PRUIO_ADC_DATA, PRUIO_ADC_EMPTY)
214  BallOrg = ALLOCATE(CSize)
215  IF 0 = BallOrg THEN Errr = @"out of memory" : EXIT CONSTRUCTOR
216  memcpy(BallOrg, BallConf, CSize)
217  AdcOrg = BallOrg + p2
218  GpioOrg = BallOrg + p1
219 
220  BallRef = BallConf + PRUIO_BALL_AZ + 1
221  FOR i AS INTEGER = 0 TO PRUIO_BALL_AZ ' lock all pins
222  BallRef[i] = 255
223  IF BIT(BallConf[i], 5) THEN CONTINUE FOR ' skip input balls
224  VAR y = BallGpio(i) ' ... or set GPIO OE register for outputs
225  Gpio[y SHR 5 AND &b11].OutE AND= NOT (1 SHL (y AND &b11111))
226  NEXT
227  FOR i AS INTEGER = 0 TO UBOUND(P8_Pins) ' unlock P8 pins in mode 7
228  VAR x = P8_Pins(i)
229  IF (BallConf[x] AND &b111) = 7 THEN BallRef[x] = BallGpio(x)
230  NEXT
231  FOR i AS INTEGER = 0 TO UBOUND(P9_Pins) ' unlock P9 pins in mode 7
232  VAR x = P9_Pins(i)
233  IF (BallConf[x] AND &b111) = 7 THEN BallRef[x] = BallGpio(x)
234  NEXT
235 END CONSTRUCTOR
236 
237 
238 /'* \brief Destructor to restore configurations and clear memory.
239 
240 The destructor copies the original configuration to DRam (if any),
241 loads new instructions to the PRU and start them. This PRU code
242 restores the devices GPIOs, Control Module and ADC to their original
243 configurations. Finaly the PRU gets powered off and the memory of the
244 PruIo instance get freed.
245 
246 The destructor cannot report error messages in member variable \ref
247 PruIo::Errr. Messages (if any) get sent directly to the ERROUT pipe of
248 the operating system instead.
249 
250 '/
251 DESTRUCTOR PruIo()
252  prussdrv_pru_disable(PruNo)
253 
254  IF BallOrg THEN
255  memcpy(BallConf, BallOrg, CSize)
256  DEALLOCATE(BallOrg)
257  DRam[1] = PRUIO_BALL_OFFS
258  ELSE
259  DRam[1] = 0
260  END IF
261  Errr = 0
262 
263  VAR l = ArrayBytes(Pru_Exit)
264  IF 0 >= prussdrv_pru_write_memory(PruIRam, 0, @Pru_Exit(0), l) THEN
265  Errr = @"failed loading Pru_Exit instructions"
266  ELSE
267  prussdrv_pruintc_init(@IntcInit) ' get interrupt initialized
268  prussdrv_pru_enable(PruNo)
269  prussdrv_pru_wait_event(PRUIO_EVNT)
270  IF DRam[0] <> PRUIO_MSG_EXIT_OK THEN _
271  Errr = @"failed executing Pru_Exit instructions"
272  END IF
273  IF Errr THEN l = FREEFILE : OPEN ERR AS l : PRINT #l, *Errr : CLOSE #l
274 
275  prussdrv_pru_disable(PruNo)
276  prussdrv_exit() ' power down PRU
277 END DESTRUCTOR
278 
279 
280 /'* \brief Load configuration from host (ARM) to driver (PRU).
281 \param Samp number of samples to fetch (defaults to zero)
282 \param Mask mask for active steps (defaults to all 8 channels active in steps 1 to 8)
283 \param Tmr timer value in [ns] to specify the sampling rate (defaults to zero, MM only)
284 \param Mds modus for output (defaults to 4 = 16 bit)
285 \param ClDv divisor for ADC input clock (defaults to 0 = full speed = 2.4 MHz)
286 \returns zero on success (otherwise a string with an error message)
287 
288 This function is used to download the configuration from the host (ARM)
289 to the driver (PRU). The PRU gets stopped (if running) and the new
290 configurations get loaded. Also the PRU instructions get
291 re-initialized.
292 
293 In case of an error the PRU will be disabled after this call. Otherwise
294 it's running and
295 
296 - waits for a call to \ref PruIo::mm_start() (in case of Samp > 1) or
297 - starts sampling and feading values to \ref PruIo::Value otherwise.
298 
299 The *Samp* parameter specifies the number of samples to convert for
300 each channel. In single mode (Samp <= 1 = default) sampling starts
301 immediately and the index in the array \ref PruIo::Value[] is equal to
302 the step number. Inactive steps return 0 (zero) in this case.
303 
304 | field | result of | defaults to |
305 | -------: | :---------: | :------------ |
306 | Value[0] | charge step | allways zero |
307 | Value[1] | step 1 | AIN0 |
308 | Value[2] | step 2 | AIN1 |
309 | ... | ... | ... |
310 
311 In MM (Samp > 1) the array \ref PruIo::Value[] contains no zero values.
312 Instead only values from active steps get collected. The charge step
313 (step 0) returns no value. So when 3 steps are active in the Mask and
314 Samp is set to 5, a total of 3 times 5 = 15 values get available in the
315 array \ref PruIo::Value[] (after the call of the function \ref
316 PruIo::mm_start() ). The array contains the active steps, so when ie.
317 steps 3, 6 and 7 are active in the Mask, the array contains:
318 
319 | field | Mask = &b110010000 |
320 | -------: | :----------------- |
321 | Value[0] | 1. sample AIN3 |
322 | Value[1] | 1. sample AIN6 |
323 | Value[2] | 1. sample AIN7 |
324 | Value[3] | 2. sample AIN3 |
325 | Value[4] | 2. sample AIN6 |
326 | Value[5] | 2. sample AIN7 |
327 | Value[6] | 3. sample AIN3 |
328 | Value[7] | 3. sample AIN6 |
329 | Value[8] | ... |
330 
331 Currently the number of samples is limited by the external memory
332 allocated by the kernel PRUSS driver. This 256 kByte by default, see
333 \ref ChaMemory for further informations.
334 
335 | active Steps | max. Samples |
336 | -----------: | :----------- |
337 | 1 | 131072 |
338 | 2 | 65536 |
339 | 3 | 43690 |
340 | 4 | 32768 |
341 | 5 | 26214 |
342 | 6 | 21845 |
343 | 7 | 18724 |
344 | 8 | 16384 |
345 | ... | ... |
346 
347 The *Mask* parameter specifies the active steps. Setting a bit in the
348 Mask activates a step defined by the step configuration (by default
349 bits 1 = AIN0, 2 = AIN1, ... up to 8 = AIN7 are set, use function \ref
350 PruIo::adc_step() to customize steps).
351 
352 \note Bit 0 controls the charge step (see \ArmRef{12}, ADC STEPENABLE
353 register).
354 
355 The highest bit 31 has a special meaning for customizing the idle step.
356 By default the idle configuration is set like the configuration of the
357 first active step, so that (in MM) the open delay can get
358 reduced to a minimum for that step (if there's enough time left before
359 restart the ADC). By setting bit 31 the configuration from \ref
360 PruIo::St_p is used instead.
361 
362 The *Tmr* parameter specifies the sampling rate. It's the number of
363 nano seconds between the starts of the ADC sampling process. The IEP
364 timer gets used. It is configured to increase by steps of 5 (it counts
365 in GHz, but runs at 200 MHz), so values like 22676 or 22679 results to
366 the same frequency. Some examples
367 
368 | Tmr [ns] | Sampling rate [Hz] |
369 | -------: | :----------------- |
370 | 1e9 | 1 |
371 | 1e6 | 1000 |
372 | 22675 | ~44100 |
373 
374 \note This value has no effect in single mode (when Samp is less than 2).
375 
376 The *Mds* parameter specifies the range of the samples. By default (Mds
377 = 4) the 12 bit samples from the ADC get left shifted by 4, so that
378 they actually are 16 bit values and can get compared with samples from
379 other ADC devices (like 16 bit audio data). Examples
380 
381 | Mds | samples |
382 | -------: | :------- |
383 | 0 | 12 bit |
384 | 1 | 13 bit |
385 | 2 | 14 bit |
386 | 3 | 15 bit |
387 | 4 | 16 bit |
388 | >4 | 16 bit |
389 
390 The *ClDv* parameter gets transfered to the ADC clock divider register
391 ADC_CLKDIV (&h4C). The default value (0 = zero) lets the analog front
392 end (AFE) running at full speed (2.4 MHz). Otherwise the clock
393 frequency gets divided by this value + 1. Some examples
394 
395 | ClDv | AFE [MHz] |
396 | ---: | :-------- |
397 | 0 | 2.4 |
398 | 1 | 1.2 |
399 | 5 | 0.4 |
400 
401 Furthermore the registers \ref PruIo::AdcReg24 to \ref PruIo::AdcReg40
402 (ie. IRQ and DMA settings) get transfered to the ADC device, but bits 0
403 to 2 from \ref PruIo::AdcReg40 are controled by the driver software.
404 See \ArmRef{12} for details on ADC configurations.
405 
406 '/
407 FUNCTION PruIo.config CDECL( _
408  BYVAL Samp AS uint32 = PRUIO_DEF_SAMPLS _
409  , BYVAL Mask AS uint32 = PRUIO_DEF_STPMSK _
410  , BYVAL Tmr AS uint32 = PRUIO_DEF_TIMERV _
411  , BYVAL Mds AS uint16 = PRUIO_DEF_LSLMOD _
412  , BYVAL ClDv AS uint16 = PRUIO_DEF_CLKDIV) AS ZSTRING PTR
413  prussdrv_pru_disable(PruNo) ' disable PRU
414 
415  VAR c = UBOUND(St_p), r = 0, n = 0, d = 0
416  FOR i AS INTEGER = c - 1 TO 0 STEP -1
417  IF BIT(Mask, i) THEN
418  r = i ' find right-most bit
419  n += 1 ' count steps
420  WITH St_p(r) ' calculate clock cycles (delay)
421  VAR opd = .Delay AND &h3FFFF _
422  , smd = .Delay SHR 24 _
423  , avr = (.Confg SHR 2) AND &b111
424  d += opd + 1 + (14 + smd) * IIF(avr, 1 SHL avr, 1)
425  END WITH
426  END IF
427  NEXT
428  IF r < 1 THEN Errr = @"no step active" : RETURN Errr
429 
430  IF Samp < 2 THEN
431  Samples = 0
432  TimerVal = 0
433  Value = CAST(uint16 PTR, CAST(ANY PTR, DRam) + PRUIO_ADC_BUFF) - 1
434  ELSE
435  Samples = Samp * n
436  IF (Samples SHL 1) > ESize THEN _
437  Errr = @"out of memory" : RETURN Errr
438  d *= (ClDv + 1) * 417 ' 417 ~= 1000000 / 2400 (= 1 GHz / 2.4 MHz)
439  d += 30 ' PRU cycles for restart [GHz]
440  IF Tmr <= d THEN Errr = @"sample rate too big" : RETURN Errr
441  TimerVal = Tmr
442  Value = CAST(uint16 PTR, ERam)
443  END IF
444  ChAz = n
445  StepMask = Mask AND ((1 SHL c) - 1)
446  ClockDiv = ClDv
447  LslMode = IIF(Mds < 4, Mds, CAST(uint16, 4))
448  St_p(c).Delay = IIF(BIT(Mask, 31), r, 0) ' adapt idle step config?
449 
450  c = PRUIO_ADC_OFFS SHR 2
451  r = OFFSETOF(PruIo, DRam)
452  IF 0 >= prussdrv_pru_write_memory(PruDRam, c, @Samples, r) THEN _
453  Errr = @"failed loading parameters" : RETURN Errr
454 
455  r = ArrayBytes(Pru_Run)
456  IF 0 >= prussdrv_pru_write_memory(PruIRam, 0, @Pru_Run(0), r) THEN _
457  Errr = @"failed loading Pru_Run instructions" : RETURN Errr
458  prussdrv_pruintc_init(@IntcInit) ' get interrupt initialized
459  prussdrv_pru_enable(PruNo)
460 
461  c = IIF(Samp < 2, PRUIO_MSG_IO_OK, PRUIO_MSG_MM_WAIT)
462  prussdrv_pru_wait_event(PRUIO_EVNT)
463  IF DRam[0] <> c THEN _
464  Errr = @"failed executing Pru_Run instructions" : RETURN Errr
465 
466  IF Samp < 2 THEN RETURN 0
467 
468  prussdrv_pru_clear_event(PRUIO_EVNT, PRUIO_IRPT)
469  prussdrv_pru_send_event(ArmPruInt) ' prepare fast start
470  RETURN 0
471 END FUNCTION
472 
473 
474 /'* \brief Customize a single configuration step.
475 \param Stp step index (0 = step 0 => charge step, 1 = step 1 (=> AIN0 by default), ..., 17 = idle step)
476 \param ChN channel number to scan (0 = AIN0, 1 = AIN1, ...)
477 \param Av new value for avaraging (defaults to 4)
478 \param SaD new value for sample delay (defaults to 0)
479 \param OpD new value for open delay (defaults to 0x98)
480 \returns zero on success (otherwise a string with an error message)
481 
482 This function is used to adapt a step configuration. In the
483 constructor, steps 1 to 8 get configured for AIN0 to AIN7 (other steps
484 stay un-configured). By this function you can customize the default
485 settings and / or configure further steps (input channel number,
486 avaraging and delay values).
487 
488 | Stp | Description |
489 | -------: | :---------- |
490 | 0 | charge step |
491 | 1 | step 1 |
492 | 2 | step 2 |
493 | ... | ... |
494 | 17 | idle step |
495 
496 \note This sets the local data on the host system (ARM). The setup gets
497  uploaded to the PRU and activated when calling function \ref
498  PruIo::config().
499 
500 It's also possible to directly write to the step configuration in
501 member variables \ref PruIo::St_p (i).Confg and \ref
502 PruIo::St_p (i).Delay. See \ArmRef{12} for details on ADC
503 configurations.
504 
505 '/
506 FUNCTION PruIo.adc_step CDECL( _
507  BYVAL Stp AS uint8 _
508  , BYVAL ChN AS uint8 _
509  , BYVAL Av AS uint8 = PRUIO_DEF_AVRAGE _
510  , BYVAL SaD AS uint8 = PRUIO_DEF_SDELAY _
511  , BYVAL OpD AS uint32 = PRUIO_DEF_ODELAY) AS ZSTRING PTR
512 
513  IF Stp > UBOUND(St_p) THEN Errr = @"step number too big" : RETURN Errr
514  IF ChN > 7 THEN Errr = @"channel number too big" : RETURN Errr
515 
516  WITH St_p(Stp)
517  VAR a = ABS((Av > 1) + (Av > 2) + (Av > 4) + (Av > 8))
518  .Confg = (a SHL 2) + (ChN SHL 19)
519  .Delay = (OpD AND &h3FFFF) + (SaD SHL 24)
520  END WITH : RETURN 0
521 END FUNCTION
522 
523 
524 '* macro to check a CPU ball number (0 to 109 is valid range)
525 #DEFINE BallCheck(_T_,_R_) IF Ball > PRUIO_BALL_AZ THEN Errr = @"unknown" _T_ " pin number" : RETURN _R_
526 
527 /'* \brief Create a text description for a pin configuration.
528 \param Ball the CPU ball number to describe
529 \returns a human-readable text string (internal string, never free it)
530 
531 This function is used to create a text description for the current
532 state of a CPU ball, that is called a pin when it's connected to one of
533 the Beaglebone headers P8 or P9.
534 
535 The description contains the pin name and its mode. Header pin names
536 start with a capital 'P', CPU ball names start with a lower case 'b'.
537 The detailed pinmux setting is only described for pins in mode 7 (GPIO
538 mode). Otherwise only the mode number gets shown. Finally locked pins
539 get marked by the text '(locked)'.
540 
541 The returned string pointer points to an internal string. Never free
542 it. The string gets overwritten on further calls to this function, so
543 make local copies if you need several descriptions at a time. The
544 string may contain an error message if the ball number is too big.
545 
546 '/
547 FUNCTION PruIo.gpio_get_config CDECL(BYVAL Ball AS uint8) AS ZSTRING PTR
548  STATIC AS STRING*50 t
549 
550  SELECT CASE AS CONST Ball ' find name
551  CASE 6 : t = "P8_03"
552  CASE 7 : t = "P8_04"
553  CASE 2 : t = "P8_05"
554  CASE 3 : t = "P8_06"
555  CASE 36 : t = "P8_07"
556  CASE 37 : t = "P8_08"
557  CASE 39 : t = "P8_09"
558  CASE 38 : t = "P8_10"
559  CASE 13 : t = "P8_11"
560  CASE 12 : t = "P8_12"
561  CASE 9 : t = "P8_13"
562  CASE 10 : t = "P8_14"
563  CASE 15 : t = "P8_15"
564  CASE 14 : t = "P8_16"
565  CASE 11 : t = "P8_17"
566  CASE 35 : t = "P8_18"
567  CASE 8 : t = "P8_19"
568  CASE 33 : t = "P8_20"
569  CASE 32 : t = "P8_21"
570  CASE 5 : t = "P8_22"
571  CASE 4 : t = "P8_23"
572  CASE 1 : t = "P8_24"
573  CASE 0 : t = "P8_25"
574  CASE 31 : t = "P8_26"
575  CASE 56 : t = "P8_27"
576  CASE 58 : t = "P8_28"
577  CASE 57 : t = "P8_29"
578  CASE 59 : t = "P8_30"
579  CASE 54 : t = "P8_31"
580  CASE 55 : t = "P8_32"
581  CASE 53 : t = "P8_33"
582  CASE 51 : t = "P8_34"
583  CASE 52 : t = "P8_35"
584  CASE 50 : t = "P8_36"
585  CASE 48 : t = "P8_37"
586  CASE 49 : t = "P8_38"
587  CASE 46 : t = "P8_39"
588  CASE 47 : t = "P8_40"
589  CASE 44 : t = "P8_41"
590  CASE 45 : t = "P8_42"
591  CASE 42 : t = "P8_43"
592  CASE 43 : t = "P8_44"
593  CASE 40 : t = "P8_45"
594  CASE 41 : t = "P8_46"
595  CASE 28 : t = "P9_11"
596  CASE 30 : t = "P9_12"
597  CASE 29 : t = "P9_13"
598  CASE 18 : t = "P9_14"
599  CASE 16 : t = "P9_15"
600  CASE 19 : t = "P9_16"
601  CASE 87 : t = "P9_17"
602  CASE 86 : t = "P9_18"
603  CASE 95 : t = "P9_19"
604  CASE 94 : t = "P9_20"
605  CASE 85 : t = "P9_21"
606  CASE 84 : t = "P9_22"
607  CASE 17 : t = "P9_23"
608  CASE 97 : t = "P9_24"
609  CASE 107 : t = "P9_25"
610  CASE 96 : t = "P9_26"
611  CASE 105 : t = "P9_27"
612  CASE 103 : t = "P9_28"
613  CASE 101 : t = "P9_29"
614  CASE 102 : t = "P9_30"
615  CASE 100 : t = "P9_31"
616  CASE 109 : t = "P9_41"
617  CASE 89 : t = "P9_42"
618  CASE ELSE
619  BallCheck("", Errr)
620  t = "b " & RIGHT("00" & Ball, 3)
621  END SELECT
622 
623  VAR r = BallConf[Ball], m = r AND &b111, g = BallGpio(Ball) SHR 5
624  IF m = 7 THEN
625  t &= ", GPIO " & g & "/" & RIGHT("0" & (BallGpio(Ball) AND 31), 2)
626  t &= *IIF(BIT(r, 5), @": input", @": output")
627  IF BIT(r, 3) THEN
628  t &= ", nopull"
629  ELSE
630  IF BIT(r, 4) THEN t &= ", pullup" ELSE t &= ", pulldown"
631  END IF
632  ELSE
633  t &= ", mode " & m
634  END IF
635  IF BallRef[Ball] = 255 THEN t &= " (locked)"
636  RETURN SADD(t)
637 END FUNCTION
638 
639 
640 
641 /'* \brief Set the configuration of a GPIO.
642 \param Ball the CPU ball number to set
643 \param Modus the mode for the GPIO
644 \param Lokk the locking specification
645 \returns zero on success (otherwise a pionter to an error message)
646 
647 This function is used to configure a digital pin. Use the macros
648 defined in pruio.bi to specify the pin number for a pin on the
649 Beaglebone headers (ie P8_03 selects pin 3 on header P8).
650 
651 Its also possible to get the state of a CPU ball (not connected to
652 a header). In this case you need to find the matching CPU ball number
653 and pass it in as the parameter Ball.
654 
655 Parameter Modus specifies the pinmux mode for the ARM control module
656 (see \ArmRef{9}). By default the pin gets configured as input pin
657 with pullup resistor, so you can connect a button between the pin and
658 ground to use it as a on/off switch. Other configurations are prepared
659 as macros:
660 
661 | macro name | Description |
662 | --------------: | :--------------------------------------- |
663 | PRUIO_IN | open input pin (no resistor) |
664 | PRUIO_IN_0 | low input pin (with pulldown resistor) |
665 | PRUIO_IN_1 | high input pin (with pullup resistor) |
666 | PRUIO_OUT0 | output pin set to low (no resistor) |
667 | PRUIO_OUT1 | output pin set to high (no resistor) |
668 | PRUIO_PIN_RESET | reset pin configuration to initial state |
669 
670 By default only unlocked pins can get changed. These are header pins on
671 P8 or P9 headers that were in mode 7 (GPIO) at start-up. All other pins
672 are locked. That are internal pins not connected to a header and pins
673 in a different mode (ie HDMI or EMMC2 pins).
674 
675 Parameter Lokk can be specified to change the locking mode of a pin.
676 Use the enumerator from \ref PRUIO_PIN_LOCKING to specify the new mode
677 (the latest is the default value):
678 
679 | enumerator name | Description |
680 | ----------------: | :-------------------------------------------------------- |
681 | PRUIO_UNLOCK_CURR | unlock a pin, don't change the configuration |
682 | PRUIO_UNLOCK_ORIG | unlock a pin, change to original (initial) configuration |
683 | PRUIO_UNLOCK_NEW | unlock a pin, change to parameter configuration |
684 | PRUIO_LOCK_CURR | lock a pin, don't change the configuration |
685 | PRUIO_LOCK_ORIG | lock a pin, change to original (initial) configuration |
686 | PRUIO_LOCK_NEW | lock a pin, change to parameter configuration |
687 | PRUIO_LOCK_CHECK | don't change pin locking, skip operation if pin is locked |
688 
689 \note Pin locking only works for function family PruIo::gpio_xxx(). It
690  doesn't work in case of direct access to internal \ref PruIo::Gpio
691  member variables.
692 
693 '/
694 FUNCTION PruIo.gpio_set CDECL( _
695  BYVAL Ball AS uint8 _
696  , BYVAL Modus AS uint8 = PRUIO_IN_0 _
697  , BYVAL Lokk AS uint8 = PRUIO_LOCK_CHECK) AS ZSTRING PTR
698 
699  BallCheck("", Errr)
700 
701  SELECT CASE AS CONST Lokk
702  CASE PRUIO_UNLOCK_CURR
703  BallRef[Ball] = BallGpio(Ball) : RETURN 0
704  CASE PRUIO_LOCK_CURR
705  BallRef[Ball] = 255 : RETURN 0
706  CASE PRUIO_UNLOCK_ORIG
707  BallConf[Ball] = PEEK(BallOrg + Ball)
708  BallRef[Ball] = BallGpio(Ball)
709  CASE PRUIO_LOCK_ORIG
710  BallConf[Ball] = PEEK(BallOrg + Ball)
711  BallRef[Ball] = 255
712  CASE ELSE ' set new config
713  SELECT CASE AS CONST Lokk
714  CASE PRUIO_UNLOCK_NEW
715  BallRef[Ball] = BallGpio(Ball)
716  CASE PRUIO_LOCK_NEW
717  BallRef[Ball] = 255
718  CASE ELSE
719  IF 255 = BallRef[Ball] THEN Errr = @"pin locked" : RETURN Errr
720  END SELECT
721 
722  VAR r = BallGpio(Ball)
723  IF Modus = PRUIO_PIN_RESET THEN
724  BallConf[Ball] = PEEK(BallOrg + Ball)
725  ELSE
726  BallConf[Ball] = Modus AND &b1111111
727  IF BIT(Modus, 5) THEN ' input Ball
728  Gpio[r SHR 5].OutE OR= 1 SHL (r AND 31)
729  ELSE ' output Ball
730  Gpio[r SHR 5].OutE AND= NOT (1 SHL (r AND 31))
731  IF BIT(Modus, 7) THEN
732  Gpio[r SHR 5].SetM OR= 1 SHL (r AND 31)
733  ELSE
734  Gpio[r SHR 5].ClrM OR= 1 SHL (r AND 31)
735  END IF
736  END IF
737  END IF
738  END SELECT
739 
740  IF DRam[0] <> PRUIO_MSG_IO_OK THEN RETURN 0
741  WHILE DRam[1] <> PRUIO_MSG_INIT_OK : WEND : DRam[1] = Ball OR (1 SHL 31)
742  RETURN 0
743 END FUNCTION
744 
745 
746 /'* \brief Get the state of a GPIO.
747 \param Ball the CPU ball number to test
748 \returns GPIO state (otherwise -1, check \ref PruIo::Errr for an error message)
749 
750 This function is used to get the state of a digital pin (GPIO). Use the
751 macros defined in pruio.bi to specify the pin number for a pin on the
752 Beaglebone headers (ie P8_03 selects pin 3 on header P8).
753 
754 It's also possible to get the state of a CPU ball (not connected to
755 a header). In this case you need to find the matching CPU ball number
756 and pass it in as the parameter Ball.
757 
758 The function returns the state of input and output pins (locked or
759 unlocked). Return values are
760 
761 | Value | Description |
762 | ----: | :---------------------------- |
763 | 1 | GPIO is in high state |
764 | 0 | GPIO is in low state |
765 | -1 | error (undefined ball number) |
766 
767 An alternative (and faster) way to get a pin (or ball) state is reading
768 the corresponding bit in member variable \ref PruIo::Gpio[i].Stat.
769 
770 '/
771 FUNCTION PruIo.gpio_get CDECL(BYVAL Ball AS uint8) AS uint32
772  BallCheck("", -1)
773  VAR r = BallRef[Ball]
774  RETURN IIF(Gpio[r SHR 5].Stat AND (r AND 31), 1, 0)
775 END FUNCTION
776 
777 
778 /'* \brief Set the state of a GPIO.
779 \param Ball the CPU ball number to test
780 \param Modus the state to set (0 = low, high otherwise)
781 \returns zero on success (otherwise a pointer to an error message)
782 
783 This function is used to set the state of an output GPIO. Use the
784 macros defined in pruio.bi to specify the pin number for a pin on the
785 Beaglebone headers (ie P8_03 selects pin 3 on header P8).
786 
787 Its also possible to set the state of a CPU ball (not connected to
788 a header). In this case you need to find the matching CPU ball number
789 and pass it in as the parameter Ball.
790 
791 This function only works on unlocked output pins. Selecting an input
792 pin or a locked pin generates an error message.
793 
794 An alternative (and faster) way to set a pin (or ball) state is writing
795 to the corresponding bit in member variables \ref PruIo::Gpio[i].SetM
796 or \ref PruIo::Gpio[i].ClrM. (No locking in this case, mind what you're
797 doing.)
798 
799 '/
800 FUNCTION PruIo.gpio_out CDECL( _
801  BYVAL Ball AS uint8 _
802  , BYVAL Modus AS uint8 = 0) AS ZSTRING PTR
803 
804  BallCheck(" output", Errr)
805  IF BIT(BallConf[Ball], 5) THEN Errr = @"input pin" : RETURN Errr
806  VAR r = BallRef[Ball]
807  IF r = 255 THEN Errr = @"output pin locked" : RETURN Errr
808  IF Modus THEN
809  Gpio[r SHR 5].SetM OR= 1 SHL (r AND 31)
810  ELSE
811  Gpio[r SHR 5].ClrM OR= 1 SHL (r AND 31)
812  END IF : RETURN 0
813 END FUNCTION
814 
815 
816 /'* \brief Create a trigger configuration for a digital trigger (GPIO).
817 \param Ball the CPU ball number to test
818 \param GpioV the state to check (defaults to high = 1)
819 \param Skip the number of samples to skip (defaults to 0 = zero, max. 1023)
820 \returns the trigger configuration (or zero in case of an error, check \ref PruIo::Errr)
821 
822 This function is used to create a configuration for a digital (= GPIO)
823 trigger. Pass the returned value as parameter to function \ref
824 PruIo::mm_start(). The measurement (or the next trigger) will start
825 when the specified GPIO gets in to the declared state.
826 
827 The parameter Skip can be used to hold up the start for a certain
828 time (previously defined by the Tmr parameter in the last call to
829 function \ref PruIo::config).
830 
831 This trigger is a fast trigger. The ADC device is waiting in idle mode
832 while the GPIO gets checked.
833 
834 '/
835 FUNCTION PruIo.mm_trg_pin CDECL( _
836  BYVAL Ball AS uint8 _
837  , BYVAL GpioV AS uint8 = 0 _
838  , BYVAL Skip AS uint16 = 0) AS uint32
839 
840  BallCheck(" trigger", 0)
841  IF 7 <> (BallConf[Ball] AND &b111) THEN _
842  Errr = @"pin must be in GPIO mode (mode 7)" : RETURN 0
843  IF Skip > 1023 THEN Errr = @"too much values to skip" : RETURN 0
844 
845  DIM AS uint32 r = (1 SHL 21) _ ' GPIO bit
846  + (Ball SHL 8) _ ' Ball number
847  + IIF(GpioV = 0, 1 SHL 7, 0) _ ' negative bit
848  + (1 SHL 4) ' fast bit
849  IF Skip THEN r += (1 SHL 5) _ ' post trigger bit
850  + (Skip SHL 22) ' number of samples to skip
851  RETURN r
852 END FUNCTION
853 
854 
855 /'* \brief Create a trigger configuration for an analog input trigger.
856 \param Stp the step number to use for trigger input
857 \param AdcV the sample value to match (positive check greater than, negative check less than)
858 \param Rela if AdcV is relative to the current input
859 \param Skip the number of samples to skip (defaults to 0 = zero, max. 1023)
860 \returns the trigger configuration (or zero in case of an error, check \ref PruIo::Errr)
861 
862 This function is used to create a configuration for an analog (= AIN)
863 trigger. Pass the returned value as parameter to function \ref
864 PruIo::mm_start(). The measurement (or the next trigger) will start
865 when the specified analog input (AIN) gets in to the declared state.
866 
867 The parameter AdcV specifies the value to compare with. A positive
868 value starts when the input is greater than AdcV. A negative value
869 starts when the input is less than AdcV.
870 
871 AdcV is scalled like the samples, so when the previuos call to function
872 \ref PruIo::config() requires 16 bit samples (Mds = 4), AdcV has to be
873 specified as 16 bit value as well.
874 
875 AdcV can either be an absolute value or a relative value. For the later
876 case set parameter Rela to any value <> zero. The driver will
877 fetch the current analog input value when the trigger gets active and
878 adds AdcV to calculate the absolute trigger value.
879 
880 This trigger value gets auto-limited to a certain range (ie &hF0 to
881 &hFF00, in case of default 16 bit setting), to avoid trigger values
882 that never can be reached.
883 
884 The parameter Skip can be used to hold up the start for a certain
885 time (previously defined by the Tmr parameter in the last call to
886 function \ref PruIo::config). Example:
887 
888 ~~~{.bas}
889  Tmr = 1e8 ' 10 Hz
890 Skip = 500 ' skip 500 samples
891 time = Skip / Tmr * 1e9 ' delay time = 5 seconds (1e9 = Hz / GHz)
892 ~~~
893 
894 This trigger is a fast trigger. Only the specified step is active while
895 waiting for the event. The trigger step can be inactive in the Mask of
896 the previous call to function \ref PruIo::config() and only be used for
897 trigger purposes. (Ie. a short open delay can get specified for the
898 trigger step since there is no channel muxing.)
899 
900 \note All error checks in this function are related to the parameters
901  of the previuos call to function \ref PruIo::config(). The
902  created specification may get invalid by changing the ADC
903  settings by a further call to function \ref PruIo::config() with
904  different parameters (ie. when the trigger step gets cleared). To
905  be on the save side, re-create your trigger specifications after
906  each call to function \ref PruIo::config().
907 
908 '/
909 FUNCTION PruIo.mm_trg_ain CDECL( _
910  BYVAL Stp AS uint8 _
911  , BYVAL AdcV AS int32 _
912  , BYVAL Rela AS uint8 = 0 _
913  , BYVAL Skip AS uint16 = 0) AS uint32
914 
915  IF Stp < 1 ORELSE Stp > 16 THEN Errr = @"invalid step number" : RETURN 0
916  IF 0 = St_p(Stp).Confg THEN _
917  Errr = @"trigger step not configured" : RETURN 0
918  IF Skip > 1023 THEN Errr = @"too much values to skip" : RETURN 0
919 
920  VAR v = ABS(AdcV) SHR LslMode
921  IF v < &hF THEN v = &hF ELSE IF v > &hFF0 THEN v = &hFF0
922 
923  DIM AS uint32 r = Stp - 1 _ ' step to watch
924  + ( v SHL 8) _ ' sample AdcV to check
925  + IIF(AdcV < 0, 1 SHL 7, 0) _ ' negative bit
926  + IIF(Rela, 1 SHL 6, 0) _ ' relative bit
927  + ( 1 SHL 4) ' fast bit
928  IF Skip THEN r += (Skip SHL 22) _ ' number of samples to skip
929  + (1 SHL 5) ' post trigger bit
930  RETURN r
931 END FUNCTION
932 
933 
934 /'* \brief Create a trigger configuration for an analog input trigger.
935 \param Stp the step number to use for trigger input
936 \param AdcV the sample value to match (positive check greater than, negative check less than)
937 \param Samp the number of samples for the pre-trigger
938 \param Rela if AdcV is relative to the current input
939 \returns the trigger configuration (or zero in case of an error, check \ref PruIo::Errr)
940 
941 This function is used to create a configuration for an analog (= AIN)
942 pre-trigger. Pass the returned value as parameter to function \ref
943 PruIo::mm_start(). The measurement on all active steps will start
944 immediately and collect the input values in a ring buffer. Normal
945 measurement starts when the specified analog input (AIN) gets in to the
946 declared state.
947 
948 Either a certain step (that must be activated in the previous call to
949 function \ref PruIo::config() ) can be checked. Or all active inputs
950 get checked against the specified AdcV. In the later case AdcV is
951 allways an absolute value (parameter Rela gets ignored).
952 
953 The parameter AdcV specifies the value to compare with. A positive
954 value starts when the input is greater than AdcV. A negative value
955 starts when the input is less than AdcV.
956 
957 AdcV is scalled like the samples, so when the previuos call to function
958 \ref PruIo::config() requires 16 bit samples (Mds = 4), AdcV has to be
959 specified as 16 bit value as well.
960 
961 AdcV can either be an absolute value or a relative value. For the later
962 case set parameter Rela to any value <> zero. The driver will
963 fetch the current analog input value when the trigger gets active and
964 add AdcV to calculate the absolute trigger value.
965 
966 The trigger value gets auto-limited to a certain range (ie &hF0 to
967 &hFF00, in case of default 16 bit setting), to avoid trigger values
968 that never can be reached.
969 
970 Parameter Samp is used to specify the number of samples to fetch
971 before the trigger event occurs. It specifies the number of sampling
972 sets for all active channels. Its maximum value is limited to 1023 and
973 also by the amount of memory available (approx. 7000 samples in DRam0
974 and DRam1) to sort the ring buffer.
975 
976 The pre-trigger is a slow trigger. The ADC device goes through all
977 activated steps while waiting for the trigger event.
978 
979 \note All error checks in this function are related to the parameters
980  of the previuos call to function \ref PruIo::config(). The
981  created specification may get invalid by changing the ADC
982  settings by a further call to function \ref PruIo::config() with
983  different parameters (ie. when the trigger step gets cleared). To
984  be on the save side, re-create your trigger specifications after
985  each call to function \ref PruIo::config().
986 
987 \note A pre-trigger is always the last trigger specification in the
988  call to function \ref PruIo::mm_start() (all further
989  specifications get ignored).
990 
991 '/
992 FUNCTION PruIo.mm_trg_pre CDECL( _
993  BYVAL Stp AS uint8 _
994  , BYVAL AdcV AS int32 _
995  , BYVAL Samp AS uint16 = 0 _
996  , BYVAL Rela AS uint8 = 0) AS uint32
997 
998  IF Stp > 16 THEN Errr = @"invalid step number" : RETURN 0
999  IF Stp andalso 0 = St_p(Stp).Confg THEN _
1000  Errr = @"trigger step not configured" : RETURN 0
1001  IF Stp ANDALSO 0 = (StepMask AND (1 SHL Stp)) THEN _
1002  Errr = @"trigger step not activated" : RETURN 0
1003  VAR t = (Samp + 1) * ChAz
1004  IF t > ((16384 - PRUIO_ADC_OFFS) SHR 1) THEN _
1005  Errr = @"too much pre-samples" : RETURN 0
1006  IF t > Samples THEN Errr = @"more pre-samples than samples" : RETURN 0
1007 
1008  VAR v = ABS(AdcV) SHR LslMode
1009  IF v < &hF THEN v = &hF ELSE IF v > &hFF0 THEN v = &hFF0
1010 
1011  DIM AS uint32 r = (Samp SHL 22) _ ' number of pre-samples
1012  + (v SHL 8) _ ' sample AdcV to check
1013  + IIF(AdcV < 0, 1 SHL 7, 0) ' negative bit
1014  IF 0 = Stp THEN r += (1 SHL 20) _ ' all step bit,
1015  ELSE r += Stp - 1 _ ' or simple step number
1016  + IIF(Rela, 1 SHL 6, 0) ' relative bit
1017  RETURN r
1018 END FUNCTION
1019 
1020 
1021 /'* \brief Start a measurement in MM.
1022 \param Trg1 settings for first trigger (default = no trigger)
1023 \param Trg2 settings for second trigger (default = no trigger)
1024 \param Trg3 settings for third trigger (default = no trigger)
1025 \param Trg4 settings for fourth trigger (default = no trigger)
1026 \returns zero on success (otherwise a string with an error message)
1027 
1028 This function starts a measurement in MM mode. The ADC configuration
1029 from the previous call to function \ref PruIo::config() are used. The
1030 measurement either starts immediately or the start gets controlled by
1031 one (or up to four) trigger event(s).
1032 
1033 Function are available to create trigger specifications:
1034 
1035 - \ref PruIo::mm_trg_pin() for digital lines
1036 - \ref PruIo::mm_trg_ain() for analog lines
1037 - \ref PruIo::mm_trg_pre() for pre-triggers on analog lines
1038 
1039 \note The created analog trigger specifications may get invalid by
1040  changing the ADC settings in a further call to function \ref
1041  PruIo::config() with different parameters (ie. when the trigger
1042  step gets cleared). To be on the save side, re-create your
1043  trigger specifications after each call to function \ref
1044  PruIo::config().
1045 
1046 '/
1047 FUNCTION PruIo.mm_start CDECL( _
1048  BYVAL Trg1 AS uint32 = 0 _
1049  , BYVAL Trg2 AS uint32 = 0 _
1050  , BYVAL Trg3 AS uint32 = 0 _
1051  , BYVAL Trg4 AS uint32 = 0) AS ZSTRING PTR
1052 
1053  IF DRam[0] <> PRUIO_MSG_MM_WAIT THEN _
1054  Errr = @"measurement mode not ready" : RETURN Errr
1055 
1056  STATIC AS uint32 tmin = (1 SHL 22), t_pin
1057  DRam[3] = 0
1058 
1059 #DEFINE PRUIO_PRE_TRIG(_T_) Trg##_T_ >= tmin ANDALSO 0 = (Trg##_T_ AND (1 SHL 4)) THEN : _
1060  IF BIT(Trg##_T_, 20) ORELSE BIT(StepMask, (Trg##_T_ AND &b1111) + 1) THEN : _
1061  VAR n = (Trg##_T_ SHR 22) * ChAz : _
1062  IF n < Samples THEN : DRam[3] = n SHL 1 : _
1063  ELSE : Errr = @"Trg" #_T_ ": too much pre-trigger samples" : RETURN Errr : _
1064  END IF : _
1065  ELSE : Errr = @"Trg" #_T_ ": pre-trigger step must be active" : RETURN Errr : _
1066  END IF
1067 
1068 #DEFINE PRUIO_GPIO_TRIG(_T_) BIT(Trg##_T_, 21) THEN : _
1069  t_pin = (Trg##_T_ SHR 8) AND &b1111111 : _
1070  IF t_pin > PRUIO_BALL_AZ THEN _
1071  Errr = @"Trg" #_T_ ": unknown trigger pin number" : RETURN Errr : _
1072  END IF : _
1073  IF BallConf[t_pin] AND &b111 <> 7 THEN _
1074  Errr = @"Trg" #_T_ ": trigger pin must be in mode 7 (GPIO)" : RETURN Errr : _
1075  ELSE Trg##_T_ AND= &b11111111111100000000000011111111uL : _
1076  Trg##_T_ OR= BallGpio(t_pin) SHL 8 : _
1077  END IF : _
1078  END IF
1079 
1080  IF Trg1 THEN
1081  IF PRUIO_PRE_TRIG(1)
1082  ELSE
1083  IF PRUIO_GPIO_TRIG(1)
1084  IF Trg2 THEN
1085  IF PRUIO_PRE_TRIG(2)
1086  ELSE
1087  IF PRUIO_GPIO_TRIG(2)
1088  IF Trg3 THEN
1089  IF PRUIO_PRE_TRIG(3)
1090  ELSE
1091  IF PRUIO_GPIO_TRIG(3)
1092  IF Trg4 THEN
1093  IF PRUIO_PRE_TRIG(4)
1094  ELSE
1095  IF PRUIO_GPIO_TRIG(4)
1096  END IF
1097  END IF
1098  END IF
1099  END IF
1100  END IF
1101  END IF
1102  END IF
1103  END IF
1104 
1105  DRam[1] = ESize ' note: index for PRUIO_TRG_PARA = 4
1106  DRam[2] = EOffs
1107  DRam[4] = Trg1
1108  DRam[5] = Trg2
1109  DRam[6] = Trg3
1110  DRam[7] = Trg4
1111 
1112  prussdrv_pru_clear_event(PruEvtout, ArmPruInt) ' off we go
1113 
1114  prussdrv_pru_wait_event(PRUIO_EVNT) ' wait for end of measurement
1115  prussdrv_pru_clear_event(PRUIO_EVNT, PRUIO_IRPT) ' clear interrupt
1116  prussdrv_pru_send_event(ArmPruInt) ' prepare next start
1117  RETURN 0
1118 END FUNCTION
1119