Data Structures | |
union | rf_packet |
struct | seen_packet |
struct | sending_item |
Defines | |
#define | PKT_FLAG_DELETED 0xff |
Functions | |
void | pkt_calc_check_byte (rf_packet *packet) |
uns8 | pkt_check_check_byte (rf_packet *packet) |
void | pkt_init (uns16 my_addr, uns16 last_sent_id) |
Initialise packet delivery system. | |
uns8 | pkt_print_packet (rf_packet *my_packet) |
uns8 | pkt_process_rf_data (uns8 *data_in) |
Process received RF data. | |
void | pkt_process_tx_queue () |
Handle queued items. | |
uns8 | pkt_queue_packet (rf_packet *packet, uns8 resend) |
uns8 | pkt_seen (uns16 pkt_id, uns16 source_addr) |
void | pkt_send_packet (rf_packet *packet) |
uns8 | pkt_send_payload (uns16 dest_addr, uns8 *payload, uns8 resend) |
Send a payload via the packet delivery system. | |
Variables | |
uns16 | pkt_my_addr = 0x66 |
uns16 | pkt_my_next_pkt_id = 0 |
static seen_packet | pkt_seen_list [PKT_SEEN_LIST_SIZE] |
uns8 | pkt_seen_list_last = 0 |
static sending_item | pkt_tx_queue [PKT_TX_QUEUE_SIZE] |
#define PKT_FLAG_DELETED 0xff |
void pkt_calc_check_byte | ( | rf_packet * | packet | ) |
00093 { 00094 00095 uns8 calc, count; 00096 00097 calc = 0; 00098 for (count = 0; count < PKT_PACKET_SIZE -1; count++) { // -1 since we don't want to include the check digit 00099 calc ^= packet->a[count]; 00100 } 00101 packet->d.check_byte = calc; 00102 }
uns8 pkt_check_check_byte | ( | rf_packet * | packet | ) |
00104 { 00105 00106 uns8 calc, count; 00107 00108 calc = 0; 00109 for (count = 0; count < PKT_PACKET_SIZE -1; count++) { // -1 since we don't want to include the check digit 00110 calc ^= packet->a[count]; 00111 } 00112 00113 if (calc == packet->d.check_byte) 00114 return 1; 00115 else 00116 return 0; 00117 00118 }
void pkt_init | ( | uns16 | my_addr, | |
uns16 | last_sent_pkt_id | |||
) |
Initialise the packet delivery system ready for use. This routine clears the transmit queue and seen queue. If you don't store the last_sent_pkt_id (eg, in EEPROM) then set this to 0.
my_addr | The address of this system | |
last_sent_pkt_id | The last pkt_id used by this system. |
00423 { 00424 // go through tx queue and set all flags to DELETED 00425 uns8 count; 00426 uns16 current_tick; 00427 00428 pkt_my_addr = my_addr; // store my address 00429 pkt_my_next_pkt_id = last_sent_id + 1; // get next packet id 00430 for (count = 0; count < PKT_TX_QUEUE_SIZE; count++) { 00431 pkt_tx_queue[count].flag = PKT_FLAG_DELETED; // deleted 00432 } 00433 00434 for (count = 0; count < PKT_SEEN_LIST_SIZE; count++ ) { 00435 pkt_seen_list[count].source_addr = 0xffff; 00436 } 00437 }
uns8 pkt_print_packet | ( | rf_packet * | my_packet | ) |
00120 { 00121 00122 serial_print_str("[Pkt: s:"); 00123 serial_print_int_hex(my_packet->d.source_addr); 00124 serial_print_str(" i:"); 00125 serial_print_int_hex(my_packet->d.pkt_id); 00126 serial_print_str(" d:"); 00127 serial_print_int_hex(my_packet->d.dest_addr); 00128 serial_print_str(" r1:"); 00129 serial_print_int_hex(my_packet->d.r1_addr); 00130 serial_print_str(" r2:"); 00131 serial_print_int_hex(my_packet->d.r2_addr); 00132 serial_print_str(" r3:"); 00133 serial_print_int_hex(my_packet->d.r3_addr); 00134 serial_print_str(" p:"); 00135 for (uns8 count = 0; count < PKT_PAYLOAD_SIZE; count++) { 00136 serial_print_int_hex(my_packet->d.payload[count]); 00137 serial_print_spc(); 00138 } 00139 serial_print_str("] "); 00140 }
uns8 pkt_process_rf_data | ( | uns8 * | data_in | ) |
Call this routine when your RF device has received a chunk of data from somewhere. The packet delivery system will handle everything including acknowledgements and ignoring packets that it has already seen.
pkt_in | A pointer to the received data. It is assumed that this will point to PKT_PACKET_SIZE bytes of data. |
00174 { 00175 00176 uns8 status = 0; 00177 uns8 count; 00178 uns16 orig_pkt_id; 00179 uns8 ack_payload[PKT_PAYLOAD_SIZE] = { 0xff, 0xff }; 00180 sending_item *pitem; 00181 rf_packet packet; 00182 start_crit_sec(); 00183 00184 memcpy(/*dst*/ (void *)&packet, // copy it in 00185 /*src*/ (void *)data_in, 00186 /*len*/ PKT_PACKET_SIZE); 00187 end_crit_sec(); 00188 00189 #ifdef PKT_DEBUG 00190 serial_putc('r'); 00191 pkt_print_packet(&packet); 00192 #endif 00193 if (!pkt_check_check_byte(&packet)) { 00194 #ifdef PKT_DEBUG_HIGH 00195 serial_print_str("CF! "); 00196 #endif 00197 return PKT_STATUS_CHECK_FAIL; 00198 } 00199 00200 // Am I the dest addr? 00201 if ((packet.d.dest_addr == pkt_my_addr) || 00202 (packet.d.dest_addr == PKT_BROADCAST_ADDR)) { 00203 status = PKT_STATUS_PKT_IS_FOR_ME; 00204 // It's for me. But is it an ack? 00205 if ((packet.d.payload[0] != 0xff) || 00206 (packet.d.payload[1] != 0xff)) { // not an ack, so send one 00207 ack_payload[2] = packet.d.pkt_id & 0xff; 00208 ack_payload[3] = packet.d.pkt_id >> 8; 00209 #ifndef PKT_DEBUG_NO_TRANSMIT 00210 uns8 send_status = pkt_send_payload(packet.d.source_addr, ack_payload, PKT_FLAG_NO_RESEND); 00211 #ifdef PKT_DEBUG 00212 serial_print_str("ACKst="); 00213 serial_print_int(send_status); 00214 #endif 00215 #endif 00216 } else { // We got an ack! 00217 status = PKT_STATUS_PKT_IS_ACK_FOR_ME; 00218 orig_pkt_id = packet.d.payload[3]; 00219 orig_pkt_id <<= 8; 00220 orig_pkt_id += packet.d.payload[2]; 00221 for (count = 0; count < PKT_TX_QUEUE_SIZE; count++) { // Search for a packet 00222 pitem = &pkt_tx_queue[count]; 00223 if ((pitem->flag != PKT_FLAG_DELETED) && 00224 (pitem->packet.d.pkt_id == orig_pkt_id)) { 00225 status = PKT_STATUS_PKT_IS_FACK_FOR_ME; // Found the ack 00226 #ifdef PKT_CALLBACK_ON_SEND_SUCCEEDED 00227 pkt_send_succeeded_callback(pitem->packet.d.dest_addr, pitem->packet.d.pkt_id); 00228 #endif 00229 00230 pitem->flag = PKT_FLAG_DELETED; 00231 } 00232 } 00233 } // [we got an ack] 00234 00235 00236 // If not seen before, then process 00237 if (!pkt_seen(packet.d.pkt_id, packet.d.source_addr)) { 00238 00239 // process payload 00240 if ((status != PKT_STATUS_PKT_IS_FACK_FOR_ME) && 00241 (status != PKT_STATUS_PKT_IS_ACK_FOR_ME)) { 00242 pkt_payload_rx_callback(packet.d.source_addr, packet.d.pkt_id, packet.d.payload); 00243 } 00244 // Add to seen list 00245 pkt_seen_list_last++; 00246 if (pkt_seen_list_last == PKT_SEEN_LIST_SIZE) { 00247 pkt_seen_list_last = 0; 00248 } 00249 pkt_seen_list[pkt_seen_list_last].pkt_id = packet.d.pkt_id; 00250 pkt_seen_list[pkt_seen_list_last].source_addr = packet.d.source_addr; 00251 } else { 00252 status = PKT_STATUS_PKT_FOR_ME_BUT_SEEN; 00253 #ifdef PKT_DEBUG_HIGH 00254 serial_print_str(" seen "); 00255 #endif 00256 } 00257 } 00258 else 00259 // Is sender + pkt_id seen? 00260 if (pkt_seen(packet.d.pkt_id, packet.d.source_addr)) { 00261 // We've seen this packet before 00262 status = PKT_STATUS_SEEN_BEFORE; 00263 } else 00264 // Am I the sender? 00265 if (packet.d.source_addr == pkt_my_addr) { 00266 status = PKT_STATUS_I_AM_SENDER; 00267 } else 00268 // Is the r1_addr = 0xffff, meaning direct send? 00269 if (packet.d.r1_addr == PKT_DIRECT_SEND_ADDR) { 00270 status = PKT_STATUS_DIRECT_SEND; 00271 } else 00272 // Am I one of the routers? 00273 if ((packet.d.r1_addr == pkt_my_addr) || 00274 (packet.d.r2_addr == pkt_my_addr) || 00275 (packet.d.r3_addr == pkt_my_addr)) { 00276 status = PKT_STATUS_PREVIOUS_ROUTED_VIA_ME; 00277 } else 00278 // Is r3 full? 00279 if (packet.d.r3_addr != 0) { 00280 status = PKT_STATUS_ROUTING_FULL; 00281 } else { // I need to re-broadcast this packet 00282 status = PKT_STATUS_NEED_TO_REBROADCAST; 00283 // Add me as a router 00284 if (packet.d.r1_addr == 0) { 00285 packet.d.r1_addr = pkt_my_addr; 00286 } else if (packet.d.r2_addr == 0) { 00287 packet.d.r2_addr = pkt_my_addr; 00288 } else { 00289 packet.d.r3_addr = pkt_my_addr; 00290 } 00291 // Update check byte now we've changed packet 00292 pkt_calc_check_byte(&packet); 00293 // queue packet no resend 00294 00295 #ifndef PKT_DEBUG_NO_TRANSMIT 00296 pkt_queue_packet(&packet, PKT_FLAG_NO_RESEND); 00297 #endif 00298 // add to seen list? 00299 } // [I need to re-broadcast this packet] 00300 00301 return status; 00302 }
void pkt_process_tx_queue | ( | ) |
Call this routine regularly (as often as possible) in your main loop in order for the packet delivery system to send any queued packets when it is appropriate to do so. It will also remove any packets from the tx queue that have been there too long.
00354 { 00355 00356 uns8 count; 00357 uns16 current_tick; 00358 uns8 sent_count; 00359 uns8 flag; 00360 sending_item *item; 00361 00362 current_tick = tick_get_count(); 00363 00364 for (count = 0; count < PKT_TX_QUEUE_SIZE; count++) { // search for a packet 00365 item = &pkt_tx_queue[count]; // grab item to save code 00366 flag = item->flag; 00367 if (flag != PKT_FLAG_DELETED) { // got something to send 00368 sent_count = item->sent_count; 00369 if (sent_count > PKT_SEND_MAX_TRIES) { // Sent too many times 00370 item->flag = PKT_FLAG_DELETED; // Delete 00371 #ifdef PKT_CALLBACK_ON_SEND_FAILED 00372 pkt_send_failed_callback(item->packet.d.dest_addr, item->packet.d.pkt_id); 00373 #endif 00374 #ifdef PKT_DEBUG 00375 serial_print_str(" SF!\n "); 00376 #endif 00377 } else if ((sent_count == 0) // Never tried to send 00378 || (tick_calc_diff(item->tick_sent, current_tick) 00379 > PKT_RESEND_TICK_DELAY*sent_count + count)) { // Or more than delay time since last try 00380 // Note slight randomness built in by adding array position (count) 00381 item->tick_sent = current_tick; // set tick count to current 00382 //delay_us(pkt_my_addr & 0x07 *30); 00383 #ifdef PKT_DEBUG_PAYLOAD_SENT 00384 item->packet.d.payload[7] = sent_count; 00385 pkt_calc_check_byte((rf_packet*)item); 00386 #endif 00387 #ifdef PKT_DEBUG_HIGH 00388 serial_print_str(" t="); 00389 serial_print_int(current_tick); 00390 serial_print_spc(); 00391 #endif 00392 pkt_send_packet((rf_packet*)item); // send it 00393 #ifdef PKT_CALLBACK_ON_SEND 00394 pkt_send_callback(item->packet.d.dest_addr, item->packet.d.pkt_id); 00395 #endif 00396 00397 if (flag != PKT_FLAG_RESEND) { // no resend? 00398 item->flag = PKT_FLAG_DELETED; // then delete 00399 #ifdef PKT_DEBUG_HIGH 00400 serial_print_str(" SNR "); 00401 pkt_print_packet((rf_packet*)item); 00402 #endif 00403 00404 } else { // Yes resend 00405 item->sent_count++; 00406 #ifdef PKT_DEBUG_HIGH 00407 serial_print_str("SC "); 00408 serial_print_int(pkt_tx_queue[count].sent_count); 00409 serial_print_spc(); 00410 #endif 00411 00412 // clear direct send, next one goes to everyone! 00413 if (item->packet.d.r1_addr == 0xffff) { 00414 item->packet.d.r1_addr = 0; 00415 } 00416 } // [Yes resend] 00417 } // [Okay to send it] 00418 } // [Got something to send] 00419 } // [Search for a packet] 00420 } // 269 + 12
uns8 pkt_queue_packet | ( | rf_packet * | packet, | |
uns8 | resend | |||
) |
00145 { 00146 uns8 count, found; 00147 // find slot 00148 found = 0; 00149 for (count = 0; count < PKT_TX_QUEUE_SIZE; count++) { 00150 if (pkt_tx_queue[count].flag == PKT_FLAG_DELETED) { 00151 found = 1; 00152 break; 00153 } 00154 } 00155 if (found) { 00156 #ifdef PKT_DEBUG_HIGH 00157 serial_print_str(" Qin "); 00158 serial_print_int(count); 00159 #endif 00160 memcpy(/*dst*/ (void *)&pkt_tx_queue[count], // copy it in 00161 /*src*/ (void *)packet, 00162 /*len*/ PKT_PACKET_SIZE); 00163 pkt_tx_queue[count].sent_count = 0; 00164 // resend = resend 00165 pkt_tx_queue[count].flag = resend; 00166 return PKT_STATUS_QUEUED; 00167 } else { 00168 return PKT_STATUS_TX_QUEUE_FULL; 00169 } 00170 00171 }
uns8 pkt_seen | ( | uns16 | pkt_id, | |
uns16 | source_addr | |||
) |
00080 { 00081 00082 uns8 count; 00083 00084 for (count = 0; count < PKT_SEEN_LIST_SIZE; count++ ) { 00085 if ((pkt_seen_list[count].pkt_id == pkt_id) && 00086 (pkt_seen_list[count].source_addr == source_addr)) { 00087 return 1; 00088 } // if 00089 } // for 00090 return 0; // didn't find it 00091 }
void pkt_send_packet | ( | rf_packet * | packet | ) | [inline] |
00328 { 00329 00330 uns8 tx_buffer[PKT_PACKET_SIZE + 3]; // +3 for RF address (fixed) 00331 uns8 count; 00332 00333 #ifdef PKT_DEBUG 00334 serial_print_str(" <S>"); 00335 #endif 00336 #ifdef PKT_DEBUG_HIGH 00337 pkt_print_packet(packet); 00338 #endif 00339 tx_buffer[0] = 0b11100111; // address 00340 tx_buffer[1] = 0b11100111; // address 00341 tx_buffer[2] = 0b11100111; // address 00342 for (count = 0; count < PKT_PACKET_SIZE; count++) { 00343 tx_buffer[count+3] = packet->a[count]; 00344 } 00345 pic_rf_transmit(tx_buffer, PKT_PACKET_SIZE + 3); 00346 //pic_rf_transmit((uns8 *)packet, PKT_PACKET_SIZE); 00347 }
uns8 pkt_send_payload | ( | uns16 | dest_addr, | |
uns8 * | payload, | |||
uns8 | resend | |||
) |
Use this routine to send a payload of data to the destination address. The payload must point to PKT_PAYLOAD_SIZE bytes of data (as defined in your config.h). The packet will be constructed, setting destination address, sender address (set previously in pkt_init) payload, initial routing directions and the check byte calculated. It will then be placed into the tx queue and will actually be sent next time pkt_process_tx_queue is called.
dest_addr | Send payload to this address. Use address of PKT_BROADCAST_ADDR to broadcast to all listening local addresses | |
pay_load | Pointer to PKT_PAYLOAD_SIZE array of bytes | |
resend | Set to PKT_FLAG_RESEND or PKT_FLAG_NO_RESEND |
00440 { 00441 00442 rf_packet my_packet; 00443 uns8 count; 00444 00445 #ifdef PKT_DEBUG_HIGH 00446 serial_print_str("\npkt send d:"); 00447 serial_print_int(dest_addr); 00448 serial_print_str("s: "); 00449 serial_print_int(pkt_my_addr); 00450 serial_print_str("\n"); 00451 #endif 00452 00453 // build packet 00454 00455 my_packet.d.source_addr = pkt_my_addr; 00456 my_packet.d.pkt_id = pkt_my_next_pkt_id++; 00457 my_packet.d.dest_addr = dest_addr; 00458 my_packet.d.r1_addr = 0; 00459 if ((dest_addr != PKT_BROADCAST_ADDR) && 00460 ((payload[0] != 0xff) || (payload[1] != 0xff))) { // if not broadcast send 00461 my_packet.d.r1_addr = PKT_DIRECT_SEND_ADDR; // for direct send 00462 } 00463 my_packet.d.r2_addr = 0; 00464 my_packet.d.r3_addr = 0; 00465 for (count = 0; count < PKT_PAYLOAD_SIZE; count++) { 00466 my_packet.d.payload[count] = payload[count]; 00467 } 00468 pkt_calc_check_byte(&my_packet); 00469 00470 #ifdef PKT_DEBUG 00471 serial_print_str(" PS"); 00472 pkt_print_packet(&my_packet); 00473 #endif 00474 00475 // Put it in the queue for sending 00476 00477 return pkt_queue_packet(&my_packet, resend); 00478 }
uns16 pkt_my_addr = 0x66 |
uns16 pkt_my_next_pkt_id = 0 |
seen_packet pkt_seen_list[PKT_SEEN_LIST_SIZE] [static] |
uns8 pkt_seen_list_last = 0 |
sending_item pkt_tx_queue[PKT_TX_QUEUE_SIZE] [static] |