libpruio  0.6.8
Fast and easy Digital/Analog Input/Output for Beaglebones
pruio_pwmss.bas
Go to the documentation of this file.
1 
11 
12 
13 ' PruIo global declarations.
14 #INCLUDE ONCE "pruio_globals.bi"
15 ' Header for PWMSS part, containing modules QEP, CAP and PWM.
16 #INCLUDE ONCE "pruio_pwmss.bi"
17 ' driver header file
18 #INCLUDE ONCE "pruio.bi"
19 
20 
21 #DEFINE PWMSS_CLK 100e6
22 
23 #DEFINE PWMSS_CLK_2 50e6
24 
25 
26 
36 CONSTRUCTOR PwmssUdt(BYVAL T AS Pruio_ PTR)
37  Top = T
38  WITH *Top
39  VAR i = .ParOffs
40  InitParA = i
41  i += 1 : .DRam[i] = &h48300000uL
42  i += 1 : .DRam[i] = IIF(.DevAct AND PRUIO_ACT_PWM0, &h44E000D4uL, 0)
43 
44  i += 1 : .DRam[i] = &h48302000uL
45  i += 1 : .DRam[i] = IIF(.DevAct AND PRUIO_ACT_PWM1, &h44E000CCuL, 0)
46 
47  i += 1 : .DRam[i] = &h48304000uL
48  i += 1 : .DRam[i] = IIF(.DevAct AND PRUIO_ACT_PWM2, &h44E000D8uL, 0)
49 
50  .ParOffs = i
51  END WITH
52 END CONSTRUCTOR
53 
54 
55 
65 FUNCTION PwmssUdt.initialize CDECL() AS ZSTRING PTR
66  WITH *Top
67  VAR p_mem = .MOffs + .DRam[InitParA] _
68  , p_raw = CAST(ANY PTR, .DRam) + PRUIO_DAT_PWM
69  FOR i AS LONG = 0 TO PRUIO_AZ_PWMSS
70  Raw(i) = p_raw
71  Raw(i)->CMax = 0
72  p_raw += SIZEOF(PwmssArr)
73 
74  Init(i) = p_mem
75  Conf(i) = p_mem + .DSize
76 
77  WITH *Conf(i)
78  IF .ClAd = 0 ORELSE _
79  .IDVER = 0 THEN _ ' subsystem disabled
80  .DeAd = 0 : .ClVa = &h30000 : p_mem += 16 : _
81  Init(i)->DeAd = 0 : Init(i)->ClAd = 0 : CONTINUE FOR
82  .ClVa = 2
83  .SYSCONFIG = 2 SHL 2
84  .CLKCONFIG = &b0100010001 ' enable all modules
85  ' ePWM registers
86  .TBPHS = 0
87  .TBSTS = &b110
88  .CMPCTL = 0
89  ' eCAP registers
90  .TSCTR = 0 ' reset counter
91  .CTRPHS = 0
92  .ECCTL1 = &b111001100
93  .ECEINT = 0 ' disable all interupts
94  .ECCLR = &b11111110 ' clear all interupt flags
95  END WITH
96  p_mem += SIZEOF(PwmssSet)
97  NEXT
98  END WITH : RETURN 0
99 END FUNCTION
100 
101 
102 
117 FUNCTION PwmssUdt.cap_pwm_get CDECL( _
118  BYVAL Nr AS UInt8 _
119  , BYVAL Freq AS Float_t PTR = 0 _
120  , BYVAL Duty AS Float_t PTR = 0) AS ZSTRING PTR
121 
122  WITH *Conf(Nr)
123  IF 2 <> .ClVa THEN Top->Errr = E0 : RETURN E0 ' PWM not enabled
124  IF 0 = BIT(.ECCTL2, 9) THEN Top->Errr = E9 : RETURN E9 ' eCAP module not in output mode
125  IF Freq THEN *Freq = PWMSS_CLK / .CAP1
126  IF Duty THEN *Duty = .CAP2 / .CAP1
127  END WITH : RETURN 0
128 END FUNCTION
129 
130 
131 
148 FUNCTION PwmssUdt.cap_pwm_set CDECL( _
149  BYVAL Nr AS UInt8 _
150  , BYVAL F AS Float_t _
151  , BYVAL D AS Float_t = 0.) AS ZSTRING PTR
152 
153  STATIC AS CONST Float_t _
154  f_min = PWMSS_CLK / &hFFFFFFFFuL '' minimal frequency
155  STATIC AS UInt32 _
156  cnt(...) = {0, 0, 0} _ '' initial module periods
157  , cmp(...) = {0, 0, 0} '' initial module compares
158 
159  WITH *Top
160  VAR r = 0
161  IF 2 <> Conf(Nr)->ClVa THEN .Errr = E0 : RETURN E0 ' PWMSS not enabled
162  IF 0 = cnt(Nr) ANDALSO _
163  0 >= F THEN .Errr = E1 : RETURN E1 ' set frequency first
164  IF F > 0. THEN
165  IF F < f_min ORELSE _
166  F > PWMSS_CLK_2 THEN .Errr = E2 : RETURN E2 ' frequency not supported
167  cnt(Nr) = CUINT(PWMSS_CLK / F)
168  END IF
169  IF D >= 0 THEN cmp(Nr) = IIF(D > 1., cnt(Nr), CUINT(cnt(Nr) * D))
170 
171  Conf(Nr)->CAP1 = cnt(Nr)
172  Conf(Nr)->CAP2 = cmp(Nr)
173  IF Conf(Nr)->ECCTL2 <> PwmMode THEN
174  Conf(Nr)->ECCTL2 = PwmMode
175  Raw(Nr)->CMax = 0
176  r = PwmMode
177  END IF
178 
179  IF .DRam[0] > PRUIO_MSG_IO_OK THEN RETURN 0
180 
181  PruReady(1) ' wait, if PRU is busy (should never happen)
182  .DRam[5] = 0 ' counter start value
183  .DRam[4] = cmp(Nr)
184  .DRam[3] = cnt(Nr)
185  .DRam[2] = Conf(Nr)->DeAd + &h100
186  .DRam[1] = r OR (PRUIO_COM_CAP_PWM SHL 24)
187  END WITH : RETURN 0
188 END FUNCTION
189 
190 
191 
206 FUNCTION PwmssUdt.cap_tim_get CDECL( _
207  BYVAL Nr AS UInt8 _
208  , BYVAL Dur1 AS Float_t PTR _
209  , BYVAL Dur2 AS Float_t PTR) AS ZSTRING PTR
210 
211  IF Dur1 = 0 ORELSE Dur2 = 0 THEN Top->Errr = @"pass pointers" : RETURN Top->Errr
212  WITH *Conf(Nr)
213  VAR dur = *Dur1 + *Dur2 _ ' [mSec]
214  , dmx = 1000. * &hFFFFFFFF / PWMSS_CLK _
215  , dmn = 1000. * 2 / PWMSS_CLK
216  SELECT CASE dur
217  CASE IS <= 0. ' get current
218  IF 2 <> .ClVa THEN Top->Errr = E0 : RETURN E0 ' PWMSS not enabled
219  IF 0 = BIT(.ECCTL2, 9) THEN Top->Errr = E9 : RETURN E9 ' eCAP module not in output mode
220  IF BIT(.ECCTL2, 4) THEN ' running
221  *Dur2 = 1000. * .CAP2 / PWMSS_CLK
222  *Dur1 = 1000. * .CAP1 / PWMSS_CLK - *Dur2
223  ELSE ' stopped
224  *Dur2 = 0.
225  *Dur1 = 0.
226  END IF
227  CASE IS < dmn ' get minimal
228  *Dur1 = dmn
229  *Dur2 = dmn / 2
230  CASE IS > dmx ' get maximal
231  *Dur1 = *Dur1 / dur * dmx
232  *Dur2 = *Dur2 / dur * dmx
233  CASE ELSE
234  *Dur1 = 1000. * CULNG(*Dur1 / dur * PWMSS_CLK)
235  *Dur2 = 1000. * CULNG(*Dur2 / dur * PWMSS_CLK)
236  END SELECT
237  END WITH : RETURN 0
238 END FUNCTION
239 
240 
241 
257 FUNCTION PwmssUdt.cap_tim_set CDECL( _
258  BYVAL Nr AS UInt8 _
259  , BYVAL Dur1 AS Float_t _
260  , BYVAL Dur2 AS Float_t _
261  , BYVAL Mode AS SHORT) AS ZSTRING PTR
262 
263  STATIC AS CONST Float_t _
264  d_min = 1000. * &h2 / PWMSS_CLK _ '' minimal durarion [mSec]
265  , d_max = 1000. * &hFFFFFFFFuLL / PWMSS_CLK '' maximal duration [mSec]
266 
267  VAR dur = Dur1 + Dur2 ' [msec]
268  WITH *Conf(Nr)
269  IF 2 <> .ClVa THEN Top->Errr = E0 : RETURN E0 ' PWMSS not enabled
270 
271  Raw(Nr)->CMax = 0
272  SELECT CASE dur
273  CASE IS <= 0. ' -> switch off
274  .CAP1 = &hFFFFFFFFuL
275  .CAP2 = &h0
276  .ECCTL2 = IIF(Mode AND &b01, PwmMode OR &b10000000000, PwmMode) ' default/invers
277  CASE IS < d_min : Top->Errr = Top->TimSS->E3 : RETURN Top->Errr ' duration too short
278  CASE IS > d_max : Top->Errr = Top->TimSS->E4 : RETURN Top->Errr ' duration too long
279  CASE ELSE
280  IF Mode >= &b10 THEN ' one-shot
281  IF 0.01 >= Dur1 THEN Top->Errr = Top->TimSS->E3 : RETURN Top->Errr ' one-shot duration too short
282  Raw(Nr)->CMax = (Mode AND &b111111110) SHR 1
283  .ECCTL2 = PwmMode OR IIF(Mode AND &b01, &b10010000000, &b00010000000) ' default/invers
284  ELSE
285  .ECCTL2 = IIF(Mode AND &b01, PwmMode OR &b10000000000, PwmMode) ' default/invers
286  END IF
287  .CAP1 = CULNG(.001 * dur * PWMSS_CLK) ' period
288  VAR x = CULNG(Dur2 / dur * .CAP1) ' match
289  .CAP2 = IIF(x > 0, x, 1)
290  END SELECT
291  .TSCTR = .CAP2
292  END WITH
293 
294  WITH *Top
295  IF .DRam[0] > PRUIO_MSG_IO_OK THEN RETURN 0
296 
297  PruReady(1) ' wait, if PRU is busy (should never happen)
298  .DRam[5] = Conf(Nr)->TSCTR
299  .DRam[4] = Conf(Nr)->CAP2
300  .DRam[3] = Conf(Nr)->CAP1
301  .DRam[2] = Conf(Nr)->DeAd + &h100
302  .DRam[1] = Conf(Nr)->ECCTL2 OR (PRUIO_COM_CAP_TIM SHL 24)
303  END WITH : RETURN 0
304 END FUNCTION
305 
306 
307 
323 FUNCTION PwmssUdt.pwm_pwm_get CDECL( _
324  BYVAL Nr AS UInt8 _
325  , BYVAL F AS Float_t PTR = 0 _
326  , BYVAL Du AS Float_t PTR = 0 _
327  , BYVAL Mo AS UInt8) AS ZSTRING PTR
328 
329  WITH *Conf(Nr)
330  IF 2 <> .ClVa THEN Top->Errr = E0 : RETURN E0 ' PWMSS not enabled
331  VAR p = CAST(UInt32, .TBPRD)
332  IF F THEN
333  VAR d1 = (.TBCTL SHR 7) AND &b111, d2 = (.TBCTL SHR 10) AND &b111
334  VAR cg = p * IIF(d1, d1 SHL 1, 1) * (1 SHL d2)
335  *F = PWMSS_CLK / IIF(BIT(.TBCTL, 1), cg SHL 1, cg)
336  END IF
337  IF Du THEN
338  VAR c = CAST(UInt32, IIF(Mo, .CMPB, .CMPA))
339  IF BIT(.TBCTL, 1) THEN ' count up-down
340  p SHL= 1
341  IF IIF(Mo, .AQCTLB, .AQCTLA) AND &b010001000000 THEN c = p - c
342  END IF
343  *Du = c / p
344  END IF
345  END WITH : RETURN 0
346 END FUNCTION
347 
348 
349 
350 
369 FUNCTION PwmssUdt.pwm_pwm_set CDECL( _
370  BYVAL Nr AS UInt8 _
371  , BYVAL F AS Float_t _
372  , BYVAL Da AS Float_t = 0. _
373  , BYVAL Db AS Float_t = 0.) AS ZSTRING PTR
374 
375  STATIC AS CONST Float_t _
376  f_min = PWMSS_CLK_2 / &h6FFF900 '' minimal frequency (128 * 14 * 65535)
377  STATIC AS Float_t _
378  freq(...) = {0., 0., 0.} _ ' module frequencies
379  , d_a(...) = {0., 0., 0.} _ ' module duty A
380  , d_b(...) = {0., 0., 0.} ' module duty B
381  STATIC AS UInt16 _
382  cnt(...) = {0, 0, 0} _ ' module periods
383  , c_a(...) = {0, 0, 0} _ ' module counters A
384  , c_b(...) = {0, 0, 0} ' module counters B
385 
386  VAR ctl = 0
387  WITH *Conf(Nr)
388  IF 2 <> .ClVa THEN Top->Errr = E0 : RETURN E0 ' PWMSS not enabled
389  IF 0 = cnt(Nr) THEN
390  IF F <= 0. THEN Top->Errr = E1 : RETURN E1 ' set frequency first
391  ELSE
392  IF F > 0. ANDALSO freq(Nr) <> F THEN cnt(Nr) = 0
393  END IF
394 
395  IF 0 = cnt(Nr) THEN ' calc new period (frequency)
396  VAR cycle = IIF(F > f_min ANDALSO F <= PWMSS_CLK_2, CUINT(.5 + PWMSS_CLK / F), 0uL)
397  IF 2 > cycle THEN Top->Errr = E2 : RETURN E2 ' frequency not supported
398 
399  freq(Nr) = ABS(F)
400  IF cycle <= &h10000 ANDALSO 0 = BIT(Top->Pwm->ForceUpDown, Nr) THEN ' count up mode
401  cnt(Nr) = cycle
402  ELSEIF cycle < &h20000 THEN ' no divisor count up-down mode
403  cnt(Nr) = cycle SHR 1
404  ctl = 2
405  ELSE ' divisor count up-down mode
406  VAR fac = cycle SHR 17 _
407  , x1 = 1 + CINT(INT(LOG(fac / 14) / LOG2))
408  IF x1 < 0 THEN x1 = 0
409  VAR x2 = (fac SHR x1) \ 2 + 1
410  cnt(Nr) = CUINT(.5 + PWMSS_CLK_2 / F / (IIF(x2, x2 SHL 1, 1) SHL x1))
411  ctl = 2 + x2 SHL 7 + x1 SHL 10 ' clock divisor
412  END IF
413  ctl OR= (3 SHL 14) + (Top->Pwm->Cntrl(Nr) AND &b0010000001111100)
414  .TBCTL = ctl
415  .TBPRD = cnt(Nr)
416  .TBCNT = 0
417  c_a(Nr) = 0
418  c_b(Nr) = 0
419  END IF
420 
421  IF Da >= 0. THEN d_a(Nr) = IIF(Da > 1., 1., Da) : c_a(Nr) = 0
422  IF 0 = c_a(Nr) THEN ' calc new duty for A output
423  IF BIT(.TBCTL, 1) ORELSE BIT(Top->Pwm->ForceUpDown, Nr) THEN 'up-down mode
424  IF d_a(Nr) >= .5 _
425  THEN .AQCTLA = Top->Pwm->AqCtl(0, Nr, 2) : c_a(Nr) = CUINT((cnt(Nr) SHL 1) * (1 - d_a(Nr))) _
426  ELSE .AQCTLA = Top->Pwm->AqCtl(0, Nr, 1) : c_a(Nr) = CUINT((cnt(Nr) SHL 1) * d_a(Nr))
427  ELSE ' up mode
428  .AQCTLA = Top->Pwm->AqCtl(0, Nr, 0) : c_a(Nr) = CUINT(.5 + (cnt(Nr) + 1) * d_a(Nr))
429  END IF
430  .CMPA = c_a(Nr)
431  END IF
432 
433  IF Db >= 0. THEN d_b(Nr) = IIF(Db > 1., 1., Db) : c_b(Nr) = 0
434  IF 0 = c_b(Nr) THEN ' calc new duty for B output
435  IF BIT(.TBCTL, 1) ORELSE BIT(Top->Pwm->ForceUpDown, Nr) THEN ' up-down mode
436  IF d_b(Nr) >= .5 _
437  THEN .AQCTLB = Top->Pwm->AqCtl(1, Nr, 2) : c_b(Nr) = CUINT((cnt(Nr) SHL 1) * (1 - d_b(Nr))) _
438  ELSE .AQCTLB = Top->Pwm->AqCtl(1, Nr, 1) : c_b(Nr) = CUINT((cnt(Nr) SHL 1) * d_b(Nr))
439  ELSE ' up mode
440  .AQCTLB = Top->Pwm->AqCtl(1, Nr, 0) : c_b(Nr) = CUINT(.5 + (cnt(Nr) + 1) * d_b(Nr))
441  END IF
442  .CMPB = c_b(Nr)
443  END IF
444 
445  IF Top->DRam[0] > PRUIO_MSG_IO_OK THEN RETURN 0
446 
447  WHILE Top->DRam[1] : WEND ' wait, if PRU is busy (should never happen)
448  Top->DRam[5] = .TBCNT + .TBPRD SHL 16
449  Top->DRam[4] = .AQCTLA + .AQCTLB SHL 16
450  Top->DRam[3] = .CMPA + .CMPB SHL 16
451  Top->DRam[2] = .DeAd + &h200
452  Top->DRam[1] = IIF(ctl, ctl, 0) + PRUIO_COM_PWM SHL 24
453  END WITH : RETURN 0
454 END FUNCTION
455 
456 
457 
470 CONSTRUCTOR PwmMod(BYVAL T AS Pruio_ PTR)
471  Top = T
472 END CONSTRUCTOR
473 
474 
475 
489 FUNCTION PwmMod.Value CDECL( _
490  BYVAL Ball AS UInt8 _
491  , BYVAL Hz AS Float_t PTR = 0 _
492  , BYVAL Du AS Float_t PTR = 0) AS ZSTRING PTR
493 
494  WITH *Top
495  DIM AS ZSTRING PTR e
496  SELECT CASE AS CONST Ball
497  CASE &h24 : e = IIF(ModeCheck(Ball,2), .PwmSS->E3, .TimSS->pwm_get(0, Hz, Du)) ' P8_07
498  CASE &h27 : e = IIF(ModeCheck(Ball,2), .PwmSS->E3, .TimSS->pwm_get(1, Hz, Du)) ' P8_09
499  CASE &h26 : e = IIF(ModeCheck(Ball,2), .PwmSS->E3, .TimSS->pwm_get(2, Hz, Du)) ' P8_10
500  CASE &h25 : e = IIF(ModeCheck(Ball,2), .PwmSS->E3, .TimSS->pwm_get(3, Hz, Du)) ' P8_08
501  CASE &h09 : e = IIF(ModeCheck(Ball,4), .PwmSS->E3, .PwmSS->pwm_pwm_get(2, Hz, Du, 1)) ' P8_13
502  CASE &h08 : e = IIF(ModeCheck(Ball,4), .PwmSS->E3, .PwmSS->pwm_pwm_get(2, Hz, Du, 0)) ' P8_19
503  CASE &h33 : e = IIF(ModeCheck(Ball,2), .PwmSS->E3, .PwmSS->pwm_pwm_get(1, Hz, Du, 1)) ' P8_34
504  CASE &h32 : e = IIF(ModeCheck(Ball,2), .PwmSS->E3, .PwmSS->pwm_pwm_get(1, Hz, Du, 0)) ' P8_36
505  CASE &h28 : e = IIF(ModeCheck(Ball,3), .PwmSS->E3, .PwmSS->pwm_pwm_get(2, Hz, Du, 1)) ' P8_45
506  CASE &h29 : e = IIF(ModeCheck(Ball,3), .PwmSS->E3, .PwmSS->pwm_pwm_get(2, Hz, Du, 0)) ' P8_46
507  CASE &h12 : e = IIF(ModeCheck(Ball,6), .PwmSS->E3, .PwmSS->pwm_pwm_get(1, Hz, Du, 0)) ' P9_14
508  CASE &h13 : e = IIF(ModeCheck(Ball,6), .PwmSS->E3, .PwmSS->pwm_pwm_get(1, Hz, Du, 1)) ' P9_16
509  CASE &h55 : e = IIF(ModeCheck(Ball,3), .PwmSS->E3, .PwmSS->pwm_pwm_get(0, Hz, Du, 1)) ' P9_21
510  CASE &h54 : e = IIF(ModeCheck(Ball,3), .PwmSS->E3, .PwmSS->pwm_pwm_get(0, Hz, Du, 0)) ' P9_22
511  CASE &h65 : e = IIF(ModeCheck(Ball,1), .PwmSS->E3, .PwmSS->pwm_pwm_get(0, Hz, Du, 1)) ' P9_29
512  CASE &h64 : e = IIF(ModeCheck(Ball,1), .PwmSS->E3, .PwmSS->pwm_pwm_get(0, Hz, Du, 0)) ' P9_31
513  CASE &h67 : e = IIF(ModeCheck(Ball,4), .PwmSS->E3, .PwmSS->cap_pwm_get(2, Hz, Du)) ' P9_28
514  CASE &h5D : e = IIF(ModeCheck(Ball,4), .PwmSS->E3, .PwmSS->cap_pwm_get(1, Hz, Du)) ' JT_05
515  CASE &h59 : e = IIF(ModeCheck(Ball,0), .PwmSS->E3, .PwmSS->cap_pwm_get(0, Hz, Du)) ' P9_42
516  'CASE P8_15 : e = IIF(ModeCheck(Ball,5), .PwmSS->E3, pru_cap_get(Hz, Du))
517  CASE ELSE : e = .PwmSS->E4
518  END SELECT : IF e THEN .Errr = e : RETURN .Errr
519  END WITH : RETURN 0
520 END FUNCTION
521 
522 
523 
564 FUNCTION PwmMod.setValue CDECL( _
565  BYVAL Ball AS UInt8, _
566  BYVAL Hz AS Float_t, _
567  BYVAL Du AS Float_t) AS ZSTRING PTR
568 
569  WITH *Top
570  SELECT CASE AS CONST Ball
571  CASE &h24 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_07
572  RETURN .TimSS->pwm_set(0, Hz, Du)
573  CASE &h27 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_09
574  RETURN .TimSS->pwm_set(1, Hz, Du)
575  CASE &h26 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_10
576  RETURN .TimSS->pwm_set(2, Hz, Du)
577  CASE &h25 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_08
578  RETURN .TimSS->pwm_set(3, Hz, Du)
579  CASE &h09 : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h0C) ' P8_13
580  RETURN .PwmSS->pwm_pwm_set(2, Hz, -1., Du)
581  CASE &h08 : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h0C) ' P8_19
582  RETURN .PwmSS->pwm_pwm_set(2, Hz, Du, -1.)
583  CASE &h33 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_34
584  RETURN .PwmSS->pwm_pwm_set(1, Hz, -1., Du)
585  CASE &h32 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_36
586  RETURN .PwmSS->pwm_pwm_set(1, Hz, Du, -1.)
587  CASE &h28 : IF ModeCheck(Ball,3) THEN ModeSet(Ball, &h0B) ' P8_45
588  RETURN .PwmSS->pwm_pwm_set(2, Hz, -1., Du)
589  CASE &h29 : IF ModeCheck(Ball,3) THEN ModeSet(Ball, &h0B) ' P8_46
590  RETURN .PwmSS->pwm_pwm_set(2, Hz, Du, -1.)
591  CASE &h12 : IF ModeCheck(Ball,6) THEN ModeSet(Ball, &h0E) ' P9_14
592  RETURN .PwmSS->pwm_pwm_set(1, Hz, Du, -1.)
593  CASE &h13 : IF ModeCheck(Ball,6) THEN ModeSet(Ball, &h0E) ' P9_16
594  RETURN .PwmSS->pwm_pwm_set(1, Hz, -1., Du)
595  CASE &h55 : IF ModeCheck(Ball,3) THEN ModeSet(Ball, &h0B) ' P9_21
596  RETURN .PwmSS->pwm_pwm_set(0, Hz, -1., Du)
597  CASE &h54 : IF ModeCheck(Ball,3) THEN ModeSet(Ball, &h0B) ' P9_22
598  RETURN .PwmSS->pwm_pwm_set(0, Hz, Du, -1.)
599  CASE &h65 : IF ModeCheck(Ball,1) THEN ModeSet(Ball, &h09) ' P9_29
600  RETURN .PwmSS->pwm_pwm_set(0, Hz, -1., Du)
601  CASE &h64 : IF ModeCheck(Ball,1) THEN ModeSet(Ball, &h09) ' P9_31
602  RETURN .PwmSS->pwm_pwm_set(0, Hz, Du, -1.)
603  CASE &h67 : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h0C) ' P9_28
604  RETURN .PwmSS->cap_pwm_set(2, Hz, Du)
605  CASE &h59 : IF ModeCheck(Ball,0) THEN ModeSet(Ball, &h08) ' P9_42
606  RETURN .PwmSS->cap_pwm_set(0, Hz, Du)
607  CASE &h5D : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h0C) ' JT_05
608  RETURN .PwmSS->cap_pwm_set(1, Hz, Du)
609  CASE &h58 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' SD_10
610  RETURN .PwmSS->cap_pwm_set(1, Hz, Du)
611  'CASE P8_15 : IF ModeCheck(Ball,5) THEN ModeSet(Ball, &h0D)
612  'RETURN pru_cap_set(Hz, Du)
613  END SELECT : .Errr = .PwmSS->E4 : RETURN .Errr ' pin has no PWM capability
614  END WITH
615 END FUNCTION
616 
617 
618 
619 
648 FUNCTION PwmMod.Sync CDECL( _
649  BYVAL Mask AS UInt8) AS ZSTRING PTR
650  WITH *Top
651  IF .MuxFnr < 1 ORELSE .MuxFnr > 255 THEN RETURN @"libpruio LKM missing"
652  PRINT #.MuxFnr, "FF" & HEX(Mask, 2) : SEEK #.MuxFnr, 1 : RETURN 0
653  END WITH
654 END FUNCTION
655 
656 'FUNCTION PwmMod.SyncToggle CDECL( _
657  'BYVAL Mask AS UInt8 = 0,
658  'BYVAL Curr AS UInt8 PTR = 0) AS ZSTRING PTR
659  'WITH *Top
660  'if Curr then
661  'PruReady(1) ' wait if PRU busy
662  '.DRam[2] = &h44E10664uL
663  '.DRam[1] = 4 OR PRUIO_COM_PEEK
664  'PruReady(1) ' wait if PRU busy
665 
666  'end if
667  'if Mask then
668  'IF .MuxFnr < 1 ORELSE .MuxFnr > 255 THEN RETURN @"libpruio LKM missing"
669 
670  'PRINT #.MuxFnr, "FF" & HEX(Mask, 2) : SEEK #.MuxFnr, 1 : RETURN 0
671  'END if
672  'END WITH
673 'END FUNCTION
674 
675 
676 
690 CONSTRUCTOR CapMod(BYVAL T AS Pruio_ PTR)
691  Top = T
692 END CONSTRUCTOR
693 
694 
695 
720 FUNCTION CapMod.config CDECL( _
721  BYVAL Ball AS UInt8 _
722  , BYVAL FLow AS Float_t = 0.) AS ZSTRING PTR
723 
724  VAR m = 0
725  WITH *Top
726  SELECT CASE AS CONST Ball
727  CASE &h67 : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h24) ' P9_28, P2_30, GP0_6
728  m = 2
729  CASE &h5C : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h24) ' JT_04, P1_32, UT0_3
730  m = 2
731  CASE &h59 : IF ModeCheck(Ball,0) THEN ModeSet(Ball, &h20) ' P9_42, P2_29, SPI2_6
732  CASE &h58 : IF ModeCheck(Ball,1) THEN ModeSet(Ball, &h22) ' SD_10
733  m = 1
734  CASE &h5D : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h24) ' JT_05, P1_30, UT0_4
735  m = 1
736  'CASE P8_15 : IF ModeCheck(Ball,5) THEN ModeSet(Ball, &h25) ' pr1_ecap0_ecap_capin_apwm_o (also on P9_42)
737  'CASE 98 : IF ModeCheck(Ball,3) THEN ModeSet(Ball, &h23)
738  'm = 2
739  'CASE 99 : IF ModeCheck(Ball,3) THEN ModeSet(Ball, &h23)
740  'm = 1
741  CASE ELSE : .Errr = .PwmSS->E6 : RETURN .Errr ' pin has no CAP capability
742  END SELECT
743  IF 2 <> .PwmSS->Conf(m)->ClVa THEN .Errr = .PwmSS->E0 : RETURN .Errr ' PWMSS not enabled
744  WITH *.PwmSS
745  VAR cnt = &hFFFFFFFFul
746  IF FLow > PWMSS_CLK/ &hFFFFFFFFul THEN
747  cnt = CUINT(PWMSS_CLK / FLow)
748  IF cnt < 256 THEN cnt = 256
749  END IF
750  .Raw(m)->CMax = cnt
751  .Conf(m)->ECCTL2 = .CapMode
752  END WITH
753 
754  IF .DRam[0] > PRUIO_MSG_IO_OK THEN RETURN 0
755 
756  PruReady(1) ' wait, if PRU is busy
757  .DRam[2] = .PwmSS->Conf(m)->DeAd + &h100
758  .DRam[1] = .PwmSS->CapMode + (PRUIO_COM_CAP SHL 24)
759  END WITH : RETURN 0
760 END FUNCTION
761 
762 
763 
788 FUNCTION CapMod.Value CDECL( _
789  BYVAL Ball AS UInt8 _
790  , BYVAL Hz AS Float_t PTR = 0 _
791  , BYVAL Du AS Float_t PTR = 0) AS ZSTRING PTR
792 
793  VAR m = 0
794  WITH *Top
795  DIM AS ZSTRING PTR e
796  IF 2 <> .PwmSS->Conf(m)->ClVa THEN
797  e = .PwmSS->E0 ' PWMSS not enabled
798  ELSE
799  SELECT CASE AS CONST Ball
800  CASE &h67 : IF ModeCheck(Ball,4) THEN e = .PwmSS->E5 ELSE m = 2 ' P9_28, P2_30, GP0_6
801  CASE &h59 : IF ModeCheck(Ball,0) THEN e = .PwmSS->E5 ' P9_42, P2_29, SPI2_6
802  CASE &h5C : IF ModeCheck(Ball,4) THEN e = .PwmSS->E5 ELSE m = 2 ' JT_04, P1_32, UT0_3
803  CASE &h58 : IF ModeCheck(Ball,1) THEN e = .PwmSS->E5 ELSE m = 1 ' SD_10
804  CASE &h5D : IF ModeCheck(Ball,4) THEN e = .PwmSS->E5 ELSE m = 1 ' JT_04, P1_32, UT0_3
805  'CASE P8_15 : IF ModeCheck(Ball,5) THEN e = .PwmSS->E5 ELSE m = -1 ' pr1_ecap0_ecap_capin_apwm_o (also on P9_42)
806  'CASE 98 : IF ModeCheck(Ball,3) THEN e = .PwmSS->E5 ELSE m = 2
807  'CASE 99 : IF ModeCheck(Ball,3) THEN e = .PwmSS->E5 ELSE m = 1
808  CASE ELSE : e = .PwmSS->E6 ' pin has no CAP capability
809  END SELECT
810  END IF : IF e THEN .Errr = e : RETURN .Errr
811 
812  IF .DRam[0] > PRUIO_MSG_IO_OK THEN
813  IF Hz THEN *Hz = 0
814  IF Du THEN *Du = 0
815  .Errr = @"IO/RB mode not running" : RETURN .Errr
816  END IF
817  END WITH
818  WITH *Top->PwmSS->Raw(m)
819  IF .CMax THEN
820  IF Hz THEN *Hz = IIF(.C2, PWMSS_CLK / .C2, 0.)
821  IF Du THEN *Du = IIF(.C2, (.C2 - .C1) / .C2, 0.)
822  RETURN 0
823  END IF
824  IF Hz THEN *Hz = 0
825  IF Du THEN *Du = 0
826  Top->Errr = Top->PwmSS->E5 : RETURN Top->Errr ' pin not in CAP mode
827  END WITH
828 END FUNCTION
829 
830 
831 
832 
846 CONSTRUCTOR QepMod(BYVAL T AS Pruio_ PTR)
847  Top = T
848 END CONSTRUCTOR
849 
850 
851 
915 FUNCTION QepMod.config CDECL( _
916  BYVAL Ball AS UInt8 _
917  , BYVAL PMax AS UInt32 = &h7FFFFFFFul _
918  , BYVAL VHz AS Float_t = 25. _
919  , BYVAL Scale AS Float_t = 1. _
920  , BYVAL Mo AS UInt8 = 0) AS ZSTRING PTR
921 
922  VAR m = 0, x = 0
923  STATIC AS Float_t fmin = PWMSS_CLK / (&hFFFF SHL 7) ' minimal frequency
924  WITH *Top
925  IF VHz < fmin ORELSE VHz > PWMSS_CLK_2 THEN _
926  .Errr = .PwmSS->E2 : RETURN .Errr ' frequency not supported
927  SELECT CASE AS CONST Ball
928  CASE &h0D, &h0C, &h0E : m = 2 ' P8_11, P8_12, P8_16
929  VAR v = IIF(Mo = PRUIO_PIN_RESET, PRUIO_PIN_RESET, &h2C)
930  IF ModeCheck(&h0C,4) THEN ModeSet(&h0C,v)
931  IF Ball = &h0C THEN x = 2 : EXIT SELECT ' P8_12
932  IF ModeCheck(&h0D,4) THEN ModeSet(&h0D,v)
933  IF Ball = &h0D THEN x = 1 : EXIT SELECT ' P8_11
934  IF ModeCheck(&h0E,4) THEN ModeSet(&h0E,v)
935  CASE &h14 : m = 1 ' P2_10
936  VAR v = IIF(Mo = PRUIO_PIN_RESET, PRUIO_PIN_RESET, &h2E)
937  IF ModeCheck(&h14,6) THEN ModeSet(&h14,v)
938  x = 2
939  CASE &h35, &h34, &h36 : m = 1 ' P8_33, P8_35, P8_31
940  VAR v = IIF(Mo = PRUIO_PIN_RESET, PRUIO_PIN_RESET, &h2A)
941  IF ModeCheck(&h34,2) THEN ModeSet(&h34,v)
942  IF Ball = &h34 THEN x = 2 : EXIT SELECT ' P8_35
943  IF ModeCheck(&h35,2) THEN ModeSet(&h35,v)
944  IF Ball = &h35 THEN x = 1 : EXIT SELECT ' P8_33
945  IF ModeCheck(&h36,2) THEN ModeSet(&h36,v)
946  CASE &h2C, &h2D, &h2E : m = 2 ' P8_41, P8_42, P8_39
947  VAR v = IIF(Mo = PRUIO_PIN_RESET, PRUIO_PIN_RESET, &h2B)
948  IF ModeCheck(&h2C,3) THEN ModeSet(&h2C,v)
949  IF Ball = &h2C THEN x = 2 : EXIT SELECT ' P8_41
950  IF ModeCheck(&h2E,3) THEN ModeSet(&h2E,v)
951  IF Ball = &h2D THEN x = 1 : EXIT SELECT ' P8_42
952  IF ModeCheck(&h2E,3) THEN ModeSet(&h2E,v)
953  CASE &h69, &h59, &h68, &h6D, &h6A : m = 0 ' P9_27, P9_42, 104, P9_41, 106
954  VAR v = IIF(Mo = PRUIO_PIN_RESET, PRUIO_PIN_RESET, &h29)
955  IF ModeCheck(&h68 ,1) THEN ModeSet(&h68 ,v)
956  IF Ball = &h59 ORELSE Ball = &h68 THEN x = 2 : EXIT SELECT
957  IF ModeCheck(&h69,1) THEN ModeSet(&h69,v)
958  IF Ball = &h69 THEN x = 1 : EXIT SELECT
959  IF ModeCheck(&h6A ,1) THEN ModeSet(&h6A ,v)
960  CASE ELSE : .Errr = .PwmSS->E8 : RETURN .Errr' pin has no QEP capability
961  END SELECT
962  IF 2 <> .PwmSS->Conf(m)->ClVa THEN .Errr = .PwmSS->E0 : RETURN .Errr' PWMSS not enabled
963  END WITH
964  WITH *Top->PwmSS->Conf(m)
965  .QPOSCNT = 0
966  .QPOSINIT = 0
967  .QPOSMAX = PMax
968  .QPOSLAT = 0
969  .QUTMR = 0
970  .QUPRD = cuint(PWMSS_CLK / VHz)
971 
972  VAR ccps = .QUPRD \ &h10000
973  IF ccps > 1 THEN ccps = 1 + INT(LOG(ccps) / LOG2)
974  SELECT CASE AS CONST x
975  CASE 2 ' up count mode
976  .QDECCTL = &b1000000000000000
977  .QEPCTL = &b0001000010001110
978  .QCAPCTL = &b1000000000000000 or (ccps shl 4)
979  CASE 1 ' direction count mode
980  .QDECCTL = &b0000000000000000
981  .QEPCTL = &b0001000010001110
982  .QCAPCTL = &b1000000000000010 or (ccps shl 4)
983  CASE ELSE ' direction count mode with index
984  .QDECCTL = &b0000000000000000
985  .QEPCTL = &b0000001010001110
986  .QCAPCTL = &b1000000000000010 or (ccps shl 4)
987  END SELECT
988  .QPOSCTL = &b0000000000000000
989  .QCTMR = 0
990  .QCPRD = 0
991 
992  VAR fx = 1 SHL ((.QCAPCTL SHR 4) AND &b111) _
993  , fp = 1 SHL (.QCAPCTL AND &b1111) _
994  , t = .QUPRD \ fx _
995  , p2 = fp / 2
996  FVh(m) = Scale * PWMSS_CLK / .QUPRD
997  FVl(m) = Scale * PWMSS_CLK / fx * fp
998  Prd(m) = CUINT(fp * t / (-p2 + SQR(p2 * p2 + t / fp))) SHL 16
999  IF Top->DRam[0] > PRUIO_MSG_IO_OK THEN RETURN 0
1000 
1001  WHILE Top->DRam[1] : WEND ' wait, if PRU is busy
1002  Top->DRam[6] = .QCAPCTL
1003  Top->DRam[5] = .QDECCTL OR .QEPCTL SHL 16
1004  Top->DRam[4] = .QUPRD
1005  Top->DRam[3] = .QPOSMAX
1006  Top->DRam[2] = .DeAd + &h180
1007  Top->DRam[1] = PRUIO_COM_QEP SHL 24
1008  END WITH : RETURN 0
1009 END FUNCTION
1010 
1011 
1012 
1041 FUNCTION QepMod.Value CDECL( _
1042  BYVAL Ball AS UInt8 _
1043  , BYVAL Posi AS UInt32 PTR = 0 _
1044  , BYVAL Velo AS Float_t PTR = 0) AS ZSTRING PTR
1045 
1046  VAR m = 0
1047  WITH *Top
1048  SELECT CASE AS CONST Ball
1049  CASE &h14 : Posi = 0 : m = 1 ' A: P2_10
1050  CASE &h0C : Posi = 0 : m = 2 ' A: P8_12
1051  CASE &h0D, &h0E : m = 2 ' B,I: P8_11, P8_16
1052  CASE &h34 : Posi = 0 : m = 1 ' A: P8_35
1053  CASE &h35, &h36 : m = 1 ' B,I: P8_33, P8_31
1054  CASE &h2C : Posi = 0 : m = 2 ' A: P8_41
1055  CASE &h2D, &h2E : m = 2 ' B,I: P8_42, P8_39
1056  CASE &h59, &h68 : Posi = 0 : m = 0 ' A: P9_42, 104
1057  CASE &h69, &h6D, &h6A : m = 0 ' B,I: P9_27, P9_41, 106
1058  CASE ELSE : .Errr = .PwmSS->E0 : RETURN .Errr 'PwmSS not enabled
1059  END SELECT
1060 
1061  IF .DRam[0] > PRUIO_MSG_IO_OK THEN
1062  IF Posi THEN *Posi = 0
1063  IF Velo THEN *Velo = 0.
1064  .Errr = @"IO/RB mode not running" : RETURN .Errr
1065  END IF
1066  END WITH
1067  WITH *Top->PwmSS->Raw(m)
1068  IF Velo THEN
1069  VAR dx = CINT(.NPos - .OPos)
1070  IF .PLat > Prd(m) THEN
1071  *Velo = dx * FVh(m)
1072  ELSE
1073  *Velo = IIF(HIWORD(.PLat), SGN(dx) * FVl(m) / HIWORD(.PLat), 0.)
1074  END IF
1075  END IF
1076  IF Posi THEN *Posi = .QPos
1077  END WITH : RETURN 0
1078 END FUNCTION
1079