aboutsummaryrefslogtreecommitdiff
path: root/arduino/ace_cpp_old/SafeSerial.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'arduino/ace_cpp_old/SafeSerial.cpp')
-rw-r--r--arduino/ace_cpp_old/SafeSerial.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/arduino/ace_cpp_old/SafeSerial.cpp b/arduino/ace_cpp_old/SafeSerial.cpp
new file mode 100644
index 0000000..bab930e
--- /dev/null
+++ b/arduino/ace_cpp_old/SafeSerial.cpp
@@ -0,0 +1,59 @@
+#include "SafeSerial.h"
+
+#include <avr/interrupt.h>
+
+typedef struct {
+ uint8_t buffer[SERIAL_BUFFER_SIZE];
+ volatile uint16_t head;
+ volatile uint16_t tail;
+} ring_buffer;
+
+static ring_buffer tx_buffer = {{0}, 0, 0};
+
+SafeSerial::begin(uint32_t baud) {
+ //enable double speed transmission
+ *ucsrXa |= (1 << u2xX);
+
+ uint16_t baudSetting = (F_CPU / 4 / baud - 1) / 2;
+ // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
+ *ubrrXh = baudSetting >> 8;
+ *ubrrXl = baudSetting;
+
+ // defaults to 8-bit, no parity, 1 stop bit
+ *ucsrXb |= (1 << *exenX) | (1 << *txenX) | (1 << *rxcieX);
+ *ucsrXb &= ~(1 << *udrieX) | (1 << *txenX) | (1 << *rxcieX);
+}
+
+
+//receive
+ISR(USART0_RX_vect) {
+ uint8_t c = UDR0;
+ serial.put(c);
+}
+
+//data register empty
+ISR(USART0_UDRE_vect) {
+ if (tx_buffer.head == tx_buffer.tail) {
+ //buffer empty, disable interruot
+ UCSR0B &= ~(1 << UDRIE0);
+ } else {
+ uint8_t c = tx_buffer.buffer[tx_buffer.tail];
+ tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE;
+ UDR0 = c; //write next byte
+ }
+}
+
+void SafeSerial::send(uint8_t byte) {
+ uint16_t i = (tx_buffer.head + 1) % SERIAL_BUFFER_SIZE;
+
+ // If the output buffer is full, there's nothing for it other than to
+ // wait for the interrupt handler to empty it a bit
+if (i == tx_buffer.tail) return;
+ //while (i == tx_buffer.tail) {};
+
+ tx_buffer.buffer[tx_buffer.head] = byte;
+ tx_buffer.head = i;
+
+ //enable data register empty interrupt
+ UCSR0B |= (1 << UDRIE0);
+};