diff options
Diffstat (limited to 'demontsc/lib/pollserial/pollserial.cpp')
| -rwxr-xr-x | demontsc/lib/pollserial/pollserial.cpp | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/demontsc/lib/pollserial/pollserial.cpp b/demontsc/lib/pollserial/pollserial.cpp new file mode 100755 index 0000000..a417098 --- /dev/null +++ b/demontsc/lib/pollserial/pollserial.cpp @@ -0,0 +1,139 @@ +/*
+ pollserial.cpp Heavily modified version of:
+
+ HardwareSerial.cpp - Hardware serial library for Wiring
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Modified 23 November 2006 by David A. Mellis
+
+ Modified July 2010 by Myles D. Metzler
+*/
+
+#include <avr/io.h>
+#include <stdlib.h>
+#include "pollserial.h"
+
+#define BUFFER_SIZE 64
+
+rbuffer rxbuffer = {0,0,0};
+
+void USART_recieve() {
+#if defined ( UDR0 )
+ if( UCSR0A & _BV(RXC0)) {
+ uint8_t i = (rxbuffer.head + 1) & (BUFFER_SIZE - 1);
+ if ( i != rxbuffer.tail) {
+ rxbuffer.buffer[rxbuffer.head] = UDR0;
+ rxbuffer.head = i;
+ }
+ }
+#else
+ if( UCSRA & _BV(RXC)) {
+ uint8_t i = (rxbuffer.head + 1) & (BUFFER_SIZE - 1);
+ if ( i != rxbuffer.tail) {
+ rxbuffer.buffer[rxbuffer.head] = UDR;
+ rxbuffer.head = i;
+ }
+ }
+#endif
+}
+
+pt2Funct pollserial::begin(long baud) {
+ uint16_t baud_setting;
+ bool use_u2x;
+
+ rxbuffer.buffer = (unsigned char*)malloc(BUFFER_SIZE*sizeof(unsigned char));
+
+ // U2X mode is needed for baud rates higher than (CPU Hz / 16)
+ if (baud > F_CPU / 16) {
+ use_u2x = true;
+ }
+ else {
+ // figure out if U2X mode would allow for a better connection
+
+ // calculate the percent difference between the baud-rate specified and
+ // the real baud rate for both U2X and non-U2X mode (0-255 error percent)
+ uint8_t nonu2x_baud_error = abs((int)(255-((F_CPU/(16*(((F_CPU/8/baud-1)/2)+1))*255)/baud)));
+ uint8_t u2x_baud_error = abs((int)(255-((F_CPU/(8*(((F_CPU/4/baud-1)/2)+1))*255)/baud)));
+
+ // prefer non-U2X mode because it handles clock skew better
+ use_u2x = (nonu2x_baud_error > u2x_baud_error);
+ }
+ if (use_u2x) {
+#if defined ( UDR0 )
+ UCSR0A = _BV(U2X0);
+#else
+ UCSRA = _BV(U2X);
+#endif
+ baud_setting = (F_CPU / 4 / baud - 1) / 2;
+ }
+ else {
+#if defined ( UDR0 )
+ UCSR0A = 0;
+#else
+ UCSRA = 0;
+#endif
+ baud_setting = (F_CPU / 8 / baud - 1) / 2;
+ }
+
+ // assign the baud_setting, a.k.a. (USART Baud Rate Register)
+#if defined ( UDR0 )
+ UBRR0 = baud_setting;
+ UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+#else
+ UBRR = baud_setting;
+ UCSRB = _BV(RXEN) | _BV(TXEN);
+#endif
+
+ return &USART_recieve;
+}
+
+void pollserial::end() {
+ UCSR0B &= ~(_BV(RXEN0) | _BV(TXEN0));
+ free(rxbuffer.buffer);
+}
+
+uint8_t pollserial::available() {
+ return (BUFFER_SIZE + rxbuffer.head - rxbuffer.tail) & (BUFFER_SIZE-1);
+}
+
+int pollserial::read() {
+ if (rxbuffer.head == rxbuffer.tail)
+ return -1;
+ else {
+ uint8_t c = rxbuffer.buffer[rxbuffer.tail];
+ //tail = (tail + 1) & 63;
+ if (rxbuffer.tail == BUFFER_SIZE)
+ rxbuffer.tail = 0;
+ else
+ rxbuffer.tail++;
+ return c;
+ }
+}
+
+void pollserial::flush() {
+ rxbuffer.head = rxbuffer.tail;
+}
+
+size_t pollserial::write(uint8_t c) {
+#if defined ( UDR0 )
+ while (!((UCSR0A) & _BV(UDRE0)));
+ UDR0 = c;
+#else
+ while (!((UCSRA) & _BV(UDRE)));
+ UDR = c;
+#endif
+}
\ No newline at end of file |
