Dependencies: XBeeLib mbed HvZAlphaNumLib HvZServerLib
lib/Tag.cpp@1:d1b5cd8b2c18, 2010-12-12 (annotated)
- Committer:
- etherealflaim
- Date:
- Sun Dec 12 19:38:47 2010 +0000
- Revision:
- 1:d1b5cd8b2c18
- Parent:
- 0:9cdba0589ba2
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
etherealflaim | 0:9cdba0589ba2 | 1 | #include "mbed.h" |
etherealflaim | 0:9cdba0589ba2 | 2 | #include "iHvZ.hpp" |
etherealflaim | 0:9cdba0589ba2 | 3 | #include "XBee.hpp" |
etherealflaim | 0:9cdba0589ba2 | 4 | |
etherealflaim | 0:9cdba0589ba2 | 5 | #include <vector> |
etherealflaim | 0:9cdba0589ba2 | 6 | #include <string> |
etherealflaim | 0:9cdba0589ba2 | 7 | |
etherealflaim | 0:9cdba0589ba2 | 8 | Tag::Tag(iHvZ *game, PinName tagbtn) |
etherealflaim | 0:9cdba0589ba2 | 9 | : m_game(game), m_tag(tagbtn), m_tag_int(tagbtn) |
etherealflaim | 0:9cdba0589ba2 | 10 | { |
etherealflaim | 0:9cdba0589ba2 | 11 | m_tag_int.rise(this, &Tag::rise); |
etherealflaim | 0:9cdba0589ba2 | 12 | m_game->xbee_device().attach(this, &Tag::rx); |
etherealflaim | 0:9cdba0589ba2 | 13 | } |
etherealflaim | 0:9cdba0589ba2 | 14 | |
etherealflaim | 0:9cdba0589ba2 | 15 | void Tag::rise() |
etherealflaim | 0:9cdba0589ba2 | 16 | { |
etherealflaim | 0:9cdba0589ba2 | 17 | Serial usb(USBTX,USBRX); |
etherealflaim | 0:9cdba0589ba2 | 18 | |
etherealflaim | 0:9cdba0589ba2 | 19 | // debounce |
etherealflaim | 0:9cdba0589ba2 | 20 | wait(.1); |
etherealflaim | 0:9cdba0589ba2 | 21 | if (!m_tag) return; |
etherealflaim | 0:9cdba0589ba2 | 22 | |
etherealflaim | 0:9cdba0589ba2 | 23 | event(TAG_EVENT_BUTTON); |
etherealflaim | 0:9cdba0589ba2 | 24 | } |
etherealflaim | 0:9cdba0589ba2 | 25 | |
etherealflaim | 0:9cdba0589ba2 | 26 | void Tag::rx() |
etherealflaim | 0:9cdba0589ba2 | 27 | { |
etherealflaim | 0:9cdba0589ba2 | 28 | event(TAG_EVENT_RX); |
etherealflaim | 0:9cdba0589ba2 | 29 | } |
etherealflaim | 0:9cdba0589ba2 | 30 | |
etherealflaim | 0:9cdba0589ba2 | 31 | void Tag::timeout() |
etherealflaim | 0:9cdba0589ba2 | 32 | { |
etherealflaim | 0:9cdba0589ba2 | 33 | event(TAG_EVENT_TIMEOUT); |
etherealflaim | 0:9cdba0589ba2 | 34 | } |
etherealflaim | 0:9cdba0589ba2 | 35 | |
etherealflaim | 0:9cdba0589ba2 | 36 | void Tag::event(TagEvent ev) |
etherealflaim | 0:9cdba0589ba2 | 37 | { |
etherealflaim | 0:9cdba0589ba2 | 38 | Serial usb(USBTX,USBRX); |
etherealflaim | 0:9cdba0589ba2 | 39 | static TagState state = TAG_STATE_WAITING; |
etherealflaim | 0:9cdba0589ba2 | 40 | static string peer = ""; |
etherealflaim | 0:9cdba0589ba2 | 41 | static string peer_tagid = ""; |
etherealflaim | 0:9cdba0589ba2 | 42 | static string type = ""; // = (m_game.status()==STATUS_HUMAN)?"STUN":"TAG"; |
etherealflaim | 0:9cdba0589ba2 | 43 | static string ack = ""; |
etherealflaim | 0:9cdba0589ba2 | 44 | |
etherealflaim | 0:9cdba0589ba2 | 45 | XBeePacket pkt; |
etherealflaim | 0:9cdba0589ba2 | 46 | |
etherealflaim | 0:9cdba0589ba2 | 47 | if (ev == TAG_EVENT_TIMEOUT) |
etherealflaim | 0:9cdba0589ba2 | 48 | { |
etherealflaim | 0:9cdba0589ba2 | 49 | // Display the timeout character (TODO) |
etherealflaim | 0:9cdba0589ba2 | 50 | usb.printf("!! TIMEOUT !!\r\n"); |
etherealflaim | 0:9cdba0589ba2 | 51 | m_game->alphanumdisplay_device().display('*'); |
etherealflaim | 0:9cdba0589ba2 | 52 | //wait(1); |
etherealflaim | 0:9cdba0589ba2 | 53 | state = TAG_STATE_WAITING; |
etherealflaim | 0:9cdba0589ba2 | 54 | } |
etherealflaim | 0:9cdba0589ba2 | 55 | |
etherealflaim | 0:9cdba0589ba2 | 56 | if (ev == TAG_EVENT_RX) |
etherealflaim | 0:9cdba0589ba2 | 57 | { |
etherealflaim | 0:9cdba0589ba2 | 58 | // Get the packet that triggered this event |
etherealflaim | 0:9cdba0589ba2 | 59 | pkt = m_game->xbee_device().read(); |
etherealflaim | 0:9cdba0589ba2 | 60 | } |
etherealflaim | 0:9cdba0589ba2 | 61 | |
etherealflaim | 0:9cdba0589ba2 | 62 | do switch (state) |
etherealflaim | 0:9cdba0589ba2 | 63 | { |
etherealflaim | 0:9cdba0589ba2 | 64 | case TAG_STATE_WAITING: |
etherealflaim | 0:9cdba0589ba2 | 65 | // Zero everything |
etherealflaim | 0:9cdba0589ba2 | 66 | peer = ""; |
etherealflaim | 0:9cdba0589ba2 | 67 | peer_tagid = ""; |
etherealflaim | 0:9cdba0589ba2 | 68 | type = ""; |
etherealflaim | 0:9cdba0589ba2 | 69 | ack = ""; |
etherealflaim | 0:9cdba0589ba2 | 70 | // Display H/Z |
etherealflaim | 0:9cdba0589ba2 | 71 | // m_game->alphanumdisplay_device().display((m_game->status()==STATUS_HUMAN)?'H':'Z'); |
etherealflaim | 0:9cdba0589ba2 | 72 | // Check transitions |
etherealflaim | 0:9cdba0589ba2 | 73 | if (ev == TAG_EVENT_BUTTON) state = TAG_STATE_TX_SEND; |
etherealflaim | 0:9cdba0589ba2 | 74 | else if (ev == TAG_EVENT_RX) state = TAG_STATE_RX_RECV; |
etherealflaim | 0:9cdba0589ba2 | 75 | else return; |
etherealflaim | 0:9cdba0589ba2 | 76 | continue; |
etherealflaim | 0:9cdba0589ba2 | 77 | // Sending states |
etherealflaim | 0:9cdba0589ba2 | 78 | case TAG_STATE_TX_SEND: |
etherealflaim | 0:9cdba0589ba2 | 79 | // First, check if this zombie is stunned (if so, they can't do anything) |
etherealflaim | 0:9cdba0589ba2 | 80 | if (m_game->stun_tracker().stunned()) return; |
etherealflaim | 0:9cdba0589ba2 | 81 | // Get whether we are tagging or stunning |
etherealflaim | 0:9cdba0589ba2 | 82 | type = (m_game->status()==STATUS_HUMAN)?"STUN":"TAG"; |
etherealflaim | 0:9cdba0589ba2 | 83 | // Generate a random acknowledge character for display |
etherealflaim | 0:9cdba0589ba2 | 84 | do { ack = string(1, 'A'+rand()%26); } while (ack == "H" || ack == "Z"); |
etherealflaim | 0:9cdba0589ba2 | 85 | // Send the SYN message |
etherealflaim | 0:9cdba0589ba2 | 86 | m_game->xbee_device().broadcast(type + "\001SYN\001" + ack); |
etherealflaim | 0:9cdba0589ba2 | 87 | // Display the acknowledge character (TODO) |
etherealflaim | 0:9cdba0589ba2 | 88 | usb.printf("CHECK: %s (send)\r\n", ack.c_str()); |
etherealflaim | 0:9cdba0589ba2 | 89 | m_game->alphanumdisplay_device().display(ack[0]); |
etherealflaim | 0:9cdba0589ba2 | 90 | // Attach a timeout that will revert to waiting |
etherealflaim | 0:9cdba0589ba2 | 91 | m_timeout.attach(this, &Tag::timeout, TAG_TIMEOUT_TIME); |
etherealflaim | 0:9cdba0589ba2 | 92 | state = TAG_STATE_TX_WAITACK; |
etherealflaim | 0:9cdba0589ba2 | 93 | continue; |
etherealflaim | 0:9cdba0589ba2 | 94 | case TAG_STATE_TX_WAITACK: |
etherealflaim | 0:9cdba0589ba2 | 95 | if (ev == TAG_EVENT_RX) |
etherealflaim | 0:9cdba0589ba2 | 96 | { |
etherealflaim | 0:9cdba0589ba2 | 97 | // Make sure it is an ack packet with the right ack character |
etherealflaim | 0:9cdba0589ba2 | 98 | vector<string> pieces = pkt.split_data(); |
etherealflaim | 0:9cdba0589ba2 | 99 | if (pieces.size() != 5) return; |
etherealflaim | 0:9cdba0589ba2 | 100 | if (pieces[0] != type) return; |
etherealflaim | 0:9cdba0589ba2 | 101 | if (pieces[1] != "ACK") return; |
etherealflaim | 0:9cdba0589ba2 | 102 | if (pieces[2] != ack) return; |
etherealflaim | 0:9cdba0589ba2 | 103 | ack = pieces[3]; |
etherealflaim | 0:9cdba0589ba2 | 104 | // Store the peer ID and tag ID |
etherealflaim | 0:9cdba0589ba2 | 105 | peer = pkt.source(); |
etherealflaim | 0:9cdba0589ba2 | 106 | peer_tagid = pieces[4]; |
etherealflaim | 0:9cdba0589ba2 | 107 | // Display the new character for verification (TODO) |
etherealflaim | 0:9cdba0589ba2 | 108 | usb.printf("CHECK: %s (send ack)\r\n", ack.c_str()); |
etherealflaim | 0:9cdba0589ba2 | 109 | m_game->alphanumdisplay_device().display(ack[0]); |
etherealflaim | 0:9cdba0589ba2 | 110 | // Attach a timeout |
etherealflaim | 0:9cdba0589ba2 | 111 | m_timeout.attach(this, &Tag::timeout, TAG_TIMEOUT_TIME); |
etherealflaim | 0:9cdba0589ba2 | 112 | state = TAG_STATE_TX_WAITBTN; |
etherealflaim | 0:9cdba0589ba2 | 113 | } |
etherealflaim | 0:9cdba0589ba2 | 114 | return; |
etherealflaim | 0:9cdba0589ba2 | 115 | case TAG_STATE_TX_WAITBTN: |
etherealflaim | 0:9cdba0589ba2 | 116 | if (ev == TAG_EVENT_BUTTON) |
etherealflaim | 0:9cdba0589ba2 | 117 | { |
etherealflaim | 0:9cdba0589ba2 | 118 | state = TAG_STATE_TX_SENDCOMP; |
etherealflaim | 0:9cdba0589ba2 | 119 | continue; |
etherealflaim | 0:9cdba0589ba2 | 120 | } |
etherealflaim | 0:9cdba0589ba2 | 121 | return; |
etherealflaim | 0:9cdba0589ba2 | 122 | case TAG_STATE_TX_SENDCOMP: |
etherealflaim | 0:9cdba0589ba2 | 123 | // Send the FIN message indicating that the transaction is complete |
etherealflaim | 0:9cdba0589ba2 | 124 | m_game->xbee_device().send(peer, type+"\001FIN\001"+ack); |
etherealflaim | 0:9cdba0589ba2 | 125 | // Display the completion character (TODO) |
etherealflaim | 0:9cdba0589ba2 | 126 | usb.printf("COMPLETE: %s\r\n", type.c_str()); |
etherealflaim | 0:9cdba0589ba2 | 127 | m_game->alphanumdisplay_device().display('^'); |
etherealflaim | 0:9cdba0589ba2 | 128 | state = TAG_STATE_WAITING; |
etherealflaim | 0:9cdba0589ba2 | 129 | m_timeout.detach(); |
etherealflaim | 0:9cdba0589ba2 | 130 | |
etherealflaim | 0:9cdba0589ba2 | 131 | // Register the successful tag or stun |
etherealflaim | 0:9cdba0589ba2 | 132 | if (type == "TAG" && m_game->status() == STATUS_ZOMBIE) |
etherealflaim | 0:9cdba0589ba2 | 133 | m_game->register_tag(peer_tagid); |
etherealflaim | 0:9cdba0589ba2 | 134 | if (type == "STUN" && m_game->status() == STATUS_HUMAN) |
etherealflaim | 0:9cdba0589ba2 | 135 | m_game->register_stun(peer_tagid); |
etherealflaim | 0:9cdba0589ba2 | 136 | return; |
etherealflaim | 0:9cdba0589ba2 | 137 | // Receiving states |
etherealflaim | 0:9cdba0589ba2 | 138 | case TAG_STATE_RX_RECV: |
etherealflaim | 0:9cdba0589ba2 | 139 | if (ev == TAG_EVENT_RX) |
etherealflaim | 0:9cdba0589ba2 | 140 | { |
etherealflaim | 0:9cdba0589ba2 | 141 | vector<string> pieces = pkt.split_data(); |
etherealflaim | 0:9cdba0589ba2 | 142 | if (pieces.size() != 3) return; |
etherealflaim | 0:9cdba0589ba2 | 143 | type = pieces[0]; |
etherealflaim | 0:9cdba0589ba2 | 144 | if (pieces[1] != "SYN") return; |
etherealflaim | 0:9cdba0589ba2 | 145 | ack = pieces[2]; |
etherealflaim | 0:9cdba0589ba2 | 146 | // Register the source |
etherealflaim | 0:9cdba0589ba2 | 147 | peer = pkt.source(); |
etherealflaim | 0:9cdba0589ba2 | 148 | // Display the verification character (TODO) |
etherealflaim | 0:9cdba0589ba2 | 149 | usb.printf("CHECK: %s (receive)\r\n", ack.c_str()); |
etherealflaim | 0:9cdba0589ba2 | 150 | m_game->alphanumdisplay_device().display(ack[0]); |
etherealflaim | 0:9cdba0589ba2 | 151 | // Attach a timeout |
etherealflaim | 0:9cdba0589ba2 | 152 | m_timeout.attach(this, &Tag::timeout, TAG_TIMEOUT_TIME); |
etherealflaim | 0:9cdba0589ba2 | 153 | state = TAG_STATE_RX_WAITBTN; |
etherealflaim | 0:9cdba0589ba2 | 154 | } |
etherealflaim | 0:9cdba0589ba2 | 155 | return; |
etherealflaim | 0:9cdba0589ba2 | 156 | case TAG_STATE_RX_WAITBTN: |
etherealflaim | 0:9cdba0589ba2 | 157 | if (ev == TAG_EVENT_BUTTON) |
etherealflaim | 0:9cdba0589ba2 | 158 | { |
etherealflaim | 0:9cdba0589ba2 | 159 | state = TAG_STATE_RX_SENDACK; |
etherealflaim | 0:9cdba0589ba2 | 160 | continue; |
etherealflaim | 0:9cdba0589ba2 | 161 | } |
etherealflaim | 0:9cdba0589ba2 | 162 | return; |
etherealflaim | 0:9cdba0589ba2 | 163 | case TAG_STATE_RX_SENDACK: |
etherealflaim | 0:9cdba0589ba2 | 164 | { |
etherealflaim | 0:9cdba0589ba2 | 165 | // Generate a new acknowledgment character |
etherealflaim | 0:9cdba0589ba2 | 166 | string oldack = ack; |
etherealflaim | 0:9cdba0589ba2 | 167 | ack = string(1, '0'+rand()%9); |
etherealflaim | 0:9cdba0589ba2 | 168 | // Send the ack packet |
etherealflaim | 0:9cdba0589ba2 | 169 | m_game->xbee_device().send(peer, type+"\001ACK\001"+oldack+"\001"+ack+"\001"+m_game->life()); |
etherealflaim | 0:9cdba0589ba2 | 170 | // Display the verification character (TODO) |
etherealflaim | 0:9cdba0589ba2 | 171 | usb.printf("CHECK: %s (receive ack)\r\n", ack.c_str()); |
etherealflaim | 0:9cdba0589ba2 | 172 | m_game->alphanumdisplay_device().display(ack[0]); |
etherealflaim | 0:9cdba0589ba2 | 173 | // Attach a timeout |
etherealflaim | 0:9cdba0589ba2 | 174 | m_timeout.attach(this, &Tag::timeout, TAG_TIMEOUT_TIME); |
etherealflaim | 0:9cdba0589ba2 | 175 | state = TAG_STATE_RX_WAITCOMP; |
etherealflaim | 0:9cdba0589ba2 | 176 | } |
etherealflaim | 0:9cdba0589ba2 | 177 | return; |
etherealflaim | 0:9cdba0589ba2 | 178 | case TAG_STATE_RX_WAITCOMP: |
etherealflaim | 0:9cdba0589ba2 | 179 | if (ev == TAG_EVENT_RX) |
etherealflaim | 0:9cdba0589ba2 | 180 | { |
etherealflaim | 0:9cdba0589ba2 | 181 | vector<string> pieces = pkt.split_data(); |
etherealflaim | 0:9cdba0589ba2 | 182 | // Make sure the completion packet is well-formed |
etherealflaim | 0:9cdba0589ba2 | 183 | if (pieces.size() != 3) return; |
etherealflaim | 0:9cdba0589ba2 | 184 | if (pieces[0] != type) return; |
etherealflaim | 0:9cdba0589ba2 | 185 | if (pieces[1] != "FIN") return; |
etherealflaim | 0:9cdba0589ba2 | 186 | if (pieces[2] != ack) return; |
etherealflaim | 0:9cdba0589ba2 | 187 | // Make sure the peer is the same |
etherealflaim | 0:9cdba0589ba2 | 188 | if (peer != pkt.source()) return; |
etherealflaim | 0:9cdba0589ba2 | 189 | // Display the completion character (TODO) |
etherealflaim | 0:9cdba0589ba2 | 190 | usb.printf("COMPLETE: %s\r\n", type.c_str()); |
etherealflaim | 0:9cdba0589ba2 | 191 | m_game->alphanumdisplay_device().display('^'); |
etherealflaim | 0:9cdba0589ba2 | 192 | m_timeout.detach(); |
etherealflaim | 0:9cdba0589ba2 | 193 | state = TAG_STATE_WAITING; |
etherealflaim | 0:9cdba0589ba2 | 194 | |
etherealflaim | 0:9cdba0589ba2 | 195 | // Stun or tag the player |
etherealflaim | 0:9cdba0589ba2 | 196 | if (type == "TAG" && m_game->status() == STATUS_HUMAN) |
etherealflaim | 0:9cdba0589ba2 | 197 | m_game->tagged(); |
etherealflaim | 0:9cdba0589ba2 | 198 | if (type == "STUN" && m_game->status() == STATUS_ZOMBIE) |
etherealflaim | 0:9cdba0589ba2 | 199 | m_game->stunned(); |
etherealflaim | 0:9cdba0589ba2 | 200 | } |
etherealflaim | 0:9cdba0589ba2 | 201 | return; |
etherealflaim | 0:9cdba0589ba2 | 202 | } while (1); |
etherealflaim | 0:9cdba0589ba2 | 203 | } |