HWA
Bare metal programming with style
ctb_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 
44 #define hwa_configure__ctb , _hwa_cfctb
45 
46 /* Mandatory argument `clock`
47  *
48  * Add 2 void arguments to the end of the list so that there are always
49  * 3 arguments following the last non-void argument.
50  */
51 #define _hwa_cfctb(o,a,k,...) \
52  do { HW_B(_hwa_cfctb_kclock_,_hw_is_clock_##k)(o,k,__VA_ARGS__,,) } while(0)
53 
54 #define _hwa_cfctb_kclock_0(o,k,...) HW_E(HW_EM_AN(k,clock))
55 #define _hwa_cfctb_kclock_1(o,k,v,...) HW_B(_hwa_cfctb_vclock_,_hw_ctb_clock_##v)(o,v,__VA_ARGS__)
56 
57 #define _hwa_cfctb_vclock_0(o,v,...) \
58  HW_E(HW_EM_VAL(v,clock,(none,ioclk [/ 2**n] with n in {0..14})))
59 
60 #define _hwa_cfctb_vclock_1(o,v,k,...) \
61  _hwa_write(o, cs, HW_VF(_hw_ctb_clock_##v)); \
62  HW_B(_hwa_cfctb_kdirection_,_hw_is_direction_##k)(o,k,__VA_ARGS__)
63 
64 #define _hw_ctb_clock_none , _hw_ctbck_none, 0
65 #define _hw_ctb_clock_ioclk , _hw_ctbck_ioclk, 16384.0
66 
67 HW_INLINE uint8_t _hw_ctbck_none( float v )
68 {
69  if ( v != 0 )
70  HWA_E(HW_EM_VL(clock,(none, ioclk/2**(0..14), external_falling, external_rising)));
71 
72  return 0 ;
73 }
74 
75 HW_INLINE uint8_t _hw_ctbck_ioclk( float v )
76 {
77  if ( v == 16384 ) return 1 ;
78  if ( v == 8192 ) return 2 ;
79  if ( v == 4096 ) return 3 ;
80  if ( v == 2048 ) return 4 ;
81  if ( v == 1024 ) return 5 ;
82  if ( v == 512 ) return 6 ;
83  if ( v == 256 ) return 7 ;
84  if ( v == 128 ) return 8 ;
85  if ( v == 64 ) return 9 ;
86  if ( v == 32 ) return 10 ;
87  if ( v == 16 ) return 11 ;
88  if ( v == 8 ) return 12 ;
89  if ( v == 4 ) return 13 ;
90  if ( v == 2 ) return 14 ;
91  if ( v == 1 ) return 15 ;
92 
93  HWA_E(HW_EM_VL(clock,(none, ioclk/2**(0..14), external_falling, external_rising)));
94 
95  return 0 ;
96 }
97 
98 /* Optionnal argument `direction`
99  */
100 #define _hwa_cfctb_kdirection_1(o,k,v,...) \
101  HW_G2(_hwa_cfctb_vdirection,HW_IS(up_loop,v))(o,v,__VA_ARGS__)
102 
103 #define _hwa_cfctb_vdirection_0(o,v,...) \
104  HW_E(HW_EM_VAL(v,direction,(up_loop)))
105 
106 #define _hwa_cfctb_vdirection_1(o,v,...) \
107  _hwa_cfctb_kdirection_0(o,__VA_ARGS__)
108 
109 #define _hwa_cfctb_kdirection_0(o,k,...) \
110  HW_B(_hwa_cfctb_kbottom_,_hw_is_bottom_##k)(o,k,__VA_ARGS__)
111 
112 /* Optionnal argument `bottom`
113  */
114 #define _hwa_cfctb_kbottom_1(o,k,v,...) \
115  HW_G2(_hwa_cfctb_vbottom,HW_IS(0,v))(o,v,__VA_ARGS__)
116 
117 #define _hwa_cfctb_vbottom_0(o,v,...) \
118  HW_E(HW_EM_VAL(v,bottom,(0)))
119 
120 #define _hwa_cfctb_vbottom_1(o,v,...) \
121  _hwa_cfctb_kbottom_0(o,__VA_ARGS__)
122 
123 #define _hwa_cfctb_kbottom_0(o,k,...) \
124  HW_B(_hwa_cfctb_ktop_,_hw_is_top_##k)(o,k,__VA_ARGS__)
125 
126 
127 /* Optionnal argument `top`
128  */
129 #define _hw_ctb_top_0xFF , 0
130 #define _hw_ctb_top_0x00FF , 0
131 #define _hw_ctb_top_255 , 0
132 #define _hw_ctb_top_max , 0
133 #define _hw_ctb_top_compare2 , 1
134 
135 #define _hwa_cfctb_ktop_1(o,k,v,...) \
136  HW_B(_hwa_cfctb_vtop_,_hw_ctb_top_##v)(o,v,__VA_ARGS__)
137 
138 #define _hwa_cfctb_vtop_0(o,v,...) \
139  HW_E(HW_EM_VAL(v,top,(0xFF,0x00FF,255,max,compare2)))
140 
141 #define _hwa_cfctb_vtop_1(o,v,...) \
142  _hwa_write(o, ctc, HW_A1(_hw_ctb_top_##v)); \
143  _hwa_cfctb_ktop_0(v,__VA_ARGS__)
144 
145 #define _hwa_cfctb_ktop_0(o,k,...) \
146  HW_B(_hwa_cfctb_koverflow_,_hw_is_overflow_##k)(o,k,__VA_ARGS__)
147 
148 
149 /* Optionnal argument `overflow`
150  */
151 #define _hwa_cfctb_koverflow_1(o,k,v,...) \
152  HW_G2(_hwa_cfctb_voverflow,HW_IS(after_bottom,v))(o,v,__VA_ARGS__)
153 
154 #define _hwa_cfctb_voverflow_0(o,v,...) \
155  HW_E(HW_EM_VAL(v,overflow,(after_bottom)))
156 
157 #define _hwa_cfctb_voverflow_1(o,v,...) \
158  _hwa_cfctb_koverflow_0(o,__VA_ARGS__)
159 
160 #define _hwa_cfctb_koverflow_0(o,...) HW_EOL(__VA_ARGS__)
161 
162 
182 #define hw_read__ctb , _hw_ctbrd
183 #define _hw_ctbrd(o,a,...) _hw_read(o,count) HW_EOL(__VA_ARGS__)
184 
185 #define hw_write__ctb , _hw_ctbwr
186 #define _hw_ctbwr(o,a,v,...) _hw_write(o,count,v) HW_EOL(__VA_ARGS__)
187 
188 #define hwa_write__ctb , _hwa_ctbwr
189 #define _hwa_ctbwr(o,a,v,...) _hwa_write(o,count,v) HW_EOL(__VA_ARGS__)
190 
191 
192 /*******************************************************************************
193  * *
194  * Context management *
195  * *
196  *******************************************************************************/
197 
198 /* Solve the configuration of the counter and its related peripherals.
199  *
200  * This kind of counter does not trigger overflow IRQs on compare match with
201  * OCRC if no compare output is in pwm mode:
202  *
203  * "In the normal mode an overflow interrupt (TOV1) is generated when
204  * Timer/Counter1 counts from $FF to $00, while in the PWM mode the overflow
205  * interrupt is generated when Timer/Counter1 counts either from $FF to $00 or
206  * from OCR1C to $00. The inverted PWM outputs OC1A and OC1B are not connected
207  * in normal mode."
208  *
209  * -> If one compare output has been put in PWM mode, the other must have been
210  * too if it is used.
211  */
212 #define _hwa_solve__ctb(o,a) \
213  _hwa_solve_ocb(o,0); \
214  _hwa_solve_ocb(o,1); \
215  if ( _hwa_mmask(o,pwm0) && _hwa_mmask(o,pwm1) \
216  && _hwa_mvalue(o,pwm0) != _hwa_mvalue(o,pwm1) ) \
217  /* "used compare outputs must be in the same NORMAL or PWM mode." */ \
218  HWA_E(HW_EM_CMOO((o,compare0),(o,compare1))); \
219  else if ( _hwa_mmask(o,ctc) && _hwa_mvalue(o,ctc)==0 \
220  && ( (_hwa_mmask(o,pwm0) && _hwa_mvalue(o,pwm1)) \
221  || (_hwa_mmask(o,pwm1) && _hwa_mvalue(o,pwm1))) ) \
222  /* "`top` must be `compare2` for `" #o "` when using the PWM mode." */ \
223  HWA_E(HW_EM_AOVM(top,o,compare2)); \
224  if ( _hwa_mvalue(o,ie)==1 \
225  && _hwa_mvalue(o,ctc)==1 \
226  && _hwa_mvalue(o,pwm0) == 0 \
227  && _hwa_mvalue(o,pwm1) == 0 ) { \
228  if ( _hwa_mmask(o,pwm0)==1 || _hwa_mmask(o,pwm1)== 1 ) \
229  /* "`" #o "` does not trigger overflow IRQs when not using PWM mode for outputs." */ \
230  HWA_E(HW_EM_1(o)); \
231  else \
232  if ( _hwa_mmask(o,pwm0)==0 ) \
233  _hwa_write(o,pwm0,1); \
234  else \
235  _hwa_write(o,pwm0,1); \
236  }
237 
238 
239 #define _hwa_setup__ctb(o,a) \
240  _hwa_setup_r( o, ccr ); \
241  _hwa_setup_r( o, count ); \
242  _hwa_setup_r( o, ocr0 ); \
243  _hwa_setup_r( o, ocr1 ); \
244  _hwa_setup_r( o, ocr2 ); \
245  _hwa_setup_r( o, dtps ); \
246  _hwa_setup_r( o, dta ); \
247  _hwa_setup_r( o, dtb ); \
248  hwa->o.compare0.config.outputh = 0xFF ; \
249  hwa->o.compare0.config.outputl = 0xFF ; \
250  hwa->o.compare1.config.outputh = 0xFF ; \
251  hwa->o.compare1.config.outputl = 0xFF ; \
252 
253 #define _hwa_init__ctb(o,a) \
254  _hwa_init_r( o, ccr, 0 ); \
255  _hwa_init_r( o, count, 0 ); \
256  _hwa_init_r( o, ocr0, 0 ); \
257  _hwa_init_r( o, ocr1, 0 ); \
258  _hwa_init_r( o, ocr2, 0 ); \
259  _hwa_init_r( o, dtps, 0 ); \
260  _hwa_init_r( o, dta, 0 ); \
261  _hwa_init_r( o, dtb, 0 )
262 
263 #define _hwa_commit__ctb(o,a) \
264  _hwa_commit_r( o, ccr ); \
265  _hwa_commit_r( o, count ); \
266  _hwa_commit_r( o, ocr0 ); \
267  _hwa_commit_r( o, ocr1 ); \
268  _hwa_commit_r( o, ocr2 ); \
269  _hwa_commit_r( o, dtps ); \
270  _hwa_commit_r( o, dta ); \
271  _hwa_commit_r( o, dtb )
272 
273 
HWA_E
#define HWA_E(...)
Trigger an error after code optimization.
Definition: hwa_2.h:17