HWA
Bare metal programming with style
swtwimaster.h
Go to the documentation of this file.
1 
2 /* This file is part of the HWA project.
3  * Copyright (c) 2018 Christophe Duparquet.
4  * All rights reserved. Read LICENSE.TXT for details.
5  */
6 
7 #if !defined DOXYGEN && !defined HW_DEVICE_ARCH_AVR
8 # warning Class _swtwimaster may not be supported by your hardware
9 #endif
10 
46 #define hw_class__swtwimaster
47 
53 #define HW_SWTWIMASTER(...) _HW_SWTWIM_(__VA_ARGS__,,,,,,,)
54 #define _HW_SWTWIM_(k,...) HW_BW(_HW_SWTWIM_1,scl,k)(k,__VA_ARGS__)
55 #define _HW_SWTWIM_10(k,...) _HW_SWTWIM_E(k,__VA_ARGS__)
56 #define _HW_SWTWIM_11(k,...) _HW_SWTWIM_12(HW_AD(__VA_ARGS__)) /* Get SCL def */
57 #define _HW_SWTWIM_12(...) _HW_SWTWIM_13(__VA_ARGS__)
58 #define _HW_SWTWIM_13(scl,...) HW_B(_HW_SWTWIM_13,HW_A0 scl)(scl,__VA_ARGS__)
59 #define _HW_SWTWIM_131(scl,...) ,HW_SWTWIMASTER,HW_SWTWIMASTER(...): HW_A2 scl
60 #define _HW_SWTWIM_130(scl,k,...) HW_BW(_HW_SWTWIM_2,sda,k)(scl,k,__VA_ARGS__)
61 
62 #define _HW_SWTWIM_20(scl,k,...) _HW_SWTWIM_E(k,__VA_ARGS__)
63 #define _HW_SWTWIM_21(scl,k,...) _HW_SWTWIM_22(scl,HW_AD(__VA_ARGS__)) /* Get SDA def */
64 #define _HW_SWTWIM_22(...) _HW_SWTWIM_23(__VA_ARGS__)
65 #define _HW_SWTWIM_23(scl,sda,...) HW_B(_HW_SWTWIM_23,HW_A0 sda)(scl,sda,__VA_ARGS__)
66 #define _HW_SWTWIM_231(scl,sda,...) ,HW_SWTWIMASTER,HW_SWTWIMASTER(...): HW_A2 sda
67 #define _HW_SWTWIM_230(scl,sda,k,...) HW_BW(_HW_SWTWIM_3,bps,k)(HW_A1 scl,scl,sda,k,__VA_ARGS__)
68 
69 #define _HW_SWTWIM_30(sclo,scl,sda,k,...) _HW_SWTWIM_E(k,__VA_ARGS__)
70 #define _HW_SWTWIM_31(sclo,scl,sda,k,bps,g,...) HW_B(_HW_SWTWIM_4,g)(sclo,scl,sda,bps,g,__VA_ARGS__)
71 #define _HW_SWTWIM_40(sclo,scl,sda,bps,...) _HW_SWTWIM_E(k,__VA_ARGS__)
72 #define _HW_SWTWIM_41(sclo,scl,sda,bps,...) _swtwimaster,swtwimaster_##sclo,(-1,scl,sda,bps)
73 
74 //#define _HW_SWTWIM_E(k,...) HW_E(HW_EM_SY("HW_SWTWIM(scl,..., sda,..., bps,...)" (k,__VA_ARGS__)))
75 #define _HW_SWTWIM_E(...) ,HW_SWTWIMASTER(),HW_EM_SY("HW_SWTWIMASTER(scl,..., sda,..., bps,...)")
76 
77 
87 #define HW_DECLARE__swtwimaster , _hw_dcswtwimaster
88 
89 #define _hw_dcswtwimaster(o,a,...) HW_BV(_hw_dcswtwimaster,declare_,HW_A0(__VA_ARGS__),o)
90 #define _hw_dcswtwimaster0(v,...) HW_E(HW_EM_OVL(v,(weak)))
91 #define _hw_dcswtwimaster1(weak,o) \
92  \
93  extern uint8_t _hw_##o##__sr ; \
94  \
95  void weak _hw_##o##__delay ( ); \
96  void weak _hw_##o##_start ( ); \
97  void weak _hw_##o##_slar ( uint8_t ); \
98  void weak _hw_##o##_slaw ( uint8_t ); \
99  uint8_t weak _hw_##o##_write ( uint8_t ); \
100  uint8_t weak _hw_##o##_write ( uint8_t ); \
101  void weak _hw_##o##_stop ( ); \
102  uint8_t weak _hw_##o##_start_read_stop ( uint8_t ); \
103  void weak _hw_##o##_start_write_stop ( uint8_t, uint8_t )
104 
105 
115 #define HW_IMPLEMENT__swtwimaster , _hw_dfswtwimaster
116 
117 #define _hw_dfswtwimaster(o,a,scl,sda,bps,...) \
118  \
119  extern void _hw_##o##__delay ( ) ; \
120  \
121  uint8_t _hw_##o##__sr ; \
122  \
123  void _hw_##o##__delay ( ) { \
124  hw_waste_cycles( HW_SYSHZ / (2*bps) - 8 /* CALL+RET */); \
125  } \
126  \
127  void _hw_##o##_start ( ) { \
128  /* SDA goes low while SCL is high */ \
129  _hw( configure, sda, mode, digital_output ); \
130  _hw_##o##__delay(); \
131  _hw( configure, scl, mode, digital_output ); \
132  } \
133  \
134  void _hw_##o##_slar ( uint8_t sla ) { \
135  uint8_t ack = _hw_##o##_write( (sla<<1) + 1 ); \
136  if ( ack == 0 ) \
137  _hw_##o##__sr = 0x40 ; /* HW_TWI_MR_SLA_ACK */ \
138  else \
139  _hw_##o##__sr = 0x48 ; /* HW_TWI_MR_SLA_NACK */ \
140  } \
141  \
142  void _hw_##o##_slaw ( uint8_t sla ) { \
143  uint8_t ack = _hw_##o##_write( (sla<<1) + 0 ); \
144  if ( ack == 0 ) \
145  _hw_##o##__sr = 0x18 ; /* HW_TWI_MT_SLA_ACK */ \
146  else \
147  _hw_##o##__sr = 0x20 ; /* HW_TWI_MT_SLA_NACK */ \
148  } \
149  \
150  uint8_t _hw_##o##_write ( uint8_t byte ) { \
151  /* SDA can change while SCL is low */ \
152  for ( uint8_t bit=0x80 ; bit ; bit>>=1 ) { \
153  if ( (byte & bit) == 0 ) \
154  _hw( configure, sda, mode, digital_output ); \
155  else { \
156  _hw( configure, sda, mode, digital_input ); \
157  while ( !hw(read, sda) ) {} \
158  } \
159  _hw( configure, scl, mode, digital_input ); \
160  while ( !hw(read, scl) ) {} /* The slave can extend the SCL low period */ \
161  _hw_##o##__delay(); \
162  _hw( configure, scl, mode, digital_output ) ; \
163  } \
164  _hw( configure, sda, mode, digital_input ); \
165  _hw( configure, scl, mode, digital_input ); \
166  while ( !hw(read, scl) ) {} /* The slave can extend the SCL low period */ \
167  _hw_##o##__delay(); \
168  byte = hw(read, sda); \
169  _hw( configure, scl, mode, digital_output ) ; \
170  return byte ; \
171  } \
172  \
173  uint8_t _hw_##o##__read ( ) { \
174  /* SDA can change while SCL is low */ \
175  uint8_t data = 0 ; \
176  for ( uint8_t bit=0x80 ; bit ; bit>>=1 ) { \
177  _hw( configure, scl, mode, digital_input ); \
178  while ( !hw(read, scl) ) {} /* The slave can extend the SCL low period */ \
179  _hw_##o##__delay(); \
180  if ( hw(read, sda) != 0 ) \
181  data |= bit ; \
182  _hw( configure, scl, mode, digital_output ) ; \
183  _hw_##o##__delay(); \
184  } \
185  return data ; \
186  } \
187  \
188  uint8_t _hw_##o##_read_ack ( ) { \
189  uint8_t data = _hw_##o##__read(); \
190  _hw( configure, sda, mode, digital_output ) ; \
191  _hw( configure, scl, mode, digital_input ); \
192  _hw_##o##__delay(); \
193  while ( !hw(read, scl) ) {} /* The slave can extend the SCL low period */ \
194  _hw( configure, scl, mode, digital_output ) ; \
195  _hw_##o##__delay(); \
196  return data ; \
197  } \
198  \
199  uint8_t _hw_##o##_read_nack ( ) { \
200  uint8_t data = _hw_##o##__read(); \
201  _hw( configure, scl, mode, digital_input ); \
202  _hw_##o##__delay(); \
203  while ( !hw(read, scl) ) {} /* The slave can extend the SCL low period */ \
204  _hw( configure, scl, mode, digital_output ) ; \
205  _hw( configure, sda, mode, digital_output ) ; \
206  _hw_##o##__delay(); \
207  return data ; \
208  } \
209  \
210  void _hw_##o##_stop ( ) { \
211  /* SDA goes high while SCL is high */ \
212  if ( hw(read, sda) ) \
213  _hw( configure, sda, mode, digital_output ) ; \
214  _hw( configure, scl, mode, digital_input ); \
215  _hw_##o##__delay(); \
216  _hw( configure, sda, mode, digital_input ); \
217  } \
218  \
219  void _hw_##o##_start_write_stop ( uint8_t sla, uint8_t v ) \
220  { \
221  _hw_##o##_start(); \
222  _hw_##o##_slaw(sla); \
223  _hw_##o##_write(v); \
224  _hw_##o##_stop(); \
225  } \
226  \
227  uint8_t _hw_##o##_start_read_stop ( uint8_t sla ) \
228  { \
229  _hw_##o##_start(); \
230  _hw_##o##_slar(sla); \
231  uint8_t v = _hw_##o##_read_nack(); \
232  _hw_##o##_stop(); \
233  return v; \
234  } \
235  \
236  extern uint8_t hw_foo()
237 
238 
252 #define hw_configure__swtwimaster , _hw_cfswtwimaster
253 
254 /* SCL and SDA are set to 0 and then configured as digital_input /
255  * digital_output. External pullup resistors are required.
256  */
257 #define _hw_cfswtwimaster(o,a,scl,sda,bps,...) \
258  do{ \
259  _hwa_begin_(,); \
260  _hwa( configure, scl, mode, digital_input_floating ); \
261  _hwa( configure, sda, mode, digital_input_floating ); \
262  _hwa( write, scl, 0 ); \
263  _hwa( write, sda, 0 ); \
264  _hwa_commit_(,); \
265  }while(0)
266 
267 
268 #define hwa_configure__swtwimaster , _hwa_cfswtwimaster
269 
270 #define _hwa_cfswtwimaster(o,a,scl,sda,bps,...) \
271  do{ \
272  _hwa( configure, scl, mode, digital_input_floating ); \
273  _hwa( configure, sda, mode, digital_input_floating ); \
274  _hwa( write, scl, 0 ); \
275  _hwa( write, sda, 0 ); \
276  }while(0)
277 
278 
330 #define hw_xfr_start__swtwimaster , _hw_swtwimaster_start
331 #define _hw_swtwimaster_start(o,a,scl,sda,bps,...) _hw_##o##_start() HW_EOL(__VA_ARGS__)
332 
333 #define hw_xfr_slar__swtwimaster , _hw_swtwimaster_slar
334 #define _hw_swtwimaster_slar(o,a,scl,sda,bps,sla,...) _hw_##o##_slar(sla) HW_EOL(__VA_ARGS__)
335 
336 #define hw_xfr_slaw__swtwimaster , _hw_swtwimaster_slaw
337 #define _hw_swtwimaster_slaw(o,a,scl,sda,bps,sla,...) _hw_##o##_slaw(sla) HW_EOL(__VA_ARGS__)
338 
339 #define hw_xfr_read__swtwimaster , _hw_swtwimasterrd
340 #define _hw_swtwimasterrd(o,a,k,...) HW_BW(_hw_swtwimasterrdack,ack,k)(o,k,__VA_ARGS__,,)
341 #define _hw_swtwimasterrdack1(o,k,...) _hw_##o##_read_ack() HW_EOL(__VA_ARGS__)
342 #define _hw_swtwimasterrdack0(o,k,...) HW_BW(_hw_swtwimasterrdnack,nack,k)(o,k,__VA_ARGS__)
343 #define _hw_swtwimasterrdnack1(o,ok,k,...) _hw_##o##_read_nack() HW_EOL(__VA_ARGS__)
344 #define _hw_swtwimasterrdnack0(o,k,...) HW_E(HW_EM_XNIL(k,(ack,nack)))
345 
346 #define hw_xfr_write__swtwimaster , _hw_swtwimaster_write
347 #define _hw_swtwimaster_write(o,a,scl,sda,bps,data,...) _hw_##o##_write(data) HW_EOL(__VA_ARGS__)
348 
349 #define hw_xfr_stop__swtwimaster , _hw_swtwimaster_stop
350 #define _hw_swtwimaster_stop(o,a,scl,sda,bps,...) _hw_##o##_stop() HW_EOL(__VA_ARGS__)
351 
352 #define hw_stat__swtwimaster , _hw_swtwimaster_stat
353 #define _hw_swtwimaster_stat(o,a,scl,sda,bps,...) _hw_##o##__sr HW_EOL(__VA_ARGS__)