Contiki-Inga 3.x
mspi.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, TU Braunschweig.
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 
30 /**
31  * \file
32  * MSPI driver implementation
33  * \author
34  * Ulf Kulau <kulau@ibr.cs.tu-bs.de>
35  */
36 
37 /**
38  * \addtogroup inga_bus_driver
39  * @{
40  */
41 
42 /**
43  * \addtogroup mspi_driver
44  * @{
45  */
46 
47 #include "mspi.h"
48 
49 /*!
50  * SPI Device Table: Holds the information about the SPI devices.
51  * \note Index contains Chip Select information
52  */
53 static spi_dev spi_bus_config[MAX_SPI_DEVICES];
54 
55 /*!
56  * Holds the current SPI-Bus configuration
57  */
58 static uint8_t spi_current_config = 0xFF;
59 
60 /*!
61  * This array holds the BCD for the 8 possible SPI devices, because the few amount
62  * of port-pins made it necessary to use a BCD-Decimal-Encoder. The first item
63  * (chip_select[0]) disables chip select. The other (chip_select[1] ...
64  * chip_select[7]) holds the MSPI_SC_PORT information for the specific SPI device.
65  *
66  * \note This is a special solution for the raven based ibr sensor node. If you want
67  * to use this driver for other applications, feel free to change the chip select
68  * management
69  */
70 static uint8_t cs_bcd[8] = {
71  /*Chip Select Disable*/
72  (0xFF & (0 << MSPI_CS_PIN_0) & (0 << MSPI_CS_PIN_1) & (0 << MSPI_CS_PIN_2)),
73  /*Chip Select Enable for specific SPI device (1...7)*/
74  (0x00 | (1 << MSPI_CS_PIN_0) | (0 << MSPI_CS_PIN_1) | (0 << MSPI_CS_PIN_2)), //1
75  (0x00 | (0 << MSPI_CS_PIN_0) | (1 << MSPI_CS_PIN_1) | (0 << MSPI_CS_PIN_2)), //2
76  (0x00 | (1 << MSPI_CS_PIN_0) | (1 << MSPI_CS_PIN_1) | (0 << MSPI_CS_PIN_2)), //3
77  (0x00 | (0 << MSPI_CS_PIN_0) | (0 << MSPI_CS_PIN_1) | (1 << MSPI_CS_PIN_2)), //4
78  (0x00 | (1 << MSPI_CS_PIN_0) | (0 << MSPI_CS_PIN_1) | (1 << MSPI_CS_PIN_2)), //5
79  (0x00 | (0 << MSPI_CS_PIN_0) | (1 << MSPI_CS_PIN_1) | (1 << MSPI_CS_PIN_2)), //6
80  (0x00 | (1 << MSPI_CS_PIN_0) | (1 << MSPI_CS_PIN_1) | (1 << MSPI_CS_PIN_2)) //7
81 
82 };
83 
84 static usart_t usart_ports[2] = {
85  { // MSPI UART0
86  &UBRR0,
87  &DDRB,
88  PORTB0,
89  &UCSR0A,
90  &UCSR0B,
91  &UCSR0C,
92  &UDR0
93  },
94 
95  { // MSPI UART1
96  &UBRR1,
97  &DDRD,
98  PORTD4,
99  &UCSR1A,
100  &UCSR1B,
101  &UCSR1C,
102  &UDR1
103  }
104 };
105 
106 /* global variable for the selected USART port*/
107 uint8_t mspi_uart_port = MSPI_USART1;
108 void
109 mspi_init(uint8_t cs, uint8_t mode, uint16_t baud)
110 {
111  /*initialize the spi port pins, setting pins output*/
112  MSPI_CS_PORT_DDR |= (1 << MSPI_CS_PIN_0) | (1 << MSPI_CS_PIN_1) | (1 << MSPI_CS_PIN_2);
113  MSPI_CS_PORT &= ~((1 << MSPI_CS_PIN_0) | (1 << MSPI_CS_PIN_1) | (1 << MSPI_CS_PIN_2));
114 
115 #if MSPI_BUS_MANAGER
116  mspi_mgr_add(cs, mode, baud);
117 #else
118  /*initialize MSPI*/
119  *(usart_ports[mspi_uart_port].UBRRn) = 0;
120  /*setting clock pin as output*/
121  *(usart_ports[mspi_uart_port].XCKn_DDR) |= (1 << usart_ports[mspi_uart_port].XCKn);
122  /*enable MSPI and set spi mode*/
123  *(usart_ports[mspi_uart_port].UCSRnC) = ((MSPI_ENABLE) | mode);
124  /*initialize RX and TX*/
125  *(usart_ports[mspi_uart_port].UCSRnB) = ((1 << RXEN0) | (1 << TXEN0));
126  *(usart_ports[mspi_uart_port].UBRRn) = baud;
127 #endif
128 }
129 /*----------------------------------------------------------------------------*/
130 void
131 mspi_chip_select(uint8_t cs)
132 {
133 #if MSPI_BUS_MANAGER
134  if (spi_current_config != spi_bus_config[cs].checksum) {
135  /*new mspi configuration is needed by this spi device*/
136  mspi_mgr_change_mode(spi_bus_config[cs]);
137  spi_current_config = spi_bus_config[cs].checksum;
138  }
139 #endif
140  /*chip select*/
141  MSPI_CS_PORT |= cs_bcd[cs];
142 }
143 /*----------------------------------------------------------------------------*/
144 void
145 mspi_chip_release(uint8_t cs)
146 {
147  /*chip deselect*/
148  MSPI_CS_PORT &= ~((1 << MSPI_CS_PIN_0) | (1 << MSPI_CS_PIN_1) | (1 << MSPI_CS_PIN_2));
149 }
150 /*----------------------------------------------------------------------------*/
151 uint8_t
152 mspi_transceive(uint8_t data)
153 {
154  uint8_t receive_data;
155  uint16_t cnt = 0;
156 
157  /*wait while transmit buffer is empty*/
158  cnt = 0;
159  while (!(*(usart_ports[mspi_uart_port].UCSRnA) & (1 << UDRE0))) {
160  cnt++;
161  if(cnt > 500) return 0xFF;
162  }
163  *(usart_ports[mspi_uart_port].UDRn) = data;
164 
165  /*wait to readout the MSPI data register*/
166  cnt = 0;
167  while (!(*(usart_ports[mspi_uart_port].UCSRnA) & (1 << RXC0))) {
168  cnt++;
169  if(cnt > 500) return 0xFF;
170  }
171  receive_data = *(usart_ports[mspi_uart_port].UDRn);
172 
173  return receive_data;
174 }
175 /*----------------------------------------------------------------------------*/
176 void
178 {
179  *(usart_ports[mspi_uart_port].UCSRnA) = MSPI_DISABLE;
180  *(usart_ports[mspi_uart_port].UCSRnB) = MSPI_DISABLE;
181  *(usart_ports[mspi_uart_port].UCSRnC) = MSPI_DISABLE;
182 }
183 /*----------------------------------------------------------------------------*/
184 
185 #if MSPI_BUS_MANAGER
186 void
187 mspi_mgr_add(uint8_t cs, uint8_t mode, uint16_t baud)
188 {
189  spi_bus_config[cs].dev_mode = mode;
190  spi_bus_config[cs].dev_baud = baud;
191  spi_bus_config[cs].checksum = mode + baud;
192 }
193 /*----------------------------------------------------------------------------*/
194 void
195 mspi_mgr_change_mode(spi_dev new_config)
196 {
197  /*initialize MSPI*/
198  *(usart_ports[mspi_uart_port].UBRRn) = 0;
199  /*setting clock pin as output*/
200  *(usart_ports[mspi_uart_port].XCKn_DDR) |= (1 << usart_ports[mspi_uart_port].XCKn);
201  /*enable MSPI and set spi mode*/
202  *(usart_ports[mspi_uart_port].UCSRnC) = ((MSPI_ENABLE) | new_config.dev_mode);
203  /*initialize RX and TX*/
204  *(usart_ports[mspi_uart_port].UCSRnB) = ((1 << RXEN0) | (1 << TXEN0));
205  *(usart_ports[mspi_uart_port].UBRRn) = new_config.dev_baud;
206 }
207 #endif