1
- use {
2
- crate :: {
3
- dprintln,
4
- target:: { self , i2c, GPIO , I2C0 , I2C1 , IO_MUX } ,
5
- } ,
6
- core:: { fmt:: Write , ops:: Deref } ,
7
- } ;
1
+ use core:: ops:: Deref ;
2
+
3
+ use crate :: target:: { self , i2c, I2C0 , I2C1 } ;
4
+
5
+ #[ derive( Clone , Copy , Debug ) ]
6
+ pub struct PinConfig {
7
+ pub pin_num : u32 ,
8
+ pub pullup : bool ,
9
+ }
8
10
9
11
unsafe fn gpio_matrix_out ( gpio : u32 , signal_idx : u32 , out_inverted : bool , oen_inverted : bool ) {
10
12
let base_address = 0x3FF44530 ; // GPIO_FUNC0_OUT_SEL_CFG_REG
@@ -13,31 +15,31 @@ unsafe fn gpio_matrix_out(gpio: u32, signal_idx: u32, out_inverted: bool, oen_in
13
15
let mut value = signal_idx;
14
16
15
17
if out_inverted {
16
- value = value | 0b100_0000_0000 ;
18
+ value |= 1 << 9 ;
17
19
}
18
20
19
21
if oen_inverted {
20
- value = value | 0b1_0000_0000_0000 ;
22
+ value |= 1 << 11 ;
21
23
}
22
24
23
- * store_address = value;
25
+ core :: ptr :: write_volatile ( store_address, value) ;
24
26
}
25
27
26
28
unsafe fn gpio_matrix_in ( gpio : u32 , signal_idx : u32 , inverted : bool ) {
27
29
let base_address = 0x3FF44130 ; // GPIO_FUNC0_IN_SEL_CFG_REG
28
- let store_address = ( base_address + 4 * gpio ) as * mut u32 ;
30
+ let store_address = ( base_address + 4 * signal_idx ) as * mut u32 ;
29
31
30
- let mut value = signal_idx ;
32
+ let mut value = gpio ;
31
33
32
34
if inverted {
33
- value = value | 64 ;
35
+ value |= 1 << 6 ;
34
36
}
35
37
36
38
if gpio != 52 {
37
- value = value | 128 ;
39
+ value |= 1 << 7 ;
38
40
}
39
41
40
- * store_address = value;
42
+ core :: ptr :: write_volatile ( store_address, value) ;
41
43
}
42
44
43
45
pub struct I2C < T > ( T ) ;
@@ -46,78 +48,35 @@ impl<T> I2C<T>
46
48
where
47
49
T : Instance ,
48
50
{
49
- pub fn new < SDA , SCL > ( i2c : T , _pins : Pins < SDA , SCL > , dport : & mut target:: DPORT ) -> Self {
51
+ pub fn new (
52
+ i2c : T ,
53
+ sda : PinConfig ,
54
+ scl : PinConfig ,
55
+ clk_speed : u32 ,
56
+ dport : & mut target:: DPORT ,
57
+ ) -> Self {
50
58
let mut i2c = Self ( i2c) ;
51
59
52
- // i2c_set_pin
53
- // TEMPORARY UNTIL I CORRECTLY IMPLEMENT PINS
54
- // manually set sda to gpio4 and scl to gpio15
55
- unsafe {
56
- let gpio = & * GPIO :: ptr ( ) ;
57
- let iomux = & * IO_MUX :: ptr ( ) ;
58
-
59
- // sda
60
- {
61
- // gpio_set_level(sda_io_num, I2C_IO_INIT_LEVEL);
62
- gpio. pin4 . write ( |w| w. bits ( 1 << 4 ) ) ;
63
-
64
- // PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[sda_io_num], PIN_FUNC_GPIO);
65
- iomux. gpio4 . modify ( |_, w| w. mcu_sel ( ) . bits ( 2 ) ) ;
66
-
67
- // gpio_set_direction(sda_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
68
- iomux
69
- . gpio4
70
- . modify ( |_, w| w. fun_ie ( ) . set_bit ( ) . mcu_oe ( ) . set_bit ( ) ) ;
71
-
72
- // gpio_set_pull_mode(sda_io_num, GPIO_PULLUP_ONLY);
73
- iomux
74
- . gpio4
75
- . modify ( |_, w| w. fun_wpd ( ) . clear_bit ( ) . fun_wpu ( ) . set_bit ( ) ) ;
76
-
77
- // gpio_matrix_out(sda_io_num, sda_out_sig, 0, 0);
78
- gpio_matrix_out ( 4 , 30 , false , false ) ;
79
- // gpio_matrix_in(sda_io_num, sda_in_sig, 0);
80
- gpio_matrix_in ( 4 , 30 , false ) ;
81
- }
82
-
83
- // scl
84
- {
85
- // gpio_set_level(scl_io_num, I2C_IO_INIT_LEVEL);
86
- gpio. pin15 . write ( |w| w. bits ( 1 << 15 ) ) ;
87
-
88
- // PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[scl_io_num], PIN_FUNC_GPIO);
89
- iomux. mtdo . modify ( |_, w| w. mcu_sel ( ) . bits ( 2 ) ) ;
60
+ // i2c_config_t documentation says that clock speed must be no higher than 1 MHz
61
+ assert ! ( clk_speed <= 1_000_000 ) ;
90
62
91
- // gpio_set_direction(scl_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
92
- iomux
93
- . mtdo
94
- . modify ( |_, w| w. fun_ie ( ) . set_bit ( ) . mcu_oe ( ) . set_bit ( ) ) ;
63
+ // sda
64
+ unsafe { gpio_matrix_out ( sda. pin_num , 30 , false , false ) } ;
65
+ unsafe { gpio_matrix_in ( sda. pin_num , 30 , false ) } ;
95
66
96
- // gpio_matrix_out(scl_io_num, scl_out_sig, 0, 0);
97
- gpio_matrix_out ( 15 , 29 , false , false ) ;
67
+ // scl
68
+ unsafe { gpio_matrix_out ( scl. pin_num , 29 , false , false ) } ;
69
+ unsafe { gpio_matrix_in ( scl. pin_num , 29 , false ) } ;
98
70
99
- // gpio_matrix_in(scl_io_num, scl_in_sig, 0);
100
- gpio_matrix_in ( 15 , 29 , false ) ;
101
-
102
- // gpio_set_pull_mode(scl_io_num, GPIO_PULLUP_ONLY);
103
- iomux
104
- . mtdo
105
- . modify ( |_, w| w. fun_wpd ( ) . clear_bit ( ) . fun_wpu ( ) . set_bit ( ) ) ;
106
- }
107
- }
108
-
109
- // i2c_hw_enable(i2c_num);
71
+ // i2c_hw_enable
110
72
i2c. reset ( dport) ;
111
73
i2c. enable ( dport) ;
112
74
113
- // i2c_hal_disable_intr_mask(&(i2c_context[i2c_num].hal), 0x3FFF);
114
- i2c. 0 . int_ena . write ( | w| unsafe { w. bits ( 0 ) } ) ;
115
- // i2c_hal_clr_intsts_mask(&(i2c_context[i2c_num].hal), 0x3FFF);
116
- i2c. 0 . int_clr . write ( | w| unsafe { w. bits ( 0x3FFF ) } ) ;
75
+ // i2c_hal_disable_intr_mask
76
+ i2c. 0 . int_ena . modify ( |_ , w| unsafe { w. bits ( 0 ) } ) ;
77
+ // i2c_hal_clr_intsts_mask
78
+ i2c. 0 . int_clr . modify ( |_ , w| unsafe { w. bits ( 0x3FFF ) } ) ;
117
79
118
- //i2c_ll_master_init(hal->dev);
119
- //MSB
120
- //i2c_ll_set_data_mode(hal->dev, I2C_DATA_MODE_MSB_FIRST, I2C_DATA_MODE_MSB_FIRST);
121
80
i2c. 0 . ctr . modify ( |_, w| unsafe {
122
81
w. bits ( 0 )
123
82
. ms_mode ( )
@@ -132,14 +91,11 @@ where
132
91
. clear_bit ( )
133
92
} ) ;
134
93
135
- //i2c_ll_set_fifo_mode(hal->dev, true);
136
- i2c. 0 . fifo_conf . modify ( |_, w| w. nonfifo_en ( ) . clear_bit ( ) ) ;
137
-
138
94
i2c. reset_fifo ( ) ;
139
95
140
96
i2c. set_filter ( Some ( 7 ) , Some ( 7 ) ) ;
141
97
142
- i2c. set_frequency ( 200_000 ) ;
98
+ i2c. set_frequency ( clk_speed ) ;
143
99
144
100
i2c. 0 . ctr . modify ( |_, w| w. clk_en ( ) . set_bit ( ) ) ;
145
101
@@ -170,8 +126,6 @@ where
170
126
171
127
/// Sets the filter with a supplied threshold in clock cycles for which a pulse must be present to pass the filter
172
128
fn set_filter ( & mut self , sda_threshold : Option < u8 > , scl_threshold : Option < u8 > ) {
173
- // i2c_hal_set_filter(&(i2c_context[i2c_num].hal), 7);
174
-
175
129
match sda_threshold {
176
130
Some ( threshold) => {
177
131
self . 0
@@ -239,65 +193,61 @@ where
239
193
}
240
194
}
241
195
196
+ /// Write `bytes` to an I2C device at address `addr`
242
197
pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
243
- dprintln ! ( "addr: {:?}, bytes: {:?}" , addr , & bytes ) ;
244
-
245
- // TODO: Use bytes.chunk(255) to remove this limitation
246
- assert ! ( bytes . len ( ) < 255 ) ;
198
+ //TODO: Confirm this hardware limit
199
+ if bytes . len ( ) > 254 {
200
+ return Err ( Error :: Transmit ) ;
201
+ }
247
202
248
203
// Address for I2C0 (obviously this shouldn't make it into the HAL)
249
204
let fifo_addr = 0x6001301c as * mut u8 ;
250
205
251
- // Clear FIFO
252
- self . 0 . fifo_conf . modify ( |_, w| w. tx_fifo_rst ( ) . set_bit ( ) ) ;
253
- self . 0 . fifo_conf . modify ( |_, w| w. tx_fifo_rst ( ) . clear_bit ( ) ) ;
254
- self . 0 . fifo_conf . modify ( |_, w| w. rx_fifo_rst ( ) . set_bit ( ) ) ;
255
- self . 0 . fifo_conf . modify ( |_, w| w. rx_fifo_rst ( ) . clear_bit ( ) ) ;
206
+ // Reset FIFO
207
+ self . reset_fifo ( ) ;
256
208
257
209
// RSTART command
258
210
self . 0 . comd0 . write ( |w| unsafe { w. command0 ( ) . bits ( 0 ) } ) ;
259
211
260
- // Address byte
212
+ // Load data into hardware FIFO buffer
261
213
unsafe {
262
- * ( fifo_addr ) = addr << 1 | 0 ;
263
- }
264
- // Data bytes
265
- for byte in bytes {
266
- unsafe {
267
- * ( fifo_addr) = * byte;
214
+ // Address byte
215
+ * fifo_addr = addr << 1 | 0 ;
216
+
217
+ // Data bytes
218
+ for byte in bytes {
219
+ * fifo_addr = * byte;
268
220
}
269
221
}
270
222
271
223
// WRITE command
272
- self . 0 . comd1 . write ( |w| unsafe {
273
- w . command1 ( )
274
- . bits ( 0b00_1100_0000_0000 | ( 1 + bytes . len ( ) as u8 ) as u16 )
275
- } ) ;
224
+ let length = ( 1 + bytes . len ( ) as u8 ) as u16 ;
225
+ self . 0
226
+ . comd1
227
+ . write ( |w| unsafe { w . command1 ( ) . bits ( 0b00_1100_0000_0000 | length ) } ) ;
276
228
277
229
// STOP command
278
230
self . 0
279
231
. comd2
280
232
. write ( |w| unsafe { w. command2 ( ) . bits ( 0b01_1000_0000_0000 ) } ) ;
281
233
282
- dprintln ! ( "txfifo_cnt: {:?}" , self . 0 . sr. read( ) . txfifo_cnt( ) . bits( ) ) ;
283
-
284
234
// Start transmission
285
235
self . 0 . ctr . modify ( |_, w| w. trans_start ( ) . set_bit ( ) ) ;
286
236
237
+ // Wait for commands to complete
287
238
while self . 0 . comd0 . read ( ) . command0_done ( ) . bit ( ) != true { }
288
- dprintln ! ( "start" ) ;
289
239
while self . 0 . comd1 . read ( ) . command1_done ( ) . bit ( ) != true { }
290
- dprintln ! ( "write" ) ;
291
240
while self . 0 . comd2 . read ( ) . command2_done ( ) . bit ( ) != true { }
292
- dprintln ! ( "stop" ) ;
293
241
294
242
Ok ( ( ) )
295
243
}
296
244
297
- pub fn read ( & mut self , _addr : u8 , _bytes : & mut [ u8 ] ) -> Result < ( ) , Error > {
245
+ /// Read into `buffer` from an I2C device at address `addr`
246
+ pub fn read ( & mut self , _addr : u8 , _buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
298
247
unimplemented ! ( )
299
248
}
300
249
250
+ /// Write `bytes` to an I2C device at address `addr` whilst reading received data into `buffer` without triggering a STOP condition
301
251
pub fn write_then_read (
302
252
& mut self ,
303
253
_addr : u8 ,
@@ -353,15 +303,6 @@ where
353
303
}
354
304
}
355
305
356
- /// Pins used by the I2C interface
357
- ///
358
- /// Note that any two pins may be used
359
- /// TODO: enforce this in the type system
360
- pub struct Pins < SDA , SCL > {
361
- pub sda : SDA ,
362
- pub scl : SCL ,
363
- }
364
-
365
306
#[ derive( Debug ) ]
366
307
pub enum Error {
367
308
Transmit ,
0 commit comments