• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

/home/jgoppert/Projects/ap/libraries/APM_FastSerial/APM_FastSerial.cpp

Go to the documentation of this file.
00001 /*
00002         APM_FastSerial.cpp - Fast Serial Output for Ardupilot Mega Hardware (atmega1280)
00003         Itīs also compatible with standard Arduino boards (atmega 168 and 328)
00004         Interrupt driven Serial output with intermediate buffer
00005         Code Jose Julio and Jordi Muņoz. DIYDrones.com
00006 
00007         This library is free software; you can redistribute it and/or
00008         modify it under the terms of the GNU Lesser General Public
00009         License as published by the Free Software Foundation; either
00010         version 2.1 of the License, or (at your option) any later version.
00011 
00012         This library works as a complement of the standard Arduino Serial
00013         library. So user must initialize Standard Serial Arduino library first.
00014         This library works in Serial port 0 and Serial port3(telemetry port)[APM]
00015         Methods: (the same as standard arduino library, inherits from Print)
00016             write()  for bytes or array of bytes (binary output)
00017                 print()  for chars, strings, numbers and floats
00018                 println()
00019 */
00020 
00021 //#include "WProgram.h"
00022 #include "APM_FastSerial.h"
00023 extern "C" {
00024   // AVR LibC Includes
00025   #include <inttypes.h>
00026   #include <avr/interrupt.h>
00027   #include <avr/io.h>
00028   #include "WConstants.h"
00029 }
00030 #define TX_BUFFER_SIZE 80   // Serial output buffer size
00031 
00032 // Serial0 buffer
00033 uint8_t tx_buffer0[TX_BUFFER_SIZE];
00034 volatile int tx_buffer0_head=0;
00035 volatile int tx_buffer0_tail=0;
00036 
00037 #if defined(__AVR_ATmega1280__)
00038 // Serial3 buffer
00039 uint8_t tx_buffer3[TX_BUFFER_SIZE];
00040 volatile int tx_buffer3_head=0;
00041 volatile int tx_buffer3_tail=0;
00042 #endif
00043 
00044 #if defined(__AVR_ATmega1280__)  // For atmega1280 we use Serial port 0 and 3
00045 // Serial0 interrupt
00046 ISR(SIG_USART0_DATA)
00047 {
00048   uint8_t data;
00049 
00050   if (tx_buffer0_tail == tx_buffer0_head)
00051     UCSR0B &= ~(_BV(UDRIE0));    // Disable interrupt
00052   else {
00053     data = tx_buffer0[tx_buffer0_tail];
00054     tx_buffer0_tail = (tx_buffer0_tail + 1) % TX_BUFFER_SIZE;   
00055     UDR0 = data;
00056   }
00057 }
00058 
00059 // Serial3 interrupt
00060 ISR(SIG_USART3_DATA)
00061 {
00062   uint8_t data;
00063 
00064   if (tx_buffer3_tail == tx_buffer3_head)           
00065     UCSR3B &= ~(_BV(UDRIE3));  // Disable interrupt
00066   else {
00067     data = tx_buffer3[tx_buffer3_tail];
00068     tx_buffer3_tail = (tx_buffer3_tail + 1) % TX_BUFFER_SIZE;   
00069     UDR3 = data;
00070   }
00071 }
00072 #else
00073 
00074 // Serial interrupt
00075 ISR(USART_UDRE_vect)
00076 {
00077   uint8_t data;
00078 
00079   if (tx_buffer0_tail == tx_buffer0_head)
00080     UCSR0B &= ~(_BV(UDRIE0));    // Disable interrupt
00081   else {
00082     data = tx_buffer0[tx_buffer0_tail];
00083     tx_buffer0_tail = (tx_buffer0_tail + 1) % TX_BUFFER_SIZE;   
00084     UDR0 = data;
00085   }
00086 }
00087 #endif
00088 
00089 // Constructors ////////////////////////////////////////////////////////////////
00090 APM_FastSerial_Class::APM_FastSerial_Class(uint8_t SerialPort)
00091 {
00092   SerialPortNumber=SerialPort;   // This could be serial port 0 or 3
00093 }
00094 
00095 // Public Methods //////////////////////////////////////////////////////////////
00096 
00097 // This is the important function (basic funtion: send a byte)
00098 void APM_FastSerial_Class::write(uint8_t b)
00099 {
00100   uint8_t Enable_tx_int=0;
00101   uint8_t new_head;
00102 
00103   if (SerialPortNumber==0)  // Serial Port 0
00104     {
00105     // if buffer was empty then we enable Serial TX interrupt
00106     if (tx_buffer0_tail == tx_buffer0_head)
00107           Enable_tx_int=1;
00108   
00109     new_head = (tx_buffer0_head + 1) % TX_BUFFER_SIZE;  // Move to next position in the ring buffer
00110     if (new_head==tx_buffer0_tail)
00111       return;            // This is an Error : BUFFER OVERFLOW. We lost this character!!
00112 
00113     tx_buffer0[tx_buffer0_head] = b;  // Add data to the tx buffer
00114     tx_buffer0_head = new_head;              // Update head pointer
00115 
00116     if (Enable_tx_int)
00117       UCSR0B |= _BV(UDRIE0);   // Enable Serial TX interrupt
00118     }
00119 #if defined(__AVR_ATmega1280__)
00120   else   // Serial Port 3
00121     {
00122     // if buffer was empty then we enable Serial TX interrupt
00123     if (tx_buffer3_tail == tx_buffer3_head)
00124           Enable_tx_int=1;
00125   
00126     new_head = (tx_buffer3_head + 1) % TX_BUFFER_SIZE;  // Move to next position in the ring buffer
00127     if (new_head==tx_buffer3_tail)
00128       return;            // This is an Error : BUFFER OVERFLOW. We lost this character!!
00129 
00130     tx_buffer3[tx_buffer3_head] = b;  // Add data to the tx buffer
00131     tx_buffer3_head = new_head;              // Update head pointer
00132 
00133     if (Enable_tx_int)
00134       UCSR3B |= _BV(UDRIE3);   // Enable Serial TX interrupt
00135     }
00136 #endif
00137 }
00138 
00139 // Send a buffer of bytes (this is util for binary protocols)
00140 void APM_FastSerial_Class::write(const uint8_t *buffer, int size)
00141 {
00142         while (size--)
00143       write(*buffer++);
00144 }
00145 
00146 // We create this two instances
00147 APM_FastSerial_Class APM_FastSerial(0);       // For Serial port 0
00148 #if defined(__AVR_ATmega1280__)
00149         APM_FastSerial_Class APM_FastSerial3(3);  // For Serial port 3  (only Atmega1280)
00150 #endif

Generated for ArduPilot Libraries by doxygen