1 /****************************************************************************
2 * This file contains NXT-specific functions, which should generally
3 * not be called directly from application programs. Using the rct_
4 * brick-independent API will result in more portable, lower-maintenance
5 * code.
6 ***************************************************************************/
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <usb.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sysexits.h>
16 #include "roboctl.h"
17
18 extern int Debug;
19
20
21
22 /****************************************************************************
23 * Description:
24 * Attempt to start a program file on an NXT brick.
25 * The rct_nxt_t structure must first be initialized using nxt_init_struct(),
26 * which is normally called (indirectly) by rct_find_bricks().
27 * 0 0x00 or 0x80
28 * 1 0x00
29 * 2-21 filaname (asciiz 15.3 + null)
30 * Author: Jason W. Bacon
31 ***************************************************************************/
32
nxt_start_program(rct_nxt_t * nxt,char * raw_filename)33 rct_status_t nxt_start_program(rct_nxt_t *nxt,char *raw_filename)
34
35 {
36 int bytes;
37 rct_status_t status;
38 char response[NXT_RESPONSE_MAX+1],
39 filename[NXT_FILENAME_MAX+1];
40
41 strlcpy(filename,raw_filename,NXT_FILENAME_MAX);
42
43 /* Make sure this is a valid sound file name */
44 if ( (status = nxt_validate_filename(filename,".rxe", __func__)) != RCT_OK )
45 return status;
46
47 bytes = nxt_send_cmd(nxt,NXT_DIRECT_CMD,NXT_DC_START_PROGRAM,
48 response,NXT_RESPONSE_MAX,"%s",filename);
49 return nxt_check_response(nxt,response,bytes,3,"NXT_DC_START_PROGRAM");
50 }
51
52
53 /****************************************************************************
54 * Description:
55 * Attempt to stop the currently running program on an NXT brick.
56 * The rct_nxt_t structure must first be initialized using nxt_init_struct(),
57 * which is normally called (indirectly) by rct_find_bricks().
58 * 0 0x00 or 0x80
59 * 1 0x01
60 * Author: Jason W. Bacon
61 ***************************************************************************/
62
nxt_stop_program(rct_nxt_t * nxt)63 rct_status_t nxt_stop_program(rct_nxt_t *nxt)
64
65 {
66 int bytes;
67 char response[NXT_RESPONSE_MAX+1];
68
69 bytes = nxt_send_simple_cmd(nxt,NXT_DIRECT_CMD,
70 NXT_DC_STOP_PROGRAM,response,
71 NXT_RESPONSE_MAX);
72
73 if (bytes != 3)
74 {
75 fputs("nxt_stop_program(): Error sending stop command.\n", stderr);
76 return RCT_COMMAND_FAILED;
77 }
78 return RCT_OK;
79 }
80
81
82 /****************************************************************************
83 * Description:
84 * Play the specified sound file.
85 * 0 0x00 or 0x80
86 * 1 0x02
87 * 2 loop (boolean 0 or 1)
88 * 3-22 filename (asciiz 15.3 + null)
89 * Author:
90 ***************************************************************************/
91
nxt_play_sound_file(rct_nxt_t * nxt,rct_flag_t flags,char * const raw_filename)92 rct_status_t nxt_play_sound_file(rct_nxt_t *nxt,rct_flag_t flags,
93 char * const raw_filename)
94
95 {
96 int bytes;
97 rct_status_t status;
98 char response[NXT_RESPONSE_MAX+1],
99 filename[NXT_FILENAME_MAX+1];
100
101 /* Make a private copy in case users want to send a string constant */
102 strlcpy(filename,raw_filename,NXT_FILENAME_MAX);
103
104 /* Make sure this is a valid sound file name */
105 if ( (status = nxt_validate_filename(filename,".rso", __func__)) != RCT_OK )
106 return status;
107
108 /* Send command with a char value of 0 or 1 for loop flag */
109 debug_printf("nxt_play_sound_file(%d,%s)\n",flags,filename);
110 bytes = nxt_send_cmd(nxt,NXT_DIRECT_CMD,NXT_DC_PLAY_SOUND_FILE,
111 response,NXT_RESPONSE_MAX,"%c%s",(flags == RCT_LOOP),filename);
112 return nxt_check_response(nxt,response,bytes,3,"NXT_DC_PLAY_SOUND_FILE");
113 }
114
115 /****************************************************************************
116 * Description:
117 * Play a tone of the given frequency (200 - 1400 Hz) and duration.
118 * 0 0x00 or 0x80
119 * 1 0x03
120 * 2-3 frequency (uword, 200 - 1400Hz)
121 * 4-5 duration, ms (uword - range not documented)
122 * Author:
123 ***************************************************************************/
124
nxt_play_tone(rct_nxt_t * nxt,int herz,int milliseconds)125 rct_status_t nxt_play_tone(rct_nxt_t *nxt,int herz,int milliseconds)
126
127 {
128 int bytes;
129 char response[NXT_RESPONSE_MAX+1];
130
131 if ( (herz < 200) || (herz > 14000) )
132 {
133 fprintf(stderr,"nxt_play_tone(): Invalid frequency: %d Hz.\n",herz);
134 return RCT_INVALID_DATA;
135 }
136 bytes = nxt_send_cmd(nxt,NXT_DIRECT_CMD,NXT_DC_PLAY_TONE,
137 response,NXT_RESPONSE_MAX,"%w%w",herz,milliseconds);
138 return nxt_check_response(nxt,response,bytes,3,"NXT_DC_PLAY_SOUND_FILE");
139 }
140
141 /****************************************************************************
142 * Description:
143 * 0 0x00 or 0x80
144 * 1 0x04
145 * 2 output port (0 - 2, or 0xFF = all for simple control)
146 * 3 power set point (-100 to 100)
147 * 4 mode byte (bit field)
148 * 5 regulation mode (ubyte, enumerated)
149 * 6 turn ratio (sbyte, -100 to 100)
150 * 7 runstate (ubyte, enumerated)
151 * 8-12? tacholimit (ulong, 0 = forever)
152 * Author:
153 ***************************************************************************/
154
nxt_set_output_state(rct_nxt_t * nxt,int port,int power,nxt_output_mode_t mode,nxt_output_regulation_mode_t regulation,int ratio,nxt_output_runstate_t runstate,unsigned long tacholimit)155 rct_status_t nxt_set_output_state(rct_nxt_t *nxt,int port,int power,
156 nxt_output_mode_t mode,
157 nxt_output_regulation_mode_t regulation,
158 int ratio,
159 nxt_output_runstate_t runstate,
160 unsigned long tacholimit)
161
162 {
163 int bytes;
164 char response[NXT_RESPONSE_MAX+1];
165
166 bytes = nxt_send_cmd(nxt,NXT_DIRECT_CMD,NXT_DC_SET_OUTPUT_STATE,
167 response,NXT_RESPONSE_MAX,"%c%c%c%c%c%c%l",port,power,mode,
168 regulation,ratio,runstate,tacholimit);
169 return nxt_check_response(nxt,response,bytes,3,"NXT_DC_SET_OUTPUT_STATE");
170 }
171
172 /****************************************************************************
173 * Description:
174 * 0 0x00 or 0x80
175 * 1 0x05
176 * 2 input port (0-3)
177 * 3 sensor type (enumerated)
178 * 4 sensor mode (enumerated)
179 * Author:
180 ***************************************************************************/
181
nxt_set_input_mode(rct_nxt_t * nxt)182 rct_status_t nxt_set_input_mode(rct_nxt_t *nxt)
183
184 {
185 return RCT_NOT_IMPLEMENTED;
186 }
187
188 /****************************************************************************
189 * Description:
190 *
191 * Author:
192 ***************************************************************************/
193
nxt_get_output_state(rct_nxt_t * nxt)194 rct_status_t nxt_get_output_state(rct_nxt_t *nxt)
195
196 {
197 return RCT_NOT_IMPLEMENTED;
198 }
199
200
nxt_get_input_values(rct_nxt_t * nxt)201 rct_status_t nxt_get_input_values(rct_nxt_t *nxt)
202
203 {
204 return RCT_NOT_IMPLEMENTED;
205 }
206
207
nxt_reset_input_scaled_value(rct_nxt_t * nxt)208 rct_status_t nxt_reset_input_scaled_value(rct_nxt_t *nxt)
209
210 {
211 return RCT_NOT_IMPLEMENTED;
212 }
213
214
nxt_message_write(rct_nxt_t * nxt)215 rct_status_t nxt_message_write(rct_nxt_t *nxt)
216
217 {
218 return RCT_NOT_IMPLEMENTED;
219 }
220
221
nxt_reset_motor_position(rct_nxt_t * nxt)222 rct_status_t nxt_reset_motor_position(rct_nxt_t *nxt)
223
224 {
225 return RCT_NOT_IMPLEMENTED;
226 }
227
228
229 /****************************************************************************
230 * Description:
231 * Read the battery level from an NXT brick.
232 * The rct_nxt_t structure must first be initialized using nxt_init_struct(),
233 * which is normally called (indirectly) by rct_find_bricks().
234 * Author: Jason W. Bacon
235 ***************************************************************************/
236
nxt_get_battery_level(rct_nxt_t * nxt)237 rct_status_t nxt_get_battery_level(rct_nxt_t *nxt)
238
239 {
240 int bytes;
241 char response[NXT_RESPONSE_MAX + 1];
242
243 /*
244 * NXT brick should respond with 5 bytes:
245 * reply command status level-lsb level-msb
246 */
247 bytes = nxt_send_simple_cmd(nxt, NXT_DIRECT_CMD,
248 NXT_DC_BATTERY_LEVEL, response,
249 NXT_RESPONSE_MAX);
250 nxt_check_response(nxt,response,bytes,5,"NXT_SC_BATTERY_LEVEL");
251 if ( bytes == 5 )
252 {
253 nxt->battery_level = buf2short((unsigned char *)response+3);
254 return RCT_OK;
255 }
256 else
257 {
258 return RCT_COMMAND_FAILED;
259 }
260 }
261
262
nxt_stop_sound_playback(rct_nxt_t * nxt)263 rct_status_t nxt_stop_sound_playback(rct_nxt_t *nxt)
264
265 {
266 return RCT_NOT_IMPLEMENTED;
267 }
268
269 /****************************************************************************
270 * Command:
271 * 0 0x00 or 0x80
272 * 1 0x0D
273 * Response:
274 * 0 0x02
275 * 1 0x0D
276 * 2 Status
277 * 3-6 Current sleep time limit (ulong)
278 * Author:
279 ***************************************************************************/
280
nxt_keep_alive(rct_nxt_t * nxt)281 rct_status_t nxt_keep_alive(rct_nxt_t *nxt)
282
283 {
284 int bytes;
285 char response[NXT_RESPONSE_MAX + 1];
286
287 /*
288 * NXT brick should respond with 7 bytes:
289 * reply command status level-lsb level-msb
290 */
291 bytes = nxt_send_simple_cmd(nxt, NXT_DIRECT_CMD,
292 NXT_DC_KEEP_ALIVE, response,
293 NXT_RESPONSE_MAX);
294 nxt_check_response(nxt,response,bytes,7,"NXT_DC_KEEP_ALIVE");
295 if ( bytes == 7 )
296 {
297 return RCT_OK;
298 }
299 else
300 {
301 return RCT_COMMAND_FAILED;
302 }
303 }
304
305
nxt_ls_get_status(rct_nxt_t * nxt)306 rct_status_t nxt_ls_get_status(rct_nxt_t *nxt)
307
308 {
309 return RCT_NOT_IMPLEMENTED;
310 }
311
312
nxt_ls_write(rct_nxt_t * nxt)313 rct_status_t nxt_ls_write(rct_nxt_t *nxt)
314
315 {
316 return RCT_NOT_IMPLEMENTED;
317 }
318
319
nxt_ls_read(rct_nxt_t * nxt)320 rct_status_t nxt_ls_read(rct_nxt_t *nxt)
321
322 {
323 return RCT_NOT_IMPLEMENTED;
324 }
325
326
nxt_get_current_program_name(rct_nxt_t * nxt)327 rct_status_t nxt_get_current_program_name(rct_nxt_t *nxt)
328
329 {
330 return RCT_NOT_IMPLEMENTED;
331 }
332
333
nxt_message_read(rct_nxt_t * nxt)334 rct_status_t nxt_message_read(rct_nxt_t *nxt)
335
336 {
337 return RCT_NOT_IMPLEMENTED;
338 }
339
340