HWA
Bare metal programming with style
ctd_2.h
Go to the documentation of this file.
1 
2 /* This file is part of the HWA project.
3  * Copyright (c) 2012,2015 Christophe Duparquet.
4  * All rights reserved. Read LICENSE.TXT for details.
5  */
6 
61 #define hwa_configure__ctd , _hwa_cfctd
62 
63 /* Mandatory argument `clock`
64  *
65  * Add 2 void arguments to the end of the list so that there are always
66  * 3 arguments following the last non-void argument.
67  */
68 #define _hwa_cfctd(o,a,k,...) do { HW_BW(_hwa_cfctd1,clock,k)(o,k,__VA_ARGS__,,) } while(0)
69 #define _hwa_cfctd10(o,k,...) HW_E(HW_EM_AN(k,clock))
70 #define _hwa_cfctd11(o,k,v,...) HW_B(_hwa_cfctd11,_hw_c1clk_##v)(o,v,__VA_ARGS__)
71 #define _hwa_cfctd110(o,v,...) HW_E(HW_EM_VAL(v,clock,(none,ioclk,ioclk/8,ioclk/64,ioclk/256,ioclk/1024,external_falling,external_rising)))
72 #define _hwa_cfctd111(o,v,k,...) \
73  hwa->o.config.clock = HW_VF(_hw_c1clk_##v); \
74  HW_BW(_hwa_cfctd_kmode_,direction,k)(o,k,__VA_ARGS__)
75 
76 
77 /* Optionnal argument `direction`
78  */
79 #define _hw_ctd_direction_up_loop , 1
80 #define _hw_ctd_direction_updown_loop , 2
81 
82 #define _hwa_cfctd_kmode_0(o,k,...) \
83  HW_E(HW_EM_AN(k,direction))
84 
85 #define _hwa_cfctd_kmode_1(o,k,v,...) \
86  HW_B(_hwa_cfctd_vmode_,_hw_ctd_direction_##v)(o,v,__VA_ARGS__)
87 
88 #define _hwa_cfctd_vmode_0(o,v,...) HW_E(HW_EM_VAL(v,direction,(up_loop,updown_loop)))
89 #define _hwa_cfctd_vmode_1(o,v,k,...) \
90  hwa->o.config.direction = HW_A1(_hw_ctd_direction_##v); \
91  HW_B(_hwa_cfctd_kbottom_,_hw_is_bottom_##k)(o,k,__VA_ARGS__)
92 
93 /* Optionnal argument `bottom`
94  */
95 #define _hwa_cfctd_kbottom_1(o,k,v,...) HW_G2(_hwa_cfctd_vbottom,HW_IS(0,v))(o,v,__VA_ARGS__)
96 #define _hwa_cfctd_vbottom_0(o,v,...) HW_E(HW_EM_VAL(v,bottom,(0)))
97 #define _hwa_cfctd_vbottom_1(o,v,k,...) HW_B(_hwa_cfctd_ktop_,_hw_is_top_##k)(o,k,__VA_ARGS__)
98 #define _hwa_cfctd_kbottom_0(o,k,...) HW_B(_hwa_cfctd_ktop_,_hw_is_top_##k)(o,k,__VA_ARGS__)
99 
100 /* Optionnal argument `top`
101  */
102 #define _hw_ctd_top_0x00FF , 1
103 #define _hw_ctd_top_0xFF , 1
104 #define _hw_ctd_top_255 , 1
105 #define _hw_ctd_top_0x01FF , 2
106 #define _hw_ctd_top_0x1FF , 2
107 #define _hw_ctd_top_511 , 2
108 #define _hw_ctd_top_0x03FF , 3
109 #define _hw_ctd_top_0x3FF , 3
110 #define _hw_ctd_top_1023 , 3
111 #define _hw_ctd_top_0xFFFF , 4
112 #define _hw_ctd_top_65536 , 4
113 #define _hw_ctd_top_max , 4
114 #define _hw_ctd_top_capture0 , 5
115 #define _hw_ctd_top_compare0 , 6
116 
117 #define _hwa_cfctd_ktop_1(o,k,v,...) \
118  HW_B(_hwa_cfctd_vtop_,_hw_ctd_top_##v)(o,v,__VA_ARGS__)
119 
120 #define _hwa_cfctd_vtop_0(o,v,...) \
121  HW_E(HW_EM_VAL(v,top,(0xFF,0x1FF,0x3FF,0xFFFF,max,capture0,compare0)))
122 
123 #define _hwa_cfctd_vtop_1(o,v,k,...) \
124  hwa->o.config.top = HW_A1(_hw_ctd_top_##v); \
125  HW_BW(_hwa_cfctdovf,overflow,k)(o,k,__VA_ARGS__)
126 
127 #define _hwa_cfctd_ktop_0(o,k,...) HW_BW(_hwa_cfctdovf,overflow,k)(o,k,__VA_ARGS__)
128 
129 /* Optionnal argument `overflow`
130  */
131 #define _hwa_cfctdovf1(o,k,v,...) HW_BV(_hwa_cfctdovf1,ctdovf_,v,o) HW_EOL(__VA_ARGS__)
132 #define _hwa_cfctdovf10(v,o) HW_E(HW_EM_VOAL(v,overflow,(after_bottom,after_top,after_max)))
133 #define _hwa_cfctdovf11(v,o) hwa->o.config.overflow = v;
134 #define _hwa_cfctdovf0(o,...) HW_EOL(__VA_ARGS__)
135 
136 #define _hw_ctdovf_after_bottom , 0
137 #define _hw_ctdovf_after_top , 1
138 #define _hw_ctdovf_after_max , 2
139 
140 
141 /* Solve and check the configuration of the counter and its compare units.
142  *
143  * Writing code for a HW_INLINE function is more comfortable than for a
144  * function-like macro but functions can not use object names. So, this
145  * function-like macro expands to the HW_INLINE function _hwa_solve_ctd() which
146  * uses pointers on objects in the HWA context to compute values to be written
147  * into the registers, stores them into the `solve` structure and returns an
148  * error code that is processed by _hwa_solve__ctd() which knows the names of
149  * the objects and then can put computed registers values into the context, even
150  * in the case of external register access, and display accurate error messages.
151  */
152 #define _hwa_solve__ctd( o, a ) \
153  do { \
154  uint8_t r = _hwa_solve_ctd( &hwa->o, &hwa->o.compare0, &hwa->o.compare1, &hwa->o.capture0 ); \
155  if ( r == 0 ) { \
156  /* \
157  * Write solved registers \
158  */ \
159  if ( hwa->o.solved.cs != 0xFF ) _hwa_write( o, cs, hwa->o.solved.cs ); \
160  if ( hwa->o.solved.wgm != 0xFF ) _hwa_write( o, wgm, hwa->o.solved.wgm ); \
161  if ( hwa->o.compare0.solved.com != 0xFF ) _hwa_write( o, com0, hwa->o.compare0.solved.com ); \
162  if ( hwa->o.compare1.solved.com != 0xFF ) _hwa_write( o, com1, hwa->o.compare1.solved.com ); \
163  if ( hwa->o.capture0.solved.acic != 0xFF ) _hwa_write( o, acic, hwa->o.capture0.solved.acic ); \
164  if ( hwa->o.capture0.solved.ices != 0xFF ) _hwa_write( o, ices, hwa->o.capture0.solved.ices ); \
165  if ( hwa->o.capture0.solved.icnc != 0xFF ) _hwa_write( o, icnc, hwa->o.capture0.solved.icnc ); \
166  /* \
167  * Configure used compare outputs as i/o outputs \
168  */ \
169  if ( hwa->o.compare0.config.output != 0xFF \
170  && hwa->o.compare0.config.output != HW_A1(_hw_occ_output_disconnected) ) \
171  _hwa( configure, (o,compare0,pin), mode, digital_output ); \
172  if ( hwa->o.compare1.config.output != 0xFF \
173  && hwa->o.compare1.config.output != HW_A1(_hw_occ_output_disconnected) ) \
174  _hwa( configure, (o,compare1,pin), mode, digital_output ); \
175  } \
176  else if ( r == 1 ) /* almost copy of _hwa_solve__cta */ \
177  /* `update` must be the same for both compare units of `o`" */ \
178  HWA_E(HW_EM_ADOO(update,(o,compare0),(o,compare1))); \
179  else if ( r == 2 ) \
180  /* "WGM value could not be solved for o" */ \
181  HWA_E(HW_EM_XSO(wgm,o)); \
182  else if ( r == 3 ) \
183  /* "configuration of `o` is required */ \
184  HWA_E(HW_EM_COR(o)); \
185  else if ( r == 4 ) \
186  HWA_E(HW_EM_AVOL(mode,compare0, (disconnected, \
187  toggle_after_match, \
188  clear_after_match, \
189  set_after_match))); \
190  else if ( r == 5 ) \
191  HWA_E(HW_EM_AVOL(mode,compare0, (disconnected, \
192  set_at_bottom_clear_after_match, \
193  clear_at_bottom_set_after_match))); \
194  else if ( r == 6 ) \
195  HWA_E(HW_EM_AVOL(mode,compare0, (disconnected, \
196  toggle_after_match, \
197  set_at_bottom_clear_after_match, \
198  clear_at_bottom_set_after_match))); \
199  else if ( r == 7 ) \
200  HWA_E(HW_EM_AVOL(mode,compare0, (disconnected, \
201  clear_after_match_up_set_after_match_down, \
202  set_after_match_up_clear_after_match_down))); \
203  else if ( r == 8 ) \
204  HWA_E(HW_EM_AVOL(mode,compare0, (disconnected, \
205  toggle_after_match, \
206  clear_after_match_up_set_after_match_down, \
207  set_after_match_up_clear_after_match_down))); \
208  else if ( r == 9 ) \
209  HWA_E(HW_EM_2(o)); \
210  else if ( r == 10 ) \
211  HWA_E(HW_EM_AVOL(mode,compare1, (disconnected, \
212  toggle_after_match, \
213  clear_after_match, \
214  set_after_match))); \
215  else if ( r == 11 ) \
216  HWA_E(HW_EM_AVOL(mode,compare1, (disconnected, \
217  set_at_bottom_clear_after_match, \
218  clear_at_bottom_set_after_match))); \
219  else if ( r == 12 ) \
220  HWA_E(HW_EM_AVOL(mode,compare1, (disconnected, \
221  clear_after_match_up_set_after_match_down, \
222  set_after_match_up_clear_after_match_down))); \
223  else if ( r == 13 ) \
224  HWA_E(HW_EM_AOVM(update,o,immediately)); \
225  else if ( r == 14 ) \
226  HWA_E(HW_EM_AOVM(update,o,after_bottom)); \
227  else if ( r == 15 ) \
228  HWA_E(HW_EM_AOVM(update,o,after_top)); \
229  else if ( r == 16 ) \
230  HWA_E(HW_EM_AOVM(overflow,o,after_max)); \
231  else if ( r == 17 ) \
232  HWA_E(HW_EM_AOVM(overflow,o,after_top)); \
233  else if ( r == 18 ) \
234  HWA_E(HW_EM_AOVM(overflow,o,after_bottom)); \
235  else \
236  HWA_E(HW_EM_X(in _hwa_solve__cta: __LINE__)); \
237  }while(0)
238 
239 
240 /* Solve the configuration of the counter with its compare and capture units
241  */
242 //HW_INLINE void _hwa_solve__ctd ( hwa_t *hwa __attribute__((unused)), hwa_ctd_t *p )
243 HW_INLINE uint8_t _hwa_solve_ctd ( hwa_ctd_t *c, hwa_occ_t *compare0,
244  hwa_occ_t *compare1, hwa_ica_t *capture0 )
245 {
246  c->solved.cs = 0xFF ;
247  c->solved.wgm = 0xFF ;
248  compare0->solved.com = 0xFF ;
249  compare1->solved.com = 0xFF ;
250  capture0->solved.acic = 0xFF ;
251  capture0->solved.ices = 0xFF ;
252  capture0->solved.icnc = 0xFF ;
253 
254  if ( c->config.clock == 0xFF )
255  return 0 ;
256 
257  /* Clock setting
258  */
259  c->solved.cs = c->config.clock ;
260 
261  /* Default config for top
262  */
263  if ( c->config.top == 0xFF )
264  c->config.top = HW_A1(_hw_ctd_top_max);
265 
266  /* Default config for overflow
267  */
268  uint8_t overflow = c->config.overflow ;
269  if ( overflow == 0xFF && c->config.top == HW_A1(_hw_ctd_top_compare0) ) {
270  if ( c->config.direction == HW_A1(_hw_ctd_direction_up_loop) )
271  overflow = HW_A1(_hw_ctdovf_after_top);
272  else /* if ( c->config.direction == HW_A1(_hw_ctd_direction_up_loop) ) */
273  overflow = HW_A1(_hw_ctdovf_after_bottom);
274  }
275 
276  /* Compare update setting
277  */
278  uint8_t compare_update = 0xFF ;
279  if ( compare0->config.update != 0xFF && compare1->config.update != 0xFF
280  && compare0->config.update != compare1->config.update )
281  return 1 ; // ("optionnal parameter 'update' of class _ctd counter must be'immediately'.");
282  compare_update = compare0->config.update ;
283 
284  /* Mode WGM Operation COUNTMODE TOP OCR OVF OCF ICF OCA OCB
285  * TOP
286  * UPD
287  *
288  * 0 0000 Normal LOOP_UP 0xFFFF IMM MAX CoM,SoM,ToM CoM,SoM,ToM
289  * 4 0100 CTC (Clear Timer on Match) LOOP_UP ocra IMM MAX TOP CoM,SoM,ToM
290  * 12 1100 CTC (Clear Timer on Match) LOOP_UP icr IMM MAX TOP CoM,SoM,ToM CoM,SoM,ToM
291  *
292  * 5 0101 Fast PWM, 8-bit LOOP_UP 0xFF TOP TOP SaBCoM,CaBSoM SaBCoM,CaBSoM
293  * 6 0110 Fast PWM, 9-bit LOOP_UP 0x1FF TOP TOP SaBCoM,CaBSoM SaBCoM,CaBSoM
294  * 7 0111 Fast PWM, 10-bit LOOP_UP 0x3FF TOP TOP SaBCoM,CaBSoM SaBCoM,CaBSoM
295  * 14 1110 Fast PWM LOOP_UP icr TOP TOP TOP ToM,SaBCoM,CaBSoM SaBCoM,CaBSoM
296  * 15 1111 Fast PWM LOOP_UP ocra TOP TOP TOP SaBCoM,CaBSoM
297  *
298  * 1 0001 PWM, Phase Correct, 8-bit LOOP_UPDOWN 0xFF TOP BOT CMUSMD,SMUCMD CMUSMD,SMUCMD
299  * 2 0010 PWM, Phase Correct, 9-bit LOOP_UPDOWN 0x1FF TOP BOT CMUSMD,SMUCMD CMUSMD,SMUCMD
300  * 3 0011 PWM, Phase Correct, 10-bit LOOP_UPDOWN 0x3FF TOP BOT CMUSMD,SMUCMD CMUSMD,SMUCMD
301  * 10 1010 PWM, Phase Correct LOOP_UPDOWN icr TOP BOT TOP ToM,CMUSMD,SMUCMD CMUSMD,SMUCMD
302  * 11 1011 PWM, Phase Correct LOOP_UPDOWN ocra TOP BOT TOP CMUSMD,SMUCMD
303  *
304  * 8 1000 PWM, Phase & Freq. Correct LOOP_UPDOWN icr BOT BOT TOP ToM,CMUSMD,SMUCMD CMUSMD,SMUCMD
305  * 9 1001 PWM, Phase & Freq. Correct LOOP_UPDOWN ocra BOT BOT TOP CMUSMD,SMUCMD
306  *
307  * 13 1101 *Reserved*
308  */
309 
310  /* Determine WGM
311  */
312  uint8_t wgm = 0xFF ;
313  if ( c->config.direction == HW_A1(_hw_ctd_direction_up_loop)
314  && c->config.top == HW_A1(_hw_ctd_top_compare0)
315  && overflow == HW_A1(_hw_ctdovf_after_top) )
316  wgm = 15 ;
317  else
318  if ( c->config.direction == HW_A1(_hw_ctd_direction_up_loop) ) {
319  if ( c->config.top == HW_A1(_hw_ctd_top_0xFFFF) )
320  wgm = 0 ;
321  else if (c->config.top == HW_A1(_hw_ctd_top_0xFF) )
322  wgm = 5 ;
323  else if (c->config.top == HW_A1(_hw_ctd_top_0x1FF) )
324  wgm = 6 ;
325  else if (c->config.top == HW_A1(_hw_ctd_top_0x3FF) )
326  wgm = 7 ;
327  else if (c->config.top == HW_A1(_hw_ctd_top_compare0) ) {
328  if ( compare_update == HW_A1(_hw_occ_update_immediately)
329  || overflow == HW_A1(_hw_ctdovf_after_top)
330  || compare1->config.output == HW_A1(_hw_occ_output_set_at_bottom_clear_after_match)
331  || compare1->config.output == HW_A1(_hw_occ_output_clear_at_bottom_set_after_match))
332  wgm = 15 ;
333  else
334  wgm = 4 ;
335  }
336  else /* if (c->top == HW_A1(_hw_ctd_top_capture0) ) */ {
337  if (compare_update == HW_A1(_hw_occ_update_after_top)
338  || overflow == HW_A1(_hw_ctdovf_after_top)
339  || compare0->config.output == HW_A1(_hw_occ_output_toggle_after_match)
340  || compare0->config.output == HW_A1(_hw_occ_output_set_at_bottom_clear_after_match)
341  || compare0->config.output == HW_A1(_hw_occ_output_clear_at_bottom_set_after_match)
342  || compare1->config.output == HW_A1(_hw_occ_output_set_at_bottom_clear_after_match)
343  || compare1->config.output == HW_A1(_hw_occ_output_clear_at_bottom_set_after_match))
344  wgm = 14 ;
345  else
346  wgm = 12 ;
347  }
348  }
349  else {
350  if (c->config.top == HW_A1(_hw_ctd_top_0xFF) )
351  wgm = 1 ;
352  else if (c->config.top == HW_A1(_hw_ctd_top_0x1FF) )
353  wgm = 2 ;
354  else if (c->config.top == HW_A1(_hw_ctd_top_0x3FF) )
355  wgm = 3 ;
356  else if (c->config.top == HW_A1(_hw_ctd_top_compare0) ) {
357  if (compare_update == HW_A1(_hw_occ_update_after_bottom)
358  || compare1->config.output == HW_A1(_hw_occ_output_clear_after_match_up_set_after_match_down)
359  || compare1->config.output == HW_A1(_hw_occ_output_set_after_match_up_clear_after_match_down))
360  wgm = 9 ;
361  else
362  wgm = 11 ;
363  }
364  else /* if (c->top == HW_A1(_hw_ctd_top_capture0) ) */ {
365  if (compare_update == HW_A1(_hw_occ_update_after_bottom)
366  || compare0->config.output == HW_A1(_hw_occ_output_toggle_after_match)
367  || compare0->config.output == HW_A1(_hw_occ_output_clear_after_match_up_set_after_match_down)
368  || compare0->config.output == HW_A1(_hw_occ_output_set_after_match_up_clear_after_match_down)
369  || compare1->config.output == HW_A1(_hw_occ_output_clear_after_match_up_set_after_match_down)
370  || compare1->config.output == HW_A1(_hw_occ_output_set_after_match_up_clear_after_match_down))
371  wgm = 8 ;
372  else
373  wgm = 10 ;
374  }
375  }
376 
377  if ( wgm == 0xFF )
378  return 2 ; // ("WGM value could not be solved for _ctd class counter.");
379 
380  c->solved.wgm = wgm ;
381 
382  /* Solve the configuration of compare output A
383  */
384  if ( compare0->config.output != 0xFF ) {
385 
386  uint8_t mode = 0xFF ;
387 
388  if ( compare0->config.output == HW_A1(_hw_occ_output_disconnected) )
389  mode = 0 ;
390  else if ( compare0->config.output == HW_A1(_hw_occ_output_toggle_after_match) )
391  mode = 1 ;
392  else if ( compare0->config.output == HW_A1(_hw_occ_output_clear_after_match)
393  || compare0->config.output == HW_A1(_hw_occ_output_set_at_bottom_clear_after_match)
394  || compare0->config.output == HW_A1(_hw_occ_output_clear_after_match_up_set_after_match_down) )
395  mode = 2 ;
396  else
397  mode = 3 ;
398 
399  compare0->solved.com = mode ;
400  }
401 
402  /* Solve the configuration of compare output B
403  */
404  if ( compare1->config.output != 0xFF ) {
405 
406  uint8_t mode = 0xFF ;
407 
408  if ( compare1->config.output == HW_A1(_hw_occ_output_disconnected) )
409  mode = 0 ;
410  else if ( compare1->config.output == HW_A1(_hw_occ_output_toggle_after_match) )
411  mode = 1 ;
412  else if ( compare1->config.output == HW_A1(_hw_occ_output_clear_after_match)
413  || compare1->config.output == HW_A1(_hw_occ_output_set_at_bottom_clear_after_match)
414  || compare1->config.output == HW_A1(_hw_occ_output_clear_after_match_up_set_after_match_down) )
415  mode = 2 ;
416  else
417  mode = 3 ;
418 
419  compare1->solved.com = mode ;
420  }
421 
422  /* Solve the configuration of the capture input
423  */
424  // if ( capture0->config.input != 0xFF ) {
425  if ( capture0->config.input != 0xFF )
426  capture0->solved.acic = capture0->config.input-1 ;
427  if ( capture0->config.edge != 0xFF )
428  capture0->solved.ices = capture0->config.edge-1 ;
429  if ( capture0->config.filter != 0xFF )
430  capture0->solved.icnc = capture0->config.filter ;
431  //}
432 
433 
434  /* Check the validity of the configuration
435  */
436  if ( c->config.direction != 0xFF || compare0->config.output != 0xFF || compare1->config.output != 0xFF ) {
437 
438  if ( c->config.direction == 0xFF )
439  return 3 ; // ("configuration of counter is required.");
440 
441  /* Check compare output A
442  */
443  if ( compare0->config.output != 0xFF ) {
444  if ( wgm==0 || wgm==12 ) {
445  if ( compare0->config.output != HW_A1(_hw_occ_output_disconnected)
446  && compare0->config.output != HW_A1(_hw_occ_output_clear_after_match)
447  && compare0->config.output != HW_A1(_hw_occ_output_set_after_match)
448  && compare0->config.output != HW_A1(_hw_occ_output_toggle_after_match) )
449  return 4 ;
450  /* ("compare output A of class _ctd counter mode must be " */
451  /* "'disconnected', 'clear_after_match', 'set_after_match', or " */
452  /* "'toggle_after_match'."); */
453  }
454  else if ( wgm==5 || wgm==6 || wgm==7 ) {
455  if ( compare0->config.output != HW_A1(_hw_occ_output_disconnected)
456  && compare0->config.output != HW_A1(_hw_occ_output_set_at_bottom_clear_after_match)
457  && compare0->config.output != HW_A1(_hw_occ_output_clear_at_bottom_set_after_match) )
458  return 5 ;
459  /* ("compare output A of class _ctd counter mode must be " */
460  /* "'disconnected', 'set_at_bottom_clear_after_match', or " */
461  /* "'clear_at_bottom_set_after_match'."); */
462  }
463  else if ( wgm==14 ) {
464  if ( compare0->config.output != HW_A1(_hw_occ_output_disconnected)
465  && compare0->config.output != HW_A1(_hw_occ_output_toggle_after_match)
466  && compare0->config.output != HW_A1(_hw_occ_output_set_at_bottom_clear_after_match)
467  && compare0->config.output != HW_A1(_hw_occ_output_clear_at_bottom_set_after_match) )
468  return 6 ;
469  /* ("compare output A of class _ctd counter mode must be " */
470  /* "'disconnected', 'toggle_after_match', " */
471  /* "'set_at_bottom_clear_after_match', or " */
472  /* "'clear_at_bottom_set_after_match'."); */
473  }
474  else if ( wgm==1 || wgm==2 || wgm==3 ) {
475  if ( compare0->config.output != HW_A1(_hw_occ_output_disconnected)
476  && compare0->config.output != HW_A1(_hw_occ_output_clear_after_match_up_set_after_match_down)
477  && compare0->config.output != HW_A1(_hw_occ_output_set_after_match_up_clear_after_match_down) )
478  return 7 ;
479  /* ("compare output A of class _ctd counter mode must be " */
480  /* "'disconnected', 'clear_after_match_up_set_after_match_down', " */
481  /* "or 'set_after_match_up_clear_after_match_down'."); */
482  }
483  else if ( wgm==8 || wgm==10 ) {
484  if ( compare0->config.output != HW_A1(_hw_occ_output_disconnected)
485  && compare0->config.output != HW_A1(_hw_occ_output_toggle_after_match)
486  && compare0->config.output != HW_A1(_hw_occ_output_clear_after_match_up_set_after_match_down)
487  && compare0->config.output != HW_A1(_hw_occ_output_set_after_match_up_clear_after_match_down) )
488  return 8 ;
489  /* ("compare output A of class _ctd counter mode must be " */
490  /* "'disconnected', 'toggle_after_match', " */
491  /* "'clear_after_match_up_set_after_match_down', " */
492  /* "or 'set_after_match_up_clear_after_match_down'."); */
493  }
494  // else if ( c->top == HW_A1(_hw_ctd_top_compare0)
495  else if ( compare0->config.output )
496  return 9 ;
497  /* ("can not use of `compare_a` as both top value and output of class _ctd counter."); */
498  }
499 
500  /* Check compare output B
501  */
502  if ( compare1->config.output != 0xFF ) {
503  if ( wgm==0 || wgm==4 || wgm==12 ) {
504  if ( compare1->config.output != HW_A1(_hw_occ_output_disconnected)
505  && compare1->config.output != HW_A1(_hw_occ_output_clear_after_match)
506  && compare1->config.output != HW_A1(_hw_occ_output_set_after_match)
507  && compare1->config.output != HW_A1(_hw_occ_output_toggle_after_match) )
508  return 10 ;
509  /* ("compare output B of class _ctd counter mode must be " */
510  /* "'disconnected', 'clear_after_match', 'set_after_match', or " */
511  /* "'toggle_after_match'."); */
512  }
513  else if ( wgm==5 || wgm==6 || wgm==7 || wgm==14 || wgm==15 ) {
514  if ( compare1->config.output != HW_A1(_hw_occ_output_disconnected)
515  && compare1->config.output != HW_A1(_hw_occ_output_set_at_bottom_clear_after_match)
516  && compare1->config.output != HW_A1(_hw_occ_output_clear_at_bottom_set_after_match) )
517  return 11 ;
518  /* ("compare output B of class _ctd counter mode must be " */
519  /* "'disconnected', 'set_at_bottom_clear_after_match', or " */
520  /* "'clear_at_bottom_set_after_match'."); */
521  }
522  else /* if ( wgm==1 || wgm==2 || wgm==3 || wgm==8 || wgm==9 || wgm==10 || wgm==11 ) */ {
523  if ( compare1->config.output != HW_A1(_hw_occ_output_disconnected)
524  && compare1->config.output != HW_A1(_hw_occ_output_clear_after_match_up_set_after_match_down)
525  && compare1->config.output != HW_A1(_hw_occ_output_set_after_match_up_clear_after_match_down) )
526  return 12 ;
527  /* ("compare output B of class _ctd counter mode must be " */
528  /* "'disconnected', 'clear_after_match_up_set_after_match_down', " */
529  /* "or 'set_after_match_up_clear_after_match_down'."); */
530  }
531  }
532 
533  /* Check compare update
534  */
535  if ( compare_update != 0xFF ) {
536  if ( wgm==0 || wgm==4 || wgm==12 ) {
537  if ( compare_update != HW_A1(_hw_occ_update_immediately) )
538  return 13 ;
539  /* ("optionnal parameter 'update' of class _ctd counter must be "\ */
540  /* "'immediately'."); */
541  }
542  else if ( wgm==8 || wgm==9 ) {
543  if ( compare_update != HW_A1(_hw_occ_update_after_bottom) )
544  return 14 ;
545  /* ("optionnal parameter 'update' of class _ctd counter must be " */
546  /* "'after_bottom'."); */
547  }
548  else
549  if( compare_update != HW_A1(_hw_occ_update_after_top) )
550  return 15 ;
551  /* ("optionnal parameter 'update' of class _ctd counter must be " */
552  /* "'after_top'."); */
553  }
554 
555  /* Overflow
556  */
557  if ( overflow != 0xFF ) {
558  if ( (wgm==0 || wgm==4 || wgm==12) ) {
559  if ( overflow != HW_A1(_hw_ctdovf_after_max) )
560  return 16 ;
561  /* ("optionnal parameter 'overflow' of class _ctd counter must be " */
562  /* "'after_max'."); */
563  }
564  else if ( (wgm==5 || wgm==6 || wgm==7 || wgm==14 || wgm==15) ) {
565  if ( overflow != HW_A1(_hw_ctdovf_after_top) )
566  return 17 ;
567  /* ("optionnal parameter 'overflow' of class _ctd counter must be " */
568  /* "'after_top'."); */
569  }
570  else if ( overflow != HW_A1(_hw_ctdovf_after_bottom) )
571  return 18 ;
572  /* ("optionnal parameter 'overflow' of class _ctd counter must be " */
573  /* "'after_bottom'."); */
574  }
575  }
576 
577  return 0 ;
578 }
579 
580 
600 #define hw_read__ctd , _hw_read_ctd
601 #define _hw_read_ctd(o,a,...) _hw_read(o,count) HW_EOL(__VA_ARGS__)
602 
603 #define hw_write__ctd , _hw_write_ctd
604 #define _hw_write_ctd(o,a,v,...) _hw_write(o,count,v) HW_EOL(__VA_ARGS__)
605 
606 #define hwa_write__ctd , _hwa_write_ctd
607 #define _hwa_write_ctd(o,a,v) _hwa_write(o,count,v)
608 
609 
610 /*******************************************************************************
611  * *
612  * Context management *
613  * *
614  *******************************************************************************/
615 
616 #define _hwa_setup__ctd(o,a) \
617  _hwa_setup_r( o, ccra ); \
618  _hwa_setup_r( o, ccrb ); \
619  _hwa_setup_r( o, ocr0 ); \
620  _hwa_setup_r( o, ocr1 ); \
621  _hwa_setup_r( o, icr0 ); \
622  _hwa_setup_r( o, ccrc ); \
623  _hwa_setup_r( o, count ); \
624  _hwa_setup_r( o, imsk ); \
625  _hwa_setup_r( o, ifr ); \
626  hwa->o.config.clock = 0xFF ; \
627  hwa->o.config.direction = 0xFF ; \
628  hwa->o.config.top = 0xFF ; \
629  hwa->o.config.overflow = 0xFF ; \
630  hwa->o.compare0.config.update = 0xFF ; \
631  hwa->o.compare0.config.output = 0xFF ; \
632  hwa->o.compare1.config.update = 0xFF ; \
633  hwa->o.compare1.config.output = 0xFF ; \
634  hwa->o.capture0.config.input = 0xFF ; \
635  hwa->o.capture0.config.edge = 0xFF ; \
636  hwa->o.capture0.config.filter = 0xFF
637 
638 #define _hwa_init__ctd(o,a) \
639  _hwa_init_r( o, ccra, 0 ); \
640  _hwa_init_r( o, ccrb, 0 ); \
641  _hwa_init_r( o, ocr0, 0 ); \
642  _hwa_init_r( o, ocr1, 0 ); \
643  _hwa_init_r( o, icr0, 0 ); \
644  _hwa_init_r( o, ccrc, 0 ); \
645  _hwa_init_r( o, count, 0 ); \
646  _hwa_init_r( o, imsk, 0 ); \
647  _hwa_init_r( o, ifr, 0 )
648 
649 #define _hwa_commit__ctd(o,a) \
650  _hwa_commit_r( o, ccra ); \
651  _hwa_commit_r( o, ccrb ); \
652  _hwa_commit_r( o, ccrc ); \
653  _hwa_commit_r( o, count ); \
654  _hwa_commit_r( o, ocr0 ); \
655  _hwa_commit_r( o, ocr1 ); \
656  _hwa_commit_r( o, icr0 ); \
657  _hwa_commit_r( o, imsk ); \
658  _hwa_commit_r( o, ifr )
659 
660 
HW_A1
#define HW_A1(...)
Element a1 of the list a0,a1,...
Definition: hwa_macros.h:36