Files
opentx/serial.cpp
T
bsongis 890e53a32b Small RAM saving.
Some code ported for the ersky9x board
Mavlink port commited
2012-03-21 18:31:00 +00:00

227 lines
5.4 KiB
C++

/*
* Authors - Gerard Valade <gerard.valade@gmail.com>
*
* Adapted from frsky
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This program 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 General Public License for
* more details.
*
*/
#include "open9x.h"
#include "serial.h"
/*
Receive serial (RS-232) characters, detecting and storing each Fr-Sky
0x7e-framed packet as it arrives. When a complete packet has been
received, process its data into storage variables. NOTE: This is an
interrupt routine and should not get too lengthy. I originally had
the buffer being checked in the perMain function (because per10ms
isn't quite often enough for data streaming at 9600baud) but alas
that scheme lost packets also. So each packet is parsed as it arrives,
directly at the ISR function (through a call to frskyProcessPacket).
If this proves a problem in the future, then I'll just have to implement
a second buffer to receive data while one buffer is being processed (slowly).
*/
#ifndef SIMU
ISR (USART0_RX_vect)
{
uint8_t iostat; //USART control and Status Register 0 A
// uint8_t rh; //USART control and Status Register 0 B
UCSR0B &= ~(1 << RXCIE0); // disable Interrupt
sei();
iostat = UCSR0A; //USART control and Status Register 0 A
uint8_t byte = UDR0;
/*
bit 7 6 5 4 3 2 1 0
RxC0 TxC0 UDRE0 FE0 DOR0 UPE0 U2X0 MPCM0
RxC0: Receive complete
TXC0: Transmit Complete
UDRE0: USART Data Register Empty
FE0: Frame Error
DOR0: Data OverRun
UPE0: USART Parity Error
U2X0: Double Tx Speed
MPCM0: MultiProcessor Comms Mode
*/
if (iostat & ((1 << FE0) | (1 << DOR0) | (1 << UPE0))) {
byte = 0;
}
//rh = UCSR0B; //USART control and Status Register 0 B
#ifdef MAVLINK
(RXHandler)(byte);
#endif
cli();
UCSR0B |= (1 << RXCIE0); // enable Interrupt
}
#endif
inline void SERIAL_EnableRXD(void) {
UCSR0B |= (1 << RXEN0); // enable RX
UCSR0B |= (1 << RXCIE0); // enable Interrupt
}
#if 0
void SERIAL_DisableRXD(void) {
UCSR0B &= ~(1 << RXEN0); // disable RX
UCSR0B &= ~(1 << RXCIE0); // disable Interrupt
}
#endif
/*
USART0 (transmit) Data Register Emtpy ISR
Usef to transmit FrSky data packets, which are buffered in frskyTXBuffer.
*/
uint8_t serialTxBuffer[MAX_TX_BUFFER]; // 32 characters
uint8_t serialTxBufferCount = 0;
uint8_t * ptrTxISR = 0;
serial_tx_state_t serialTxState = TX_STATE_EMPTY;
#ifndef SIMU
ISR(USART0_UDRE_vect)
{
if (serialTxBufferCount > 0) {
UDR0 = *ptrTxISR++;
serialTxBufferCount--;
} else {
UCSR0B &= ~(1 << UDRIE0); // disable UDRE0 interrupt
serialTxState = TX_STATE_EMPTY;
}
}
#endif
void SERIAL_start_uart_send() {
ptrTxISR = serialTxBuffer;
serialTxBufferCount = 0;
}
void SERIAL_end_uart_send() {
ptrTxISR = serialTxBuffer;
//UCSR0B |= (1 << UDRIE0); // enable UDRE0 interrupt
serialTxState = TX_STATE_READY;
}
void SERIAL_send_uart_bytes(uint8_t * buf, uint16_t len) {
while (len--) {
*ptrTxISR++ = *buf++;
serialTxBufferCount++;
}
}
#if 0
void SERIAL_transmitBuffer(uint8_t len) {
serialTxBufferCount = len;
ptrTxISR = serialTxBuffer;
//UCSR0B |= (1 << UDRIE0); // enable UDRE0 interrupt
serialTxState = TX_STATE_READY;
}
#endif
void SERIAL_startTX(void) {
if (serialTxState == TX_STATE_READY) {
serialTxState = TX_STATE_BUSY;
UCSR0B |= (1 << UDRIE0); // enable UDRE0 interrupt
}
}
static void uart_19200(void) {
#ifndef SIMU
#define BAUD 19200
#include <util/setbaud.h>
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
#endif
}
static void uart_38400(void) {
#ifndef SIMU
#undef BAUD // avoid compiler warning
#define BAUD 38400
#include <util/setbaud.h>
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
#endif
}
static void uart_57600(void) {
#ifndef SIMU
#undef BAUD // avoid compiler warning
#define BAUD 57600
#include <util/setbaud.h>
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
#endif
}
inline void SERIAL_EnableTXD(void) {
//UCSR0B |= (1 << TXEN0); // enable TX
UCSR0B |= (1 << TXEN0) | (1 << UDRIE0); // enable TX and TX interrupt
}
#if 0
void SERIAL_DisableTXD(void) {
UCSR0B &= ~(1 << TXEN0); // disable TX
UCSR0B &= ~(1 << UDRIE0); // disable Interrupt
}
#endif
void SERIAL_Init(void) {
DDRE &= ~(1 << DDE0); // set RXD0 pin as input
PORTE &= ~(1 << PORTE0); // disable pullup on RXD0 pin
uint8_t b = 1; // TODO g_eeGeneral.baudRate;
if (b == 0) {
uart_19200();
}
else if (b == 1) {
uart_38400();
}
else if (b == 2) {
uart_57600();
}
#if 0
uart_57600();
#endif
// UCSR0A &= ~(1 << U2X0); // disable double speed operation
// set 8N1
UCSR0B = 0 | (0 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (0 << RXEN0) | (0 << TXEN0) | (0 << UCSZ02);
UCSR0C = 0 | (1 << UCSZ01) | (1 << UCSZ00);
while (UCSR0A & (1 << RXC0))
UDR0; // flush receive buffer
SERIAL_EnableTXD();
SERIAL_EnableRXD();
}