Autogeneration of MSP430-rgb-PWM-firmware works
[cerebrum.git] / msp / uart_io.c
blob95d0a8541f698f1b40e43796e0013b76dbde43a2
1 /*
2 * Copyright (c) 2012, Alexander I. Mykyta
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 are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 /*==================================================================================================
27 * File History:
28 * NAME DATE COMMENTS
29 * Alex M. 11/15/2010 born
31 *=================================================================================================*/
33 /**
34 * \addtogroup MOD_UART
35 * \{
36 **/
38 /**
39 * \file
40 * \brief Code for \ref MOD_UART "UART IO"
41 * \author Alex Mykyta (amykyta3@gmail.com)
42 **/
44 #include <stdint.h>
45 #include <stddef.h>
47 #include <msp430.h>
48 #include "result.h"
49 #include "uart_io.h"
50 #include "uart_io_internal.h"
51 #include "fifo.h"
53 ///\cond PRIVATE
54 #if (UIO_USE_INTERRUPTS == 1)
55 char rxbuf[UIO_RXBUF_SIZE];
56 FIFO_t RXFIFO;
57 char txbuf[UIO_TXBUF_SIZE];
58 FIFO_t TXFIFO;
60 uint8_t txbusy;
61 #endif
62 ///\endcond
64 ///\addtogroup UART_FUNCTIONS
65 ///\{
67 //==================================================================================================
68 // Hardware Abstraction Layer
69 //==================================================================================================
70 /**
71 * \brief Initializes the UART controller
72 * \param None
73 * \return Nothing
74 * \attention The initialization routine does \e not setup the IO ports!
75 **/
76 void init_uart(void){
77 #if defined(__MSP430_HAS_USCI__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
78 UIO_CTL1 |= UCSWRST; // soft reset
79 UIO_CTL0 = 0;
80 UIO_CTL1 = (UIO_CLK_SRC*64)+UCSWRST;
81 UIO_BR0 = UIO_BR0_DEFAULT;
82 UIO_BR1 = UIO_BR1_DEFAULT;
83 UIO_MCTL = UIO_MCTL_DEFAULT;
85 UIO_CTL1 &= ~UCSWRST;
87 #if (UIO_USE_INTERRUPTS == 1)
88 fifo_init(&RXFIFO,rxbuf,UIO_RXBUF_SIZE);
89 fifo_init(&TXFIFO,txbuf,UIO_TXBUF_SIZE);
90 txbusy = 0;
91 #if (UIO_ISR_SPLIT == 0)
92 UIO_IE = UCRXIE;
93 #else
94 UIO_IE = UIO_UCARXIE;
95 #endif
96 #endif
98 #elif defined(__MSP430_HAS_UCA__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
99 #error "Hardware Abstraction for UCA not written yet!"
100 #endif
103 //--------------------------------------------------------------------------------------------------
105 * \brief Gets a character from the inuart_put stream
106 * \param None
107 * \retval uint8_t Character
109 uint16_t uart_getc_nonblocking(void){
110 #if defined(__MSP430_HAS_USCI__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
111 #if (UIO_USE_INTERRUPTS == 1)
112 uint16_t chr;
113 if(fifo_rdcount(&RXFIFO) == 0){ // no char received
114 return(0x0100);
115 }else{
116 fifo_read(&RXFIFO,&chr,1);
117 return(chr);
119 #else
120 if((UIO_IFG & UCRXIFG) == 0){ // no char received
121 return(0x0100);
122 }else{
123 return(UIO_RXBUF);
125 #endif
127 #elif defined(__MSP430_HAS_UCA__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
128 #error "Hardware Abstraction for UCA not written yet!"
129 #endif
132 //--------------------------------------------------------------------------------------------------
134 * \brief Gets a character from the inuart_put stream
135 * \details If a character is not immediately available, function will block until it receives one.
136 * \param None
137 * \retval uint8_t Character
139 uint8_t uart_getc(void){
140 #if defined(__MSP430_HAS_USCI__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
141 #if (UIO_USE_INTERRUPTS == 1)
142 uint8_t chr;
143 while(fifo_rdcount(&RXFIFO) == 0); // wait until char recieved
144 fifo_read(&RXFIFO,&chr,1);
145 return(chr);
146 #else
147 while((UIO_IFG & UCRXIFG) == 0); // wait until char recieved
148 return(UIO_RXBUF);
149 #endif
151 #elif defined(__MSP430_HAS_UCA__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
152 #error "Hardware Abstraction for UCA not written yet!"
153 #endif
156 //--------------------------------------------------------------------------------------------------
158 * \brief Returns the number of characters immediately available for inuart_put
159 * \param None
160 * \retval uint16_t Characters available
162 uint16_t incount(void){
163 #if defined(__MSP430_HAS_USCI__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
164 #if (UIO_USE_INTERRUPTS == 1)
165 return(fifo_rdcount(&RXFIFO));
166 #else
167 if((UIO_IFG & UCRXIFG) != 0){
168 return(1);
170 else{
171 return(0);
173 #endif
175 #elif defined(__MSP430_HAS_UCA__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
176 #error "Hardware Abstraction for UCA not written yet!"
177 #endif
180 //--------------------------------------------------------------------------------------------------
182 * \brief Sends a character
183 * \param [in] c Character to be sent
184 * \return Nothing
186 void uart_putc(uint8_t c){
187 #if defined(__MSP430_HAS_USCI__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
188 #if (UIO_USE_INTERRUPTS == 1)
189 uint8_t chr;
190 while(fifo_wrcount(&TXFIFO) == 0); // wait until fifo has room for another
191 fifo_write(&TXFIFO,&c,1);
193 if(txbusy == 0){
194 txbusy = 1;
195 fifo_read(&TXFIFO,&chr,1);
196 UIO_TXBUF = chr;
197 #if (UIO_ISR_SPLIT == 0)
198 UIO_IE |= UCTXIE;
199 #else
200 UIO_IE |= UIO_UCATXIE;
201 #endif
204 #else
205 while((UIO_IFG & UCTXIFG) == 0); // wait until txbuf is empty
206 UIO_TXBUF = c;
207 #endif
209 #elif defined(__MSP430_HAS_UCA__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
210 #error "Hardware Abstraction for UCA not written yet!"
211 #endif
214 //--------------------------------------------------------------------------------------------------
216 ///\cond PRIVATE
217 #if defined(__MSP430_HAS_USCI__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
218 #if (UIO_USE_INTERRUPTS == 1)
219 #if (UIO_ISR_SPLIT == 0)
220 // RX/TX Interrupt Service Routine
221 #pragma vector=UIO_ISR_VECTOR
222 __interrupt void UIO_rxtxISR(void) {
224 uint16_t iv = UIO_IV;
225 uint8_t chr;
226 if(iv == 0x02){
227 // Data Recieved
228 chr = UIO_RXBUF;
229 fifo_write(&RXFIFO,&chr,1);
230 }else if(iv == 0x04){
231 // Transmit Buffer Empty
232 if(fifo_read(&TXFIFO,&chr,1) == RES_OK){
233 UIO_TXBUF = chr;
234 }else{
235 txbusy = 0;
236 UIO_IE &= ~UCTXIE; // disable tx interrupt
240 #else
241 // RX Interrupt Service Routine
242 #pragma vector=UIO_RXISR_VECTOR
243 __interrupt void UIO_rxISR(void) {
244 uint8_t chr;
245 chr = UIO_RXBUF;
246 fifo_write(&RXFIFO,&chr,1);
249 // TX Interrupt Service Routine
250 #pragma vector=UIO_TXISR_VECTOR
251 __interrupt void UIO_txISR(void) {
252 uint8_t chr;
253 if(fifo_read(&TXFIFO,&chr,1) == RES_OK){
254 UIO_TXBUF = chr;
255 }else{
256 txbusy = 0;
257 UIO_IE &= ~UIO_UCATXIE; // disable tx interrupt
260 #endif
261 #endif
263 #elif defined(__MSP430_HAS_UCA__) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
264 #error "Hardware Abstraction for UCA not written yet!"
265 #endif
267 ///\endcond
269 //==================================================================================================
270 // General functions
271 //==================================================================================================
273 * \brief Sends a string to the serial port
274 * \param [in] s Pointer to string to be sent
275 * \return Nothing
277 void uart_puts(char *s) {
278 while(*s) {
279 //if(*s == '\n') What the heck is this for?
280 // uart_putc('\r');
281 uart_putc(*s++);
285 //--------------------------------------------------------------------------------------------------
287 * \brief Reads in a string until a newline character ( \c \n)is received
288 * \details If an entire is not immediately available, function will block until it receives a
289 * newline character.
290 * \param [in] line Pointer to line buffer to be used. Buffer /e MUST be large enough to receive
291 * the line!
292 * \return Pointer to the received string
294 char* uart_getline(char *line){
295 char *ch = line;
296 uint8_t k;
298 // until we read a newline
299 while ((k = uart_getc()) != '\n') {
300 *ch++ = k;
303 // newline dropped and Null-terminating character added
304 *ch = '\0';
306 // return original pointer
307 return(line);
310 //--------------------------------------------------------------------------------------------------
312 * \brief Prints a HEX formatted string
313 * \param [in] value Value to be printed
314 * \param [in] places Number of digits to print. Use \c 0 to automatically determine how many digits.
315 * \return Nothing
317 void uart_putx(uint16_t value, uint16_t places){
318 int16_t i;
319 uint16_t j;
320 uint16_t bitmask;
321 if(places == 0){
322 // size places to fit number
323 bitmask = 0xF000;
324 places = 4;
325 while(((value & bitmask) == 0) && (places > 0)){
326 places--;
327 bitmask = bitmask >> 4;
329 if(places == 0){
330 places = 1;
333 for(i = ((places-1)<<2); i >= 0; i -= 4) {
334 j = (value >> i) & 0xf;
335 if(j < 10)
336 uart_putc('0' + j);
337 else
338 uart_putc('A' - 10 + j);
342 //--------------------------------------------------------------------------------------------------
344 * \brief Prints an unsigned decimal formatted string
345 * \param [in] value Value to be printed
346 * \return Nothing
348 void uart_putd(uint16_t value){
349 uint16_t n;
350 uint8_t str[5];
351 n = 5;
354 n -=1;
355 str[n]=(value % 10) + '0';
356 value /= 10;
357 } while(value != 0);
360 uart_putc(str[n]);
361 n++;
362 } while(n<5);
365 //--------------------------------------------------------------------------------------------------
367 * \brief Prints an unsigned decimal formatted string (32 bit version)
368 * \param [in] value Value to be printed
369 * \return Nothing
371 void uart_putd32(uint32_t value){
372 uint16_t n;
373 uint8_t str[10];
374 n = 10;
377 n -=1;
378 str[n]=(value % 10) + '0';
379 value /= 10;
380 } while(value != 0);
383 uart_putc(str[n]);
384 n++;
385 } while(n<10);
387 //--------------------------------------------------------------------------------------------------
389 * \brief Prints a signed decimal formatted string
390 * \param [in] value Value to be printed
391 * \return Nothing
393 void uart_putsd(int16_t value){
394 uint16_t n;
395 uint16_t uvalue;
396 uint8_t str[5];
397 n = 5;
399 if(value < 0){
400 uart_putc('-');
401 value = -value;
403 uvalue = (uint16_t) value;
406 n -=1;
407 str[n]=(uvalue % 10) + '0';
408 uvalue /= 10;
409 } while(uvalue != 0);
412 uart_putc(str[n]);
413 n++;
414 } while(n<5);
417 ///\}
419 ///\}