libpruio  0.2
Input/Output driver for digital/analog lines on Beagleboard hardware
 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 *libpruio* library,
14 
15 - a driver for ARM33xx micro processors,
16 - developed on [Beaglebone hardware](http://www.beaglebone.org), supporting
17 - analog input and
18 - digital input and output features.
19 
20 It's designed for easy configuration and data handling at high speed.
21 \em libpruio software runs on the host (ARM) and in parallel on a
22 Programmable Realtime Unit SubSystem (= PRUSS or just PRU) and controls
23 the subsystems
24 
25 - Control Module
26 - GPIO: General Purpose Input / Output,
27 - PWMSS: Pulse-Width Modulation Subsystem,
28 - TSC_ADC_SS: Touch Screen Controler and Analog-to-Digital Convertor SubSystem (or just ADC).
29 
30 The driver supports three run modi
31 
32 - IO mode: digital and analog lines, timing conrolled by the host,
33 - RB mode: digital and analog lines, accurate ADC timing conrolled by the PRU,
34 - MM mode: analog lines and optional triggers, accurate ADC timing controlled by the PRU.
35 
36 The \em libpruio library is developed and tested on a Beaglebone Black
37 under Ubuntu 13.10 and Debian Image 2014-08-05. It should run on all
38 Beaglebone platforms with Debian based LINUX operating system. It's
39 compiled by the [FreeBasic compiler](http://www.freebasic.net). A
40 wrapper for C 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 ChaChangelog
50 
51 or at the world wide web:
52 
53  - [en: libpruio (fast and easy D/A - I/O)](http://beagleboard.org/project/libpruio/)
54  - [en: libpruio (BB D/A - I/O fast and easy)](http://www.freebasic.net/forum/viewtopic.php?f=14&t=22501)
55  - [de: libpruio (D/A - I/O schnell und einfach)](http://www.freebasic-portal.de/downloads/fb-on-arm/libpruio-325.html)
56 
57 
58 \section SecLicence Licence:
59 
60 \subsection SubLicLib libpruio (LGPLv2):
61 
62 Copyright © 2014 by \Email
63 
64 This program is free software; you can redistribute it and/or modify it
65 under the terms of the Lesser GNU General Public License version 2 as
66 published by the Free Software Foundation.
67 
68 This program is distributed in the hope that it will be useful, but
69 WITHOUT ANY WARRANTY; without even the implied warranty of
70 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
71 General Public License for more details.
72 
73 You should have received a copy of the GNU General Public License
74 along with this program; if not, write to the Free Software
75 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-
76 1301, USA. For further details please refer to:
77 http://www.gnu.org/licenses/lgpl-2.0.html
78 
79 \subsection SubLicExa Examples (GPLv3):
80 
81 Copyright © 2014 by \Email
82 
83 The examples of this bundle are free software as well; you can
84 redistribute them and/or modify them under the terms of the GNU
85 General Public License version 3 as published by the Free Software
86 Foundation.
87 
88 The programs are distributed in the hope that they will be useful, but
89 WITHOUT ANY WARRANTY; without even the implied warranty of
90 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
91 General Public License for more details.
92 
93 You should have received a copy of the GNU General Public License
94 along with this program; if not, write to the Free Software
95 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-
96 1301, USA. For further details please refer to:
97 http://www.gnu.org/licenses/gpl-3.0.html
98 
99 '/
100 
101 '* Tell the header pruio.bi that we won't include libpruio.so.
102 #DEFINE __PRUIO_COMPILING__
103 '* The start of the pinmux-helper folder names in /sys/devices/ocp.*/.
104 #DEFINE PMUX_NAME "pruio-"
105 
106 
107 ' driver header file
108 #INCLUDE ONCE "pruio.bi"
109 ' Header file with convenience macros.
110 #INCLUDE ONCE "pruio_pins.bi"
111 ' source code of ADC part
112 #INCLUDE ONCE "pruio_adc.bas"
113 ' source code of GPIO part
114 #INCLUDE ONCE "pruio_gpio.bas"
115 ' source code of PWMSS part, containing modules QEP, CAP and PWM
116 #INCLUDE ONCE "pruio_pwmss.bas"
117 ' Header file with Pru_Init instructions.
118 #INCLUDE ONCE "pasm_init.bi"
119 ' Header file with Pru_Run instructions.
120 #INCLUDE ONCE "pasm_run.bi"
121 ' FB include
122 #INCLUDE ONCE "dir.bi"
123 
124 '* \brief Declaration for C runtime function memcpy().
125 DECLARE FUNCTION memcpy CDECL ALIAS "memcpy"(BYVAL AS ANY PTR, BYVAL AS ANY PTR, BYVAL AS size_t) AS ANY PTR
126 
127 
128 /'* \brief Constructor, initialize subsystems, create default configuration.
129 \param Act Mask to specify active subsystems (defaults to all active).
130 \param Av Avaraging for default steps (0 to 16, defaults to 0).
131 \param OpD Open delay for default steps (0 to 0x3FFFF, defaults to 0x98)
132 \param SaD Sample delay for default steps (0 to 255, defaults to 0).
133 
134 The constructor tries to
135 
136 - open the PRUSS interrupt (/dev/uio5),
137 - load the pasm_init.p instructions to the PRU and executes them, and
138 - call the initialize functions of the subsystem UDTs.
139 
140 It reports a failure by setting the member variable PruIo::Errr to
141 an appropriate text (the structure should be freed in that case).
142 
143 Otherwise (PruIo::Errr = 0) the constructor tries to enable the
144 subsystems and read their configurations. This gets done for the active
145 subsystems only. Use parameter *Act* to specify active systems and the
146 PRU number to run the software:
147 
148 | Bit | Function |
149 | --: | :------------------------------- |
150 | 8 | PWMSS-2: 0 = inactiv, 1 = active |
151 | 7 | PWMSS-1: 0 = inactiv, 1 = active |
152 | 6 | PWMSS-0: 0 = inactiv, 1 = active |
153 | 5 | GPIO-3: 0 = inactiv, 1 = active |
154 | 4 | GPIO-2: 0 = inactiv, 1 = active |
155 | 3 | GPIO-1: 0 = inactiv, 1 = active |
156 | 2 | GPIO-0: 0 = inactiv, 1 = active |
157 | 1 | ADC: 0 = inactiv, 1 = active |
158 | 0 | 0 = PRU-0, 1 = PRU-1 |
159 
160 For convenience, use enumerators PruIo::ActivateDevice. By default
161 all subsystems are activated. (A subsystem has to be active before it
162 can get disabled.)
163 
164 The other parameters *Av*, *OpD* and *SaD* are used to create a default
165 step configuration for analog input. They get passed to function
166 AdcUdt::initialize() to generates default step configuration data for
167 all analog lines (AIN-0 to AIN-7) in the steps 1 to 8. For these steps,
168 the default values can get customized using the (optional) parameter
169 list:
170 
171 - parameter *Av* sets avaraging in a certain number of steps. Options
172  are 1, 2, 4, 8 or 16. (A non-matching parameter get increased either
173  to the next higher or to the last option.)
174 
175 - parameter *OpD* sets the open delay, which is the number of clock
176  cycles the ADC waits between setting the step configuration and
177  sending the start of conversion signal.
178 
179 - parameter *SaD* sets the sample delay, which is the number of clock
180  cycles the ADC waits before starting (the width of the start of
181  conversion signal). It specifies the number of clock cycles between
182  the single conversion processes.
183 
184 See \ArmRef{12} for details on step configuration.
185 
186 These step configurations can get customized or extended later on by
187 calling function AdcUdt::setStep().
188 
189 '/
190 CONSTRUCTOR PruIo( _
191  BYVAL Act AS UInt16 = PRUIO_DEF_ACTIVE _
192  , BYVAL Av AS UInt8 = PRUIO_DEF_AVRAGE _
193  , BYVAL OpD AS UInt32 = PRUIO_DEF_ODELAY _
194  , BYVAL SaD AS UInt8 = PRUIO_DEF_SDELAY)
195 
196  VAR fnr = FREEFILE ' test interrupt access
197  IF OPEN("/dev/uio5" FOR OUTPUT AS fnr) THEN _
198  Errr = @"cannot open /dev/uio5" : EXIT CONSTRUCTOR
199  CLOSE #fnr
200 
201  VAR p = "/sys/devices/" _
202  , n = DIR(p & "ocp.*", fbDirectory)
203  IF LEN(n) THEN MuxAcc = p & n & "/"
204 
205  IF Act AND PRUIO_ACT_PRU1 THEN
206  PruIRam = PRUSS0_PRU1_IRAM
207  PruDRam = PRUSS0_PRU1_DATARAM
208  PruEvtOut = PRU_EVTOUT_1
209  ArmPruInt = ARM_PRU1_INTERRUPT
210  PruNo = 1
211  ELSE
212  PruIRam = PRUSS0_PRU0_IRAM
213  PruDRam = PRUSS0_PRU0_DATARAM
214  PruEvtOut = PRU_EVTOUT_0
215  ArmPruInt = ARM_PRU0_INTERRUPT
216  PruNo = 0
217  END IF
218  prussdrv_init()
219  IF prussdrv_open(PRUIO_EVNT) THEN _ ' open PRU Interrupt
220  Errr = @"failed opening prussdrv library" : EXIT CONSTRUCTOR
221 
222  prussdrv_map_prumem(PruDRam, CAST(ANY PTR, @DRam))
223  prussdrv_map_extmem(@ERam)
224  ESize = prussdrv_extmem_size()
225  EAddr = prussdrv_get_phys_addr(ERam)
226  DRam[0] = 0
227  DRam[1] = PRUIO_DAT_ALL ' start of data block
228  ParOffs = 1
229  DevAct = Act
230 
231 '' order must match the order in
232 '' pruio_init.p xxx_Init and in
233 '' pruio_run.p xxx_Config macro calls
234  Adc = NEW AdcUdt(@THIS)
235  Gpio = NEW GpioUdt(@THIS)
236 
237  VAR offs = ParOffs
238  ParOffs += 1 : DRam[ParOffs] = &h44E10800 ' pinmux registers
239 
240  PwmSS = NEW PwmssUdt(@THIS)
241  '& AdcUdt::AdcUdt(); GpioUdt::GpioUdt(); PwmssUdt::PwmssUdt();
242 
243  ASSERT(ParOffs < DRam[1] SHR 4)
244  prussdrv_pru_disable(PruNo) ' disable PRU (if running before)
245  VAR l = ArrayBytes(Pru_Init)
246  IF 0 >= prussdrv_pru_write_memory(PruIRam, 0, @Pru_Init(0), l) THEN _
247  Errr = @"failed loading Pru_Init instructions" : EXIT CONSTRUCTOR
248  prussdrv_pruintc_init(@IntcInit) ' get interrupt initialized
249  prussdrv_pru_enable(PruNo)
250 
251  Pwm = NEW PwmMod(@THIS)
252  Cap = NEW CapMod(@THIS)
253  'Qep = NEW QepMod(@THIS)
254  '& PwmMod::PwmMod(); CapMod::CapMod(); QepMod::QepMod();
255 
256  prussdrv_pru_wait_event(PRUIO_EVNT)
257  IF DRam[0] <> PRUIO_MSG_INIT_OK THEN _
258  Errr = @"failed executing Pru_Init instructions" : EXIT CONSTRUCTOR
259 
260  DSize = DRam[ParOffs] - DRam[1]
261  DInit = ALLOCATE(DSize * 2)
262  IF 0 = DInit THEN Errr = @"out of memory" : EXIT CONSTRUCTOR
263 
264  MOffs = DInit - DRam[1]
265  DConf = DInit + DSize
266  VAR p0 = CAST(ANY PTR, DRam) + DRam[1]
267  memcpy(DInit, p0, DSize)
268  memcpy(DConf, p0, DSize)
269 
270  Init = MOffs + DRam[offs]
271  Conf = CAST(ANY PTR, Init) + DSize
272  BallInit = CAST(ANY PTR, Init) + OFFSETOF(BallSet, Value(0))
273  BallConf = BallInit + DSize
274 
275  IF Adc->initialize(Av, OpD, SaD) THEN EXIT CONSTRUCTOR
276  IF Gpio->initialize() THEN EXIT CONSTRUCTOR
277  IF PwmSS->initialize() THEN EXIT CONSTRUCTOR
278  '& AdcUdt::initialize(); GpioUdt::initialize(); PwmssUdt::initialize();
279 END CONSTRUCTOR
280 
281 
282 /'* \brief Destructor to restore configurations and clear memory.
283 
284 The destructor copies the original configuration to DRam (if any),
285 loads new instructions to the PRU and start them. This PRU code
286 restores the subsystems GPIOs, Control Module and ADC to their original
287 configurations. Finaly the PRU gets powered off and the memory of the
288 PruIo instance get freed.
289 
290 The destructor cannot report error messages in member variable
291 PruIo::Errr. Messages (if any) get sent directly to the ERROUT pipe of
292 the operating system instead.
293 
294 '/
295 DESTRUCTOR PruIo()
296  VAR mux = ""
297  IF DRam THEN
298  IF DInit THEN
299  prussdrv_pru_disable(PruNo)
300 
301  IF LEN(MuxAcc) THEN ' reset pinmuxing
302  FOR i AS LONG = 0 TO PRUIO_AZ_BALL
303  IF BallInit[i] = BallConf[i] THEN CONTINUE FOR
304  IF setPin(i, BallInit[i]) THEN mux &= !"\n" & *Errr
305  NEXT
306  END IF
307 
308  DRam[1] = PRUIO_DAT_ALL ' reset subsystems configuration
309  memcpy(CAST(ANY PTR, DRam) + DRam[1], DInit, DSize)
310  DEALLOCATE(DInit)
311  DRam[2] = 0
312 
313  Errr = 0
314  VAR l = ArrayBytes(Pru_Run)
315  IF 0 >= prussdrv_pru_write_memory(PruIRam, 0, @Pru_Run(0), l) THEN
316  Errr = @"failed loading Pru_Exit instructions"
317  ELSE
318  prussdrv_pruintc_init(@IntcInit) ' get interrupt initialized
319  prussdrv_pru_enable(PruNo)
320  prussdrv_pru_wait_event(PRUIO_EVNT)
321  IF DRam[0] <> PRUIO_MSG_CONF_OK THEN _
322  Errr = @"failed executing Pru_Exit instructions"
323  END IF
324  ELSE
325  Errr = @"destructor warning: subsystems are NOT restored"
326  END IF
327  prussdrv_pru_disable(PruNo)
328  prussdrv_exit() ' power down PRU
329  ELSE
330  Errr = @"destructor warning: constructor failed"
331  END IF
332 
333  IF LEN(mux) THEN _
334  VAR fnr = FREEFILE : OPEN ERR AS fnr : PRINT #fnr, MID(mux, 2) : CLOSE #fnr
335  IF Errr THEN _
336  VAR fnr = FREEFILE : OPEN ERR AS fnr : PRINT #fnr, *Errr : CLOSE #fnr
337 END DESTRUCTOR
338 
339 
340 /'* \brief Load configuration from host (ARM) to driver (PRU).
341 \param Samp Number of samples to fetch (defaults to zero).
342 \param Mask Mask for active ADC steps (defaults to all 8 channels active in steps 1 to 8).
343 \param Tmr Timer value in [ns] to specify the sampling rate (defaults to zero, MM only).
344 \param Mds Modus for output (defaults to 4 = 16 bit).
345 \returns Zero on success (otherwise a string with an error message).
346 
347 This function is used to download the configuration from the host (ARM)
348 to the driver (PRU). The PRU gets stopped (if running) and the new
349 configurations get loaded. Also the Pru_Run instructions get
350 re-initialized.
351 
352 In case of an error the PRU will be disabled after this call. Otherwise
353 it's running and
354 
355 - waits for a call to PruIo::mm_start() or PruIo::rb_start() (in case of Samp > 1) or
356 - it starts sampling immediately and feads values to AdcUdt::Value otherwise.
357 
358 The *Samp* parameter specifies the number of samples to convert for
359 each channel. In single mode (Samp <= 1 = default) sampling starts
360 immediately and the index in the array PruIo::Value[] is equal to the
361 step number. Inactive steps return 0 (zero) in this case.
362 
363 | field | result of | defaults to |
364 | -------: | :---------: | :------------ |
365 | Value[0] | charge step | allways zero |
366 | Value[1] | step 1 | AIN-0 |
367 | Value[2] | step 2 | AIN-1 |
368 | ... | ... | ... |
369 
370 In MM (Samp > 1) the array PruIo::Value[] contains no zero values.
371 Instead only values from active steps get collected. The charge step
372 (step 0) returns no value. So when 3 steps are active in the Mask and
373 Samp is set to 5, a total of 3 times 5 = 15 values get available in the
374 array AdcUdt::Value[] (after the call to function PruIo::mm_start() ).
375 The array contains the active steps, so when ie. steps 3, 6 and 7 are
376 active in the Mask, the array contains:
377 
378 | field | Mask = &b110010000 |
379 | -------: | :----------------- |
380 | Value[0] | 1. sample AIN-3 |
381 | Value[1] | 1. sample AIN-6 |
382 | Value[2] | 1. sample AIN-7 |
383 | Value[3] | 2. sample AIN-3 |
384 | Value[4] | 2. sample AIN-6 |
385 | Value[5] | 2. sample AIN-7 |
386 | Value[6] | 3. sample AIN-3 |
387 | Value[7] | 3. sample AIN-6 |
388 | Value[8] | ... |
389 
390 Currently the number of samples is limited by the external memory
391 allocated by the kernel PRUSS driver. This is 256 kByte by default (=
392 128 kSamples). See ChaMemory for informations on how to extend
393 this memory block.
394 
395 | number of active Steps | max. Samples |
396 | ---------------------: | :----------- |
397 | 1 | 131072 |
398 | 2 | 65536 |
399 | 3 | 43690 |
400 | 4 | 32768 |
401 | 5 | 26214 |
402 | 6 | 21845 |
403 | 7 | 18724 |
404 | 8 | 16384 |
405 | ... | ... |
406 
407 The *Mask* parameter specifies the active steps. Setting a bit in the
408 Mask activates a step defined by the step configuration (by default
409 bits 1 = AIN-0, 2 = AIN-1, ... up to 8 = AIN-7 are set, use function
410 AdcUdt::setStep() to customize steps).
411 
412 \note Bit 0 controls the charge step (see \ArmRef{12}, ADC STEPENABLE
413 register).
414 
415 The highest bit 31 has a special meaning for customizing the idle step.
416 By default the idle configuration is set like the configuration of the
417 first active step, so that (in MM) the open delay can get
418 reduced to a minimum for that step (if there's enough time left before
419 restarting the ADC). By setting bit 31 the configuration from
420 AdcUdt::Conf->St_p`[0]` is used instead.
421 
422 The *Tmr* parameter specifies the sampling rate. It's the number of
423 nano seconds between the starts of the ADC sampling process. The IEP
424 timer gets used. It is configured to increase by steps of 5 (it counts
425 in GHz, but runs at 200 MHz), so values like 22676 or 22679 results to
426 the same frequency. Some examples
427 
428 | Tmr [ns] | Sampling rate [Hz] |
429 | -------: | :----------------- |
430 | 1e9 | 1 |
431 | 1e6 | 1000 |
432 | 22675 | ~44100 |
433 
434 \note This value has no effect in single mode (when Samp is less than 2).
435 
436 The *Mds* parameter specifies the bit encoding (range) of the samples.
437 By default (Mds = 4) the samples from the ADC (12 bit) get left shifted
438 by 4, so that they actually are 16 bit values and can get compared with
439 samples from other ADC devices (like 16 bit audio data). Examples
440 
441 | Mds | samples |
442 | ----: | :------ |
443 | 0 | 12 bit |
444 | 1 | 13 bit |
445 | 2 | 14 bit |
446 | 3 | 15 bit |
447 | >= 4 | 16 bit |
448 
449 '/
450 FUNCTION PruIo.config CDECL( _
451  BYVAL Samp AS UInt32 = PRUIO_DEF_SAMPLS _
452  , BYVAL Mask AS UInt32 = PRUIO_DEF_STPMSK _
453  , BYVAL Tmr AS UInt32 = PRUIO_DEF_TIMERV _
454  , BYVAL Mds AS UInt16 = PRUIO_DEF_LSLMOD) AS ZSTRING PTR
455 
456  prussdrv_pru_disable(PruNo) ' disable PRU
457  IF Adc->configure(Samp, Mask, Tmr, Mds) THEN RETURN Errr
458 
459  DRam[1] = PRUIO_DAT_ALL
460  memcpy(CAST(ANY PTR, DRam) + DRam[1], DConf, DSize)
461 
462  VAR l = ArrayBytes(Pru_Run)
463  IF 0 >= prussdrv_pru_write_memory(PruIRam, 0, @Pru_Run(0), l) THEN _
464  Errr = @"failed loading Pru_Run instructions" : RETURN Errr
465  prussdrv_pruintc_init(@IntcInit) ' get interrupt initialized
466  prussdrv_pru_enable(PruNo)
467  prussdrv_pru_wait_event(PRUIO_EVNT)
468  SELECT CASE AS CONST Samp
469  CASE 0 : l = DRam[0] <> PRUIO_MSG_CONF_OK
470  CASE 1 : l = DRam[0] <> PRUIO_MSG_IO_OK
471  CASE ELSE : l = DRam[0] <> PRUIO_MSG_MM_WAIT
472  END SELECT
473  IF l THEN ?" MURX: " & DRam[0] : _
474  Errr = @"failed executing Pru_Run instructions" : RETURN Errr
475  IF Samp < 2 THEN RETURN 0
476 
477  prussdrv_pru_clear_event(PRUIO_EVNT, PRUIO_IRPT)
478  prussdrv_pru_send_event(ArmPruInt) ' prepare fast MM start
479  RETURN 0
480 END FUNCTION
481 
482 
483 /'* \brief Create a text description for a CPU ball configuration.
484 \param Ball The CPU ball number to describe.
485 \param Mo The configuration to read (0 = Init, else Conf).
486 \returns A human-readable text string (internal string, never free it).
487 
488 This function is used to create a text description for the current
489 state of a CPU ball (called a pin when it's connected to one of
490 the Beaglebone headers P8 or P9).
491 
492 The description contains the pin name and its mode. Header pin names
493 start with a capital 'P', CPU ball names start with a lower case 'b'.
494 The detailed pinmux setting is only described for pins in mode 7 (GPIO
495 mode). Otherwise only the mode number gets shown.
496 
497 \note The returned string pointer points to an internal string buffer.
498  Never free it. The string gets overwritten on further calls to
499  this function, so make local copies if you need several
500  descriptions at a time. The string may contain an error message
501  if the ball number is too big.
502 
503 '/
504 FUNCTION PruIo.Pin CDECL( _
505  BYVAL Ball AS UInt8, _
506  BYVAL Mo AS UInt32 = 0) AS ZSTRING PTR
507  STATIC AS STRING*50 t
508 
509  VAR x = nameBall(Ball)
510  IF x THEN
511  t = *x
512  ELSE
513  IF Ball > PRUIO_AZ_BALL THEN _
514  Errr = @"unknown pin number" : RETURN Errr
515  t = "b " & RIGHT("00" & Ball, 3)
516  END IF
517 
518  VAR r = IIF(Mo, BallInit[Ball], BallConf[Ball]) _
519  , m = r AND &b111
520  IF m = 7 THEN
521  VAR i = BallGpio(Ball) SHR 5 _
522  , n = BallGpio(Ball) AND 31 _
523  , m = 1 SHL n
524  t &= ", GPIO " & i & "/" & RIGHT("0" & n, 2)
525  IF BIT(r, 5) THEN
526  t &= ": input"
527  ELSE
528  WITH *IIF(Mo, Gpio->Init(i), Gpio->Conf(i))
529  t &= ": output-" & *IIF((.DATAOUT OR .SETDATAOUT) AND m, @"1", @"0")
530  END WITH
531  END IF
532  ELSE
533  t &= ", mode " & m _
534  & ": input " & *IIF(BIT(r, 5), @"enabled", @"disabled")
535  END IF
536 
537  IF BIT(r, 3) THEN
538  t &= ", nopull"
539  ELSE
540  IF BIT(r, 4) THEN t &= ", pullup" ELSE t &= ", pulldown"
541  END IF
542 
543  RETURN SADD(t)
544 END FUNCTION
545 
546 
547 /'* \brief Set a new pin configuration.
548 \param Ball The CPU ball number (use macros from pruio_pins.bi).
549 \param Mo The new modus to set.
550 \returns Zero on success (otherwise a string with an error message).
551 
552 This function tries to set a new header pin configuration. Each digital
553 header pin is connected to a CPU ball. The CPU ball can get muxxed to
554 
555 - several internal targets (like GPIO, CAP, PWM, ...),
556 - internal pullup or pulldown resistors, as well as
557 - an internal receiver module for input pins.
558 
559 The function will fail if
560 
561 - the libpruio device tree overlays isn't loaded, or
562 - the required pin isn't defined in that overlay (ie HDMI), or
563 - the user has no write access to the state configuration files (see
564  section SecPinmux for details), or
565 - the required mode isn't available in the overlay.
566 
567 The function returns an error message in case of a failure.
568 
569 \since 0.2
570 '/
571 FUNCTION PruIo.setPin CDECL( _
572  BYVAL Ball AS UInt8 _
573  , BYVAL Mo AS UInt8) AS ZSTRING PTR
574 
575  IF Ball > PRUIO_AZ_BALL THEN _
576  Errr = @"unknown setPin ball number" : RETURN Errr
577 
578  VAR m = IIF(Mo = PRUIO_PIN_RESET, BallInit[Ball], Mo)
579  if BallConf[Ball] = m then RETURN 0 ' nothing to do
580 
581  IF 0 = LEN(MuxAcc) THEN Errr = @"no ocp.* access" : RETURN Errr
582 
583  VAR p = DIR(MuxAcc & "/" & PMUX_NAME & HEX(Ball, 2) & ".*", fbDirectory)
584  IF 0 = LEN(p) THEN Errr = @"no pin control" : RETURN Errr
585 
586  VAR h = HEX(m, 2) _
587  , r = SHELL("echo x" & h & " > " & MuxAcc & p & "/state")
588  IF 0 = r THEN BallConf[Ball] = m : RETURN 0
589 
590  STATIC AS STRING*30 e = "pinmux failed: P._.. -> x.."
591  VAR x = nameBall(Ball)
592  if x then MID(e, 16, 5) = *x else MID(e, 16, 5) = "bal" & HEX(Ball, 2)
593  MID(e, 26, 2) = h : Errr = SADD(e) : RETURN Errr
594 END FUNCTION
595 
596 
597 /'* \brief Get header pin connected to CPU ball.
598 \param Ball The CPU ball number.
599 \returns A string pointer (don't free it) on success (otherwise zero).
600 
601 This function creates a text description of the header pin connected to
602 a CPU ball. The returned string is owned by this function and must not
603 be freed.
604 
605 When the CPU ball is not connected to a header pin, this function
606 returns 0 (zero).
607 
608 \since 0.2
609 '/
610 FUNCTION PruIo.nameBall CDECL(BYVAL Ball AS UInt8) AS ZSTRING PTR
611  SELECT CASE AS CONST Ball ' find name
612  CASE 6 : RETURN @"P8_03"
613  CASE 7 : RETURN @"P8_04"
614  CASE 2 : RETURN @"P8_05"
615  CASE 3 : RETURN @"P8_06"
616  CASE 36 : RETURN @"P8_07"
617  CASE 37 : RETURN @"P8_08"
618  CASE 39 : RETURN @"P8_09"
619  CASE 38 : RETURN @"P8_10"
620  CASE 13 : RETURN @"P8_11"
621  CASE 12 : RETURN @"P8_12"
622  CASE 9 : RETURN @"P8_13"
623  CASE 10 : RETURN @"P8_14"
624  CASE 15 : RETURN @"P8_15"
625  CASE 14 : RETURN @"P8_16"
626  CASE 11 : RETURN @"P8_17"
627  CASE 35 : RETURN @"P8_18"
628  CASE 8 : RETURN @"P8_19"
629  CASE 33 : RETURN @"P8_20"
630  CASE 32 : RETURN @"P8_21"
631  CASE 5 : RETURN @"P8_22"
632  CASE 4 : RETURN @"P8_23"
633  CASE 1 : RETURN @"P8_24"
634  CASE 0 : RETURN @"P8_25"
635  CASE 31 : RETURN @"P8_26"
636  CASE 56 : RETURN @"P8_27"
637  CASE 58 : RETURN @"P8_28"
638  CASE 57 : RETURN @"P8_29"
639  CASE 59 : RETURN @"P8_30"
640  CASE 54 : RETURN @"P8_31"
641  CASE 55 : RETURN @"P8_32"
642  CASE 53 : RETURN @"P8_33"
643  CASE 51 : RETURN @"P8_34"
644  CASE 52 : RETURN @"P8_35"
645  CASE 50 : RETURN @"P8_36"
646  CASE 48 : RETURN @"P8_37"
647  CASE 49 : RETURN @"P8_38"
648  CASE 46 : RETURN @"P8_39"
649  CASE 47 : RETURN @"P8_40"
650  CASE 44 : RETURN @"P8_41"
651  CASE 45 : RETURN @"P8_42"
652  CASE 42 : RETURN @"P8_43"
653  CASE 43 : RETURN @"P8_44"
654  CASE 40 : RETURN @"P8_45"
655  CASE 41 : RETURN @"P8_46"
656  CASE 28 : RETURN @"P9_11"
657  CASE 30 : RETURN @"P9_12"
658  CASE 29 : RETURN @"P9_13"
659  CASE 18 : RETURN @"P9_14"
660  CASE 16 : RETURN @"P9_15"
661  CASE 19 : RETURN @"P9_16"
662  CASE 87 : RETURN @"P9_17"
663  CASE 86 : RETURN @"P9_18"
664  CASE 95 : RETURN @"P9_19"
665  CASE 94 : RETURN @"P9_20"
666  CASE 85 : RETURN @"P9_21"
667  CASE 84 : RETURN @"P9_22"
668  CASE 17 : RETURN @"P9_23"
669  CASE 97 : RETURN @"P9_24"
670  CASE 107 : RETURN @"P9_25"
671  CASE 96 : RETURN @"P9_26"
672  CASE 105 : RETURN @"P9_27"
673  CASE 103 : RETURN @"P9_28"
674  CASE 101 : RETURN @"P9_29"
675  CASE 102 : RETURN @"P9_30"
676  CASE 100 : RETURN @"P9_31"
677  CASE 109 : RETURN @"P9_41"
678  CASE 89 : RETURN @"P9_42"
679  END SELECT : RETURN 0
680 END FUNCTION
681 
682 
683 /'* \brief Start ring buffer mode.
684 \returns Zero on success (otherwise a string with an error message).
685 
686 Start endless measuremnt in ring buffer mode. The active steps defined
687 in the last call to function PruIo::config() get sampled at the
688 specified sampling rate. The fetched values are stored in a ring buffer
689 and the index of the currently stored value gets reported in DRam[0].
690 
691 Inactive steps get no entry in the ring buffer, it only contains values
692 from the active steps (as in MM mode). Use AdcUdt::Value[index] to
693 read the samples.
694 
695 RB mode runs endless. Stop it by up-loading a new configuration (by
696 calling function PruIo::config() ).
697 
698 '/
699 FUNCTION PruIo.rb_start CDECL() AS ZSTRING PTR
700  IF DRam[0] <> PRUIO_MSG_MM_WAIT THEN _
701  Errr = @"ring buffer mode not ready" : RETURN Errr
702 
703  DRam[1] = Adc->Samples SHL 1 ' size of ring buffer
704  DRam[2] = EAddr
705  DRam[3] = 0
706  DRam[4] = 1 SHL 4
707 
708  prussdrv_pru_clear_event(PruEvtOut, ArmPruInt) ' off we go
709  RETURN 0
710 END FUNCTION
711 
712 
713 /'* \brief Start a measurement in MM.
714 \param Trg1 Specification for first trigger (default = no trigger).
715 \param Trg2 Specification for second trigger (default = no trigger).
716 \param Trg3 Specification for third trigger (default = no trigger).
717 \param Trg4 Specification for fourth trigger (default = no trigger).
718 \returns Zero on success (otherwise a string with an error message).
719 
720 This function starts a measurement in MM mode. The ADC configuration
721 from the previous call to function PruIo::config() are used. The
722 measurement either starts immediately or the start gets controlled by
723 one (or up to four) trigger event(s).
724 
725 Function are available to create trigger specifications:
726 
727 - AdcUdt::mm_trg_pin() for digital lines
728 - AdcUdt::mm_trg_ain() for analog lines
729 - AdcUdt::mm_trg_pre() for pre-triggers on analog lines
730 
731 \note The created analog trigger specifications may get invalid by
732  changing the ADC settings in a further call to function
733  PruIo::config() with different parameters (ie. when the trigger
734  step gets cleared). To be on the save side, re-create your
735  trigger specifications after each call to function
736  PruIo::config().
737 
738 MM mode runs endless. Stop it by up-loading a new configuration (by
739 calling function PruIo::config() ).
740 
741 '/
742 FUNCTION PruIo.mm_start CDECL( _
743  BYVAL Trg1 AS UInt32 = 0 _
744  , BYVAL Trg2 AS UInt32 = 0 _
745  , BYVAL Trg3 AS UInt32 = 0 _
746  , BYVAL Trg4 AS UInt32 = 0) AS ZSTRING PTR
747 
748  IF DRam[0] <> PRUIO_MSG_MM_WAIT THEN _
749  Errr = @"measurement mode not ready" : RETURN Errr
750 
751  STATIC AS UInt32 tmin = (1 SHL 22), t_pin
752  DRam[3] = 0
753 
754 #DEFINE PRUIO_PRE_TRIG(_T_) Trg##_T_ >= tmin ANDALSO (Trg##_T_ AND (1 SHL 4)) THEN : _
755  IF BIT(Trg##_T_, 5) ORELSE BIT(Adc->Conf->STEPENABLE, (Trg##_T_ AND &b1111) + 1) THEN : _
756  VAR n = (Trg##_T_ SHR 22) * Adc->ChAz : _
757  IF n < Adc->Samples THEN : DRam[3] = n SHL 1 : _
758  ELSE : Errr = @"Trg" #_T_ ": too much pre-trigger samples" : RETURN Errr : _
759  END IF : _
760  ELSE : Errr = @"Trg" #_T_ ": pre-trigger step must be active" : RETURN Errr : _
761  END IF
762 
763 #DEFINE PRUIO_GPIO_TRIG(_T_) BIT(Trg##_T_, 21) THEN : _
764  t_pin = (Trg##_T_ SHR 8) AND &b1111111 : _
765  IF t_pin > PRUIO_AZ_BALL THEN _
766  Errr = @"Trg" #_T_ ": unknown trigger pin number" : RETURN Errr : _
767  END IF : _
768  IF BallConf[t_pin] AND &b111 <> 7 THEN _
769  Errr = @"Trg" #_T_ ": trigger pin must be in mode 7 (GPIO)" : RETURN Errr : _
770  ELSE Trg##_T_ AND= &b11111111111100000000000011111111uL : _
771  Trg##_T_ OR= BallGpio(t_pin) SHL 8 : _
772  END IF : _
773  END IF
774 
775  IF Trg1 THEN
776  IF PRUIO_PRE_TRIG(1)
777  ELSE
778  IF PRUIO_GPIO_TRIG(1)
779  IF Trg2 THEN
780  IF PRUIO_PRE_TRIG(2)
781  ELSE
782  IF PRUIO_GPIO_TRIG(2)
783  IF Trg3 THEN
784  IF PRUIO_PRE_TRIG(3)
785  ELSE
786  IF PRUIO_GPIO_TRIG(3)
787  IF Trg4 THEN
788  IF PRUIO_PRE_TRIG(4)
789  ELSE
790  IF PRUIO_GPIO_TRIG(4)
791  END IF
792  END IF
793  END IF
794  END IF
795  END IF
796  END IF
797  END IF
798  END IF
799 
800  DRam[1] = ESize
801  DRam[2] = EAddr
802  DRam[4] = Trg1
803  DRam[5] = Trg2
804  DRam[6] = Trg3
805  DRam[7] = Trg4
806 
807  prussdrv_pru_clear_event(PruEvtOut, ArmPruInt) ' off we go
808 
809  prussdrv_pru_wait_event(PRUIO_EVNT) ' wait for end of measurement
810  prussdrv_pru_clear_event(PRUIO_EVNT, PRUIO_IRPT) ' clear interrupt
811  prussdrv_pru_send_event(ArmPruInt) ' prepare next start
812  RETURN 0
813 END FUNCTION
814