1,256 → 1,264 |
/**************************************************************************** |
* 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 <avr/io.h> |
#include <avr/interrupt.h> |
#include <util/delay.h> |
#include "main.h" |
#include "usart1.h" |
|
#if !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
|
volatile uint8_t rxd_buffer_locked = 0; |
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN]; |
volatile uint8_t txd_buffer[TXD_BUFFER_LEN]; |
volatile uint8_t ReceivedBytes = 0; |
volatile uint8_t *pRxData = 0; |
volatile uint8_t RxDataLen = 0; |
|
/* ########################################################################## |
* 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 TX in USART |
DDRB &= ~(1<<DDB3); // set TXD pin as input |
PORTB &= ~(1 << PORTB3); // disable pullup on TXD pin |
} |
|
/** |
* enable the txd pin of usart1 |
*/ |
void usart1_EnableTXD(void) { |
DDRB |= (1<<DDB3); // set TXD pin as output |
PORTB &= ~(1 << PORTB3); // disable pullup on TXD pin |
UCSR1B |= (1 << TXEN1); // enable TX in USART |
UCSR1B |= (1 << TXCIE1); // enable 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++; |
} |
} |
|
/** |
* transmit interrupt handler |
* unused |
*/ |
ISR(SIG_USART1_DATA) { |
} |
|
/** |
* 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); |
} |
|
/** |
* short script to directly send a request thorugh usart including en- and disabling it |
* where <address> is the address of the receipient, <label> is which data set to request |
* and <ms> represents the milliseconds delay between data |
*/ |
void usart1_request_mk_data(uint8_t address, char label, uint8_t ms) { |
// re-enable TXD pin |
usart1_EnableTXD(); |
|
unsigned char mstenth = ms/10; |
sendMKData(label, address, &mstenth, 1); |
// wait until UDR ready |
while (!(UCSR1A & (1 << UDRE1))); |
// disable TXD pin again |
usart1_DisableTXD(); |
} |
|
#endif |
/**************************************************************************** |
* 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 <avr/io.h> |
#include <avr/interrupt.h> |
#include <util/delay.h> |
#include "main.h" |
#include "usart1.h" |
|
#if !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
|
volatile uint8_t rxd_buffer_locked = 0; |
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN]; |
volatile uint8_t txd_buffer[TXD_BUFFER_LEN]; |
volatile uint8_t ReceivedBytes = 0; |
volatile uint8_t *pRxData = 0; |
volatile uint8_t RxDataLen = 0; |
|
/* ########################################################################## |
* 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 TX in USART |
DDRB &= ~(1 << DDB3); // set TXD pin as input |
PORTB &= ~(1 << PORTB3); // disable pullup on TXD pin |
} |
|
/** |
* enable the txd pin of usart1 |
*/ |
void usart1_EnableTXD(void) { |
DDRB |= (1 << DDB3); // set TXD pin as output |
PORTB &= ~(1 << PORTB3); // disable pullup on TXD pin |
UCSR1B |= (1 << TXEN1); // enable TX in USART |
UCSR1B |= (1 << TXCIE1); // enable 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++; |
} |
} |
|
/** |
* transmit interrupt handler |
* unused |
*/ |
ISR(SIG_USART1_DATA) { |
} |
|
/* |
* 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) { |
uint8_t c; |
// catch the received byte |
c = UDR1; |
if (rxd_buffer_locked) return; // if rxd buffer is locked immediately return |
static uint16_t crc; |
static uint8_t ptr_rxd_buffer = 0; |
static uint8_t c1 = 0; |
static uint8_t c2 = 0; |
static uint8_t usart_rx_ok = 0; |
uint8_t crc1, crc2; |
// the rxd buffer is unlocked |
if (usart_rx_ok == 0) { |
if ((c2 == '#') && (c1 == 'b') && (c == 'D' || c == 'V' || c == 'O')) { |
usart_rx_ok = 1; |
rxd_buffer[ptr_rxd_buffer++] = c2; |
crc = c2; |
rxd_buffer[ptr_rxd_buffer++] = c1; |
crc += c1; |
rxd_buffer[ptr_rxd_buffer++] = c; |
crc += c; |
c2 = 0; |
c1 = 0; |
LED1_ON |
LED2_OFF |
} else { |
c2 = c1; |
c1 = c; |
} |
} 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 |
LED1_OFF |
} else { // checksum invalid |
rxd_buffer_locked = 0; // unlock rxd buffer |
LED2_ON |
} |
ptr_rxd_buffer = 0; // reset rxd buffer pointer |
usart_rx_ok = 0; |
} |
} else { // rxd buffer overrun |
ptr_rxd_buffer = 0; // reset rxd buffer |
rxd_buffer_locked = 0; // unlock rxd buffer |
usart_rx_ok = 0; |
LED2_ON |
} |
} |
|
/** |
* 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); |
} |
|
/** |
* short script to directly send a request thorugh usart including en- and disabling it |
* where <address> is the address of the receipient, <label> is which data set to request |
* and <ms> represents the milliseconds delay between data |
*/ |
void usart1_request_mk_data(uint8_t address, char label, uint8_t ms) { |
// re-enable TXD pin |
usart1_EnableTXD(); |
|
unsigned char mstenth = ms / 10; |
sendMKData(label, address, &mstenth, 1); |
// wait until UDR ready |
while (!(UCSR1A & (1 << UDRE1))); |
// disable TXD pin again |
usart1_DisableTXD(); |
} |
|
#endif |