#include "Arduino.h" #include "config.h" #include "def.h" #include "Serial.h" #include "MultiWii.h" static volatile uint8_t serialHeadRX[UART_NUMBER],serialTailRX[UART_NUMBER]; static uint8_t serialBufferRX[RX_BUFFER_SIZE][UART_NUMBER]; static volatile uint8_t serialHeadTX[UART_NUMBER],serialTailTX[UART_NUMBER]; static uint8_t serialBufferTX[TX_BUFFER_SIZE][UART_NUMBER]; // ******************************************************* // For Teensy 2.0, these function emulate the API used for ProMicro // it cant have the same name as in the arduino API because it wont compile for the promini (eaven if it will be not compiled) // ******************************************************* #if defined(TEENSY20) unsigned char T_USB_Available(){ int n = Serial.available(); if (n > 255) n = 255; return n; } #endif // ******************************************************* // Interrupt driven UART transmitter - using a ring buffer // ******************************************************* #if defined(PROMINI) || defined(MEGA) #if defined(PROMINI) ISR(USART_UDRE_vect) { // Serial 0 on a PROMINI #endif #if defined(MEGA) ISR(USART0_UDRE_vect) { // Serial 0 on a MEGA #endif uint8_t t = serialTailTX[0]; if (serialHeadTX[0] != t) { if (++t >= TX_BUFFER_SIZE) t = 0; UDR0 = serialBufferTX[t][0]; // Transmit next byte in the ring serialTailTX[0] = t; } if (t == serialHeadTX[0]) UCSR0B &= ~(1<= TX_BUFFER_SIZE) t = 0; UDR1 = serialBufferTX[t][1]; // Transmit next byte in the ring serialTailTX[1] = t; } if (t == serialHeadTX[1]) UCSR1B &= ~(1<= TX_BUFFER_SIZE) t = 0; UDR2 = serialBufferTX[t][2]; serialTailTX[2] = t; } if (t == serialHeadTX[2]) UCSR2B &= ~(1<= TX_BUFFER_SIZE) t = 0; UDR3 = serialBufferTX[t][3]; serialTailTX[3] = t; } if (t == serialHeadTX[3]) UCSR3B &= ~(1<= TX_BUFFER_SIZE) serialTailTX[0] = 0; #if !defined(TEENSY20) USB_Send(USB_CDC_TX,serialBufferTX[serialTailTX[0]],1); #else Serial.write(serialBufferTX[serialTailTX[0]],1); #endif } break; case 1: UCSR1B |= (1<> 8; uint8_t l = ((F_CPU / 4 / baud -1) / 2); switch (port) { #if defined(PROMINI) case 0: UCSR0A = (1<= 100) && !defined(TEENSY20) case 0: UDIEN &= ~(1<tail) to avoid a test condition : data is lost anyway if it happens void store_uart_in_buf(uint8_t data, uint8_t portnum) { #if defined(SERIAL_RX) if (portnum == RX_SERIAL_PORT) { if (!spekFrameFlags) { sei(); uint32_t spekTimeNow = (timer0_overflow_count << 8) * (64 / clockCyclesPerMicrosecond()); //Move timer0_overflow_count into registers so we don't touch a volatile twice uint32_t spekInterval = spekTimeNow - spekTimeLast; //timer0_overflow_count will be slightly off because of the way the Arduino core timer interrupt handler works; that is acceptable for this use. Using the core variable avoids an expensive call to millis() or micros() spekTimeLast = spekTimeNow; if (spekInterval > 2500) { //Potential start of a Spektrum frame, they arrive every 11 or every 22 ms. Mark it, and clear the buffer. serialTailRX[portnum] = 0; serialHeadRX[portnum] = 0; spekFrameFlags = 0x01; } cli(); } } #endif uint8_t h = serialHeadRX[portnum]; serialBufferRX[h++][portnum] = data; if (h >= RX_BUFFER_SIZE) h = 0; serialHeadRX[portnum] = h; } #if defined(PROMINI) ISR(USART_RX_vect) { store_uart_in_buf(UDR0, 0); } #endif #if defined(PROMICRO) ISR(USART1_RX_vect) { store_uart_in_buf(UDR1, 1); } #endif #if defined(MEGA) ISR(USART0_RX_vect) { store_uart_in_buf(UDR0, 0); } ISR(USART1_RX_vect) { store_uart_in_buf(UDR1, 1); } ISR(USART2_RX_vect) { store_uart_in_buf(UDR2, 2); } ISR(USART3_RX_vect) { store_uart_in_buf(UDR3, 3); } #endif uint8_t SerialRead(uint8_t port) { #if defined(PROMICRO) #if defined(TEENSY20) if(port == 0) return Serial.read(); #else #if (ARDUINO >= 100) if(port == 0) USB_Flush(USB_CDC_TX); #endif if(port == 0) return USB_Recv(USB_CDC_RX); #endif #endif uint8_t t = serialTailRX[port]; uint8_t c = serialBufferRX[t][port]; if (serialHeadRX[port] != t) { if (++t >= RX_BUFFER_SIZE) t = 0; serialTailRX[port] = t; } return c; } #if defined(SERIAL_RX) uint8_t SerialPeek(uint8_t port) { uint8_t c = serialBufferRX[serialTailRX[port]][port]; if ((serialHeadRX[port] != serialTailRX[port])) return c; else return 0; } #endif uint8_t SerialAvailable(uint8_t port) { #if defined(PROMICRO) #if !defined(TEENSY20) if(port == 0) return USB_Available(USB_CDC_RX); #else if(port == 0) return T_USB_Available(); #endif #endif return ((uint8_t)(serialHeadRX[port] - serialTailRX[port]))%RX_BUFFER_SIZE; } uint8_t SerialUsedTXBuff(uint8_t port) { return ((uint8_t)(serialHeadTX[port] - serialTailTX[port]))%TX_BUFFER_SIZE; } void SerialSerialize(uint8_t port,uint8_t a) { uint8_t t = serialHeadTX[port]; if (++t >= TX_BUFFER_SIZE) t = 0; serialBufferTX[t][port] = a; serialHeadTX[port] = t; } void SerialWrite(uint8_t port,uint8_t c){ SerialSerialize(port,c);UartSendData(port); }