dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
unittest.cpp
Go to the documentation of this file.
1 
11 /*
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20  * for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, see <http://www.gnu.org/licenses/>
24  */
25 
26 /*
27  * NOTE: This program uses the Google Test infrastructure to drive the unit test
28  *
29  * Main site for Google Test: http://code.google.com/p/googletest/
30  * Documentation and examples: http://code.google.com/p/googletest/wiki/Documentation
31  */
32 
33 #include "gtest/gtest.h"
34 
35 #include <stdio.h> /* printf */
36 #include <stdlib.h> /* abort */
37 #include <string.h> /* memset */
38 #include <stdint.h> /* uint*_t */
39 
40 extern "C" {
41 #include "pios_dsm_priv.h"
42 #include "../../PiOS/Common/pios_dsm.c"
43 
44 int PIOS_DSM_Reset(struct pios_dsm_dev *dsm_dev)
45 {
46  dsm_dev->resolution = DSM_UNKNOWN;
47 
48  for (int i = 0; i < PIOS_DSM_NUM_INPUTS; i++) {
49  dsm_dev->state.channel_data[i] = 0;
50  }
51 
52  return 0;
53 }
54 
55 int PIOS_DSM_GetResolution(struct pios_dsm_dev *dsm_dev)
56 {
57  uint8_t resolution = (dsm_dev->resolution == DSM_10BIT) ? 10 : 11;
58  return resolution;
59 }
60 
61 }
62 
63 // example data can be found at http://wiki.paparazziuav.org/wiki/DSM
64 // format described at https://bitbucket.org/PhracturedBlue/deviation/src/92e1705cf895b415ab16f6e1d7df93ee11d55afe/doc/DSM.txt?at=default
65 
66 // To use a test fixture, derive a class from testing::Test.
67 class DsmTest : public testing::Test {
68 protected:
69  virtual void SetUp() {
71  state = &dev.state;
72  }
73 
74  virtual void TearDown() {
75  }
76  void pack_channels_10bit(uint16_t channels[DSM_CHANNELS_PER_FRAME], struct pios_dsm_state *state, bool frame);
77  void pack_channels_11bit(uint16_t channels[DSM_CHANNELS_PER_FRAME], struct pios_dsm_state *state, bool frame);
78  int validate_file(const char *fn, int resolution, int channels, bool skip);
79  int get_packet(FILE *fid, uint8_t *buf);
80  struct pios_dsm_state *state;
81  struct pios_dsm_dev dev;
82 };
83 
84 const int idx11[] = {1,5,2,3,0,7,6,1,5,2,3,4,8,9};
85 const int idx10[] = {1,5,4,2,6,0,3,1,5,4,2,6,0,3};
86 
88 void DsmTest::pack_channels_10bit(uint16_t channels[DSM_CHANNELS_PER_FRAME], struct pios_dsm_state *state, bool frame)
89 {
90  for (int i = 0; i < DSM_CHANNELS_PER_FRAME; i++) {
91  uint16_t j = idx10[i + DSM_CHANNELS_PER_FRAME*frame];
92  uint16_t val = channels[j];
93  uint16_t word = ((frame & (i == 0)) ? 0x8000 : 0) | ((j & 0x000F) << 10) | (val & 0x03FF);
94  state->received_data[2 + i * 2 + 1] = word & 0x00FF;
95  state->received_data[2 + i * 2] = (word >> 8) & 0x00FF;
96  }
97 }
98 
100 void DsmTest::pack_channels_11bit(uint16_t channels[DSM_CHANNELS_PER_FRAME], struct pios_dsm_state *state, bool frame)
101 {
102  for (int i = 0; i < DSM_CHANNELS_PER_FRAME; i++) {
103  uint16_t j = idx11[i + DSM_CHANNELS_PER_FRAME*frame];
104  uint16_t val = channels[j];
105  uint16_t word = ((frame & (i == 0)) ? 0x8000 : 0) | ((j & 0x000F) << 11) | (val & 0x07FF);
106  state->received_data[2 + i * 2 + 1] = word & 0x00FF;
107  state->received_data[2 + i * 2] = (word >> 8) & 0x00FF;
108  }
109 }
110 
111 void verify_channels(uint16_t *c1, uint16_t *c2)
112 {
113  for (int i = 0; i < DSM_CHANNELS_PER_FRAME; i++) {
114  EXPECT_EQ(c1[i], c2[i]);
115  }
116 }
117 
118 TEST_F(DsmTest, Invalid) {
119  uint16_t channels[DSM_CHANNELS_PER_FRAME] = {512, 513, 514, 515, 516, 517, 518};
120  pack_channels_10bit(channels, state, false);
121  for (int i = 0; i < DSM_FRAME_LENGTH; i++)
122  state->received_data[i] = 0;
123  EXPECT_EQ(-2, PIOS_DSM_UnrollChannels(&dev));
124 }
125 
126 TEST_F(DsmTest, DSM_10BIT) {
127  uint16_t channels[PIOS_DSM_NUM_INPUTS] = {512, 513, 514, 515, 516, 517, 518, 0, 0, 0, 0, 0};
128  pack_channels_10bit(channels, state, false);
129  EXPECT_EQ(0, PIOS_DSM_UnrollChannels(&dev));
130  pack_channels_10bit(channels, state, true);
131  EXPECT_EQ(0, PIOS_DSM_UnrollChannels(&dev));
132 
133  EXPECT_EQ(10, PIOS_DSM_GetResolution(&dev));
134  verify_channels(channels, state->channel_data);
135 }
136 
137 TEST_F(DsmTest, DSM_11BIT) {
138  uint16_t channels[PIOS_DSM_NUM_INPUTS] = {512, 513, 514, 515, 516, 517, 518, 0, 0, 0, 0, 0};
139  pack_channels_11bit(channels, state, false);
140  EXPECT_EQ(0, PIOS_DSM_UnrollChannels(&dev));
141  pack_channels_11bit(channels, state, true);
142  EXPECT_EQ(0, PIOS_DSM_UnrollChannels(&dev));
143 
144  EXPECT_EQ(11, PIOS_DSM_GetResolution(&dev));
145  verify_channels(channels, state->channel_data);
146 }
147 
148 int DsmTest::get_packet(FILE *fid, uint8_t *buf)
149 {
150  double t;
151  uint8_t val;
152 
153  for (int i = 0; i < DSM_FRAME_LENGTH; i++) {
154  if (fscanf(fid, "%lf,%hhx,,", &t, &val) == 2) {
155  buf[i] = val;
156  } else
157  return -1;
158  }
159  return 0;
160 }
161 
162 
163 int DsmTest::validate_file(const char *fn, int resolution, int channels, bool skip)
164 {
165  FILE *fid = fopen(fn, "r");
166  char *line = NULL;
167  size_t len = 0;
168 
169  // throwaway intro line
170  getline(&line, &len, fid);
171 
172  const int MIN = (resolution == 11) ? 340 : 150;
173  const int MAX = (resolution == 11) ? 2048 : 1024;
174  if (resolution == 11)
175 
176  if (skip) {
177  // throw away a packet, test started on the other frame
178  get_packet(fid, state->received_data);
179  }
180 
181  // warm up parser. this will not always pass the checks as
182  // an out odd packet might not correctly identify the
183  // protocol
184  get_packet(fid, state->received_data);
185  PIOS_DSM_UnrollChannels(&dev);
186 
187  get_packet(fid, state->received_data);
188  EXPECT_EQ(0, PIOS_DSM_UnrollChannels(&dev));
189 
190  EXPECT_EQ(resolution, PIOS_DSM_GetResolution(&dev));
191 
192  while(get_packet(fid, state->received_data) == 0) {
193  EXPECT_EQ(0, PIOS_DSM_UnrollChannels(&dev));
194  EXPECT_EQ(resolution, PIOS_DSM_GetResolution(&dev));
195 
196  bool valid[PIOS_DSM_NUM_INPUTS];
197  for (int i = 0; i < PIOS_DSM_NUM_INPUTS; i++) {
198  // this file only has 7 channels
199  valid[i] = ((i >= channels) && dev.state.channel_data[i] == 0) ||
200  ((i < channels) && ((dev.state.channel_data[i] > MIN) && (dev.state.channel_data[i] <= MAX)));
201  //fprintf(stdout, "%d %d %d %d\r\n", i, valid[i], dev.state.channel_data[i], channels);
202  EXPECT_TRUE(valid[i]);
203 
204  if (!valid[i]) {
205  for (int i = 0; i < PIOS_DSM_NUM_INPUTS; i++) {
206  fprintf(stdout, "%d, ", dev.state.channel_data[i]);
207  }
208  fprintf(stdout, "\r\n");
209 
210  fclose(fid);
211  return 0;
212  }
213  }
214 
215  /*for (int i = 0; i < PIOS_DSM_NUM_INPUTS; i++) {
216  fprintf(stdout, "%d, ", dev.state.channel_data[i]);
217  }
218  fprintf(stdout, "\r\n");*/
219  }
220 
221  fclose(fid);
222 
223  return 0;
224 }
225 
226 TEST_F(DsmTest, DX7_DSM2_11ms_odd) {
227  validate_file("DX7_11msDSM2.txt",11,8,false);
228 }
229 
230 TEST_F(DsmTest, DX7_DSM2_11ms_even) {
231  validate_file("DX7_11msDSM2.txt",11,8,true);
232 }
233 
234 TEST_F(DsmTest, DX7_DSM2_22ms_odd) {
235  validate_file("DX7_22msDSM2.txt",11,8,false);
236 }
237 TEST_F(DsmTest, DX7_DSM2_22ms_even) {
238  validate_file("DX7_22msDSM2.txt",11,8,true);
239 }
240 
241 TEST_F(DsmTest, DX7_DSMX_11ms_odd) {
242  validate_file("DX7_11msDSMX.txt",11,8,false);
243 }
244 
245 TEST_F(DsmTest, DX7_DSMX_11ms_even) {
246  validate_file("DX7_11msDSMX.txt",11,8,true);
247 }
248 
249 TEST_F(DsmTest, DX7_DSMX_22ms_odd) {
250  validate_file("DX7_22msDSMX.txt",11,8,false);
251 }
252 
253 TEST_F(DsmTest, DX7_DSMX_22ms_even) {
254  validate_file("DX7_22msDSMX.txt",11,8,true);
255 }
256 
257 TEST_F(DsmTest, DX18_DSM2_2048_odd) {
258  validate_file("DX18_11msDSM2_2048res.txt",11,10,false);
259 }
260 
261 TEST_F(DsmTest, DX18_DSM2_2048_even) {
262  validate_file("DX18_11msDSM2_2048res.txt",11,10,true);
263 }
264 
265 
266 TEST_F(DsmTest, DX18_DSM2_1024_odd) {
267  // Note: even though this file is named like it has 10 bit
268  // resolution, it appears to differ in having 12 channels
269  validate_file("DX18_22msDSM2_1024res.txt",11,12,false);
270 }
271 
272 TEST_F(DsmTest, DX18_DSM2_1024_even) {
273  // Note: even though this file is named like it has 10 bit
274  // resolution, it appears to differ in having 12 channels
275  validate_file("DX18_22msDSM2_1024res.txt",11,12,true);
276 }
277 
278 TEST_F(DsmTest, DX18_DSM2_XPlus_1024_odd) {
279  // Note: we do not decode the XPlus channels but it is
280  // important to make sure they are handled appropriately
281  validate_file("DX18_22msDSM2_XPlus_1024res.txt",11,12,false);
282 }
283 
284 TEST_F(DsmTest, DX18_DSM2_XPlus_1024_even) {
285  // Note: we do not decode the XPlus channels but it is
286  // important to make sure they are handled appropriately
287  validate_file("DX18_22msDSM2_XPlus_1024res.txt",11,12,true);
288 }
289 
290 TEST_F(DsmTest, DX18_DSMX_22ms_odd) {
291  validate_file("DX18_22msDSMX.txt",11,12,false);
292 }
293 
294 TEST_F(DsmTest, DX18_DSMX_22ms_even) {
295  validate_file("DX18_22msDSMX.txt",11,12,true);
296 }
297 
298 TEST_F(DsmTest, DX18_DSMX_11ms_odd) {
299  validate_file("DX18_11msDSMX.txt",11,10,false);
300 }
301 
302 TEST_F(DsmTest, DX18_DSMX_11ms_even) {
303  validate_file("DX18_11msDSMX.txt",11,10,true);
304 }
305 
306 TEST_F(DsmTest, DX18_DSMX_22ms_XPlus_odd) {
307  validate_file("DX18_22msDSMX_XPlus.txt",11,12,false);
308 }
309 
310 TEST_F(DsmTest, DX18_DSMX_22ms_XPlus_even) {
311  validate_file("DX18_22msDSMX_XPlus.txt",11,12,true);
312 }
313 
318 TEST_F(DsmTest, DX7_DSM2_10BIT) {
319 
320  FILE *fid = fopen("DX7_DSM2_10bit.dat", "r");
321 
322  int c;
323  int i = 0;
324 
325  while((c = fgetc(fid)) != EOF) {
326  state->received_data[i++] = c;
327 
328  if (i >= DSM_FRAME_LENGTH) {
329  PIOS_DSM_UnrollChannels(&dev);
330  EXPECT_EQ(10, PIOS_DSM_GetResolution(&dev));
331  i = 0;
332 
333  const uint8_t channels = 7;
334  const uint16_t MIN = 45;
335  const uint16_t MAX = 1024;
336 
337  bool valid[PIOS_DSM_NUM_INPUTS];
338  for (int j = 0; j < PIOS_DSM_NUM_INPUTS; j++) {
339  // this file only has 7 channels
340  valid[j] = ((j >= channels) && dev.state.channel_data[j] == 0) ||
341  ((j < channels) && ((dev.state.channel_data[j] > MIN) && (dev.state.channel_data[j] <= MAX)));
342  EXPECT_TRUE(valid[j]);
343  }
344  }
345  }
346 
347  fclose(fid);
348 }
#define DSM_CHANNELS_PER_FRAME
TEST_F(RneFromLLATest, Equator)
Definition: unittest.cpp:68
void verify_channels(uint16_t *c1, uint16_t *c2)
Definition: unittest.cpp:111
int get_packet(FILE *fid, uint8_t *buf)
Definition: unittest.cpp:148
const int idx10[]
Definition: unittest.cpp:85
struct pios_dsm_dev dev
Definition: unittest.cpp:81
volatile int j
Definition: loadabletest.c:12
int PIOS_DSM_Reset(struct pios_dsm_dev *dsm_dev)
Definition: unittest.cpp:44
virtual void TearDown()
Definition: unittest.cpp:74
Spektrum/JR DSMx satellite receiver private structures.
const int idx11[]
Definition: unittest.cpp:84
int validate_file(const char *fn, int resolution, int channels, bool skip)
Definition: unittest.cpp:163
#define MAX(a, b)
Definition: misc_math.h:40
void pack_channels_10bit(uint16_t channels[DSM_CHANNELS_PER_FRAME], struct pios_dsm_state *state, bool frame)
pack data into DSM2 10 bit packets
Definition: unittest.cpp:88
int PIOS_DSM_GetResolution(struct pios_dsm_dev *dsm_dev)
Definition: unittest.cpp:55
uint8_t i
Definition: msp_messages.h:97
void pack_channels_11bit(uint16_t channels[DSM_CHANNELS_PER_FRAME], struct pios_dsm_state *state, bool frame)
pack data into DSM2 11 bit packets
Definition: unittest.cpp:100
#define PIOS_DSM_NUM_INPUTS
Definition: pios_board.h:193
#define DSM_FRAME_LENGTH
#define MIN(a, b)
Definition: misc_math.h:41
struct pios_dsm_state * state
Definition: unittest.cpp:80
virtual void SetUp()
Definition: unittest.cpp:69
enum arena_state state