blob: efa509af3caf4b89f3e12bb5b4644f02675391f9 [file] [log] [blame]
adamdunkels9fcf9d62003-09-04 19:46:32 +00001/**
2 * \file
3 * RS232 communication device driver for the MSP430.
4 * \author Adam Dunkels <adam@sics.se>
5 *
6 * This file contains an RS232 device driver for the MSP430 microcontroller.
7 *
8 */
9
10#include <io.h>
11#include <signal.h>
12
13#include "rs232.h"
14
15void beep(void);
16
17unsigned char lastchar, lastchar_changed;
18
19#define RECVBUF_SIZE 32
20
21static unsigned char recvbuf[RECVBUF_SIZE];
22static unsigned char recvbufptr1 = 0,
23 recvbufptr2 = 0;
24
25interrupt(UART1RX_VECTOR) rs232_rx_usart1(void)
26{
27 volatile unsigned char dummy;
28
29 /* Check status register for receive errors. */
30 if(URCTL1 & RXERR) {
31 /* Clear error flags by forcing a dummy read. */
32 dummy = RXBUF1;
33 } else {
34 recvbuf[recvbufptr1] = RXBUF1;
35 recvbufptr1 = (recvbufptr1 + 1) % RECVBUF_SIZE;
36 }
37}
38/*-----------------------------------------------------------------------------------*/
39/**
40 * Initalize the RS232 port.
41 *
42 * \param none Not used.
43 * \return An error value or RS_ERR_OK if initialization succeeded.
44 */
45/*-----------------------------------------------------------------------------------*/
46unsigned char
47rs232_init(char none)
48{
49 /* This code taken from the FU Berlin sources and reformatted. */
50
51#define DELTA 600
52
53 unsigned int compare, oldcapture = 0;
54 unsigned int i;
55
56 BCSCTL1 = 0xa4; /* ACLK is devided by 4. RSEL=6 no division for MCLK
57 and SSMCLK. XT2 is off. */
58
59 BCSCTL2 = 0x00; /* Init FLL to desired frequency using the 32762Hz
60 crystal DCO frquenzy = 2,4576 MHz */
61
62 WDTCTL = WDTPW + WDTHOLD; /* Stop WDT */
63 BCSCTL1 |= DIVA1 + DIVA0; /* ACLK = LFXT1CLK/8 */
64 for(i = 0xffff; i > 0; --i); /* Delay for XTAL to settle */
65
66 /* Set DCO for 2,4576 Mhz: */
67 CCTL2 = CCIS0 + CM0 + CAP; /* Define CCR2, CAP, ACLK */
68 TACTL = TASSEL1 + TACLR + MC1; /* SMCLK, continous mode */
69 while(1) {
70 while((CCTL2 & CCIFG) != CCIFG); /* Wait until capture occured! */
71 CCTL2 &= ~CCIFG; /* Capture occured, clear flag */
72 compare = CCR2; /* Get current captured SMCLK */
73 compare = compare - oldcapture; /* SMCLK difference */
74 oldcapture = CCR2; /* Save current captured SMCLK */
75
76 if(DELTA == compare) {
77 break; /* if equal, leave "while(1)" */
78 } else if(DELTA < compare) { /* DCO is too fast, slow it down */
79 DCOCTL--;
80 if(DCOCTL == 0xFF) { /* Did DCO role under? */
81 BCSCTL1--;
82 }
83 } else { /* -> Select next lower RSEL */
84 DCOCTL++;
85 if(DCOCTL == 0x00) { /* Did DCO role over? */
86 BCSCTL1++;
87 }
88 /* -> Select next higher RSEL */
89 }
90 }
91 CCTL2 = 0; /* Stop CCR2 function */
92 TACTL = 0; /* Stop Timer_A */
93
94
95
96 /* Radio on 19200 Bit/s */
97#if 0
98 UCTL0 = CHAR; /* 8-bit character */
99 UTCTL0 = SSEL1; /* UCLK = SMCLK */
100 UBR00 = 0x80; /* 2,457MHz/19200 = 128 -> 0x80 */
101 UBR10 = 0x00; /* */
102 UMCTL0 = 0x00; /* no modulation */
103 ME1 |= UTXE0 + URXE0; /* Enable USART0 TXD/RXD */
104 /*IE1 |= URXIE0;*/ /* Enable USART0 RX interrupt */
105#endif /* 0 */
106
107 /* RS232 */
108 UCTL1 = CHAR; /* 8-bit character */
109 UTCTL1 = SSEL1; /* UCLK = MCLK */
110
111#define RS232_SPEED 57600
112
113 if(RS232_SPEED == 19200) {
114 /* Set RS232 to 19200 */
115 UBR01 = 0x80; /* 2,457MHz/19200 = 128 -> 0x80 */
116 UBR11 = 0x00; /* */
117 UMCTL1 = 0x00; /* no modulation */
118 } else if(RS232_SPEED == 38400) {
119 /* Set RS232 to 38400 */
120 UBR01 = 0x40; /* 2,457MHz/38400 = 64 -> 0x40 */
121 UBR11 = 0x00; /* */
122 UMCTL1 = 0x00; /* no modulation */
123 } else if(RS232_SPEED == 57600) {
124 UBR01 = 0x2a; /* 2,457MHz/57600 = 42.7 -> 0x2A */
125 UBR11 = 0x00; /* */
126 UMCTL1 = 0x5b; /* */
127 } else if(RS232_SPEED == 115200) {
128 UBR01 = 0x15; /* 2,457MHz/115200 = 21.4 -> 0x15 */
129 UBR11 = 0x00; /* */
130 UMCTL1 = 0x4a; /* */
131 }
132
133
134 ME2 |= (UTXE1 | URXE1); /* Enable USART1 TXD/RXD */
135 IE2 |= URXIE1; /* Enable USART1 RX interrupt */
136 BCSCTL1 &= ~(DIVA1 + DIVA0); /* remove /8 divisor from ACLK again */
137
138
139 rs232_put('!');
140
141 return RS_ERR_OK;
142}
143/*-----------------------------------------------------------------------------------*/
144/**
145 * Configure the RS232 port.
146 *
147 * \param params RS232 parameters.
148 * \param parity Parity.
149 * \return An error value or RS_ERR_OK if configuration succeeded.
150 */
151/*-----------------------------------------------------------------------------------*/
152unsigned char
153rs232_params(unsigned char params, unsigned char parity)
154{
155 return RS_ERR_OK;
156}
157/*-----------------------------------------------------------------------------------*/
158/**
159 * Get a byte from the serial port.
160 *
161 * \param c A pointer to the location where the byte is to be stored.
162 *
163 * \return An error value or RS_ERR_OK. If no data is available, the
164 * function returns RS_ERR_NO_DATA which is not a fatal error.
165 */
166/*-----------------------------------------------------------------------------------*/
167unsigned char
168rs232_get(char *c)
169{
170 if(recvbufptr1 == recvbufptr2) {
171 return RS_ERR_NO_DATA;
172 }
173 *c = recvbuf[recvbufptr2];
174 recvbufptr2 = (recvbufptr2 + 1) % RECVBUF_SIZE;
175 return RS_ERR_OK;
176}
177/*-----------------------------------------------------------------------------------*/
178/**
179 * Transmit a byte over the serial port.
180 *
181 * \param c A pointer to the location where the byte is to be stored.
182 *
183 * \return An error value or RS_ERR_OK. If the transmission buffer was
184 * full, RS_ERR_OVERFLOW is returned.
185 */
186/*-----------------------------------------------------------------------------------*/
187unsigned char
188rs232_put(char c)
189{
190 /* Loop until the transmission buffer is available. */
191 while ((IFG2 & UTXIFG1) == 0);
192
193 /* Transmit the data. */
194 TXBUF1 = c;
195
196 return RS_ERR_OK;
197}
198/*-----------------------------------------------------------------------------------*/