Rev 387 | Rev 685 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 387 | Rev 389 | ||
---|---|---|---|
1 | /**************************************************************************** |
1 | /**************************************************************************** |
2 | * Copyright (C) 2009 by Claas Anders "CaScAdE" Rathje * |
2 | * Copyright (C) 2009 by Claas Anders "CaScAdE" Rathje * |
3 | * admiralcascade@gmail.com * |
3 | * admiralcascade@gmail.com * |
4 | * Project-URL: http://www.mylifesucks.de/oss/c-osd/ * |
4 | * Project-URL: http://www.mylifesucks.de/oss/c-osd/ * |
5 | * * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License. * |
8 | * the Free Software Foundation; either version 2 of the License. * |
9 | * * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
13 | * GNU General Public License for more details. * |
14 | * * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the * |
16 | * along with this program; if not, write to the * |
17 | * Free Software Foundation, Inc., * |
17 | * Free Software Foundation, Inc., * |
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
19 | ****************************************************************************/ |
19 | ****************************************************************************/ |
20 | 20 | ||
21 | #include <avr/io.h> |
21 | #include <avr/io.h> |
22 | #include <avr/interrupt.h> |
22 | #include <avr/interrupt.h> |
23 | #include <util/delay.h> |
23 | #include <util/delay.h> |
24 | #include "main.h" |
24 | #include "main.h" |
25 | #include "usart1.h" |
25 | #include "usart1.h" |
26 | 26 | ||
27 | volatile uint8_t rxd_buffer_locked = 0; |
27 | volatile uint8_t rxd_buffer_locked = 0; |
28 | volatile uint8_t rxd_buffer[RXD_BUFFER_LEN]; |
28 | volatile uint8_t rxd_buffer[RXD_BUFFER_LEN]; |
29 | volatile uint8_t txd_buffer[TXD_BUFFER_LEN]; |
29 | volatile uint8_t txd_buffer[TXD_BUFFER_LEN]; |
30 | volatile uint8_t ReceivedBytes = 0; |
30 | volatile uint8_t ReceivedBytes = 0; |
31 | volatile uint8_t *pRxData = 0; |
31 | volatile uint8_t *pRxData = 0; |
32 | volatile uint8_t RxDataLen = 0; |
32 | volatile uint8_t RxDataLen = 0; |
33 | 33 | ||
34 | /* ########################################################################## |
34 | /* ########################################################################## |
35 | * USART stuff |
35 | * USART stuff |
36 | * ##########################################################################*/ |
36 | * ##########################################################################*/ |
37 | 37 | ||
38 | /** |
38 | /** |
39 | * init usart1 |
39 | * init usart1 |
40 | */ |
40 | */ |
41 | void usart1_init() { |
41 | void usart1_init() { |
42 | UBRR1H = ((F_CPU / (16UL * baud)) - 1) >> 8; |
42 | UBRR1H = ((F_CPU / (16UL * baud)) - 1) >> 8; |
43 | UBRR1L = (F_CPU / (16UL * baud)) - 1; |
43 | UBRR1L = (F_CPU / (16UL * baud)) - 1; |
44 | 44 | ||
45 | // Enable receiver and transmitter; enable RX interrupt |
45 | // Enable receiver and transmitter; enable RX interrupt |
46 | UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1); |
46 | UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1); |
47 | 47 | ||
48 | //asynchronous 8N1 |
48 | //asynchronous 8N1 |
49 | UCSR1C = (1 << URSEL1) | (3 << UCSZ10); |
49 | UCSR1C = (1 << URSEL1) | (3 << UCSZ10); |
50 | } |
50 | } |
51 | 51 | ||
52 | /** |
52 | /** |
53 | * disable the txd pin of usart1 |
53 | * disable the txd pin of usart1 |
54 | */ |
54 | */ |
55 | void usart1_DisableTXD(void) { |
55 | void usart1_DisableTXD(void) { |
56 | //UCSR1B &= ~(1 << TXCIE1); // disable TX-Interrupt |
56 | UCSR1B &= ~(1 << TXCIE1); // disable TX-Interrupt |
57 | UCSR1B &= ~(1 << TXEN1); // disable TX in USART |
57 | UCSR1B &= ~(1 << TXEN1); // disable TX in USART |
58 | DDRB &= ~(1<<DDB3); // set TXD pin as input |
58 | DDRB &= ~(1<<DDB3); // set TXD pin as input |
59 | PORTB &= ~(1 << PORTB3); |
59 | PORTB &= ~(1 << PORTB3); // disable pullup on TXD pin |
60 | } |
60 | } |
61 | 61 | ||
62 | /** |
62 | /** |
63 | * enable the txd pin of usart1 |
63 | * enable the txd pin of usart1 |
64 | */ |
64 | */ |
65 | void usart1_EnableTXD(void) { |
65 | void usart1_EnableTXD(void) { |
66 | DDRB |= (1<<DDB3); // set TXD pin as output |
66 | DDRB |= (1<<DDB3); // set TXD pin as output |
67 | PORTB &= ~(1 << PORTB3); |
67 | PORTB &= ~(1 << PORTB3); // disable pullup on TXD pin |
68 | UCSR1B |= (1 << TXEN1); // enable TX in USART |
68 | UCSR1B |= (1 << TXEN1); // enable TX in USART |
69 | //UCSR1B |= (1 << TXCIE1); // enable TX-Interrupt |
69 | UCSR1B |= (1 << TXCIE1); // enable TX-Interrupt |
70 | } |
70 | } |
71 | - | ||
72 | 71 | ||
73 | /** |
72 | /** |
74 | * send a single <character> through usart1 |
73 | * send a single <character> through usart1 |
75 | */ |
74 | */ |
76 | void usart1_putc(unsigned char character) { |
75 | void usart1_putc(unsigned char character) { |
77 | // wait until UDR ready |
76 | // wait until UDR ready |
78 | while (!(UCSR1A & (1 << UDRE1))); |
77 | while (!(UCSR1A & (1 << UDRE1))); |
79 | UDR1 = character; |
78 | UDR1 = character; |
80 | } |
79 | } |
81 | 80 | ||
82 | /** |
81 | /** |
83 | * send a <string> throught usart1 |
82 | * send a <string> throught usart1 |
84 | */ |
83 | */ |
85 | void usart1_puts(char *s) { |
84 | void usart1_puts(char *s) { |
86 | while (*s) { |
85 | while (*s) { |
87 | usart1_putc(*s); |
86 | usart1_putc(*s); |
88 | s++; |
87 | s++; |
89 | } |
88 | } |
90 | } |
89 | } |
91 | 90 | ||
92 | /** |
91 | /** |
93 | * transmit interrupt handler |
92 | * transmit interrupt handler |
94 | * unused |
93 | * unused |
95 | */ |
94 | */ |
96 | SIGNAL(SIG_USART1_DATA) { |
95 | ISR(SIG_USART1_DATA) { |
97 | } |
96 | } |
98 | 97 | ||
99 | /** |
98 | /** |
100 | * receive data through usart1 |
99 | * receive data through usart1 |
101 | * portions taken and adapted from |
100 | * portions taken and adapted from |
102 | * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Fbranches%2FV0.72p+Code+Redesign+killagreg%2Fuart0.c |
101 | * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Fbranches%2FV0.72p+Code+Redesign+killagreg%2Fuart0.c |
103 | */ |
102 | */ |
104 | ISR(SIG_USART1_RECV) { |
103 | ISR(SIG_USART1_RECV) { |
105 | if (rxd_buffer_locked) return; // if rxd buffer is locked immediately return |
104 | if (rxd_buffer_locked) return; // if rxd buffer is locked immediately return |
106 | LED1_ON |
105 | LED1_ON |
107 | static uint16_t crc; |
106 | static uint16_t crc; |
108 | static uint8_t ptr_rxd_buffer = 0; |
107 | static uint8_t ptr_rxd_buffer = 0; |
109 | uint8_t crc1, crc2; |
108 | uint8_t crc1, crc2; |
110 | uint8_t c; |
109 | uint8_t c; |
111 | 110 | ||
112 | c = UDR1; // catch the received byte |
111 | c = UDR1; // catch the received byte |
113 | 112 | ||
114 | // the rxd buffer is unlocked |
113 | // the rxd buffer is unlocked |
115 | if ((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received |
114 | if ((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received |
116 | { |
115 | { |
117 | /* |
116 | /* |
118 | // skip other datasets |
117 | // skip other datasets |
119 | if (ptr_rxd_buffer == 2 && rxd_buffer[ptr_rxd_buffer] != 'O') { |
118 | if (ptr_rxd_buffer == 2 && rxd_buffer[ptr_rxd_buffer] != 'O') { |
120 | ptr_rxd_buffer = 0; // reset rxd buffer |
119 | ptr_rxd_buffer = 0; // reset rxd buffer |
121 | rxd_buffer_locked = 0; // unlock rxd buffer |
120 | rxd_buffer_locked = 0; // unlock rxd buffer |
122 | }*/ |
121 | }*/ |
123 | rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer |
122 | rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer |
124 | crc = c; // init crc |
123 | crc = c; // init crc |
125 | } else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes |
124 | } else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes |
126 | { |
125 | { |
127 | if (c != '\r') // no termination character |
126 | if (c != '\r') // no termination character |
128 | { |
127 | { |
129 | rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer |
128 | rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer |
130 | crc += c; // update crc |
129 | crc += c; // update crc |
131 | } else // termination character was received |
130 | } else // termination character was received |
132 | { |
131 | { |
133 | // the last 2 bytes are no subject for checksum calculation |
132 | // the last 2 bytes are no subject for checksum calculation |
134 | // they are the checksum itself |
133 | // they are the checksum itself |
135 | crc -= rxd_buffer[ptr_rxd_buffer - 2]; |
134 | crc -= rxd_buffer[ptr_rxd_buffer - 2]; |
136 | crc -= rxd_buffer[ptr_rxd_buffer - 1]; |
135 | crc -= rxd_buffer[ptr_rxd_buffer - 1]; |
137 | // calculate checksum from transmitted data |
136 | // calculate checksum from transmitted data |
138 | crc %= 4096; |
137 | crc %= 4096; |
139 | crc1 = '=' + crc / 64; |
138 | crc1 = '=' + crc / 64; |
140 | crc2 = '=' + crc % 64; |
139 | crc2 = '=' + crc % 64; |
141 | // compare checksum to transmitted checksum bytes |
140 | // compare checksum to transmitted checksum bytes |
142 | if ((crc1 == rxd_buffer[ptr_rxd_buffer - 2]) && (crc2 == rxd_buffer[ptr_rxd_buffer - 1])) { // checksum valid |
141 | if ((crc1 == rxd_buffer[ptr_rxd_buffer - 2]) && (crc2 == rxd_buffer[ptr_rxd_buffer - 1])) { // checksum valid |
143 | rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character |
142 | rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character |
144 | ReceivedBytes = ptr_rxd_buffer + 1; // store number of received bytes |
143 | ReceivedBytes = ptr_rxd_buffer + 1; // store number of received bytes |
145 | rxd_buffer_locked = 1; // lock the rxd buffer |
144 | rxd_buffer_locked = 1; // lock the rxd buffer |
146 | } else { // checksum invalid |
145 | } else { // checksum invalid |
147 | rxd_buffer_locked = 0; // unlock rxd buffer |
146 | rxd_buffer_locked = 0; // unlock rxd buffer |
148 | } |
147 | } |
149 | ptr_rxd_buffer = 0; // reset rxd buffer pointer |
148 | ptr_rxd_buffer = 0; // reset rxd buffer pointer |
150 | } |
149 | } |
151 | } else // rxd buffer overrun |
150 | } else // rxd buffer overrun |
152 | { |
151 | { |
153 | ptr_rxd_buffer = 0; // reset rxd buffer |
152 | ptr_rxd_buffer = 0; // reset rxd buffer |
154 | rxd_buffer_locked = 0; // unlock rxd buffer |
153 | rxd_buffer_locked = 0; // unlock rxd buffer |
155 | } |
154 | } |
156 | LED1_OFF |
155 | LED1_OFF |
157 | } |
156 | } |
158 | 157 | ||
159 | /** |
158 | /** |
160 | * Decode the recevied Buffer |
159 | * Decode the recevied Buffer |
161 | * portions taken and adapted from |
160 | * portions taken and adapted from |
162 | * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c |
161 | * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c |
163 | */ |
162 | */ |
164 | void Decode64(void) { |
163 | void Decode64(void) { |
165 | uint8_t a, b, c, d; |
164 | uint8_t a, b, c, d; |
166 | uint8_t x, y, z; |
165 | uint8_t x, y, z; |
167 | uint8_t ptrIn = 3; |
166 | uint8_t ptrIn = 3; |
168 | uint8_t ptrOut = 3; |
167 | uint8_t ptrOut = 3; |
169 | uint8_t len = ReceivedBytes - 6; |
168 | uint8_t len = ReceivedBytes - 6; |
170 | 169 | ||
171 | while (len) { |
170 | while (len) { |
172 | a = rxd_buffer[ptrIn++] - '='; |
171 | a = rxd_buffer[ptrIn++] - '='; |
173 | b = rxd_buffer[ptrIn++] - '='; |
172 | b = rxd_buffer[ptrIn++] - '='; |
174 | c = rxd_buffer[ptrIn++] - '='; |
173 | c = rxd_buffer[ptrIn++] - '='; |
175 | d = rxd_buffer[ptrIn++] - '='; |
174 | d = rxd_buffer[ptrIn++] - '='; |
176 | 175 | ||
177 | x = (a << 2) | (b >> 4); |
176 | x = (a << 2) | (b >> 4); |
178 | y = ((b & 0x0f) << 4) | (c >> 2); |
177 | y = ((b & 0x0f) << 4) | (c >> 2); |
179 | z = ((c & 0x03) << 6) | d; |
178 | z = ((c & 0x03) << 6) | d; |
180 | 179 | ||
181 | if (len--) rxd_buffer[ptrOut++] = x; |
180 | if (len--) rxd_buffer[ptrOut++] = x; |
182 | else break; |
181 | else break; |
183 | if (len--) rxd_buffer[ptrOut++] = y; |
182 | if (len--) rxd_buffer[ptrOut++] = y; |
184 | else break; |
183 | else break; |
185 | if (len--) rxd_buffer[ptrOut++] = z; |
184 | if (len--) rxd_buffer[ptrOut++] = z; |
186 | else break; |
185 | else break; |
187 | } |
186 | } |
188 | pRxData = &rxd_buffer[3]; |
187 | pRxData = &rxd_buffer[3]; |
189 | RxDataLen = ptrOut - 3; |
188 | RxDataLen = ptrOut - 3; |
190 | } |
189 | } |
191 | 190 | ||
192 | /** |
191 | /** |
193 | * request Data through USART in special MK format by adding checksum and |
192 | * request Data through USART in special MK format by adding checksum and |
194 | * encode data in modified Base64 |
193 | * encode data in modified Base64 |
195 | * portions taken and adapted from |
194 | * portions taken and adapted from |
196 | * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c |
195 | * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c |
197 | */ |
196 | */ |
198 | void sendMKData(unsigned char cmd, unsigned char addr, unsigned char *snd, unsigned char len) { |
197 | void sendMKData(unsigned char cmd, unsigned char addr, unsigned char *snd, unsigned char len) { |
199 | unsigned int pt = 0; |
198 | unsigned int pt = 0; |
200 | unsigned char a, b, c; |
199 | unsigned char a, b, c; |
201 | unsigned char ptr = 0; |
200 | unsigned char ptr = 0; |
202 | 201 | ||
203 | txd_buffer[pt++] = '#'; // Start-Byte |
202 | txd_buffer[pt++] = '#'; // Start-Byte |
204 | txd_buffer[pt++] = 'a' + addr; // Adress |
203 | txd_buffer[pt++] = 'a' + addr; // Adress |
205 | txd_buffer[pt++] = cmd; // Command |
204 | txd_buffer[pt++] = cmd; // Command |
206 | while (len) { |
205 | while (len) { |
207 | if (len) { |
206 | if (len) { |
208 | a = snd[ptr++]; |
207 | a = snd[ptr++]; |
209 | len--; |
208 | len--; |
210 | } else a = 0; |
209 | } else a = 0; |
211 | if (len) { |
210 | if (len) { |
212 | b = snd[ptr++]; |
211 | b = snd[ptr++]; |
213 | len--; |
212 | len--; |
214 | } else b = 0; |
213 | } else b = 0; |
215 | if (len) { |
214 | if (len) { |
216 | c = snd[ptr++]; |
215 | c = snd[ptr++]; |
217 | len--; |
216 | len--; |
218 | } else c = 0; |
217 | } else c = 0; |
219 | txd_buffer[pt++] = '=' + (a >> 2); |
218 | txd_buffer[pt++] = '=' + (a >> 2); |
220 | txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4)); |
219 | txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4)); |
221 | txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6)); |
220 | txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6)); |
222 | txd_buffer[pt++] = '=' + (c & 0x3f); |
221 | txd_buffer[pt++] = '=' + (c & 0x3f); |
223 | } |
222 | } |
224 | 223 | ||
225 | // add crc |
224 | // add crc |
226 | unsigned int tmpCRC = 0, i; |
225 | unsigned int tmpCRC = 0, i; |
227 | for (i = 0; i < pt; i++) { |
226 | for (i = 0; i < pt; i++) { |
228 | tmpCRC += txd_buffer[i]; |
227 | tmpCRC += txd_buffer[i]; |
229 | } |
228 | } |
230 | tmpCRC %= 4096; |
229 | tmpCRC %= 4096; |
231 | txd_buffer[i++] = '=' + tmpCRC / 64; |
230 | txd_buffer[i++] = '=' + tmpCRC / 64; |
232 | txd_buffer[i++] = '=' + tmpCRC % 64; |
231 | txd_buffer[i++] = '=' + tmpCRC % 64; |
233 | txd_buffer[i++] = '\r'; |
232 | txd_buffer[i++] = '\r'; |
234 | 233 | ||
235 | usart1_puts((char*) txd_buffer); |
234 | usart1_puts((char*) txd_buffer); |
236 | } |
235 | } |
237 | 236 | ||
238 | /** |
237 | /** |
239 | * short script to directly send a request thorugh usart including en- and disabling it |
238 | * short script to directly send a request thorugh usart including en- and disabling it |
240 | * where <address> is the address of the receipient, <label> is which data set to request |
239 | * where <address> is the address of the receipient, <label> is which data set to request |
241 | * and <ms> represents the milliseconds delay between data |
240 | * and <ms> represents the milliseconds delay between data |
242 | */ |
241 | */ |
243 | void usart1_request_mk_data(uint8_t address, char label, uint8_t ms) { |
242 | void usart1_request_mk_data(uint8_t address, char label, uint8_t ms) { |
244 | // re-enable TXD pin |
243 | // re-enable TXD pin |
245 | usart1_EnableTXD(); |
244 | usart1_EnableTXD(); |
246 | 245 | ||
247 | unsigned char mstenth = ms/10; |
246 | unsigned char mstenth = ms/10; |
248 | sendMKData(label, address, &mstenth, 1); |
247 | sendMKData(label, address, &mstenth, 1); |
249 | - | ||
- | 248 | // wait until UDR ready |
|
- | 249 | while (!(UCSR1A & (1 << UDRE1))); |
|
250 | // disable TXD pin again |
250 | // disable TXD pin again |
251 | usart1_DisableTXD(); |
251 | usart1_DisableTXD(); |
252 | } |
252 | } |
253 | 253 |