Rev 1465 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include "usart.h"
#include "tracking.h"
/********************************************************************************************************************/
/* */
/* MK Protokoll */
/* http://www.mikrokopter.de/ucwiki/en/SerialCommands?highlight=(command) */
/* http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol) */
/* */
/* Slave-Address Part */
/* 1 FC */
/* 2 NC */
/* 3 MK3MAG */
/* */
/* Auszug von Commands, nur OSD verwendet: */
/* Received by NC | ent by NC */
/* | since NC */
/* Description ID Address Data | ID Address Data Firmware */
/* Debug Request 'd' AnyAddr u8 AutoSendInterval. Value is | 'D' SlaveAddr Debug Data Struct */
/* multiplied by 10 in receiver and , | */
/* then used as milliseconds. Subsciption | */
/* needs to be renewed every 4s. | */
/* Request OSD 'o' NC-Addr 1 byte sending interval (in 10ms steps)| 'O' NC-Addr NaviDataStruct 0.12h */
/* Data | */
/* Redirect UART 'u' NC-Addr 1 byte param for uart selector (0=FC, | - - - 0.12h */
/* 1=MK3MAG, 2=MKGPS), can be switched | */
/* back to NC debug by sending the magic | */
/* packet "0x1B,0x1B,0x55,0xAA,0x00" | */
/* Set 3D-Data 'c' AnyAddr u8 Interval | 'C' NC-Addr struct Data3D 0.14a */
/* Interval */
/* */
/********************************************************************************************************************/
char rx_buffer
[RXD_BUFFER_SIZE
];
volatile uint8_t rx_len
;
volatile uint8_t rx_ready
= 0;
uint8_t rx_GPS
;
static char start
;
static char end
;
/**************************************************************/
/* */
/* USART */
/* 8 Datenbits, 1 Stopbit, keine Parität */
/* */
/**************************************************************/
void USART_Init
(unsigned int baud
)
{ uint16_t ubrx
;
ubrx
= F_CPU
/(baud
* 16L) - 1;
/* Set baud rate */
UBRR0H
= (unsigned char)(ubrx
>>8);
UBRR0L
= (unsigned char)ubrx
;
/* RX Complete Interrupt Enable, Enable receiver and transmitter */
UCSR0B
= (1<<RXCIE0
) | (1<<RXEN0
) | (1<<TXEN0
);
/* Asynchronous USART, no Parity, Set frame format: 8data, 1stop bit */
UCSR0C
= (1<<UCSZ01
) | (1<<UCSZ00
); // 8data Bit
}
void USART_send_Chr
(unsigned char data
)
{
/* Wait for empty transmit Puffer */
while ( !( UCSR0A
& (1<<UDRE0
)) ) ;
/* Put data into Puffer, sends the data */
UDR0
= data
;
}
void USART_send_Str
(char *str
)
{
while (*str
) {
USART_send_Chr
(*str
);
str
++;
}
}
/*
// verwendet Orginal H&I MK-Software http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol)
// kann auch vereinfacht werden ==> gleich kodierten String senden char *tx_osd = {"#co?]==EH\r\0"}
// Funktion getestet und funktioniert
void tx_Mk(unsigned char addr, char cmd, char *data, uint8_t len)
{ char tx_buffer[TXD_BUFFER_SIZE];
uint8_t tx_i = 0;
uint8_t i = 0;
unsigned char a,b,c;
unsigned int tmpCRC = 0;
tx_buffer[tx_i++] = '#'; // Start-Byte
tx_buffer[tx_i++] = 'a' + addr; // Adress
tx_buffer[tx_i++] = cmd; // Command
// code64
while (len) {
if (len) { a = data[i++]; len--;} else a = 0;
if (len) { b = data[i++]; len--;} else b = 0;
if (len) { c = data[i++]; len--;} else c = 0;
tx_buffer[tx_i++] = '=' + (a >> 2);
tx_buffer[tx_i++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
tx_buffer[tx_i++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
tx_buffer[tx_i++] = '=' + (c & 0x3f);
}
// add crc
for (i = 0; i < tx_i; i++) {
tmpCRC += tx_buffer[i];
}
tmpCRC %= 4096;
tx_buffer[i++] = '=' + tmpCRC / 64;
tx_buffer[i++] = '=' + tmpCRC % 64;
tx_buffer[i++] = '\r'; // End-Byte
tx_buffer[i++] = '\0'; // USART_send_Str(...) ==> End-while
USART_send_Str(tx_buffer);
} */
ISR
(USART0_RX_vect
)
{ char received
;
static uint8_t line_flag
= 1;
static char* ptr_write
= rx_buffer
;
static uint8_t frame
= 6;
received
= UDR0
;
if (rx_ready
== 0) {
if ((received
== start
) && line_flag
) { // start '#', '$' or 0x80
line_flag
= 0; // New line has begun
ptr_write
= rx_buffer
; // Begin at start of buffer
rx_len
= 0;
}
if (line_flag
== 0) { // Are we receiving a line?
*ptr_write
= received
; // Add current byte
rx_len
++;
// GPS Datensatzende
if (rx_GPS
) {
if (received
== end
) { // End of MK-GPS or NMEA-line?
line_flag
= 1; // Yes, start new line
rx_ready
= 1; // Lock buffer until line has been processed
}
}
// Pololu Micro Serial very reduced/simplified; rx_len-checks 1 higher ==> already incremented
else {
if ((rx_len
== 2) && (received
!= 0x01)) line_flag
= 1; // device
if ((rx_len
== 3) && (received
> 0x01)) frame
= 6; else frame
= 5; // command
if (rx_len
== frame
) {
line_flag
= 1;
rx_ready
= 1; // Lock buffer until line has been processed
}
}
ptr_write
++;
if(rx_len
== RXD_BUFFER_SIZE
) line_flag
= 1; // Line too long? Try again
}
}
}
uint8_t hexDigitToInt
(uint8_t digit
)
{
if (digit
>= '0' && digit
<= '9') return digit
- '0';
if (digit
>= 'a' && digit
<= 'f') return digit
- 'a' + 10;
if (digit
>= 'A' && digit
<= 'F') return digit
- 'A' + 10;
return 0;
}
uint8_t decodeNMEA
(void)
{ uint8_t ret
= 0;
uint8_t crc
;
uint8_t tmpCRC
= 0;
uint8_t i
;
if (rx_ready
== 1 && rx_len
> 0) {
// Calculate checksum
for (i
= 1; i
< rx_len
&& rx_buffer
[i
] != '*'; i
++) {
tmpCRC
^= rx_buffer
[i
];
}
if (rx_len
>= i
+ 3) {
crc
= hexDigitToInt
(rx_buffer
[i
+ 1]) << 4 | hexDigitToInt
(rx_buffer
[i
+ 2]);
if (crc
== tmpCRC
) {
rx_buffer
[i
] = 0;
strcpy(data_decode
, &rx_buffer
[1]); // Data without $, crc
ret
= 1;
wi232RX
= 1; // So antenna-symbol will blink
cli
();
rx_timeout
= 0; // Got valid data, reset counter
sei
();
}
}
}
if (rx_timeout
< RX_TIME_OLD
) wi232RX
= 1;
rx_ready
= 0; // Unlock buffer, next NMEA string can be received
return ret
;
}
// verwendet aus Orginal H&I MK-Software http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol)
void Decode64
(char *ptrOut
, uint8_t len
, uint8_t ptrIn
)
{ unsigned char a
,b
,c
,d
;
unsigned char ptr
= 0;
unsigned char x
,y
,z
;
while(len
)
{
a
= rx_buffer
[ptrIn
++] - '=';
b
= rx_buffer
[ptrIn
++] - '=';
c
= rx_buffer
[ptrIn
++] - '=';
d
= rx_buffer
[ptrIn
++] - '=';
x
= (a
<< 2) | (b
>> 4);
y
= ((b
& 0x0f) << 4) | (c
>> 2);
z
= ((c
& 0x03) << 6) | d
;
if(len
--) ptrOut
[ptr
++] = x
; else break;
if(len
--) ptrOut
[ptr
++] = y
; else break;
if(len
--) ptrOut
[ptr
++] = z
; else break;
}
}
// eingearbeitet Original H&I MK-Software mkprotocol.h und mkprotocol.c
uint8_t rx_line_decode
(char rx_ID
)
{ uint8_t ret
= 0;
uint8_t crc1
,crc2
;
int tmpCRC
= 0;
// rx_ready gleichzeitig usart rx_buffer schreiben gesperrt
if ((rx_ready
== 1) && (rx_len
> 2) && (rx_buffer
[2] == rx_ID
)) {
// Checksumme
// verwendet http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol)
for(uint8_t i
= 0; i
< rx_len
- 3;i
++) {
tmpCRC
+= rx_buffer
[i
];
}
tmpCRC
%= 4096;
crc1
= '=' + tmpCRC
/ 64;
crc2
= '=' + tmpCRC
% 64;
if ((crc1
== rx_buffer
[rx_len
-3]) && (crc2
== rx_buffer
[rx_len
-2])) {
Decode64
(data_decode
, rx_len
- 6, 3); // Daten ohne Satzzeichen, header und crc
ret
= 1;
}
cli
();
rx_timeout
= 0; // wenn kein gültiger Datensatz rx_ID ==> Counter wird nicht mehr rückgesetzt
sei
();
}
// für Blinken des Antennenzeichens, MK antwortet immer mit cmd Großbuchstaben
if ((rx_timeout
< RX_TIME_OLD
) && (rx_buffer
[2] >= 'A') && (rx_buffer
[2] <= 'Z')) wi232RX
= 1;
rx_ready
= 0; // Puffer Schreiben entsperren, neuer MK-Datensatz kann wieder empfangen/gepuffert werden
return(ret
);
}
void USART_RX_Mode
(uint8_t tracking
)
{
switch (tracking
) {
case TRACKING_GPS
:
start
= '#';
end
= '\r';
rx_GPS
= 1;
break;
case TRACKING_NMEA
:
start
= '$';
end
= '\n';
rx_GPS
= 1;
break;
default:
start
= 0x80;
rx_GPS
= 0;
break;
}
}
uint8_t Get_Pololu_cmd
(char *ptrOut
, uint8_t ptrIn
)
{
rx_len
-=2; // ohne Start-Char und device
if (rx_ready
== 1) {
for (uint8_t i
= 0; i
< rx_len
; i
++)
ptrOut
[i
] = rx_buffer
[ptrIn
++]; // ab Pololu-Command
}
else
rx_len
= 0;
rx_ready
= 0; // Puffer Schreiben entsperren, neuer Pololu-Datensatz kann wieder empfangen/gepuffert werden
return(rx_len
);
}