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