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

Subversion Repositories minsoc

[/] [minsoc/] [trunk/] [sw/] [drivers/] [i2c.c] - Blame information for rev 63

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 36 rfajardo
#include "../support/board.h"
2
#include "../support/support.h"
3
#include "i2c.h"
4
 
5
int i2c_rd_done, i2c_wr_done;
6
 
7
int i2c_pending_write;
8
 
9
int i2c_rd_ptr, i2c_wr_ptr;
10
 
11
int i2c_buf_overflow;
12
i2c_type i2c_data[I2C_BUF_LEN];
13
 
14
unsigned char start, pointer_write, write_hbyte, write_lbyte, read_hbyte, read_lbyte;
15
unsigned char cmd_list[5];
16
unsigned char dat_list[5];
17
int i2c_index;
18
int i2c_end;
19
 
20
i2c_type * i2c_get(void)
21
{
22 53 ConX.
        if ( !i2c_rd_done )
23
                return NULL;
24 36 rfajardo
 
25 53 ConX.
        i2c_rd_done--;
26 36 rfajardo
 
27 53 ConX.
        int tmp;
28
        tmp = i2c_rd_ptr;
29 36 rfajardo
 
30 53 ConX.
        if (i2c_rd_ptr < I2C_BUF_LEN-1)
31
                i2c_rd_ptr++;
32
        else
33
                i2c_rd_ptr = 0;
34 36 rfajardo
 
35 53 ConX.
        return &i2c_data[tmp];
36 36 rfajardo
}
37
 
38
void i2c_init(void)
39
{
40 53 ConX.
        REG8(I2C_BASE+I2C_PRESC_HI) = 0x00;
41
        REG8(I2C_BASE+I2C_PRESC_LO) = 49;       //100kHz
42
        REG8(I2C_BASE+I2C_CTR) = I2C_CTR_EN | I2C_CTR_IRQ_EN;
43
        i2c_rd_done = 0;
44
        i2c_wr_done = 0;
45
        i2c_index = 0;
46
        i2c_wr_ptr = 0;
47
        i2c_rd_ptr = 0;
48
        i2c_buf_overflow = 0;
49 36 rfajardo
}
50
 
51
void i2c_set_ack_lvl(int ack_lvl, int final_ack_lvl)
52
{
53 53 ConX.
        int ack, final_ack;
54 36 rfajardo
 
55 53 ConX.
        ack = ( ack_lvl ) ? I2C_CR_NACK : I2C_CR_ACK;
56
        final_ack = ( final_ack_lvl ) ? I2C_CR_NACK : I2C_CR_ACK;
57 36 rfajardo
 
58 53 ConX.
        start = I2C_CR_STA | I2C_CR_WR | ack;
59
        pointer_write = I2C_CR_WR | ack;
60
        write_hbyte = I2C_CR_WR | ack;
61
        write_lbyte = I2C_CR_WR | I2C_CR_STO | final_ack;
62
        read_hbyte = I2C_CR_RD | ack;
63
        read_lbyte = I2C_CR_RD | I2C_CR_STO | final_ack;
64 36 rfajardo
}
65
 
66
void i2c_byte_transfer(void)
67
{
68 53 ConX.
        if ( i2c_index > 0 )
69
                if ( cmd_list[i2c_index-1] == read_hbyte )
70
                        i2c_data[i2c_wr_ptr].data = (REG8(I2C_BASE+I2C_RXR) << 8) & 0xFF00;
71 36 rfajardo
 
72 53 ConX.
        REG8(I2C_BASE+I2C_TXR) = dat_list[i2c_index];
73
        REG8(I2C_BASE+I2C_CR) = cmd_list[i2c_index];
74
 
75
        i2c_index++;
76 36 rfajardo
}
77
 
78
void i2c_irq(void)
79
{
80 53 ConX.
        REG8(I2C_BASE+I2C_CR) = I2C_CR_CLR_IRQ;
81
        if (i2c_index <= i2c_end )
82
                i2c_byte_transfer();
83
        else
84
        {
85
                if ( cmd_list[i2c_index-1] == read_lbyte )
86
                        i2c_data[i2c_wr_ptr].data |= REG8(I2C_BASE+I2C_RXR);
87 36 rfajardo
 
88 53 ConX.
                i2c_index = 0;
89 36 rfajardo
 
90 53 ConX.
                if ( i2c_pending_write )
91
                        i2c_wr_done = 1;
92
                else
93
                {
94
                        if (i2c_wr_ptr < I2C_BUF_LEN-1)
95
                                i2c_wr_ptr++;
96
                        else
97
                                i2c_wr_ptr = 0;
98 36 rfajardo
 
99 53 ConX.
                        if (i2c_wr_ptr == i2c_rd_ptr+1)
100
                        {
101
                                i2c_rd_done = 1;
102
                                i2c_buf_overflow++;
103
                        }
104
                        else
105
                                i2c_rd_done++;
106
                }
107
        }
108 36 rfajardo
}
109
 
110
int i2c_trans(i2c_mode * mode, i2c_type * data)
111
{
112 53 ConX.
        if ( i2c_index != 0 )       //if previous command not fully processed, bail out
113
                return -1;
114 36 rfajardo
 
115 53 ConX.
        i2c_wr_done = 0;
116 36 rfajardo
 
117 53 ConX.
        int i = 0;
118 36 rfajardo
 
119 53 ConX.
        if ( mode->ptr_set || mode->read_write )    //start conditions with pointer set: (write always set ptr)
120
        {
121 36 rfajardo
                dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
122
                dat_list[i] |= I2C_TXR_W;
123
                cmd_list[i++] = start;
124
 
125 53 ConX.
                dat_list[i] = data->pointer;
126
                cmd_list[i++] = pointer_write;
127 36 rfajardo
 
128 53 ConX.
                if ( !mode->read_write )                //REstart for read, NO-REstart for write
129
                {
130
                        dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
131
                        dat_list[i] |= I2C_TXR_R;
132
                        cmd_list[i++] = start;
133
                }
134
        }
135
        else                    //start conditions with NO pointer set (read only): ONE start
136
        {
137
                dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
138
                dat_list[i] |= I2C_TXR_R;
139
                cmd_list[i++] = start;
140
        }
141 36 rfajardo
 
142 53 ConX.
        if ( mode->byte_word )  //read/write high byte
143
        {
144
                dat_list[i] = data->data >> 8;
145
                cmd_list[i++] = (mode->read_write) ? write_hbyte : read_hbyte;
146
        }
147 36 rfajardo
 
148 53 ConX.
        dat_list[i] = data->data;   //read/write low byte
149
        cmd_list[i] = (mode->read_write) ? write_lbyte : read_lbyte;
150 36 rfajardo
 
151 53 ConX.
        i2c_end = i;
152 36 rfajardo
 
153 53 ConX.
        if ( !mode->read_write )    //set data to 0 for read, avoid or implications ((short)data |= byte)
154
        {
155
                i2c_data[i2c_wr_ptr] = *data;
156
                i2c_data[i2c_wr_ptr].data = 0x0000;
157
        }
158 36 rfajardo
 
159 53 ConX.
        i2c_pending_write = mode->read_write;
160
 
161
        i2c_index = 0;
162
        i2c_byte_transfer();
163
 
164
        return mode->read_write+1;
165 36 rfajardo
}

powered by: WebSVN 2.1.0

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