Protocol

  • The protocol is based on individual serial data frames that are organized as shown in the following table.

Start-Byte

Address Byte

ID-Byte

n Data-Bytes coded

CRC-Byte1

CRC-Byte2

Stop-Byte

'#'

'a'+ Addr

'V','D' etc

"modified-base64"

variable

variable

'\r'

Commands

  • The Commands based on the dataframes above are listed here

The structs used below are defined in uart.h. For implementation details, see uart.c. Addresses are defined as follows:


Here you find some of the structs and defines used for serial commands:




Address used for communication:

   1 #define FC_ADDRESS      1  //(b)
   2 #define NC_ADDRESS      2  //(c)
   3 #define MK3MAG_ADDRESS  3  //(d)
   4 #define BL_CTRL_ADDRESS 5  //(f)
   5 

Common Commands

Received

Sent

Description

ID

Address

Data

ID

Address

Data

Labels of the analog values in the Debug Data Struct (see 'd')

'a'

AnyAddr

u8 Index of Analog Channel

'A'

SlaveAddr

u8 Index, char[16] label text

ExternControl

'b'

AnyAddr

ExternControl Struct

'B'

SlaveAddr

unsigned char, echo of ExternControl.Frame as confirmation

Request display

'h'

AnyAddr

u8 ~RemoteKey, u8 AutoSendInterval

'H'

SlaveAddr

char[80] DisplayText

Request display

'l'

AnyAddr

u8 MenuItem

'L'

SlaveAddr

u8 MenuItem, u8 MaxMenuItem, char[80] Display Text

Version Request

'v'

AnyAddr

none

'V'

SlaveAddr

VersionStruct

Debug Request

'd'

AnyAddr

u8 AutoSendInterval
Value is multiplied by 10 in receiver and then used as milliseconds. Subsciption needs to be renewed every 4s.
These values can be display in MK-Tool as values or graphs.

'D'

SlaveAddr

DebugOutStruct

Reset

'R'

AnyAddr

none

-

-

-

Get External Control

'g'

AnyAddr

none

'G'

SlaveAddr

ExternControl Struct

Flight-Ctrl

Received by FC

Sent by FC

Description

ID

Address

Data

ID

Address

Data

since FC Firmware

Compass Heading

'K'

FC-Addr

s16 Compass Value

'k'

MK3MAG-Addr

Nick Roll Attitude ...

0.71f

Engine Test

't'

FC-Addr

u8[16] values for the engines

'T'

FC-Addr

-

0.71f

Settings Request

'q'

FC-Addr

u8 Settings Index ( 1..5 READ or 0xff for actual setting)
u8 Settings Index (11..15 RESET setting to default (channel mapping will not be changed))
u8 Settings Index (21..25 RESET setting to default (complete reset including channel settings))

'Q'

FC-Addr

u8 Settings Index, u8 Settings Version, ParamsetStruct

0.71f

Write Settings

's'

FC-Addr

u8 Settings Index, u8 Settings Version, ParamsetStruct

'S'

FC-Addr

u8 Settings Index (1 ..5, 0=Error)

0.71f

Read PPM Channels

'p'

FC-Addr

none

'P'

FC-Addr

s16 PPM-Array[11]

0.71f

Set 3D-Data Interval

'c'

AnyAddr

u8 Interval

'C'

FC-Addr

struct Data3D

0.72p

Mixer Request

'n'

FC-Addr

none

'N'

FC-Addr

u8 MixerRevision, u8 Name[12], u8 MixerTable[16][4]

0.73

Mixer Write

'm'

FC-Addr

u8 MixerRevision, u8 Name[12], u8 MixerTable[16][4]

'M'

FC-Addr

u8 ack (1 = okay, 0 = error)

0.73

Change setting

'f'

FC-Addr

u8 Number of new Setting

'F'

FC-Addr

u8 Number

0.77

Serial Poti

'y'

FC-Addr

s8 Poti[12]

-

-

-

0.77

BL parameter request

'u'

FC-Addr

u8 BL_Addr

'U'

FC-Addr

u8 Status1, u8 Status2, u8 BL_Addr, BLConfig Struct

0.80

BL parameter write

'w'

FC-Addr

u8 BL_Addr, BLConfig Struct

'W'

FC-Addr

u8Status1, u8 Status2

0.80

Navi-Ctrl

Received by NC

Sent by NC

Description

ID

Address

Data

ID

Address

Data

since NC Firmware

Serial Link Test

'z'

NC-Addr

u16 EchoPattern

'Z'

NC-Addr

u16 EchoPattern

0.14f

Error Text Request

'e'

NC-Addr

none

'E'

NC-Addr

char[] Error Message String

0.12h

Send target Position

's'

NC-Addr

WayPointStruct

-

