Contiki-NG
i2cmaster.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * I2C communication device drivers for Zolertia Z1 sensor node.
36  * \author
37  * Enric M. Calvo, Zolertia <ecalvo@zolertia.com>
38  * Marcus Lundén, SICS <mlunden@sics.se>
39  */
40 
41 #include "i2cmaster.h"
42 #include "isr_compat.h"
43 
44 signed char tx_byte_ctr, rx_byte_ctr;
45 unsigned char rx_buf[2];
46 unsigned char *tx_buf_ptr;
47 unsigned char *rx_buf_ptr;
48 unsigned char receive_data;
49 unsigned char transmit_data1;
50 unsigned char transmit_data2;
51 unsigned char prescale_lsb = I2C_PRESC_Z1_LSB;
52 unsigned char prescale_msb = I2C_PRESC_Z1_MSB;
53 volatile unsigned int i; /* volatile to prevent optimization */
54 
55 /* ------------------------------------------------------------------------------
56  * Change the data rate prior initializing transmission or reception
57  * ----------------------------------------------------------------------------- */
58 void
59 i2c_setrate(uint8_t p_lsb, uint8_t p_msb)
60 {
61  prescale_lsb = p_lsb;
62  prescale_lsb = p_msb;
63 }
64 /* ------------------------------------------------------------------------------
65  * This function initializes the USCI module for master-receive operation.
66  * ----------------------------------------------------------------------------- */
67 void
68 i2c_receiveinit(uint8_t slave_address)
69 {
70  UCB1CTL1 = UCSWRST; /* Enable SW reset */
71  UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; /* I2C Master, synchronous mode */
72  UCB1CTL1 = UCSSEL_2 | UCSWRST; /* Use SMCLK, keep SW reset */
73  UCB1BR0 = prescale_lsb; /* prescaler (default 400 kHz) */
74  UCB1BR1 = prescale_msb;
75  UCB1I2CSA = slave_address; /* set slave address */
76  UCB1CTL1 &= ~UCTR; /* I2C Receiver */
77  UCB1CTL1 &= ~UCSWRST; /* Clear SW reset, resume operation */
78  UCB1I2CIE = UCNACKIE;
79 #if I2C_RX_WITH_INTERRUPT
80  UC1IE = UCB1RXIE; /* Enable RX interrupt if desired */
81 #endif
82 }
83 /* ------------------------------------------------------------------------------
84  * Initializes USCI for master-transmit operation.
85  * ------------------------------------------------------------------------------ */
86 void
87 i2c_transmitinit(uint8_t slave_address)
88 {
89  UCB1CTL1 |= UCSWRST; /* Enable SW reset */
90  UCB1CTL0 |= (UCMST | UCMODE_3 | UCSYNC); /* I2C Master, synchronous mode */
91  UCB1CTL1 = UCSSEL_2 + UCSWRST; /* Use SMCLK, keep SW reset */
92  UCB1BR0 = prescale_lsb; /* prescaler (default 400 kHz) */
93  UCB1BR1 = prescale_msb;
94  UCB1I2CSA = slave_address; /* Set slave address */
95  UCB1CTL1 &= ~UCSWRST; /* Clear SW reset, resume operation */
96  UCB1I2CIE = UCNACKIE;
97  UC1IE = UCB1TXIE; /* Enable TX ready interrupt */
98 }
99 /* ------------------------------------------------------------------------------
100  * This function is used to start an I2C communication in master-receiver mode WITHOUT INTERRUPTS
101  * for more than 1 byte
102  * ------------------------------------------------------------------------------ */
103 static volatile uint8_t rx_byte_tot = 0;
104 uint8_t
105 i2c_receive_n(uint8_t byte_ctr, uint8_t *rx_buf)
106 {
107 
108  rx_byte_tot = byte_ctr;
109  rx_byte_ctr = byte_ctr;
110  rx_buf_ptr = rx_buf;
111 
112  while((UCB1CTL1 & UCTXSTT) || (UCB1STAT & UCNACKIFG)) /* Slave acks address or not? */
113  PRINTFDEBUG("____ UCTXSTT not clear OR NACK received\n");
114 
115 #if I2C_RX_WITH_INTERRUPT
116  PRINTFDEBUG(" RX Interrupts: YES \n");
117 
118  /* SPECIAL-CASE: Stop condition must be sent while receiving the 1st byte for 1-byte only read operations */
119  if(rx_byte_tot == 1) { /* See page 537 of slau144e.pdf */
120  dint();
121  UCB1CTL1 |= UCTXSTT; /* I2C start condition */
122  while(UCB1CTL1 & UCTXSTT) /* Waiting for Start bit to clear */
123  PRINTFDEBUG("____ STT clear wait\n");
124  UCB1CTL1 |= UCTXSTP; /* I2C stop condition */
125  eint();
126  } else { /* all other cases */
127  UCB1CTL1 |= UCTXSTT; /* I2C start condition */
128  }
129  return 0;
130 
131 #else
132  uint8_t n_received = 0;
133 
134  PRINTFDEBUG(" RX Interrupts: NO \n");
135 
136  UCB1CTL1 |= UCTXSTT; /* I2C start condition */
137 
138  while(rx_byte_ctr > 0) {
139  if(UC1IFG & UCB1RXIFG) { /* Waiting for Data */
140  rx_buf[rx_byte_tot - rx_byte_ctr] = UCB1RXBUF;
141  rx_byte_ctr--;
142  UC1IFG &= ~UCB1RXIFG; /* Clear USCI_B1 RX int flag */
143  n_received++;
144  }
145  }
146  UCB1CTL1 |= UCTXSTP; /* I2C stop condition */
147  return n_received;
148 #endif
149 }
150 /* ------------------------------------------------------------------------------
151  * This function is used to check if there is communication in progress.
152  * ------------------------------------------------------------------------------ */
153 uint8_t
154 i2c_busy(void)
155 {
156  return UCB1STAT & UCBBUSY;
157 }
158 /*----------------------------------------------------------------------------
159  * Setup ports and pins for I2C use.
160  * ------------------------------------------------------------------------------ */
161 
162 void
163 i2c_enable(void)
164 {
165  I2C_PxSEL |= (I2C_SDA | I2C_SCL); /* Secondary function (USCI) selected */
166  I2C_PxSEL2 |= (I2C_SDA | I2C_SCL); /* Secondary function (USCI) selected */
167  I2C_PxDIR |= I2C_SCL; /* SCL is output (not needed?) */
168  I2C_PxDIR &= ~I2C_SDA; /* SDA is input (not needed?) */
169  I2C_PxREN |= (I2C_SDA | I2C_SCL); /* Activate internal pull-up/-down resistors */
170  I2C_PxOUT |= (I2C_SDA | I2C_SCL); /* Select pull-up resistors */
171 }
172 void
173 i2c_disable(void)
174 {
175  I2C_PxSEL &= ~(I2C_SDA | I2C_SCL); /* GPIO function selected */
176  I2C_PxSEL2 &= ~(I2C_SDA | I2C_SCL); /* GPIO function selected */
177  I2C_PxREN &= ~(I2C_SDA | I2C_SCL); /* Deactivate internal pull-up/-down resistors */
178  I2C_PxOUT &= ~(I2C_SDA | I2C_SCL); /* Select pull-up resistors */
179 }
180 /* ------------------------------------------------------------------------------
181  * This function is used to start an I2C communication in master-transmit mode.
182  * ------------------------------------------------------------------------------ */
183 static volatile uint8_t tx_byte_tot = 0;
184 void
185 i2c_transmit_n(uint8_t byte_ctr, uint8_t *tx_buf)
186 {
187  tx_byte_tot = byte_ctr;
188  tx_byte_ctr = byte_ctr;
189  tx_buf_ptr = tx_buf;
190  UCB1CTL1 |= UCTR + UCTXSTT; /* I2C TX, start condition */
191 }
192 /*----------------------------------------------------------------------------*/
193 ISR(USCIAB1TX, i2c_tx_interrupt)
194 {
195  /* TX Part */
196  if(UC1IFG & UCB1TXIFG) { /* TX int. condition */
197  if(tx_byte_ctr == 0) {
198  UCB1CTL1 |= UCTXSTP; /* I2C stop condition */
199  UC1IFG &= ~UCB1TXIFG; /* Clear USCI_B1 TX int flag */
200  } else {
201  UCB1TXBUF = tx_buf_ptr[tx_byte_tot - tx_byte_ctr];
202  tx_byte_ctr--;
203  }
204  }
205  /* RX Part */
206 #if I2C_RX_WITH_INTERRUPT
207  else if(UC1IFG & UCB1RXIFG) { /* RX int. condition */
208  rx_buf_ptr[rx_byte_tot - rx_byte_ctr] = UCB1RXBUF;
209  rx_byte_ctr--;
210  if(rx_byte_ctr == 1) { /* stop condition should be set before receiving last byte */
211  /* Only for 1-byte transmissions, STOP is handled in receive_n_int */
212  if(rx_byte_tot != 1) {
213  UCB1CTL1 |= UCTXSTP; /* I2C stop condition */
214  }
215  UC1IFG &= ~UCB1RXIFG; /* Clear USCI_B1 RX int flag. XXX Just in case, check if necessary */
216  }
217  }
218 #endif
219 }
220 
221 ISR(USCIAB1RX, i2c_rx_interrupt)
222 {
223  if(UCB1STAT & UCNACKIFG) {
224  PRINTFDEBUG("!!! NACK received in RX\n");
225  UCB1CTL1 |= UCTXSTP;
226  UCB1STAT &= ~UCNACKIFG;
227  }
228 }
I2C communication device driver header file for Zolertia Z1 sensor node.