Contiki 3.x
uart1_i2c_master.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 
42 #include "uart1_i2c_master.h"
43 #include "isr_compat.h"
44 #include "contiki.h"
45 #include <stdlib.h>
46 #include "dev/watchdog.h"
47 #include "lib/ringbuf.h"
48 #include "isr_compat.h"
49 
50 #include "platform-conf.h"
51 
52 //#define UART1_DEBUG
53 #ifdef UART1_DEBUG
54  #include <stdio.h>
55  #define PRINTF(...) printf(__VA_ARGS__)
56 #else
57  #define PRINTF(...)
58 #endif
59 
60 signed char tx_byte_ctr, rx_byte_ctr;
61 unsigned char rx_buf[2];
62 unsigned char* tx_buf_ptr;
63 unsigned char* rx_buf_ptr;
64 unsigned char receive_data;
65 unsigned char transmit_data1;
66 unsigned char transmit_data2;
67 volatile unsigned int i; // volatile to prevent optimization
68 
69 
70 
71 static int (*uart1_input_handler)(unsigned char c);
72 
73 static volatile uint8_t serial_transmitting;
74 
75 #ifdef UART1_CONF_TX_WITH_INTERRUPT
76 #define TX_WITH_INTERRUPT UART1_CONF_TX_WITH_INTERRUPT
77 #else /* UART1_CONF_TX_WITH_INTERRUPT */
78 #define TX_WITH_INTERRUPT 1
79 #endif /* UART1_CONF_TX_WITH_INTERRUPT */
80 
81 #if TX_WITH_INTERRUPT
82 #define TXBUFSIZE 64
83 
84 static struct ringbuf txbuf;
85 #endif /* TX_WITH_INTERRUPT */
86 
87 
88 //------------------------------------------------------------------------------
89 // void i2c_receiveinit(unsigned char slave_address,
90 // unsigned char prescale)
91 //
92 // This function initializes the USCI module for master-receive operation.
93 //
94 // IN: unsigned char slave_address => Slave Address
95 // unsigned char prescale => SCL clock adjustment
96 //-----------------------------------------------------------------------------
97 void
98 i2c_receiveinit(uint8_t slave_address) {
99  UCB1CTL1 = UCSWRST; // Enable SW reset
100  UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
101  UCB1CTL1 = UCSSEL_2 | UCSWRST; // Use SMCLK, keep SW reset
102  UCB1BR0 = I2C_PRESC_400KHZ_LSB; // prescaler for 400 kHz data rate
103  UCB1BR1 = I2C_PRESC_400KHZ_MSB;
104  UCB1I2CSA = slave_address; // set slave address
105 
106  UCB1CTL1 &= ~UCTR; // I2C Receiver
107 
108  UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
109  UCB1I2CIE = UCNACKIE;
110 #if I2C_RX_WITH_INTERRUPT
111  UC1IE |= UCB1RXIE; // Enable RX interrupt if desired
112 #endif
113 }
114 
115 //------------------------------------------------------------------------------
116 // void i2c_transmitinit(unsigned char slave_address,
117 // unsigned char prescale)
118 //
119 // Initializes USCI for master-transmit operation.
120 //
121 // IN: unsigned char slave_address => Slave Address
122 // unsigned char prescale => SCL clock adjustment
123 //------------------------------------------------------------------------------
124 void
125 i2c_transmitinit(uint8_t slave_address) {
126  UCB1CTL1 |= UCSWRST; // Enable SW reset
127  UCB1CTL0 |= (UCMST | UCMODE_3 | UCSYNC); // I2C Master, synchronous mode
128  UCB1CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
129  UCB1BR0 = I2C_PRESC_400KHZ_LSB; // prescaler for 400 kHz data rate
130  UCB1BR1 = I2C_PRESC_400KHZ_MSB;
131  UCB1I2CSA = slave_address; // Set slave address
132 
133  UCB1CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
134  UCB1I2CIE = UCNACKIE;
135  UC1IE |= UCB1TXIE; // Enable TX ready interrupt
136 }
137 
138 //------------------------------------------------------------------------------
139 // void i2c_receive_n(unsigned char byte_ctr, unsigned char * rx_buf)
140 // This function is used to start an I2C communication in master-receiver mode WITHOUT INTERRUPTS
141 // for more than 1 byte
142 // IN: unsigned char byte_ctr => number of bytes to be read
143 // OUT: unsigned char rx_buf => receive data buffer
144 // OUT: int n_received => number of bytes read
145 //------------------------------------------------------------------------------
146 static volatile uint8_t rx_byte_tot = 0;
147 uint8_t
148 i2c_receive_n(uint8_t byte_ctr, uint8_t *rx_buf) {
149 
150  rx_byte_tot = byte_ctr;
151  rx_byte_ctr = byte_ctr;
152  rx_buf_ptr = rx_buf;
153 
154  while ((UCB1CTL1 & UCTXSTT) || (UCB1STAT & UCNACKIFG)); // Slave acks address or not?
155  //PRINTF ("____ UCTXSTT not clear OR NACK received\n");
156 
157 #if I2C_RX_WITH_INTERRUPT
158  PRINTF(" RX Interrupts: YES \n");
159 
160  // SPECIAL-CASE: Stop condition must be sent while receiving the 1st byte for 1-byte only read operations
161  if(rx_byte_tot == 1){ // See page 537 of slau144e.pdf
162  dint();
163  UCB1CTL1 |= UCTXSTT; // I2C start condition
164  while(UCB1CTL1 & UCTXSTT); // Waiting for Start bit to clear
165  // PRINTF ("____ STT clear wait\n");
166  UCB1CTL1 |= UCTXSTP; // I2C stop condition
167  eint();
168  }
169  else{ // all other cases
170  UCB1CTL1 |= UCTXSTT; // I2C start condition
171  }
172  return 0;
173 
174 #else
175  uint8_t n_received = 0;
176 
177 // PRINTF(" RX Interrupts: NO \n");
178 
179  UCB1CTL1 |= UCTXSTT; // I2C start condition
180 
181  while (rx_byte_ctr > 0){
182  if (UC1IFG & UCB1RXIFG) { // Waiting for Data
183  rx_buf[rx_byte_tot - rx_byte_ctr] = UCB1RXBUF;
184  rx_byte_ctr--;
185  UC1IFG &= ~UCB1RXIFG; // Clear USCI_B1 RX int flag
186  n_received++;
187  }
188  }
189  UCB1CTL1 |= UCTXSTP; // I2C stop condition
190  return n_received;
191 #endif
192 }
193 
194 
195 //------------------------------------------------------------------------------
196 // uint8_t i2c_busy()
197 //
198 // This function is used to check if there is communication in progress.
199 //
200 // OUT: unsigned char => 0: I2C bus is idle,
201 // 1: communication is in progress
202 //------------------------------------------------------------------------------
203 uint8_t
204 i2c_busy(void) {
205  return (UCB1STAT & UCBBUSY);
206 }
207 
208 /*----------------------------------------------------------------------------*/
209 /* Setup ports and pins for I2C use. */
210 
211 void
212 i2c_enable(void) {
213  I2C_PxSEL |= (I2C_SDA | I2C_SCL); // Secondary function (USCI) selected
214  I2C_PxSEL2 |= (I2C_SDA | I2C_SCL); // Secondary function (USCI) selected
215  I2C_PxDIR |= I2C_SCL; // SCL is output (not needed?)
216  I2C_PxDIR &= ~I2C_SDA; // SDA is input (not needed?)
217  I2C_PxREN |= (I2C_SDA | I2C_SCL); // Activate internal pull-up/-down resistors
218  I2C_PxOUT |= (I2C_SDA | I2C_SCL); // Select pull-up resistors
219 }
220 
221 void
222 i2c_disable(void) {
223  I2C_PxSEL &= ~(I2C_SDA | I2C_SCL); // GPIO function selected
224  I2C_PxSEL2 &= ~(I2C_SDA | I2C_SCL); // GPIO function selected
225  I2C_PxREN &= ~(I2C_SDA | I2C_SCL); // Deactivate internal pull-up/-down resistors
226  I2C_PxOUT &= ~(I2C_SDA | I2C_SCL); // Select pull-up resistors
227 }
228 
229 /*----------------------------------------------------------------------------*/
230 //------------------------------------------------------------------------------
231 // void i2c_transmit_n(unsigned char byte_ctr, unsigned char *field)
232 //
233 // This function is used to start an I2C communication in master-transmit mode.
234 //
235 // IN: unsigned char byte_ctr => number of bytes to be transmitted
236 // unsigned char *tx_buf => Content to transmit. Read and transmitted from [0] to [byte_ctr]
237 //------------------------------------------------------------------------------
238 static volatile uint8_t tx_byte_tot = 0;
239 void
240 i2c_transmit_n(uint8_t byte_ctr, uint8_t *tx_buf) {
241  tx_byte_tot = byte_ctr;
242  tx_byte_ctr = byte_ctr;
243  tx_buf_ptr = tx_buf;
244  UCB1CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
245 }
246 
247 
248 /*----------------------------------------------------------------------------*/
249 uint8_t
250 uart1_active(void)
251 {
252  return (UCA1STAT & UCBUSY) | serial_transmitting;
253 }
254 /*---------------------------------------------------------------------------*/
255 void
256 uart1_set_input(int (*input)(unsigned char c))
257 {
258  PRINTF("UART1 input handler set\n");
259  uart1_input_handler = input;
260 }
261 /*---------------------------------------------------------------------------*/
262 
263 void
264 uart1_writeb(unsigned char c)
265 {
266  //PRINTF("UART1 writeb **\n");
267  /* watchdog_periodic(); */
268 // #if TX_WITH_INTERRUPT
269 // printf("Uart1 write with interrupt\n");
270  /* Put the outgoing byte on the transmission buffer. If the buffer
271  is full, we just keep on trying to put the byte into the buffer
272  until it is possible to put it there. */
273 // while(ringbuf_put(&txbuf, c) == 0)
274 // {
275 // watchdog_periodic();
276 // }
277 
278  /* If there is no transmission going, we need to start it by putting
279  the first byte into the UART. */
280 // if(serial_transmitting == 0)
281 // {
282 // serial_transmitting = 1;
283 // UCA1TXBUF = ringbuf_get(&txbuf);
284 // }
285 
286 //#else /* TX_WITH_INTERRUPT */
287  //PRINTF("UART1 tx without interrupt\n");
288  /* Loop until the transmission buffer is available. */
289  PRINTF("W");
290  while((UCA1STAT & UCBUSY)); //while send in progress
291 
292  /* Transmit the data. */
293  RS485_TXEN_PORT(OUT) |= BV(RS485_TXEN_PIN);
294  UCA1TXBUF = c;
295  while((UCA1STAT & UCBUSY)); //while send in progress
296  RS485_TXEN_PORT(OUT) &= ~BV(RS485_TXEN_PIN);
297 
298  PRINTF("char written to UCA1TXBUF\n");
299 //#endif /* TX_WITH_INTERRUPT */
300 }
301 
302 
303 void
304 uart1_writearray(unsigned char* c,int length)
305 {
306  RS485_TXEN_PORT(OUT) |= BV(RS485_TXEN_PIN);
307  static int i=0; //create counter variable
308  for(i=0;i<length;i++) //for every character in array
309  {
311  uart1_writeb(c[i]); //write byte
312  }
313  while((UCA1STAT & UCBUSY)); //while send in progress
314  RS485_TXEN_PORT(OUT) &= ~BV(RS485_TXEN_PIN); //clear tx enable pin
315 }
316 
317 /*----------------------------------------------------------------------------*/
318 /**
319  * Configure pins for RS232 port.
320  *
321  */
322 void
324 {
325  PRINTF("UART1 pin init\n");
326  UCA1CTL1 |= UCSWRST; /* Hold peripheral in reset state */
327 
328  /* Configure TX/RX Pins. */
329  UART1_RX_PORT(SEL) |= BV(UART1_RX_PIN); /*3.7 as input*/
330  UART1_RX_PORT(DIR) &= ~BV(UART1_RX_PIN); /*3.7 as input*/
331  UART1_TX_PORT(SEL) |= BV(UART1_TX_PIN); /*3.6 as output*/
332  UART1_TX_PORT(DIR) |= BV(UART1_TX_PIN); /*3.6 as output*/
333 
334  /* Configure RS485 TXEN pin. */
335  RS485_TXEN_PORT(DIR) |= BV(RS485_TXEN_PIN);
336  RS485_TXEN_PORT(OUT) &= ~BV(RS485_TXEN_PIN);
337 }
338 
339 
340 /*----------------------------------------------------------------------------*/
341 /**
342  * Initalize the RS232 port.
343  *
344  */
345 void
346 uart1_init(unsigned long ubr)
347 {
348  PRINTF("UART1 init\n");
349 
350  UCA1CTL0 = 0x00;
351  UCA1CTL1 |= UCSSEL_3; /* CLK = SMCLK */
352 // UCA1BR0 = BAUD2UBR(38400); /*Hard coded as passing an arg in didn't work */
353  UCA1BR0 = 0x40;
354  UCA1BR1 = 0x03;
355  UCA1MCTL = UCBRS_2; /* Modulation UCBRSx = 4 */
356 
357  UCA1CTL1 &= ~UCSWRST; /* Initialize USCI state machine */
358 
359  serial_transmitting = 0;
360 
361  /* XXX Clear pending interrupts before enable */
362  IFG2 &= ~UCA1RXIFG;
363  IFG2 &= ~UCA1TXIFG;
364  UCA1CTL1 &= ~UCSWRST; /* Initialize USCI state machine **before** enabling interrupts */
365  UC1IE |= UCA1RXIE;
366 
367  //PRINTF("UART1 now inited\n");
368 }
369 
370 
371 /*----------------------------------------------------------------------------*/
372 ISR(USCIAB1TX, uart1_i2c_tx_interrupt)
373 {
374  // TX Part
375  if (UC1IFG & UCB1TXIFG) { // TX int. condition
376  //PRINTF("I2C TX int \n");
377  UC1IFG &= ~UCB1TXIFG; // Clear USCI_B1 TX int flag
378  if (tx_byte_ctr == 0) {
379  UCB1CTL1 |= UCTXSTP; // I2C stop condition
380  }
381  else {
382  UCB1TXBUF = tx_buf_ptr[tx_byte_tot - tx_byte_ctr];
383  tx_byte_ctr--;
384  }
385  }
386  // RX Part
387 #if I2C_RX_WITH_INTERRUPT //TODO: Is this right as we are in the TX interrupt?
388  else if (UC1IFG & UCB1RXIFG){ // RX int. condition
389  UC1IFG &= ~UCB1RXIFG; // Clear USCI_B1 RX int flag. XXX Just in case, check if necessary
390  PRINTF("USCIAB1TX: UCB1RXIFG\n");
391  rx_buf_ptr[rx_byte_tot - rx_byte_ctr] = UCB1RXBUF;
392  rx_byte_ctr--;
393  if (rx_byte_ctr == 1){ //stop condition should be set before receiving last byte
394  // Only for 1-byte transmissions, STOP is handled in receive_n_int
395  if (rx_byte_tot != 1)
396  UCB1CTL1 |= UCTXSTP; // I2C stop condition
397  }
398  }
399 #endif
400 #if TX_WITH_INTERRUPT
401  else if(IFG2 & UCA1TXIFG) {
402  IFG2 &= ~UCA1TXIFG;
403  PRINTF("USCIAB1TX: UCA1TXIFG\n");
404  if(ringbuf_elements(&txbuf) == 0) {
405  serial_transmitting = 0;
406  RS485_TXEN_PORT(OUT) &= ~BV(RS485_TXEN_PIN);
407  } else {
408  UCA0TXBUF = ringbuf_get(&txbuf);
409  }
410  }
411 #endif /* TX_WITH_INTERRUPT */
412 }
413 
414 ISR(USCIAB1RX, uart1_i2c_rx_interrupt)
415 {
416  //printf("!");
417  //PRINTF("ISR\n");
418  uint8_t c;
419 #if I2C_RX_WITH_INTERRUPT
420  if(UCB1STAT & UCNACKIFG) {
421  UCB1CTL1 |= UCTXSTP;
422  UCB1STAT &= ~UCNACKIFG;
423  }
424 #endif
425  if( UC1IFG & UCA1RXIFG){
426  if(UCA1STAT & UCRXERR) {
427  /* Check status register for receive errors. */
428  c = UCA1RXBUF; /* Clear error flags by forcing a dummy read. */
429  } else {
430  c = UCA1RXBUF;
431  //PRINTF("%i\n", c);
432  if(uart1_input_handler != NULL) {
433  if(uart1_input_handler(c)) {
434  LPM4_EXIT;
435  }
436  }
437  }
438  }
440 }
int ringbuf_get(struct ringbuf *r)
Get a byte from the ring buffer.
Definition: ringbuf.c:80
void uart1_init(unsigned long ubr)
Initalize the RS232 port.
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1503
void i2c_enable(void)
Configure serial controller in I2C mode and set I2C speed.
int ringbuf_elements(struct ringbuf *r)
Get the number of elements currently in the ring buffer.
Definition: ringbuf.c:119
#define NULL
The null pointer.
Structure that holds the state of a ring buffer.
Definition: ringbuf.h:68
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
I2C communication device driver header file for Zolertia Z1 sensor node.
void i2c_disable(void)
Configure serial controller in disabled mode.
void uart1_pin_init(void)
Configure pins for RS232 port.
Header file for the ring buffer library