4
4
gpio:: { InputPin , InputSignal , OutputPin , OutputSignal } ,
5
5
target:: { i2c, DPORT , I2C0 , I2C1 } ,
6
6
} ,
7
- core:: ops:: Deref ,
7
+ core:: { ops:: Deref , ptr } ,
8
8
} ;
9
9
10
10
const DPORT_BASE_ADDR : u32 = 0x3FF4_0000 ;
@@ -231,6 +231,7 @@ where
231
231
base_addr + FIFO_OFFSET
232
232
}
233
233
234
+ // TODO: Enable ACK checks and return error if ACK check fails
234
235
pub fn write ( & mut self , addr : u8 , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
235
236
// Reset FIFO
236
237
self . reset_fifo ( ) ;
@@ -241,16 +242,16 @@ where
241
242
. bits ( Command :: new ( Opcode :: RSTART , false , false , false , None ) . into ( ) )
242
243
} ) ;
243
244
244
- // Load bytes into FIFO
245
+ // Load into FIFO
245
246
unsafe {
246
247
let fifo_addr = self . fifo_addr ( OperationType :: WRITE ) as * mut u8 ;
247
248
248
249
// Address
249
- core :: ptr:: write_volatile ( fifo_addr, addr << 1 | OperationType :: WRITE as u8 ) ;
250
+ ptr:: write_volatile ( fifo_addr, addr << 1 | OperationType :: WRITE as u8 ) ;
250
251
251
252
// Data
252
253
for byte in bytes {
253
- core :: ptr:: write_volatile ( fifo_addr, * byte) ;
254
+ ptr:: write_volatile ( fifo_addr, * byte) ;
254
255
}
255
256
}
256
257
@@ -285,6 +286,7 @@ where
285
286
Ok ( ( ) )
286
287
}
287
288
289
+ // TODO: Enable ACK checks and return error if ACK check fails
288
290
pub fn read ( & mut self , addr : u8 , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
289
291
dprintln ! ( "starting I2C read" ) ;
290
292
assert ! ( buffer. len( ) > 1 ) ; //TODO: temporary, just simplifying the logic during implementation
@@ -300,7 +302,7 @@ where
300
302
301
303
// Load address into FIFO
302
304
let fifo_addr = self . fifo_addr ( OperationType :: READ ) as * mut u8 ;
303
- unsafe { core :: ptr:: write_volatile ( fifo_addr, addr << 1 | OperationType :: READ as u8 ) } ;
305
+ unsafe { ptr:: write_volatile ( fifo_addr, addr << 1 | OperationType :: READ as u8 ) } ;
304
306
305
307
// WRITE command
306
308
self . 0 . comd1 . write ( |w| unsafe {
@@ -352,20 +354,178 @@ where
352
354
// Read bytes from FIFO
353
355
dprintln ! ( "rxfifo: {:?}" , self . 0 . sr. read( ) . rxfifo_cnt( ) . bits( ) ) ;
354
356
for byte in buffer. iter_mut ( ) {
355
- * byte = unsafe { core :: ptr:: read_volatile ( fifo_addr) } ;
357
+ * byte = unsafe { ptr:: read_volatile ( fifo_addr) } ;
356
358
}
357
359
dprintln ! ( "{:?}" , & buffer) ;
358
360
359
361
Ok ( ( ) )
360
362
}
361
363
364
+ // TODO: Enable ACK checks and return error if ACK check fails
362
365
pub fn write_then_read (
363
366
& mut self ,
364
367
addr : u8 ,
365
368
bytes : & [ u8 ] ,
366
369
buffer : & mut [ u8 ] ,
367
370
) -> Result < ( ) , Error > {
368
- unimplemented ! ( )
371
+ // Reset FIFO
372
+ self . reset_fifo ( ) ;
373
+
374
+ // START
375
+ self . 0 . comd0 . write ( |w| unsafe {
376
+ w. command0 ( ) . bits (
377
+ Command :: new (
378
+ Opcode :: RSTART ,
379
+ false ,
380
+ false ,
381
+ false ,
382
+ None ,
383
+ ) . into ( )
384
+ )
385
+ } ) ;
386
+
387
+ // load into FIFO
388
+ let fifo_addr = self . fifo_addr ( OperationType :: WRITE ) as * mut u8 ;
389
+ unsafe {
390
+ // load address
391
+ ptr:: write_volatile ( fifo_addr, addr << 1 | OperationType :: WRITE as u8 ) ;
392
+
393
+ // load data
394
+ for byte in bytes {
395
+ ptr:: write_volatile ( fifo_addr, * byte) ;
396
+ }
397
+ }
398
+
399
+ // WRITE
400
+ self . 0 . comd1 . write ( |w| unsafe {
401
+ w. command1 ( ) . bits (
402
+ Command :: new (
403
+ Opcode :: WRITE ,
404
+ false ,
405
+ true ,
406
+ true ,
407
+ Some ( 1 + bytes. len ( ) as u8 ) ,
408
+ ) . into ( ) ,
409
+ )
410
+ } ) ;
411
+
412
+ // repeat START
413
+ self . 0 . comd2 . write ( |w| unsafe {
414
+ w. command2 ( ) . bits (
415
+ Command :: new (
416
+ Opcode :: RSTART ,
417
+ false ,
418
+ false ,
419
+ false ,
420
+ None ,
421
+ ) . into ( ) ,
422
+ )
423
+ } ) ;
424
+
425
+ // WRITE slave address
426
+ self . 0 . comd3 . write ( |w| unsafe {
427
+ w. command3 ( ) . bits (
428
+ Command :: new (
429
+ Opcode :: WRITE ,
430
+ false ,
431
+ true ,
432
+ true ,
433
+ Some ( 1 ) ,
434
+ ) . into ( ) ,
435
+ )
436
+ } ) ;
437
+
438
+ // load slave address into FIFO
439
+ unsafe { ptr:: write_volatile ( fifo_addr, addr << 1 | OperationType :: READ as u8 ) } ;
440
+
441
+ if buffer. len ( ) > 1 {
442
+ // READ first n - 1 bytes
443
+ self . 0 . comd4 . write ( |w| unsafe {
444
+ w. command4 ( ) . bits (
445
+ Command :: new (
446
+ Opcode :: READ ,
447
+ true ,
448
+ false ,
449
+ false ,
450
+ Some ( buffer. len ( ) as u8 - 1 ) ,
451
+ ) . into ( )
452
+ )
453
+ } ) ;
454
+
455
+ // READ last byte
456
+ self . 0 . comd5 . write ( |w| unsafe {
457
+ w. command5 ( ) . bits (
458
+ Command :: new (
459
+ Opcode :: READ ,
460
+ false ,
461
+ false ,
462
+ false ,
463
+ Some ( 1 ) ,
464
+ ) . into ( )
465
+ )
466
+ } ) ;
467
+
468
+ // STOP
469
+ self . 0 . comd6 . write ( |w| unsafe {
470
+ w. command6 ( ) . bits (
471
+ Command :: new (
472
+ Opcode :: STOP ,
473
+ false ,
474
+ false ,
475
+ false ,
476
+ None ,
477
+ ) . into ( ) ,
478
+ )
479
+ } ) ;
480
+ } else {
481
+ // READ byte
482
+ self . 0 . comd4 . write ( |w| unsafe {
483
+ w. command4 ( ) . bits (
484
+ Command :: new (
485
+ Opcode :: READ ,
486
+ false ,
487
+ false ,
488
+ false ,
489
+ Some ( 1 ) ,
490
+ ) . into ( )
491
+ )
492
+ } ) ;
493
+
494
+ // STOP
495
+ self . 0 . comd5 . write ( |w| unsafe {
496
+ w. command5 ( ) . bits (
497
+ Command :: new (
498
+ Opcode :: STOP ,
499
+ false ,
500
+ false ,
501
+ false ,
502
+ None ,
503
+ ) . into ( ) ,
504
+ )
505
+ } ) ;
506
+ }
507
+
508
+ // Start transmission
509
+ self . 0 . ctr . modify ( |_, w| w. trans_start ( ) . set_bit ( ) ) ;
510
+
511
+ // Busy wait for all commands to be marked as done
512
+ while self . 0 . comd0 . read ( ) . command0_done ( ) . bit ( ) != true { }
513
+ while self . 0 . comd1 . read ( ) . command1_done ( ) . bit ( ) != true { }
514
+ while self . 0 . comd2 . read ( ) . command2_done ( ) . bit ( ) != true { }
515
+ while self . 0 . comd3 . read ( ) . command3_done ( ) . bit ( ) != true { }
516
+ while self . 0 . comd4 . read ( ) . command4_done ( ) . bit ( ) != true { }
517
+ while self . 0 . comd5 . read ( ) . command5_done ( ) . bit ( ) != true { }
518
+ if buffer. len ( ) > 1 {
519
+ while self . 0 . comd6 . read ( ) . command6_done ( ) . bit ( ) != true { }
520
+ }
521
+
522
+ // read bytes from FIFO
523
+ let fifo_addr = self . fifo_addr ( OperationType :: READ ) as * mut u8 ;
524
+ for byte in buffer. iter_mut ( ) {
525
+ * byte = unsafe { ptr:: read_volatile ( fifo_addr) } ;
526
+ }
527
+
528
+ Ok ( ( ) )
369
529
}
370
530
371
531
/// Return the raw interface to the underlying I2C peripheral
@@ -430,6 +590,7 @@ pub enum Error {
430
590
}
431
591
432
592
/// I2C Command
593
+ /// TODO: turn this into an enum instead
433
594
struct Command {
434
595
/// Opcode of the command
435
596
opcode : Opcode ,
@@ -438,8 +599,9 @@ struct Command {
438
599
/// This bit is to set an expected ACK value for the transmitter
439
600
ack_exp : bool ,
440
601
/// When transmitting a byte, this bit enables checking the ACK value received against the ack_exp value
441
- ack_en : bool ,
442
- /// Length of data to be read or written, maximum length of 255, minimum of 1
602
+ ack_check_en : bool ,
603
+ /// Length of data (in bytes) to be read or written. The maximum length is 255, while the
604
+ /// minimum is 1. When the opcode is RSTART, STOP, or END, this value is meaningless.
443
605
length : Option < u8 > ,
444
606
}
445
607
@@ -449,14 +611,14 @@ impl Command {
449
611
opcode : Opcode ,
450
612
ack_value : bool ,
451
613
ack_exp : bool ,
452
- ack_en : bool ,
614
+ ack_check_en : bool ,
453
615
length : Option < u8 > ,
454
616
) -> Self {
455
617
Self {
456
618
opcode,
457
619
ack_value,
458
620
ack_exp,
459
- ack_en ,
621
+ ack_check_en ,
460
622
length,
461
623
}
462
624
}
@@ -469,7 +631,7 @@ impl From<Command> for u16 {
469
631
None => 0 ,
470
632
} ;
471
633
472
- if c. ack_en {
634
+ if c. ack_check_en {
473
635
cmd |= 1 << 8 ;
474
636
} else {
475
637
cmd &= !( 1 << 8 ) ;
0 commit comments