-

-

0.12h

Send Waypoint

'w'

NC-Addr

WayPointStruct (sending an invalid position will clear the WPList)

'W'

NC-Addr

u8 Number of WPs

0.12h

Request Waypoint

'x'

NC-Addr

u8 WP-Index

'X'

NC-Addr

u8 Number of WPs, u8 WP-Index, WayPointStruct

0.14f

Request OSD-Data

'o'

NC-Addr

1 byte sending interval ( in 10ms steps )

'O'

NC-Addr

NaviDataStruct

0.12h

Redirect UART

'u'

NC-Addr

1 byte param for uart selector (0=FC, 1=MK3MAG, 2=MKGPS), can be switched back to NC debug by sending the magic packet "0x1B,0x1B,0x55,0xAA,0x00"

-

-

-

0.12h

Set 3D-Data Interval

'c'

AnyAddr

u8 Interval

'C'

NC-Addr

struct Data3D

0.14a

Set/get NC-Parameter

'j'

NC-Addr

u8 get(=0)/set(=1),u8 parameterId, s16 value (only when set)

'J'

NC_Addr

u8 parameterId, s16 value

0.20

BL Ctrl Status

'k'

AnyAddr

u8 Interval

'K'

SlaveAddr

BLDataStruct

SystemTime

't'

NC-Addr

u8 Interval

'T'

NC-Addr

struct DateTime_t (from timer1.h)

0.31

MK3-MAG

Received by MK3-MAG

Sent by MK3-MAG

Description

ID

Address

Data

ID

Address

Data

since MK3-MAG Firmware

Heading Request

'w'

MK3MAG-Addr

Attitude (s16 Nick, s16 Roll, u8 Param1, u8 Param2, u8 CalcState, u8 Orientation)

'K'

FC-Addr

s16 Heading

since beginning


Slave Adresses

  • Since Navi 0.12h FC 0.71f Mag 0.19 there are constant SlaveAdresses:

Slave-Address

Part

1

FC

2

NC

3

MK3MAG

Data Format

  • Have a look into the Functions Decode64 and SendOutData in uart.c of the FC Firmware to see how the Data is encoded and decoded:

       1 void SendOutData(unsigned char cmd,unsigned char addr, unsigned char *snd, unsigned char len)
       2 {
       3  unsigned int pt = 0;
       4  unsigned char a,b,c;
       5  unsigned char ptr = 0;
       6  SendeBuffer[pt++] = '#';               // Start-Byte
       7  SendeBuffer[pt++] = 'a' + addr;        // Adress
       8  SendeBuffer[pt++] = cmd;               // Command
       9  while(len)
      10   {
      11    if(len) { a = snd[ptr++]; len--;} else a = 0;
      12    if(len) { b = snd[ptr++]; len--;} else b = 0;
      13    if(len) { c = snd[ptr++]; len--;} else c = 0;
      14    SendeBuffer[pt++] = '=' + (a >> 2);
      15    SendeBuffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
      16    SendeBuffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
      17    SendeBuffer[pt++] = '=' + ( c & 0x3f);
      18   }
      19  AddCRC(pt);
      20 }
      21 void Decode64(unsigned char *ptrOut, unsigned char len, unsigned char ptrIn,unsigned char max)
      22 {
      23  unsigned char a,b,c,d;
      24  unsigned char ptr = 0;
      25  unsigned char x,y,z;
      26  while(len)
      27   {
      28    a = RxdBuffer[ptrIn++] - '=';
      29    b = RxdBuffer[ptrIn++] - '=';
      30    c = RxdBuffer[ptrIn++] - '=';
      31    d = RxdBuffer[ptrIn++] - '=';
      32    if(ptrIn > max - 2) break;     // dont process more data than recieved
      33    x = (a << 2) | (b >> 4);
      34    y = ((b & 0x0f) << 4) | (c >> 2);
      35    z = ((c & 0x03) << 6) | d;
      36    if(len--) ptrOut[ptr++] = x; else break;
      37    if(len--) ptrOut[ptr++] = y; else break;
      38    if(len--) ptrOut[ptr++] = z; else break;
      39   }
      40 }
      41 
    
    • /!\ ToDo: describe data-format

Checksum

  •    1 unsigned int tmpCRC = 0;
       2 for(int i = 0; i <  DataBufferLength;i++)
       3  {
       4   tmpCRC += DataBuffer[i];
       5  }
       6 tmpCRC %= 4096;
       7 CRC1 = '=' + tmpCRC / 64;
       8 CRC2 = '=' + tmpCRC % 64;
       9 
    

The checksum is calculated over the Start-Byte, Adress-Byte, ID-Byte and the following Data-Bytes.

/!\ ToDo: describe checksum calculation verbaly

Implementations

Links