Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / colonet / robot / colonet_dragonfly / colonet_dragonfly.c @ 508

History | View | Annotate | Download (8.15 KB)

1
/** @file colonet.c
2
 * @brief Colonet library for DRAGONFLY colony robots
3
 *
4
 * @author Eugene Marinelli
5
 * @date 10/10/07
6
 *
7
 * @bug Handler registration not tested
8
 * @bug Request reponding not implemented - only accepts commands.
9
 */
10

    
11
#include <assert.h>
12
#include <dragonfly_lib.h>
13
#include <battery.h>
14
#include <string.h>
15
#include <wireless.h>
16

    
17
#include <colonet_dragonfly.h>
18

    
19
typedef struct {
20
  unsigned char msgId; //is this necessary?
21
  void (*handler)(void);
22
} UserHandler;
23

    
24
/* Globals (internal) */
25
static UserHandler user_handlers[USER_DEFINED_MSG_TOTAL];
26

    
27
static int robot_x, robot_y;
28
static int server_xbee_id; // ID of server xbee; set when a colonet packet is received.
29

    
30
/* Internal function prototypes */
31
static void packet_string_to_struct(ColonetRobotServerPacket* dest_pkt, unsigned char* pkt_buf);
32
static unsigned int two_bytes_to_int(char high, char low);
33
static void colonet_handle_receive(char type, int source, unsigned char* packet, int length);
34
static void request_abs_position(void);
35
static void move_to_position_routine(int x, int y);
36

    
37
static PacketGroupHandler colonet_pgh;
38

    
39
/* Public functions */
40
int colonet_init() {
41
  colonet_pgh.groupCode = COLONET_PACKET_GROUP_ID;
42
  colonet_pgh.timeout_handler = NULL;
43
  colonet_pgh.handle_response = NULL;
44
  colonet_pgh.handle_receive = colonet_handle_receive;
45
  colonet_pgh.unregister = NULL;
46

    
47
  // TODO this should return an error if wl_init has not been called yet.
48
  wl_register_packet_group(&colonet_pgh);
49

    
50
  robot_x = 0;
51
  robot_y = 0;
52
  server_xbee_id = -1;
53

    
54
  return 0;
55
}
56

    
57
/* colonet_add_message
58
 * Adds a user-defined message
59
 */
60
int colonet_add_message(unsigned char msgId, void (*handler)(void)) {
61
  if(msgId < USER_DEFINED_MSG_ID_START  /* || msgId > USER_DEFINED_MSG_ID_END */){
62
    return -1;
63
  }
64

    
65
  /* Register this function in the array */
66
  user_handlers[msgId-USER_DEFINED_MSG_ID_START].msgId = msgId;
67
  user_handlers[msgId-USER_DEFINED_MSG_ID_START].handler = handler;
68

    
69
  return 0;
70
}
71

    
72
static void request_abs_position() {
73
  if (server_xbee_id != -1) { // if -1, then we don't know the server's xbee id yet.
74
    ColonetRobotServerPacket pkt;
75
    pkt.client_id = -1;
76
    pkt.msg_code = ROBOT_REQUEST_POSITION_FROM_SERVER;
77
    wl_send_robot_to_robot_global_packet(colonet_pgh.groupCode, 0, (char*)&pkt, sizeof(pkt), server_xbee_id, 0);
78
  }
79
}
80

    
81
static void move_to_position_routine(int x, int y) {
82
  /* TODO emarinel - control algorithm */
83
  motor1_set(1, 200);
84
  motor2_set(1, 200);
85
}
86

    
87
/* Private functions */
88

    
89
/** @brief Handles colonet packets.  Should be called by parse_buffer
90
 * when it is determined that a colonet message has been received.
91
 *
92
 * @param robot_id The robot id
93
 * @param pkt_buf The packet buffer (e.g. wl_buf)
94
 *
95
 * @return -1 on error (invalid msgId), 0 on success
96
 */
