HWA
Bare metal programming with style
twia_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
35
#define hw_configure__twia , _hw_cftwia
36
#define _hw_cftwia( o,a, ... ) _hw_cftwia_( _hw, o, __VA_ARGS__,, )
37
38
#define hwa_configure__twia , _hwa_cftwia
39
#define _hwa_cftwia( o,a, ... ) _hw_cftwia_( _hwa, o, __VA_ARGS__,, )
40
41
/* Optionnal argument `bps`
42
* The 'TWEN' bit that makes the TWI take control of the I/O pins
43
* is set by the 'xfr_' actions.
44
*/
45
#define _hw_cftwia_(h,o,k,...) do { HW_BW(_hw_cftwiabps,bps,k)(h,o,k,__VA_ARGS__); }while(0)
46
#define _hw_cftwiabps0(h,o,k,...) HW_BW(_hw_cftwiasa,slave_address,k)(h,o,k,__VA_ARGS__)
47
#define _hw_cftwiabps1(h,o,k,v,...) HW_B(_hw_cftwiabps1,v)(h,o,v,__VA_ARGS__)
48
#define _hw_cftwiabps11(h,o,v,...) HW_E(HW_EM_VAM(bps))
49
#define _hw_cftwiabps10(h,o,v,k,...) \
50
uint32_t hw_bps=(v), br=0, psc=0, pscreg=0 ; \
51
float brpsc = ((1.0*HW_SYSHZ / hw_bps)-16)/2 ; \
52
if ( brpsc < 256 ) { \
53
psc = 1 ; \
54
pscreg = 0 ; \
55
br = (uint32_t)(0.5 + brpsc) ; \
56
if ( brpsc < 1 && HW_SYSHZ != hw_bps*(16+2*psc*br) ) \
57
HWA_E(HW_EM_XSO(v,bps));
/* value of bps unreachable */
\
58
} else if ( brpsc < 4*256 ) { \
59
psc = 4 ; \
60
pscreg = 1 ; \
61
br = (uint32_t)(0.5 + brpsc/4) ; \
62
} else if ( brpsc < 16*256 ) { \
63
psc = 16 ; \
64
pscreg = 2 ; \
65
br = (uint32_t)(0.5 + brpsc/16) ; \
66
} else if ( brpsc < 64*256 ) { \
67
psc = 64 ; \
68
pscreg = 3 ; \
69
br = (uint32_t)(0.5 + brpsc/64) ; \
70
} else \
71
HWA_E(HW_EM_XSO(v,bps));
/* value of bps too low */
\
72
h##_write( o, psc, pscreg ); \
73
h##_write( o, br, br ); \
74
HW_BW(_hw_cftwiasa,slave_address,k)(h,o,k,__VA_ARGS__)
75
76
/* Optionnal argument `slave_address`
77
*/
78
#define _hw_cftwiasa0(h,o,k,...) HW_BW(_hw_cftwiagc,general_call,k)(h,o,k,__VA_ARGS__)
79
#define _hw_cftwiasa1(h,o,k,v,...) HW_B(_hw_cftwiasa1,v)(h,o,v,__VA_ARGS__)
80
#define _hw_cftwiasa11(h,o,v,...) HW_E(HW_EM_VAM(slave_address))
81
#define _hw_cftwiasa10(h,o,v,k,...) \
82
uint8_t hw_sla=(v); \
83
if ( hw_sla < 0 || hw_sla > 127 ) \
84
HWA_E(HW_EM_VAL(v,slave_address,(0..127))); \
85
h##_write( o, sla, hw_sla ); \
86
HW_BW(_hw_cftwiagc,general_call,k)(h,o,k,__VA_ARGS__)
87
88
/* Optionnal argument `general_call`
89
*/
90
#define _hw_cftwiagc0 _hw_cftwiasam
91
#define _hw_cftwiagc1(h,o,k,v,...) HW_BV(_hw_cftwiagc1,state_,v,h,o) (h,o,__VA_ARGS__) // PUSH
92
#define _hw_cftwiagc10(v,...) HW_E(HW_EM_VOAST(v,general_call)) HW_EAT // POP
93
#define _hw_cftwiagc11(v,n,h,o) h##_write( o, gce, v); _hw_cftwiasam // POP
94
95
96
/* Optionnal argument `slave_address_mask`
97
*/
98
#define _hw_cftwiasam(h,o,k,...) HW_BW(_hw_cftwiasam,slave_address_mask,k)(h,o,k,__VA_ARGS__)
99
#define _hw_cftwiasam0(h,o,...) HW_EOL(__VA_ARGS__)
100
#define _hw_cftwiasam1(h,o,k,v,...) HW_B(_hw_cftwia_vslam_,v)(h,o,v,__VA_ARGS__)
101
#define _hw_cftwiasam11(h,o,v,...) HW_E(HW_EM_VAM(slave_address_mask))
102
#define _hw_cftwiasam10(h,o,v,...) \
103
uint8_t hw_sam=(v); \
104
if ( hw_sam < 0 || hw_sam > 127 ) \
105
HWA_E(HW_EM_VAL(v,slave_address_mask,(0..127))); \
106
h##_write( o, slam, hw_sam ) HW_EOL(__VA_ARGS__)
107
108
109
/* Submitted by gotnone via GitHub */
121
#define hw_turn__twia , _hw_tntwia_
122
#define hwa_turn__twia , _hwa_tntwia_
123
124
#define _hw_tntwia_(o,a, v, ...) HW_B(_hw_tntwia__,_hw_state_##v)(_hw,o,v,__VA_ARGS__)
125
#define _hwa_tntwia_(o,a, v, ...) HW_B(_hw_tntwia__,_hw_state_##v)(_hwa,o,v,__VA_ARGS__)
126
#define _hw_tntwia__0(h,o, v, ...) HW_E(HW_EM_ST(v))
127
#define _hw_tntwia__1(h,o, v, ...) h##_write(o, en, HW_A1(_hw_state_##v)) HW_EOL(__VA_ARGS__)
128
129
161
/* TODO:
162
* * create a relative '(TWI,bus)' to handle TWI bus operations?
163
* * use get/put for bus transfers?
164
*
165
* FIXME: could use a function 'hw_id(uint8_t v){ return v; }' to check the
166
* presence of a value so that '*ptr' would be OK?
167
* --> Could use surrounding parentheses.
168
*
169
* FIXME: bus_xfer_ack / bus_xfer_nack actions?
170
*/
171
#define hw_xfr_start__twia , _hw_twia_txstart
172
#define _hw_twia_txstart(o,a,k,...) HW_BW(_hw_twiaend,irq,k)(o,ifenstart,k,__VA_ARGS__)
173
174
175
#define hw_xfr_stop__twia , _hw_twia_txstop
176
#define _hw_twia_txstop(o,a,k,...) HW_BW(_hw_twiaend,irq,k)(o,ifenstop,k,__VA_ARGS__)
177
178
179
#define hw_xfr_slaw__twia , _hw_twia_txslaw
180
#define _hw_twia_txslaw(o,a,v,k,...) \
181
do{ \
182
uint8_t hw_sla=(v); \
183
if ( hw_sla > 127 ) \
184
HWA_E(HW_EM_VAL(v,slave address,(0..127))); \
185
_hw_write(o,dr,(hw_sla<<1)+0); \
186
HW_BW(_hw_twiaend,irq,k)(o,ifen,k,__VA_ARGS__); \
187
}while(0)
188
189
190
#define hw_xfr_slar__twia , _hw_twia_txslar
191
#define _hw_twia_txslar(o,a,v,k,...) \
192
do{ \
193
uint8_t hw_sla=(v); \
194
if ( hw_sla > 127 ) \
195
HWA_E(HW_EM_VAL(v,slave address,(0..127))); \
196
_hw_write(o,dr,(hw_sla<<1)+1); \
197
HW_BW(_hw_twiaend,irq,k)(o,ifen,k,__VA_ARGS__); \
198
}while(0)
199
200
#define hw_xfr_write__twia , _hw_twiawr
201
#define _hw_twiawr(o,a,v,k,...) \
202
do { \
203
_hw_write(o,dr,(v)); \
204
HW_BW(_hw_twiaend,irq,k)(o,ifen,k,__VA_ARGS__); \
205
} while(0)
206
207
208
#define hw_xfr_read__twia , _hw_twiard
209
#define _hw_twiard(o,a,k,...) HW_BW(_hw_twiardack,ack,k)(o,k,__VA_ARGS__,,)
210
#define _hw_twiardack1(o,ok,k,...) HW_BW(_hw_twiaend,irq,k)(o,ifenack,k,__VA_ARGS__)
211
#define _hw_twiardack0(o,k,...) HW_BW(_hw_twiardnack,nack,k)(o,k,__VA_ARGS__)
212
#define _hw_twiardnack1(o,ok,k,...) HW_BW(_hw_twiaend,irq,k)(o,ifen,k,__VA_ARGS__)
213
#define _hw_twiardnack0(o,k,...) HW_E(HW_EM_XNIL(k,(ack,nack)))
214
215
216
#define _hw_twiaend0(o,v,...) _hw_write(o,cr,_hw_twia_cr_##v) HW_EOL(__VA_ARGS__)
217
#define _hw_twiaend1(o,v,...) _hw_write(o,cr,_hw_twia_cr_##v##ie) HW_EOL(__VA_ARGS__)
218
219
229
#define hw_read__twia , _hw_rdtwia
230
#define _hw_rdtwia(o,a,...) _hw_read(o,dr) HW_EOL(__VA_ARGS__)
231
232
233
248
#define hw_stat__twia , _hw_stat_twia
249
#define _hw_stat_twia(o,a,...) (_hw_read(o,sr)&0xF8) HW_EOL(__VA_ARGS__)
250
251
257
#define HW_TWI_START 0x08
258
262
#define HW_TWI_REP_START 0x10
263
268
#define HW_TWI_MT_SLA_ACK 0x18
269
273
#define HW_TWI_MT_SLA_NACK 0x20
274
278
#define HW_TWI_MT_DATA_ACK 0x28
279
283
#define HW_TWI_MT_DATA_NACK 0x30
284
288
#define HW_TWI_MT_ARB_LOST 0x38
289
294
#define HW_TWI_MR_ARB_LOST 0x38
295
299
#define HW_TWI_MR_SLA_ACK 0x40
300
304
#define HW_TWI_MR_SLA_NACK 0x48
305
309
#define HW_TWI_MR_DATA_ACK 0x50
310
314
#define HW_TWI_MR_DATA_NACK 0x58
315
320
#define HW_TWI_SR_SLA_ACK 0x60
321
325
#define HW_TWI_SR_ARB_LOST_SLA_ACK 0x68
326
330
#define HW_TWI_SR_GCALL_ACK 0x70
331
336
#define HW_TWI_SR_ARB_LOST_GCALL_ACK 0x78
337
341
#define HW_TWI_SR_DATA_ACK 0x80
342
346
#define HW_TWI_SR_DATA_NACK 0x88
347
351
#define HW_TWI_SR_GCALL_DATA_ACK 0x90
352
356
#define HW_TWI_SR_GCALL_DATA_NACK 0x98
357
361
#define HW_TWI_SR_STOP 0xA0
362
367
#define HW_TWI_ST_SLA_ACK 0xA8
368
372
#define HW_TWI_ST_ARB_LOST_SLA_ACK 0xB0
373
377
#define HW_TWI_ST_DATA_ACK 0xB8
378
382
#define HW_TWI_ST_DATA_NACK 0xC0
383
387
#define HW_TWI_ST_LAST_DATA 0xC8
388
393
#define HW_TWI_NO_INFO 0xF8
394
398
#define HW_TWI_BUS_ERROR 0x00
399
400
401
402
/*******************************************************************************
403
* *
404
* Context management *
405
* *
406
*******************************************************************************/
407
408
#define _hwa_setup__twia(o,a) \
409
_hwa_setup_r( o, br ); \
410
_hwa_setup_r( o, cr ); \
411
_hwa_setup_r( o, sr ); \
412
_hwa_setup_r( o, ar ); \
413
_hwa_setup_r( o, amr )
414
415
416
#define _hwa_init__twia(o,a) \
417
_hwa_init_r( o, br, 0x00 ); \
418
_hwa_init_r( o, cr, 0x00 ); \
419
_hwa_init_r( o, sr, 0xF8 ); \
420
_hwa_init_r( o, ar, 0xFE ); \
421
_hwa_init_r( o, amr, 0x00 )
422
423
424
#define _hwa_commit__twia(o,a) \
425
_hwa_commit_r( o, br ); \
426
_hwa_commit_r( o, cr ); \
427
_hwa_commit_r( o, sr ); \
428
_hwa_commit_r( o, ar ); \
429
_hwa_commit_r( o, amr )
430
431
461
/*******************************************************************************
462
* *
463
* Implementation *
464
* *
465
*******************************************************************************/
466
467
#define HW_DECLARE__twia , _hw_declare_twia
468
469
#define _hw_declare_twia(o,a,...) \
470
void _hw_##o##_start_write_stop ( uint8_t sla, uint8_t v ); \
471
uint8_t _hw_##o##_start_read_stop ( uint8_t sla ) HW_EOL(__VA_ARGS__)
472
473
474
#define HW_IMPLEMENT__twia , _hw_define_twia
475
476
#define _hw_define_twia(o,a,...) \
477
void _hw_##o##_start_write_stop ( uint8_t sla, uint8_t v ) \
478
{ \
479
hw( xfr_start, o ); \
480
while( !hw( read, (o,irq) ) ) {} \
481
hw( xfr_slaw, o, sla & 0x7F ); \
482
while( !hw( read, (o,irq) ) ) {} \
483
hw( xfr_write, o, v ); \
484
while( !hw( read, (o,irq) ) ) {} \
485
hw( xfr_stop, o ); \
486
} \
487
\
488
uint8_t _hw_##o##_start_read_stop ( uint8_t sla ) \
489
{ \
490
hw( xfr_start, o ); \
491
while( !hw( read, (o,irq) ) ) {} \
492
hw( xfr_slaw, o, sla & 0x7F ); \
493
while( !hw( read, (o,irq) ) ) {} \
494
hw( xfr_read, o, nack ); \
495
while( !hw( read, (o,irq) ) ) {} \
496
hw( xfr_stop, o ); \
497
\
498
return hw( read, o ); \
499
} \
500
\
501
extern uint8_t hw_foo() \
502
\
503
HW_EOL(__VA_ARGS__)
Generated for HWA by
1.8.6