Sat, 07 Nov 2015 13:23:07 +0100
Initial code from reprappro Marlin repository
0 | 1 | /* |
2 | HardwareSerial.cpp - Hardware serial library for Wiring | |
3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. | |
4 | ||
5 | This library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | This library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with this library; if not, write to the Free Software | |
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | ||
19 | Modified 23 November 2006 by David A. Mellis | |
20 | Modified 28 September 2010 by Mark Sproul | |
21 | */ | |
22 | ||
23 | ||
24 | ||
25 | #include "Marlin.h" | |
26 | ||
27 | #ifndef REPRAPPRO_MULTIMATERIALS | |
28 | ||
29 | #include "MarlinSerial.h" | |
30 | ||
31 | #if MOTHERBOARD != 8 // !teensylu | |
32 | // this next line disables the entire HardwareSerial.cpp, | |
33 | // this is so I can support Attiny series and any other chip without a uart | |
34 | #if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) | |
35 | ||
36 | #if defined(UBRRH) || defined(UBRR0H) | |
37 | ring_buffer rx_buffer = { { 0 }, 0, 0 }; | |
38 | #endif | |
39 | ||
40 | FORCE_INLINE void store_char(unsigned char c) | |
41 | { | |
42 | int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE; | |
43 | ||
44 | // if we should be storing the received character into the location | |
45 | // just before the tail (meaning that the head would advance to the | |
46 | // current location of the tail), we're about to overflow the buffer | |
47 | // and so we don't write the character or advance the head. | |
48 | if (i != rx_buffer.tail) { | |
49 | rx_buffer.buffer[rx_buffer.head] = c; | |
50 | rx_buffer.head = i; | |
51 | } | |
52 | } | |
53 | ||
54 | ||
55 | //#elif defined(SIG_USART_RECV) | |
56 | #if defined(USART0_RX_vect) | |
57 | // fixed by Mark Sproul this is on the 644/644p | |
58 | //SIGNAL(SIG_USART_RECV) | |
59 | SIGNAL(USART0_RX_vect) | |
60 | { | |
61 | #if defined(UDR0) | |
62 | unsigned char c = UDR0; | |
63 | #elif defined(UDR) | |
64 | unsigned char c = UDR; // atmega8, atmega32 | |
65 | #else | |
66 | #error UDR not defined | |
67 | #endif | |
68 | store_char(c); | |
69 | } | |
70 | #endif | |
71 | ||
72 | // Constructors //////////////////////////////////////////////////////////////// | |
73 | ||
74 | MarlinSerial::MarlinSerial() | |
75 | { | |
76 | ||
77 | } | |
78 | ||
79 | // Public Methods ////////////////////////////////////////////////////////////// | |
80 | ||
81 | void MarlinSerial::begin(long baud) | |
82 | { | |
83 | uint16_t baud_setting; | |
84 | bool useU2X0 = true; | |
85 | ||
86 | #if F_CPU == 16000000UL | |
87 | // hardcoded exception for compatibility with the bootloader shipped | |
88 | // with the Duemilanove and previous boards and the firmware on the 8U2 | |
89 | // on the Uno and Mega 2560. | |
90 | if (baud == 57600) { | |
91 | useU2X0 = false; | |
92 | } | |
93 | #endif | |
94 | ||
95 | if (useU2X0) { | |
96 | UCSR0A = 1 << U2X0; | |
97 | baud_setting = (F_CPU / 4 / baud - 1) / 2; | |
98 | } else { | |
99 | UCSR0A = 0; | |
100 | baud_setting = (F_CPU / 8 / baud - 1) / 2; | |
101 | } | |
102 | ||
103 | // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) | |
104 | UBRR0H = baud_setting >> 8; | |
105 | UBRR0L = baud_setting; | |
106 | ||
107 | sbi(UCSR0B, RXEN0); | |
108 | sbi(UCSR0B, TXEN0); | |
109 | sbi(UCSR0B, RXCIE0); | |
110 | } | |
111 | ||
112 | void MarlinSerial::end() | |
113 | { | |
114 | cbi(UCSR0B, RXEN0); | |
115 | cbi(UCSR0B, TXEN0); | |
116 | cbi(UCSR0B, RXCIE0); | |
117 | } | |
118 | ||
119 | ||
120 | ||
121 | int MarlinSerial::peek(void) | |
122 | { | |
123 | if (rx_buffer.head == rx_buffer.tail) { | |
124 | return -1; | |
125 | } else { | |
126 | return rx_buffer.buffer[rx_buffer.tail]; | |
127 | } | |
128 | } | |
129 | ||
130 | int MarlinSerial::read(void) | |
131 | { | |
132 | // if the head isn't ahead of the tail, we don't have any characters | |
133 | if (rx_buffer.head == rx_buffer.tail) { | |
134 | return -1; | |
135 | } else { | |
136 | unsigned char c = rx_buffer.buffer[rx_buffer.tail]; | |
137 | rx_buffer.tail = (unsigned int)(rx_buffer.tail + 1) % RX_BUFFER_SIZE; | |
138 | return c; | |
139 | } | |
140 | } | |
141 | ||
142 | void MarlinSerial::flush() | |
143 | { | |
144 | // don't reverse this or there may be problems if the RX interrupt | |
145 | // occurs after reading the value of rx_buffer_head but before writing | |
146 | // the value to rx_buffer_tail; the previous value of rx_buffer_head | |
147 | // may be written to rx_buffer_tail, making it appear as if the buffer | |
148 | // don't reverse this or there may be problems if the RX interrupt | |
149 | // occurs after reading the value of rx_buffer_head but before writing | |
150 | // the value to rx_buffer_tail; the previous value of rx_buffer_head | |
151 | // may be written to rx_buffer_tail, making it appear as if the buffer | |
152 | // were full, not empty. | |
153 | rx_buffer.head = rx_buffer.tail; | |
154 | } | |
155 | ||
156 | ||
157 | ||
158 | ||
159 | /// imports from print.h | |
160 | ||
161 | ||
162 | ||
163 | ||
164 | void MarlinSerial::print(char c, int base) | |
165 | { | |
166 | print((long) c, base); | |
167 | } | |
168 | ||
169 | void MarlinSerial::print(unsigned char b, int base) | |
170 | { | |
171 | print((unsigned long) b, base); | |
172 | } | |
173 | ||
174 | void MarlinSerial::print(int n, int base) | |
175 | { | |
176 | print((long) n, base); | |
177 | } | |
178 | ||
179 | void MarlinSerial::print(unsigned int n, int base) | |
180 | { | |
181 | print((unsigned long) n, base); | |
182 | } | |
183 | ||
184 | void MarlinSerial::print(long n, int base) | |
185 | { | |
186 | if (base == 0) { | |
187 | write(n); | |
188 | } else if (base == 10) { | |
189 | if (n < 0) { | |
190 | print('-'); | |
191 | n = -n; | |
192 | } | |
193 | printNumber(n, 10); | |
194 | } else { | |
195 | printNumber(n, base); | |
196 | } | |
197 | } | |
198 | ||
199 | void MarlinSerial::print(unsigned long n, int base) | |
200 | { | |
201 | if (base == 0) write(n); | |
202 | else printNumber(n, base); | |
203 | } | |
204 | ||
205 | void MarlinSerial::print(double n, int digits) | |
206 | { | |
207 | printFloat(n, digits); | |
208 | } | |
209 | ||
210 | void MarlinSerial::println(void) | |
211 | { | |
212 | print('\r'); | |
213 | print('\n'); | |
214 | } | |
215 | ||
216 | void MarlinSerial::println(const String &s) | |
217 | { | |
218 | print(s); | |
219 | println(); | |
220 | } | |
221 | ||
222 | void MarlinSerial::println(const char c[]) | |
223 | { | |
224 | print(c); | |
225 | println(); | |
226 | } | |
227 | ||
228 | void MarlinSerial::println(char c, int base) | |
229 | { | |
230 | print(c, base); | |
231 | println(); | |
232 | } | |
233 | ||
234 | void MarlinSerial::println(unsigned char b, int base) | |
235 | { | |
236 | print(b, base); | |
237 | println(); | |
238 | } | |
239 | ||
240 | void MarlinSerial::println(int n, int base) | |
241 | { | |
242 | print(n, base); | |
243 | println(); | |
244 | } | |
245 | ||
246 | void MarlinSerial::println(unsigned int n, int base) | |
247 | { | |
248 | print(n, base); | |
249 | println(); | |
250 | } | |
251 | ||
252 | void MarlinSerial::println(long n, int base) | |
253 | { | |
254 | print(n, base); | |
255 | println(); | |
256 | } | |
257 | ||
258 | void MarlinSerial::println(unsigned long n, int base) | |
259 | { | |
260 | print(n, base); | |
261 | println(); | |
262 | } | |
263 | ||
264 | void MarlinSerial::println(double n, int digits) | |
265 | { | |
266 | print(n, digits); | |
267 | println(); | |
268 | } | |
269 | ||
270 | // Private Methods ///////////////////////////////////////////////////////////// | |
271 | ||
272 | void MarlinSerial::printNumber(unsigned long n, uint8_t base) | |
273 | { | |
274 | unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. | |
275 | unsigned long i = 0; | |
276 | ||
277 | if (n == 0) { | |
278 | print('0'); | |
279 | return; | |
280 | } | |
281 | ||
282 | while (n > 0) { | |
283 | buf[i++] = n % base; | |
284 | n /= base; | |
285 | } | |
286 | ||
287 | for (; i > 0; i--) | |
288 | print((char) (buf[i - 1] < 10 ? | |
289 | '0' + buf[i - 1] : | |
290 | 'A' + buf[i - 1] - 10)); | |
291 | } | |
292 | ||
293 | void MarlinSerial::printFloat(double number, uint8_t digits) | |
294 | { | |
295 | // Handle negative numbers | |
296 | if (number < 0.0) | |
297 | { | |
298 | print('-'); | |
299 | number = -number; | |
300 | } | |
301 | ||
302 | // Round correctly so that print(1.999, 2) prints as "2.00" | |
303 | double rounding = 0.5; | |
304 | for (uint8_t i=0; i<digits; ++i) | |
305 | rounding /= 10.0; | |
306 | ||
307 | number += rounding; | |
308 | ||
309 | // Extract the integer part of the number and print it | |
310 | unsigned long int_part = (unsigned long)number; | |
311 | double remainder = number - (double)int_part; | |
312 | print(int_part); | |
313 | ||
314 | // Print the decimal point, but only if there are digits beyond | |
315 | if (digits > 0) | |
316 | print("."); | |
317 | ||
318 | // Extract digits from the remainder one at a time | |
319 | while (digits-- > 0) | |
320 | { | |
321 | remainder *= 10.0; | |
322 | int toPrint = int(remainder); | |
323 | print(toPrint); | |
324 | remainder -= toPrint; | |
325 | } | |
326 | } | |
327 | // Preinstantiate Objects ////////////////////////////////////////////////////// | |
328 | ||
329 | ||
330 | MarlinSerial MSerial; | |
331 | ||
332 | MarlinSerial MSerial1; | |
333 | ||
334 | #endif // whole file | |
335 | #endif //teensylu | |
336 | ||
337 | #endif REPRAPPRO_MULTIMATERIALS | |
338 |