libpruio  0.6.8
Fast and easy Digital/Analog Input/Output for Beaglebones
pruio_timer.bas
Go to the documentation of this file.
1 
9 
10 
11 ' PruIo global declarations.
12 #INCLUDE ONCE "pruio_globals.bi"
13 ' Header for PWMSS part, containing modules QEP, CAP and PWM.
14 #INCLUDE ONCE "pruio_pwmss.bi"
15 ' Header for TIMER part.
16 #INCLUDE ONCE "pruio_timer.bi"
17 ' driver header file
18 #INCLUDE ONCE "pruio.bi"
19 
20 
21 #DEFINE TMRSS_CLK 24e6
22 
23 
33 CONSTRUCTOR TimerUdt(BYVAL T AS Pruio_ PTR)
34  Top = T
35  WITH *Top
36  VAR i = .ParOffs
37  InitParA = i
38  i += 1 : .DRam[i] = &h48044000uL
39  i += 1 : .DRam[i] = IIF(.DevAct AND PRUIO_ACT_TIM4, &h44E00088uL, 0)
40 
41  i += 1 : .DRam[i] = &h48046000uL
42  i += 1 : .DRam[i] = IIF(.DevAct AND PRUIO_ACT_TIM5, &h44E000ECuL, 0)
43 
44  i += 1 : .DRam[i] = &h48048000uL
45  i += 1 : .DRam[i] = IIF(.DevAct AND PRUIO_ACT_TIM6, &h44E000F0uL, 0)
46 
47  i += 1 : .DRam[i] = &h4804A000uL
48  i += 1 : .DRam[i] = IIF(.DevAct AND PRUIO_ACT_TIM7, &h44E0007CuL, 0)
49  .ParOffs = i
50  END WITH
51 END CONSTRUCTOR
52 
53 
54 
64 FUNCTION TimerUdt.initialize CDECL() AS ZSTRING PTR
65  WITH *Top
66  VAR p_mem = .MOffs + .DRam[InitParA] _
67  , p_raw = CAST(ANY PTR, .DRam) + PRUIO_DAT_TIMER
68 
69  FOR i AS LONG = 0 TO PRUIO_AZ_TIMER
70  Raw(i) = p_raw
71  p_raw += SIZEOF(TimerArr)
72 
73  Init(i) = p_mem
74  Conf(i) = p_mem + .DSize
75 
76  WITH *Conf(i)
77  IF .ClAd = 0 ORELSE _
78  .TIDR = 0 THEN _ ' subsystem disabled
79  .DeAd = 0 : .ClVa = &h30000 : p_mem += 16 : _
80  Init(i)->DeAd = 0 : Init(i)->ClAd = 0 : CONTINUE FOR
81  .ClVa = 2
82  '.TCAR1 = 0
83  '.TCAR2 = 0
84  END WITH
85 
86  'WITH *Init(i)
87  '.TCAR1 = 0
88  '.TCAR2 = 0
89  'END WITH
90 
91  p_mem += SIZEOF(TimerSet)
92  NEXT
93  END WITH : RETURN 0
94 END FUNCTION
95 
96 
97 
157 FUNCTION TimerUdt.setValue CDECL( _
158  BYVAL Ball AS UInt8 _
159  , BYVAL Dur1 AS Float_t _
160  , BYVAL Dur2 AS Float_t = 0. _
161  , BYVAL Mode AS SHORT = 0) AS ZSTRING PTR
162 
163  STATIC AS CONST Float_t _
164  d_min = 1000. * &h4 / TMRSS_CLK '' minimal duration [mSec]
165  DIM AS UInt32 nr = 0
166 
167  WITH *Top
168  SELECT CASE AS CONST Ball
169  CASE &h24 : nr = 0 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_07, GP1_5, R7 mode 2
170  CASE &h25 : nr = 3 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_08, GP1_6, T7 mode 2
171  CASE &h26 : nr = 2 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_10
172  CASE &h27 : nr = 1 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P8_09
173  CASE &h5A : nr = 3 : IF ModeCheck(Ball,5) THEN ModeSet(Ball, &h0D) ' P2_27, E18 mode 5
174  CASE &h6C : nr = 0 : IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A) ' P2_31, A15 mode 2
175  CASE &h67 : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h0C) ' P9_28
176  RETURN .PwmSS->cap_tim_set(2, Dur1, Dur2, Mode)
177  CASE &h5D : IF ModeCheck(Ball,4) THEN ModeSet(Ball, &h0C) ' JT_05
178  RETURN .PwmSS->cap_tim_set(1, Dur1, Dur2, Mode)
179  CASE &h59 : IF ModeCheck(Ball,0) THEN ModeSet(Ball, &h08) ' P9_42
180  RETURN .PwmSS->cap_tim_set(0, Dur1, Dur2, Mode)
181  CASE ELSE : .Errr = E1 : RETURN E1 ' no Timer pin
182  END SELECT
183 
184  IF 2 <> Conf(nr)->ClVa THEN .Errr = E0 : RETURN E0 ' TIMER not enabled
185  'IF ModeCheck(Ball,2) THEN ModeSet(Ball, &h0A)
186 
187  VAR dur = Dur1 + Dur2 ' [mSec]
188  WITH *Conf(nr)
189  Raw(nr)->CMax = 0
190  SELECT CASE dur
191  CASE IS <= 0. : .TCLR = IIF(Mode AND &b01, TimHigh, Tim_Low) ' stop
192  CASE IS < d_min : Top->Errr = E3 : RETURN E3 ' duration too short
193  CASE ELSE
194  VAR cnt = CULNGINT(.001 * dur * TMRSS_CLK)
195  SELECT CASE AS CONST (cnt SHR 32) '' faster than LOG -> prescaler
196  CASE 0 : .TCLR = TimMode
197  CASE 1 : .TCLR = TimMode OR &b100000 : cnt SHR= 1
198  CASE 2 TO 3 : .TCLR = TimMode OR &b100100 : cnt SHR= 2
199  CASE 4 TO 7 : .TCLR = TimMode OR &b101000 : cnt SHR= 3
200  CASE 8 TO 15 : .TCLR = TimMode OR &b101100 : cnt SHR= 4
201  CASE 16 TO 31 : .TCLR = TimMode OR &b110000 : cnt SHR= 5
202  CASE 32 TO 63 : .TCLR = TimMode OR &b110100 : cnt SHR= 6
203  CASE 64 TO 127 : .TCLR = TimMode OR &b111000 : cnt SHR= 7
204  CASE 128 TO 255 : .TCLR = TimMode OR &b111100 : cnt SHR= 8
205  CASE ELSE : Top->Errr = E4 : RETURN E4 ' duration too long
206  END SELECT
207  .TLDR = &hFFFFFFFFuL - cnt
208 
209  VAR match = CULNG(Dur1 / dur * cnt)
210  SELECT CASE match
211  CASE IS <= 2 : .TMAR = &hFFFFFFFEuL : .TCRR = .TMAR : .TLDR += 1
212  .TCLR XOR= &b0110000000000 ' toggle on overflow
213  CASE IS > cnt - 2 : .TMAR = .TLDR + 2 : .TCRR = .TMAR + 2 : .TLDR += 1
214  .TCLR XOR= &b1110000000000 ' pulse instead of toggle
215  CASE ELSE : .TMAR = &hFFFFFFFFuL - match : .TCRR = .TMAR + 2
216  END SELECT
217 
218  IF Mode AND &b01 THEN .TCLR XOR= &b0000010000000 ' invers
219  IF Mode >= &b10 THEN ' one-shot
220  IF 0.01 >= Dur1 THEN Top->Errr = E3 : RETURN Top->Errr ' duration too short
221  Raw(nr)->CMax = (Mode AND &b111111110) SHR 1
222  .TCLR OR= &b100000000 ' one shot, bit 8!!
223  END IF
224  END SELECT
225  END WITH
226 
227  IF .DRam[0] > PRUIO_MSG_IO_OK THEN RETURN 0
228 
229  PruReady(1) ' wait, if PRU is busy (should never happen)
230  .DRam[5] = Conf(nr)->TMAR
231  .DRam[4] = Conf(nr)->TLDR
232  .DRam[3] = Conf(nr)->TCRR
233  .DRam[2] = Conf(nr)->DeAd
234  .DRam[1] = Conf(nr)->TCLR OR (PRUIO_COM_TIM_TIM SHL 24)
235  END WITH : RETURN 0
236 END FUNCTION
237 
238 
239 
257 FUNCTION TimerUdt.Value CDECL( _
258  BYVAL Ball AS UInt8 _
259  , BYVAL Dur1 AS Float_t PTR _
260  , BYVAL Dur2 AS Float_t PTR) AS ZSTRING PTR
261 
262  IF Dur1 = 0 ORELSE Dur2 = 0 THEN Top->Errr = @"pass pointers" : RETURN Top->Errr
263  DIM AS Uint32 nr
264  WITH *Top
265  SELECT CASE AS CONST Ball
266  CASE &h24 : nr = 0 : IF ModeCheck(Ball,2) THEN RETURN E2 ' P8_07, GP1_5, R7 mode 2
267  CASE &h25 : nr = 3 : IF ModeCheck(Ball,2) THEN RETURN E2 ' P8_08, GP1_6, T7 mode 2
268  CASE &h26 : nr = 2 : IF ModeCheck(Ball,2) THEN RETURN E2 ' P8_10
269  CASE &h27 : nr = 1 : IF ModeCheck(Ball,2) THEN RETURN E2 ' P8_09
270  CASE &h5A : nr = 3 : IF ModeCheck(Ball,5) THEN RETURN E2 ' P2_27, E18 mode 5
271  CASE &h6C : nr = 0 : IF ModeCheck(Ball,2) THEN RETURN E2 ' P2_31, A15 mode 2
272  CASE &h67 : RETURN IIF(ModeCheck(Ball,4), E2, .PwmSS->cap_tim_get(2, Dur1, Dur2)) ' P9_28
273  CASE &h5D : RETURN IIF(ModeCheck(Ball,4), E2, .PwmSS->cap_tim_get(1, Dur1, Dur2)) ' JT_05
274  CASE &h59 : RETURN IIF(ModeCheck(Ball,0), E2, .PwmSS->cap_tim_get(0, Dur1, Dur2)) ' P9_42
275  CASE ELSE : .Errr = E1 : RETURN E1 ' no Timer pin
276  END SELECT
277  END WITH
278  WITH *Conf(nr)
279  VAR dur = *Dur1 + *Dur2 _ ' [mSec]
280  , dmax = 1000. * &hFFFFFFFF00uLL / TMRSS_CLK _
281  , dmin = 1000. * 4 / TMRSS_CLK
282  SELECT CASE dur
283  CASE IS <= 0. ' get current
284  IF 2 <> .ClVa THEN Top->Errr = E0 : RETURN E0 ' TIMER subsystem not enabled
285  IF BIT(.TCLR, 13) THEN Top->Errr = E2 : RETURN E2 ' pin not in TIMER mode
286  IF BIT(.TCLR, 6) THEN ' running
287  VAR f = IIF(BIT(.TCLR, 5), (1 SHL ((.TCLR SHR 2) AND &b111)) * 2000., 1000.)
288  *Dur1 = f * ( .TMAR - .TLDR) / TMRSS_CLK
289  *Dur2 = f * (&hFFFFFFFFuL - .TMAR) / TMRSS_CLK
290  ELSE ' stopped
291  *Dur2 = 0.
292  *Dur1 = 0.
293  END IF
294  CASE IS <= dmin ' get minimal
295  *Dur1 = dmin
296  *Dur2 = dmin / 2
297  CASE IS >= dmax ' get maximal, splited by ratio Dur1/Dur2
298  *Dur1 = *Dur1 / dur * dmax
299  *Dur2 = *Dur2 / dur * dmax
300  CASE ELSE '!!! log !!!
301  VAR cnt = CULNGINT(.001 * dur * TMRSS_CLK), n = cnt SHR 32
302  IF n THEN n = LOG(n) / LOG2 : cnt = (cnt SHR n) SHL n
303  *Dur1 = 1000. * CULNGINT(*Dur1 / dur * cnt) / TMRSS_CLK
304  *Dur2 = 1000. * CULNGINT(*Dur2 / dur * cnt) / TMRSS_CLK
305  END SELECT
306  END WITH : RETURN 0
307 END FUNCTION
308 
309 
310 
328 FUNCTION TimerUdt.pwm_set CDECL( _
329  BYVAL Nr AS UInt8 _
330  , BYVAL Freq AS Float_t _
331  , BYVAL Duty AS Float_t = 0.) AS ZSTRING PTR
332 
333  STATIC AS CONST Float_t _
334  f_min = TMRSS_CLK / &hFFFFFFFF00uLL _'' minimal frequency
335  , f_max = TMRSS_CLK / &h4 '' maximal frequency
336  STATIC AS UInt32 r = 0 _
337  , cnt(...) = {0, 0, 0, 0} _ '' initial timer periods
338  , cmp(...) = {0, 0, 0, 0} '' initial timer match values
339 
340  WITH *Top
341  IF 2 <> Conf(Nr)->ClVa THEN .Errr = E0 : RETURN E0 ' TIMER not enabled
342 
343  IF Freq < 0. THEN ' frequency unchanged
344  IF 0 = cnt(Nr) THEN .Errr = .PwmSS->E1 : RETURN .Errr ' set frequency first
345  r = PwmMode OR (Conf(Nr)->TCLR AND &b111100)
346  ELSE
347  IF Freq < f_min ORELSE _
348  Freq > f_max THEN .Errr = .PwmSS->E2 : RETURN .Errr ' frequency not supported
349  VAR x = CULNGINT(TMRSS_CLK / Freq)
350  SELECT CASE AS CONST x SHR 32 '' faster than LOG -> set prescaler
351  CASE 0 : cnt(Nr) = x : r = PwmMode
352  CASE 1 : cnt(Nr) = x SHR 1 : r = PwmMode OR &b100000
353  CASE 2 TO 3 : cnt(Nr) = x SHR 2 : r = PwmMode OR &b100100
354  CASE 4 TO 7 : cnt(Nr) = x SHR 3 : r = PwmMode OR &b101000
355  CASE 8 TO 15 : cnt(Nr) = x SHR 4 : r = PwmMode OR &b101100
356  CASE 16 TO 31 : cnt(Nr) = x SHR 5 : r = PwmMode OR &b110000
357  CASE 32 TO 63 : cnt(Nr) = x SHR 6 : r = PwmMode OR &b110100
358  CASE 64 TO 127 : cnt(Nr) = x SHR 7 : r = PwmMode OR &b111000
359  CASE 128 TO 255 : cnt(Nr) = x SHR 8 : r = PwmMode OR &b111100
360  CASE ELSE : .Errr = .PwmSS->E2 : RETURN .Errr ' frequency not supported
361  END SELECT
362  END IF
363  Conf(Nr)->TLDR = &hFFFFFFFFuL - cnt(Nr)
364 
365  IF Duty >= 0. THEN ' change duty
366  cmp(Nr) = IIF(Duty >= 1., cnt(Nr), CUINT(cnt(Nr) * Duty))
367  SELECT CASE cmp(Nr)
368  CASE IS <= 1 : r = Tim_Low
369  CASE IS >= cnt(Nr) - 1 : r = TimHigh
370  CASE ELSE : Conf(Nr)->TMAR = Conf(Nr)->TLDR + cmp(Nr) - 1
371  END SELECT
372  END IF
373 
374  IF Conf(Nr)->TCLR = r THEN ' control reg unchanged
375  r = 0
376  ELSE
377  Conf(Nr)->TCLR = r
378  Conf(Nr)->TCRR = &hFFFFFFFEuL
379  END IF
380 
381  IF .DRam[0] > PRUIO_MSG_IO_OK THEN RETURN 0
382 
383  PruReady(1) ' wait, if PRU is busy (should never happen)
384  .DRam[5] = Conf(Nr)->TCRR
385  .DRam[4] = Conf(Nr)->TMAR
386  .DRam[3] = Conf(Nr)->TLDR
387  .DRam[2] = Conf(Nr)->DeAd
388  .DRam[1] = r OR (PRUIO_COM_TIM_PWM SHL 24)
389  END WITH : RETURN 0
390 END FUNCTION
391 
392 
393 
408 FUNCTION TimerUdt.pwm_get CDECL( _
409  BYVAL Nr AS UInt8 _
410  , BYVAL Freq AS Float_t PTR = 0 _
411  , BYVAL Duty AS Float_t PTR = 0) AS ZSTRING PTR
412 
413  WITH *Conf(Nr)
414  IF 2 <> .ClVa THEN Top->Errr = E0 /' TIMER disabled '/ : RETURN E0
415 
416  VAR cnt = &hFFFFFFFFuLL - .TLDR + 1 _
417  , pre = (.TCLR AND &b111100) SHR 2
418  SELECT CASE .TCLR
419  CASE TimHigh : IF Duty THEN *Duty = 1.
420  CASE Tim_Low : IF Duty THEN *Duty = 0.
421  CASE ELSE
422  IF (PwmMode AND .TCLR) <> PwmMode THEN Top->Errr = E2 : RETURN E2 ' TIMER not in PWM output mode
423  IF Duty THEN *Duty = (.TMAR -.TLDR + 1) / cnt
424  END SELECT
425  IF Freq THEN *Freq = TMRSS_CLK / (cnt SHL IIF(pre, (pre AND &b111) + 1, 0))
426  END WITH : RETURN 0
427 END FUNCTION
428