pic_packet.h File Reference
Pic meshed packed network library.
More...
Go to the source code of this file.
Detailed Description
Assumes either nrf2401a or nrf24l01 library
Define Documentation
#define PKT_BROADCAST_ADDR 0xfffe |
Send to anyone that will listen
#define PKT_CONFIG_ADDR 0xfffd |
Magic config packet address
#define PKT_DIRECT_SEND_ADDR 0xffff |
Router address for direct send only (no routing)
#define PKT_FLAG_BROADCAST 2 |
Packet should be broadcast to anyone on the network
#define PKT_FLAG_NO_RESEND 0 |
Packet should not be resent if it fails to reach destination
#define PKT_FLAG_RESEND 1 |
Packet should be resent if it fails to reach destination
#define PKT_STATUS_CHECK_FAIL 12 |
Packet is corrupt, ignoring
#define PKT_STATUS_DIRECT_SEND 6 |
Packet is direct send, but not for me, ignoring
#define PKT_STATUS_I_AM_SENDER 2 |
I have sent this packet, so ignoring
#define PKT_STATUS_NEED_TO_REBROADCAST 9 |
Packet is not for me, but protocol states I need to rebroadcast it
#define PKT_STATUS_PKT_FOR_ME_BUT_SEEN 13 |
Packet is for me but seen previously
#define PKT_STATUS_PKT_IS_ACK_FOR_ME 4 |
Packet is ACK for me, but didn't find in my transmit queue
#define PKT_STATUS_PKT_IS_FACK_FOR_ME 5 |
Packet is ACK for me, found in and removed from transmit queue (successful send)
#define PKT_STATUS_PKT_IS_FOR_ME 3 |
#define PKT_STATUS_PREVIOUS_ROUTED_VIA_ME 7 |
Packet has my address in the router list, ignoring
#define PKT_STATUS_QUEUED 10 |
Packet queued for transmition
#define PKT_STATUS_ROUTING_FULL 8 |
Packet not retransmitted since its routing list is full
#define PKT_STATUS_SEEN_BEFORE 1 |
Packet is already in seen list, ignoring
#define PKT_STATUS_TX_QUEUE_FULL 11 |
Packet has not been queued for transmition since my transmit queue is full
#define RF_RX_BUFFER_SIZE PKT_PACKET_SIZE |
Function Documentation
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.
- Parameters:
-
| my_addr | The address of this system |
| last_sent_pkt_id | The last pkt_id used by this system. |
void pkt_payload_rx_callback |
( |
uns16 |
source_addr, |
|
|
uns16 |
pkt_id, |
|
|
uns8 * |
payload | |
|
) |
| | |
Once a packet has been received, if it has not been seen before and it is destined to this address (set using pkt_init), then this routine will be called. You must have this routine defined in your own code.
- Parameters:
-
| source_addr | The address of the system that sent the packet |
| pkt_id | The ID of the packet (the source_addr and pkt_id are used to uniquely identify the packet |
| payload | A pointer to PKT_PACKET_SIZE bytes received |
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.
- Parameters:
-
| 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( (void *)&packet,
00185 (void *)data_in,
00186 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
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
00205 if ((packet.d.payload[0] != 0xff) ||
00206 (packet.d.payload[1] != 0xff)) {
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 {
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++) {
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;
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 }
00234
00235
00236
00237 if (!pkt_seen(packet.d.pkt_id, packet.d.source_addr)) {
00238
00239
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
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
00260 if (pkt_seen(packet.d.pkt_id, packet.d.source_addr)) {
00261
00262 status = PKT_STATUS_SEEN_BEFORE;
00263 } else
00264
00265 if (packet.d.source_addr == pkt_my_addr) {
00266 status = PKT_STATUS_I_AM_SENDER;
00267 } else
00268
00269 if (packet.d.r1_addr == PKT_DIRECT_SEND_ADDR) {
00270 status = PKT_STATUS_DIRECT_SEND;
00271 } else
00272
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
00279 if (packet.d.r3_addr != 0) {
00280 status = PKT_STATUS_ROUTING_FULL;
00281 } else {
00282 status = PKT_STATUS_NEED_TO_REBROADCAST;
00283
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
00292 pkt_calc_check_byte(&packet);
00293
00294
00295 #ifndef PKT_DEBUG_NO_TRANSMIT
00296 pkt_queue_packet(&packet, PKT_FLAG_NO_RESEND);
00297 #endif
00298
00299 }
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.
void pkt_send_callback |
( |
uns16 |
dest_addr, |
|
|
uns16 |
pkt_id | |
|
) |
| | |
void pkt_send_failed_callback |
( |
uns16 |
dest_addr, |
|
|
uns16 |
pkt_id | |
|
) |
| | |
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.
- Parameters:
-
| 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 |
void pkt_send_succeeded_callback |
( |
uns16 |
dest_addr, |
|
|
uns16 |
pkt_id | |
|
) |
| | |