97
static void colonet_handle_receive(char type, int wl_source, unsigned char* packet, int length) {
98
  ColonetRobotServerPacket pkt;
99
  unsigned char* args; //up to 7 char args
100
  unsigned int int_args[3]; //up to 3 int (2-byte) args
101

    
102
  /* Globally store this id. */
103
  server_xbee_id = wl_source;
104

    
105
  usb_puts("Packet received.\n");
106
  char buf[40];
107
  sprintf(buf, "length=%d\n", length);
108

    
109
  int i;
110
  for (i = 0; i < length; i++) {
111
    sprintf(buf, "%d: %d ", i, packet[i]);
112
    usb_puts(buf);
113
  }
114
  usb_puts("\n");
115

    
116
  //printf("received message from %d of length %d\n", source, length);
117

    
118
  ///assert(length == sizeof(ColonetRobotServerPacket));
119
  packet_string_to_struct(&pkt, packet);
120

    
121
  char buf2[40];
122
  sprintf(buf2, "client_id:%d, msg_code:%d\n", pkt.client_id, pkt.msg_code);
123
  usb_puts(buf2);
124

    
125
  args = pkt.data;
126

    
127
  int_args[0] = two_bytes_to_int(args[0], args[1]);
128
  int_args[1] = two_bytes_to_int(args[2], args[3]);
129
  int_args[2] = two_bytes_to_int(args[4], args[5]);
130

    
131
  if (type == COLONET_REQUEST) {
132
    usb_puts("type is colonet request\n");
133

    
134
    /* TODO - send back data! */
135

    
136
    switch (pkt.msg_code) {
137
      //Sharp
138
    case READ_DISTANCE:
139
      break;
140
    case LINEARIZE_DISTANCE:
141
      break;
142
    case LOG_DISTANCE:
143
      break;
144

    
145
      //Analog
146
    case CALL_ANALOG8:
147
      break;
148
    case CALL_ANALOG10:
149
      break;
150
    case WHEEL:
151
      break;
152

    
153
    case BATTERY:
154
      sprintf((char*)pkt.data, "%d", (int)battery8());
155
      wl_send_robot_to_robot_global_packet(colonet_pgh.groupCode, 0, (char*)&pkt, sizeof(pkt), wl_source, 0);
156
      break;
157

    
158
      //BOM
159
    case GETMAXBOM:
160
      break;
161

    
162
      //Dio
163
    case DIGITAL_INPUT:
164
      break;
165
    case BUTTON1_READ:
166
      break;
167
    case BUTTON2_READ:
168
      break;
169

    
170
      //Bumper
171
    case DETECT_BUMP:
172
      break;
173
    }
174
  } else if (type == COLONET_COMMAND) {
175
    usb_puts("colonet command...\n");
176

    
177
/* TODO uncomment this stuff */
178
/*     if (pkt.msg_code >= USER_DEFINED_MSG_ID_START && */
179
/*         pkt.msg_code <= USER_DEFINED_MSG_ID_END) { */
180
/*       if (user_handlers[pkt.msg_code - USER_DEFINED_MSG_ID_START].handler) { */
181
/*         /\* Call the user's handler function if it the function's address */
182
/*          * is non-zero (has been set) *\/ */
183
/*         user_handlers[pkt.msg_code - USER_DEFINED_MSG_ID_START].handler(); */
184
/*       } */
185
/*     } */
186

    
187
    switch (pkt.msg_code) {
188
/*     default: */
189
/*       printf("%s: Error - message code %d not implemented\n", __FUNCTION__, */
190
/*              pkt.msg_code); */
191
/*       break; */
192

    
193
    case SERVER_REPORT_POSITION_TO_ROBOT:
194
      robot_x = int_args[0];
195
      robot_y = int_args[1];
196

    
197
      sprintf(buf, "my position is: %d %d\n", robot_x, robot_y);
198
      usb_puts(buf);
199
      break;
200

    
201
    case MOVE_TO_ABSOLUTE_POSITION:
202
      move_to_position_routine(int_args[0], int_args[1]);
203
      break;
204

    
205
      //Buzzer
206
    case BUZZER_INIT:
207
      buzzer_init();
208
      break;
209
    case BUZZER_SET_VAL:
210
      buzzer_set_val(args[0]);
211
      break;
212
    case BUZZER_SET_FREQ:
213
      buzzer_set_freq(args[0]);
214
      break;
215
    case BUZZER_CHIRP:
216
      buzzer_chirp(int_args[0], int_args[1]);
217
      break;
218
    case BUZZER_OFF:
219
      buzzer_off();
220
      break;
221
    case ORB_INIT:
222
      orb_init();
223
      break;
224
    //Orb
225
    case ORB_SET:
226
      orb_set(args[0], args[1], args[2]);
227
      break;
228
    case ORB_SET_COLOR:
229
      orb_set_color(int_args[0]);
230
      break;
231
    case ORB_DISABLE:
232
      orb_disable();
233
      break;
234
    case ORB_ENABLE:
235
      orb_enable();
236
      break;
237
    case LED_INIT:
238
      break;
239
    case LED_USER:
240
      break;
241
    case ORB_SEND:
242
      //orb_send();
243
      break;
244
      //Motors
245
    case MOTORS_INIT:
246
      usb_puts("calling motors_init\n");
247
      motors_init();
248
      break;
249
    case MOTOR1_SET:
250
      sprintf(buf, "calling motor1_set [%i] [%i]\n", args[0], args[1]);
251
      usb_puts(buf);
252
      motor1_set(args[0], args[1]);
253
      break;
254
    case MOTOR2_SET:
255
      sprintf(buf, "calling motor2_set [%i] [%i]\n", args[0], args[1]);
256
      usb_puts(buf);
257
      motor2_set(args[0], args[1]);
258
      break;
259
    case MOTORS_OFF:
260
      usb_puts("calling motors_off\n");
261
      motors_off();
262
      break;
263
    case MOVE:
264
      sprintf(buf, "calling move with: %d, %d\n", args[0], args[1]);
265
      usb_puts(buf);
266
      move(args[0], args[1]);
267
      break;
268
    case XBEE_INIT:
269
      xbee_init();
270
      break;
271

    
272
    case XBEE_PUTC:
273
      xbee_putc((char)args[0]);
274
      break;
275

    
276
    case USB_INIT:
277
      usb_init();
278
      break;
279

    
280
    case USB_PUTC:
281
      usb_putc((char)args[0]);
282
      break;
283

    
284
    case PRINTF:
285
      printf("%s", pkt.data);
286
      break;
287
    case KILL_ROBOT:
288
      motors_off();
289
      buzzer_off();
290
      exit(0); //kill the robot
291
      break;
292
      //Time
293
    case DELAY_MS:
294
      delay_ms(int_args[0]);
295
      break;
296

    
297
      //Analog
298
    case ANALOG_INIT:
299
      //TODO: how do we really init the analog? this doesn't work:
300
      //analog_init();
301
      break;
302

    
303
      //BOM
304
    case BOM_ON:
305
      bom_on();
306
      break;
307
    case BOM_OFF:
308
      bom_off();
309
      break;
310

    
311
    //Dio
312
    case DIGITAL_OUTPUT:
313
      digital_output(int_args[0], int_args[1]);
314
      break;
315
    }
316
  } else {
317
    sprintf(buf, "%s: Error: Invalid colonet message type", __FUNCTION__);
318
    usb_puts(buf);
319
  }
320
}
321

    
322
static void packet_string_to_struct(ColonetRobotServerPacket* dest_pkt, unsigned char* pkt_buf) {
323
  memcpy(dest_pkt, pkt_buf, sizeof(ColonetRobotServerPacket));
324
}
325

    
326
/* two_bytes_to_int(char a, char b)
327
 * Returns int of form [high][low]
328
 */
329
static unsigned int two_bytes_to_int(char high, char low) {
330
  return (((unsigned int)high)<<8) + (unsigned int)low;
331
}