0,0 → 1,218 |
/**************************************************************************** |
* Copyright (C) 2009 by Claas Anders "CaScAdE" Rathje * |
* admiralcascade@gmail.com * |
* Project-URL: http://www.mylifesucks.de/oss/c-osd/ * |
* * |
* This program is free software; you can redistribute it and/or modify * |
* it under the terms of the GNU General Public License as published by * |
* the Free Software Foundation; either version 2 of the License. * |
* * |
* 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. * |
* * |
* You should have received a copy of the GNU General Public License * |
* along with this program; if not, write to the * |
* Free Software Foundation, Inc., * |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
****************************************************************************/ |
|
#include "usart1.h" |
|
/* ########################################################################## |
* USART stuff |
* ##########################################################################*/ |
|
/** |
* init usart1 |
*/ |
void usart1_init() { |
UBRR1H = ((F_CPU / (16UL * baud)) - 1) >> 8; |
UBRR1L = (F_CPU / (16UL * baud)) - 1; |
|
// Enable receiver and transmitter; enable RX interrupt |
UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1); |
|
//asynchronous 8N1 |
UCSR1C = (1 << URSEL1) | (3 << UCSZ10); |
} |
|
/** |
* disable the txd pin of usart1 |
*/ |
void usart1_DisableTXD(void) { |
UCSR1B &= ~(1 << TXCIE1); // disable TX-Interrupt |
UCSR1B &= ~(1 << TXEN1); // disable TXD in USART |
DDRB &= ~(1<<DDB3); // set TXD pin as input |
PORTB &= ~(1 << PORTB3); |
} |
|
/** |
* enable the txd pin of usart1 |
*/ |
void usart1_EnableTXD(void) { |
DDRB |= (1<<DDB3); // set TXD pin as output |
PORTB &= ~(1 << PORTB3); |
UCSR1B |= (1 << TXEN1); // enable TX in USART |
UCSR1B |= (1 << TXCIE1); // disable TX-Interrupt |
} |
|
|
/** |
* send a single <character> through usart1 |
*/ |
void usart1_putc(unsigned char character) { |
// wait until UDR ready |
while (!(UCSR1A & (1 << UDRE1))); |
UDR1 = character; |
} |
|
/** |
* send a <string> throught usart1 |
*/ |
void usart1_puts(char *s) { |
while (*s) { |
usart1_putc(*s); |
s++; |
} |
} |
|
/** |
* receive data through usart1 |
* portions taken and adapted from |
* http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Fbranches%2FV0.72p+Code+Redesign+killagreg%2Fuart0.c |
*/ |
ISR(SIG_USART1_RECV) { |
if (rxd_buffer_locked) return; // if rxd buffer is locked immediately return |
LED1_ON |
static uint16_t crc; |
static uint8_t ptr_rxd_buffer = 0; |
uint8_t crc1, crc2; |
uint8_t c; |
|
c = UDR1; // catch the received byte |
|
// the rxd buffer is unlocked |
if ((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received |
{ |
/* |
// skip other datasets |
if (ptr_rxd_buffer == 2 && rxd_buffer[ptr_rxd_buffer] != 'O') { |
ptr_rxd_buffer = 0; // reset rxd buffer |
rxd_buffer_locked = 0; // unlock rxd buffer |
}*/ |
rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer |
crc = c; // init crc |
} else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes |
{ |
if (c != '\r') // no termination character |
{ |
rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer |
crc += c; // update crc |
} else // termination character was received |
{ |
// the last 2 bytes are no subject for checksum calculation |
// they are the checksum itself |
crc -= rxd_buffer[ptr_rxd_buffer - 2]; |
crc -= rxd_buffer[ptr_rxd_buffer - 1]; |
// calculate checksum from transmitted data |
crc %= 4096; |
crc1 = '=' + crc / 64; |
crc2 = '=' + crc % 64; |
// compare checksum to transmitted checksum bytes |
if ((crc1 == rxd_buffer[ptr_rxd_buffer - 2]) && (crc2 == rxd_buffer[ptr_rxd_buffer - 1])) { // checksum valid |
rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character |
ReceivedBytes = ptr_rxd_buffer + 1; // store number of received bytes |
rxd_buffer_locked = 1; // lock the rxd buffer |
} else { // checksum invalid |
rxd_buffer_locked = 0; // unlock rxd buffer |
} |
ptr_rxd_buffer = 0; // reset rxd buffer pointer |
} |
} else // rxd buffer overrun |
{ |
ptr_rxd_buffer = 0; // reset rxd buffer |
rxd_buffer_locked = 0; // unlock rxd buffer |
} |
LED1_OFF |
} |
|
/** |
* Decode the recevied Buffer |
* portions taken and adapted from |
* http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c |
*/ |
void Decode64(void) { |
uint8_t a, b, c, d; |
uint8_t x, y, z; |
uint8_t ptrIn = 3; |
uint8_t ptrOut = 3; |
uint8_t len = ReceivedBytes - 6; |
|
while (len) { |
a = rxd_buffer[ptrIn++] - '='; |
b = rxd_buffer[ptrIn++] - '='; |
c = rxd_buffer[ptrIn++] - '='; |
d = rxd_buffer[ptrIn++] - '='; |
|
x = (a << 2) | (b >> 4); |
y = ((b & 0x0f) << 4) | (c >> 2); |
z = ((c & 0x03) << 6) | d; |
|
if (len--) rxd_buffer[ptrOut++] = x; |
else break; |
if (len--) rxd_buffer[ptrOut++] = y; |
else break; |
if (len--) rxd_buffer[ptrOut++] = z; |
else break; |
} |
pRxData = &rxd_buffer[3]; |
RxDataLen = ptrOut - 3; |
} |
|
/** |
* request Data through USART in special MK format by adding checksum and |
* encode data in modified Base64 |
* portions taken and adapted from |
* http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c |
*/ |
void sendMKData(unsigned char cmd, unsigned char addr, unsigned char *snd, unsigned char len) { |
unsigned int pt = 0; |
unsigned char a, b, c; |
unsigned char ptr = 0; |
|
txd_buffer[pt++] = '#'; // Start-Byte |
txd_buffer[pt++] = 'a' + addr; // Adress |
txd_buffer[pt++] = cmd; // Command |
while (len) { |
if (len) { |
a = snd[ptr++]; |
len--; |
} else a = 0; |
if (len) { |
b = snd[ptr++]; |
len--; |
} else b = 0; |
if (len) { |
c = snd[ptr++]; |
len--; |
} else c = 0; |
txd_buffer[pt++] = '=' + (a >> 2); |
txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4)); |
txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6)); |
txd_buffer[pt++] = '=' + (c & 0x3f); |
} |
|
// add crc |
unsigned int tmpCRC = 0, i; |
for (i = 0; i < pt; i++) { |
tmpCRC += txd_buffer[i]; |
} |
tmpCRC %= 4096; |
txd_buffer[i++] = '=' + tmpCRC / 64; |
txd_buffer[i++] = '=' + tmpCRC % 64; |
txd_buffer[i++] = '\r'; |
|
usart1_puts((char*) txd_buffer); |
} |