OpenCores
URL https://opencores.org/ocsvn/ssbcc/ssbcc/trunk

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [example/] [i2c/] [lib_i2c.s] - Blame information for rev 11

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sinclairrf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;
3 5 sinclairrf
; Copyright 2012, 2014, Sinclair R.F., Inc.
4 2 sinclairrf
;
5
; Major I2C functions:
6 5 sinclairrf
;   i2c_send_start      ( - )           send the start condition
7
;   i2c_send_restart    ( - )           send a restart after ACK during write
8
;   i2c_send_byte       ( u - f )       send a byte (address, register, data, ...)
9
;   i2c_read_byte       ( f - u )       read a byte and either ACK (f=0) or STOP (f=1)
10
;   i2c_send_stop       ( - )           send a stop after ACK during write
11 2 sinclairrf
;
12 5 sinclairrf
; Example to set a single register (ignoring returned ACK/NACK value)
13
;   .call(i2c_send_start)
14
;   .call(i2c_send_byte,write_address) drop
15
;   .call(i2c_send_byte,register) drop
16
;   .call(i2c_send_byte,data) drop
17
;   .call(i2c_send_stop)
18
;
19
; Example to read two bytes (ignoring returned ACK/NACK value)
20
;   .call(i2c_send_start)
21
;   .call(i2c_send_byte,write_address) drop
22
;   .call(i2c_send_byte,register) drop
23
;   .call(i2c_send_restart)
24
;   .call(i2c_send_byte,read_address) drop
25
;   .call(i2c_read_byte,0)
26
;   .call(i2c_read_byte,1)
27
;
28 2 sinclairrf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29
 
30
; Compute how many iterations in the quarter-clock-cycle function are required.
31
;   ceil(100 MHz / 400 kHz / 4) ==> 63 clock cycles per I2C SCL quarter cycle
32
;   The function consumes:
33
;     3 clock cycles to call the function
34
;     3 clock cycles for the "outport(O_SCL)"
35
;     1 clock cycle to initialize the loop count
36
;     2 clock cycles to return
37
;     9 TOTAL
38
;   Add 2 to ensure rounding up when evaluting the integer fraction.
39
;   The loop is 3 clock cycles per iteration
40 5 sinclairrf
.IFNDEF C_I2C_QUARTER_CYCLE
41 11 sinclairrf
.constant C_I2C_QUARTER_CYCLE ${max(1,(63-9+2)/3)}
42 5 sinclairrf
.ENDIF
43 2 sinclairrf
 
44
; ( - )
45
.function i2c_send_start
46
 
47
  .call(i2c_quarter_cycle,1)
48
  .call(i2c_quarter_cycle,0)
49
.return
50
 
51
; Set a start without the preceding stop.
52
; ( - )
53
.function i2c_send_restart
54
  .call(i2c_quarter_cycle,0)
55
  .call(i2c_quarter_cycle,1)
56
 
57
  .call(i2c_quarter_cycle,0)
58
.return
59
 
60
; Send the byte and indicate false if the acknowledge bit was received.
61
; ( u - f )
62
.function i2c_send_byte
63
  ; send the byte, msb first
64
  ; ( u - )
65
  ${8-1} :outer
66
    ; send the next bit
67
    swap <<msb swap
68
    .call(i2c_clock_cycle,over) drop
69
  .jumpc(outer,1-) drop drop
70
  ; get the acknowledge bit at the middle of the high portion of SCL
71
  ; ( - f )
72
  .call(i2c_clock_cycle,1)
73
.return
74
 
75 5 sinclairrf
; Read the next byte from the device and generate an ACK or a STOP.
76
; ( f - u )
77 2 sinclairrf
.function i2c_read_byte
78 5 sinclairrf
  ; Read 8 bits and pack them into the returned value.
79
  ; ( f - u f )
80 2 sinclairrf
 
81
    swap <<0 .call(i2c_clock_cycle,1) or swap
82
  .jumpc(loop,1-) drop
83 5 sinclairrf
  swap
84
  ; Generate the ACK/STOP based on f.
85
  ; ( u f - u )
86
 
87
  .call(i2c_quarter_cycle,0)
88
  .call(i2c_quarter_cycle,1)
89
  O_SDA outport
90
  .call(i2c_quarter_cycle,1)
91
  .call(i2c_quarter_cycle)      ; SCL is high on STOP, low on ACK, consumes f
92
.return
93
 
94 2 sinclairrf
; Send a stop by bringing SDA high while SCL is high.
95
; ( - )
96
.function i2c_send_stop
97
 
98
  .call(i2c_quarter_cycle,1)
99
  1 .outport(O_SDA) .call(i2c_quarter_cycle,1)
100
.return
101
 
102
; Send the clock as a "0110" pattern and sample SDA in the middle of the high
103
; portion.
104
; ( u_sda_out - u_sda_in )
105
.function i2c_clock_cycle
106
  .outport(O_SDA)
107
  .call(i2c_quarter_cycle,0)
108
  .call(i2c_quarter_cycle,1)
109
  .inport(I_SDA)
110
  .call(i2c_quarter_cycle,1)
111
  .call(i2c_quarter_cycle,0)
112
.return
113
 
114
; Output the I2C SCL value and then wait for a quarter of the I2C clock cycle.
115
; ( u_scl - )
116
.function i2c_quarter_cycle
117
  .outport(O_SCL)
118
  ${C_I2C_QUARTER_CYCLE-1} :loop .jumpc(loop,1-)
119
.return(drop)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.