<> = Protocol = . The protocol is based on individual serial data frames that are organized as shown in the following table. ||Start-Byte ||<#cccccc>Address Byte ||<#cccccc>ID-Byte ||<#cccccc>n Data-Bytes coded ||<#cccccc>CRC-Byte1 ||<#cccccc>CRC-Byte2 ||<#cccccc>Stop-Byte || ||'#' ||'a'+ Addr ||'V','D' etc ||"modified-base64" ||variable ||variable ||'\r' || = UART settings = * 57600bd * 8 Bit * 1 Stopbit * no parity = Commands = . The Commands based on the dataframes above are listed [[en/SerialCommands|here]] '''IMPORTANT: Make sure, that you use packed struktures in your compiler.''' <> = Slave Adresses = . Since Navi 0.12h FC 0.71f Mag 0.19 there are constant !SlaveAdresses: ||Slave-Address ||<#cccccc>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: {{{#!cplusplus void SendOutData(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; SendeBuffer[pt++] = '#'; // Start-Byte SendeBuffer[pt++] = 'a' + addr; // Adress SendeBuffer[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; SendeBuffer[pt++] = '=' + (a >> 2); SendeBuffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4)); SendeBuffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6)); SendeBuffer[pt++] = '=' + ( c & 0x3f); } AddCRC(pt); } void Decode64(unsigned char *ptrOut, unsigned char len, unsigned char ptrIn,unsigned char max) { unsigned char a,b,c,d; unsigned char ptr = 0; unsigned char x,y,z; while(len) { a = RxdBuffer[ptrIn++] - '='; b = RxdBuffer[ptrIn++] - '='; c = RxdBuffer[ptrIn++] - '='; d = RxdBuffer[ptrIn++] - '='; if(ptrIn > max - 2) break; // dont process more data than recieved 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; } } }}} . /!\ ToDo: describe data-format = Checksum = . {{{#!cplusplus unsigned int tmpCRC = 0; for(int i = 0; i < DataBufferLength;i++) { tmpCRC += DataBuffer[i]; } tmpCRC %= 4096; CRC1 = '=' + tmpCRC / 64; CRC2 = '=' + tmpCRC % 64; }}} The checksum is calculated over the Start-Byte, Adress-Byte, ID-Byte and the following Data-Bytes. /!\ ToDo: describe checksum calculation verbaly = Implementations = . Sometimes its a lot more easy to look at code rather than reather than to look at Specifications/Documentation: * uart.c in the Flight-Ctrl Firmware ( C ) * MKCommunicator.java from [[DUBwise]] ( Java / J2ME ) * mktool.cpp @ [[QMKGroundStation]] ( C++ ) * !GroundStation ( !LabView ) * !VibrationTest [[en/VibrationTest]] ( Python ) * [[https://github.com/crathje/NCSimulator/blob/master/src/de/mylifesucks/oss/ncsimulator/protocol/CommunicationBase.java|CommunicationBase.java]] [[http://www.mylifesucks.de/oss/NCSimulator/|NCSimulator]] ( Java ) * [[http://svn.mikrokopter.de/filedetails.php?repname=Projects&path=%2FC-OSD%2Ftrunk%2Fusart1.c|usart1.c]] [[http://www.mylifesucks.de/oss/c-osd/|C-OSD]] ( C ) * [[http://svn.mikrokopter.de/filedetails.php?repname=Projects&path=%2FC-OSD%2FC-Epilepsy%2Fusart0.c|usart0.c]] [[http://www.mylifesucks.de/oss/c-epilepsy/|C-Epilepsy]] ( C ) * [[en/MoteCtrl|Wii-MoteCtrl]] * PiMote (Raspberry pie) ---- . CategoryCoding KategorieEnglish KategorieFirmware