Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1545 | LPDunwell | 1 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 | // This code (protocol) is inspired by the RCDSL implementation of Stefan Engelke. |
||
3 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
4 | /* |
||
5 | Copyright (c) 2008 Stefan Engelke <stefan@tinkerer.eu> |
||
6 | |||
7 | Permission is hereby granted, free of charge, to any person |
||
8 | obtaining a copy of this software and associated documentation |
||
9 | files (the "Software"), to deal in the Software without |
||
10 | restriction, including without limitation the rights to use, copy, |
||
11 | modify, merge, publish, distribute, sublicense, and/or sell copies |
||
12 | of the Software, and to permit persons to whom the Software is |
||
13 | furnished to do so, subject to the following conditions: |
||
14 | |||
15 | The above copyright notice and this permission notice shall be |
||
16 | included in all copies or substantial portions of the Software. |
||
17 | |||
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
||
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
||
22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
||
23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
25 | DEALINGS IN THE SOFTWARE. |
||
26 | */ |
||
27 | |||
28 | /*********************************************************************************************************** |
||
29 | * FC_JN_RECEIVER by DLP |
||
30 | ************************************************************************************************************ |
||
31 | |||
32 | Connection of receiver to SV1 of FC: |
||
33 | TXD <--> pin 3 (RXD1 Atmega644p) |
||
34 | RXD <--> pin 4 (TXD1 Atmega644p) |
||
35 | |||
36 | Data is sent at every 20 ms @ 57600 Baud 8-N-1 |
||
37 | ************************************************************************************************************ |
||
38 | Data Frame Jennic: |0xFF|0xFF|STATUS|CHN|CH0D1|CH0D0|CH1D1|CH1D0|CRC| |
||
39 | |||
40 | STATUS = Jennic Network Status (0 = OK, 1 = Coordinator not available, 2 = General Error) |
||
41 | CHN = Channel Pair (0 = Channel 0 & 1 ...etc) |
||
42 | |||
43 | Channel Pair: |CHN|CHnD1|CHnD0|CHnD1|CHnD0|CRC| |
||
44 | CHN is the lower Channel index of the Channel Pair |
||
45 | n is the Channel |
||
46 | D1D0 is servo value as u16 in range of 7373 (1ms) to 14745 (2ms) |
||
47 | there are 8 channels submitted, i.e 4 servo pairs |
||
48 | |||
49 | Frame example with signal received: |
||
50 | FFFF 00 0036012B1E7f |
||
51 | FFFF 00 022AFB2AECC2 |
||
52 | FFFF 00 042B4D2B4414 |
||
53 | FFFF 00 0636872B33DE |
||
54 | |||
55 | Frame example with no signal received: |
||
56 | FFFF 01 (Network Coordinator not Accessible) |
||
57 | or |
||
58 | FFFF 02 (General Error) |
||
59 | ***********************************************************************************************************/ |
||
60 | |||
61 | #include <stdlib.h> |
||
62 | #include "jennic.h" |
||
63 | #include "rc.h" |
||
64 | #include "uart0.h" |
||
65 | |||
66 | uint8_t jen_status = 0; |
||
67 | uint8_t PacketBuffer[9]; |
||
68 | |||
69 | typedef union |
||
70 | { |
||
71 | int16_t Servo[2]; |
||
72 | uint8_t byte[4]; |
||
73 | } ChannelPair_t; |
||
74 | |||
75 | ChannelPair_t ChannelPair; |
||
76 | |||
77 | // to be called within the UART RX ISR |
||
78 | void jen_parser (uint8_t c) |
||
79 | { |
||
80 | static uint8_t last_c = 0; |
||
81 | static uint8_t crc = 0; |
||
82 | static uint8_t cnt = 0; |
||
83 | uint8_t packet_len = 5; |
||
84 | |||
85 | // sync condition |
||
86 | if ((c==0xFF) && (last_c==0xFF)) |
||
87 | { |
||
88 | cnt = 0; // reset counter |
||
89 | crc = 0; // reset checksum |
||
90 | return; |
||
91 | } |
||
92 | |||
93 | if (cnt > packet_len) // packet complete, crc received |
||
94 | { |
||
95 | // calculate checksum |
||
96 | crc = ~crc; |
||
97 | if (crc == 0xFF) crc = 0xFE; |
||
98 | // decode packet if checksum correct |
||
99 | if (c == crc) jen_decode_packet (); |
||
100 | |||
101 | // handle next packet |
||
102 | cnt = 0; |
||
103 | crc = 0; |
||
104 | } |
||
105 | |||
106 | else // collect channel data bytes |
||
107 | { |
||
108 | PacketBuffer[cnt++] = c; |
||
109 | crc += c; |
||
110 | } |
||
111 | |||
112 | last_c = c; // store last byte for sync check |
||
113 | } |
||
114 | |||
115 | void jen_decode_packet (void) |
||
116 | { |
||
117 | uint8_t i; |
||
118 | |||
119 | jen_status = PacketBuffer[0]; |
||
120 | |||
121 | // header condition |
||
122 | if (!(PacketBuffer[1] & 0xF0)) |
||
123 | { |
||
124 | if (!jen_status) RC_Quality = 200; |
||
125 | else if (jen_status) |
||
126 | { |
||
127 | RC_Quality = 0; |
||
128 | for (i = 0; i<5; i++) |
||
129 | { |
||
130 | PPM_diff[i] = 0; |
||
131 | PPM_in[i] = 0; |
||
132 | } |
||
133 | } |
||
134 | |||
135 | i = PacketBuffer[1] & 0x0F; // lower nibble header indicates the channel pair |
||
136 | if (i < 10) // maximum 12 channels |
||
137 | { |
||
138 | // big to little endian |
||
139 | ChannelPair.byte[1] = PacketBuffer[2]; |
||
140 | ChannelPair.byte[0] = PacketBuffer[3]; |
||
141 | ChannelPair.byte[3] = PacketBuffer[4]; |
||
142 | ChannelPair.byte[2] = PacketBuffer[5]; |
||
143 | |||
144 | // new servo signal properly received |
||
145 | jen_new_signal (i, ChannelPair.Servo[0]); |
||
146 | jen_new_signal (i+1, ChannelPair.Servo[1]); |
||
147 | } |
||
148 | } // end of header condition |
||
149 | } |
||
150 | |||
151 | // Parameters: channel - channel number (0-9) |
||
152 | // signal - signal between 7363 and 14875 |
||
153 | void jen_new_signal (uint8_t channel, int16_t signal) |
||
154 | { |
||
155 | int16_t tmp; |
||
156 | uint8_t index = channel + 1; // mk channels start with 1 |
||
157 | |||
158 | signal-= 11059; // shift to neutral |
||
159 | signal/= 24; // scale to mk rc resolution |
||
160 | |||
161 | // calculate exponential history for signal |
||
162 | tmp = (3 * (PPM_in[index]) + signal) / 4; |
||
163 | |||
164 | if (tmp > signal+1) tmp--; |
||
165 | else if (tmp < signal-1) tmp++; |
||
166 | |||
167 | if (RC_Quality == 200) PPM_diff[index] = ((tmp - PPM_in[index]) / 3) * 3; // cut off lower 3 bit for noise reduction |
||
168 | else PPM_diff[index] = 0; |
||
169 | |||
170 | PPM_in[index] = tmp; // update channel value |
||
171 | |||
172 | if(index < 5) DebugOut.Analog[(20+index)] = PPM_in[index]; // debug output is handy whilst developing |
||
173 | |||
174 | if (index == 4) NewPpmData = 0; |
||
175 | } |