Andriy Makukha
/
football_project_wo_output
football_project_wo_output
Fork of football_project by
main.cpp@78:43a6b54f0372, 2016-05-09 (annotated)
- Committer:
- andriym
- Date:
- Mon May 09 01:08:01 2016 +0000
- Revision:
- 78:43a6b54f0372
- Parent:
- 76:6638d83939d5
- Child:
- 79:9db29f41dc9d
Changed radio configs, Player tracking table, Switch team button, Output class (for different displays and Serial), different boards support.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
elmbed | 76:6638d83939d5 | 1 | #include <RFM69.h> |
andriym | 78:43a6b54f0372 | 2 | #include <list> |
andriym | 78:43a6b54f0372 | 3 | #include "output.h" |
AntonLS | 0:28ca4562fe1a | 4 | |
andriym | 78:43a6b54f0372 | 5 | using namespace std; |
andriym | 78:43a6b54f0372 | 6 | |
andriym | 78:43a6b54f0372 | 7 | Timer t; |
andriym | 78:43a6b54f0372 | 8 | Output out; |
elmbed | 17:d8b901d791fd | 9 | |
andriym | 78:43a6b54f0372 | 10 | /////////////////////////////////// PINS /////////////////////////////////// |
andriym | 78:43a6b54f0372 | 11 | #ifdef NORDIC |
andriym | 78:43a6b54f0372 | 12 | //PwmOut speaker(PB_8); // TODO: add sound for Nordic |
andriym | 78:43a6b54f0372 | 13 | DigitalIn din(BTN1); |
andriym | 78:43a6b54f0372 | 14 | AnalogIn ain(P0_1); // used for randomizing |
andriym | 78:43a6b54f0372 | 15 | #else // not NORDIC |
andriym | 78:43a6b54f0372 | 16 | #ifdef NUCLEO |
andriym | 78:43a6b54f0372 | 17 | PwmOut speaker(PB_8); |
andriym | 78:43a6b54f0372 | 18 | DigitalIn din(USER_BUTTON); |
andriym | 78:43a6b54f0372 | 19 | AnalogIn ain(A5); // used for randomizing |
andriym | 78:43a6b54f0372 | 20 | #else // LPC assumed |
andriym | 78:43a6b54f0372 | 21 | PwmOut speaker(p21); |
andriym | 78:43a6b54f0372 | 22 | DigitalIn din(p5); |
andriym | 78:43a6b54f0372 | 23 | AnalogIn ain(p15); // used for randomizing |
andriym | 78:43a6b54f0372 | 24 | #endif // NUCLEO |
andriym | 78:43a6b54f0372 | 25 | #endif // NORDIC |
AntonLS | 30:c60b0d52b067 | 26 | |
andriym | 78:43a6b54f0372 | 27 | /////////////////////////////////// RADIO /////////////////////////////////// |
andriym | 78:43a6b54f0372 | 28 | #ifdef NORDIC |
andriym | 78:43a6b54f0372 | 29 | static RFM69 radio(P0_20,P0_22,P0_25,P0_24,P0_23); // Update according to your setup |
andriym | 78:43a6b54f0372 | 30 | #else // not NORDIC |
andriym | 78:43a6b54f0372 | 31 | #ifdef NUCLEO |
andriym | 78:43a6b54f0372 | 32 | static RFM69 radio(D11,D12,D13,D10,D9); |
andriym | 78:43a6b54f0372 | 33 | #else // LPC assumed |
andriym | 78:43a6b54f0372 | 34 | static RFM69 radio(p11,p12,p13,p10,p9); |
andriym | 78:43a6b54f0372 | 35 | #endif // NUCLEO |
andriym | 78:43a6b54f0372 | 36 | #endif // NORDIC |
AntonLS | 12:6d313d575f84 | 37 | |
elmbed | 76:6638d83939d5 | 38 | static bool promiscuousMode = true; // set 'true' to sniff all packets on the same network |
AntonLS | 0:28ca4562fe1a | 39 | |
andriym | 78:43a6b54f0372 | 40 | /////////////////////////////////// FUNCTIONS /////////////////////////////////// |
andriym | 78:43a6b54f0372 | 41 | |
andriym | 78:43a6b54f0372 | 42 | void beep(float period, float time) { |
andriym | 78:43a6b54f0372 | 43 | #ifdef ENABLE_SOUND |
andriym | 78:43a6b54f0372 | 44 | speaker.period(period); |
andriym | 78:43a6b54f0372 | 45 | speaker =0.5; //50% duty cycle - max volume |
andriym | 78:43a6b54f0372 | 46 | wait(time); |
andriym | 78:43a6b54f0372 | 47 | speaker=0.0; // turn off audio |
andriym | 78:43a6b54f0372 | 48 | #endif |
andriym | 78:43a6b54f0372 | 49 | } |
andriym | 78:43a6b54f0372 | 50 | |
andriym | 78:43a6b54f0372 | 51 | void binary_sound(int z) { |
andriym | 78:43a6b54f0372 | 52 | // Beeps numbers according to their binary form |
andriym | 78:43a6b54f0372 | 53 | // (used for debugging in display-less and serial-less environments) |
andriym | 78:43a6b54f0372 | 54 | #ifdef ENABLE_SOUND |
andriym | 78:43a6b54f0372 | 55 | speaker.period(0.004); |
andriym | 78:43a6b54f0372 | 56 | while(z) { |
andriym | 78:43a6b54f0372 | 57 | speaker = 0.5; |
andriym | 78:43a6b54f0372 | 58 | if(z&1) wait(0.5); |
andriym | 78:43a6b54f0372 | 59 | else wait(0.25); |
andriym | 78:43a6b54f0372 | 60 | speaker = 0.0; |
andriym | 78:43a6b54f0372 | 61 | wait(1.0); |
andriym | 78:43a6b54f0372 | 62 | z >>= 1; |
andriym | 78:43a6b54f0372 | 63 | } |
andriym | 78:43a6b54f0372 | 64 | beep(0.002, 1.0); |
andriym | 78:43a6b54f0372 | 65 | #endif |
andriym | 78:43a6b54f0372 | 66 | } |
andriym | 78:43a6b54f0372 | 67 | |
andriym | 78:43a6b54f0372 | 68 | void generate_name(char rand_name[], uint8_t size) { |
andriym | 78:43a6b54f0372 | 69 | // Generate random name on the 62 character alphabet |
andriym | 78:43a6b54f0372 | 70 | memset(rand_name, 0x00, size); |
andriym | 78:43a6b54f0372 | 71 | char alph[63] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; |
andriym | 78:43a6b54f0372 | 72 | uint32_t seed = ((ain.read_u16()+3)/17)*(radio.readTemperature(-1)+37)*((ain.read_u16()+5)/13); |
andriym | 78:43a6b54f0372 | 73 | srand(seed); |
andriym | 78:43a6b54f0372 | 74 | for(int i=0;i<size-1;i++) { |
andriym | 78:43a6b54f0372 | 75 | rand_name[i] = alph[abs(rand()) % 62]; |
andriym | 78:43a6b54f0372 | 76 | } |
andriym | 78:43a6b54f0372 | 77 | } |
andriym | 78:43a6b54f0372 | 78 | |
andriym | 78:43a6b54f0372 | 79 | /////////////////////////////////// CLASSES /////////////////////////////////// |
andriym | 78:43a6b54f0372 | 80 | |
andriym | 78:43a6b54f0372 | 81 | struct Contact { |
andriym | 78:43a6b54f0372 | 82 | int16_t rssi; |
andriym | 78:43a6b54f0372 | 83 | uint32_t time_ms; |
andriym | 78:43a6b54f0372 | 84 | }; |
andriym | 78:43a6b54f0372 | 85 | |
andriym | 78:43a6b54f0372 | 86 | class Player { |
andriym | 78:43a6b54f0372 | 87 | public: |
andriym | 78:43a6b54f0372 | 88 | char name[NAME_LEN+1]; |
andriym | 78:43a6b54f0372 | 89 | int8_t team; |
andriym | 78:43a6b54f0372 | 90 | Player(const char rand_name[]) { |
andriym | 78:43a6b54f0372 | 91 | memset(name, 0x00, NAME_LEN+1); |
andriym | 78:43a6b54f0372 | 92 | memcpy(name, rand_name, NAME_LEN); |
andriym | 78:43a6b54f0372 | 93 | } |
andriym | 78:43a6b54f0372 | 94 | void update(int8_t _team, int rssi, uint32_t time=NULL) { |
andriym | 78:43a6b54f0372 | 95 | // Remember this contact |
andriym | 78:43a6b54f0372 | 96 | team = _team; |
andriym | 78:43a6b54f0372 | 97 | Contact c; |
andriym | 78:43a6b54f0372 | 98 | c.rssi = rssi; |
andriym | 78:43a6b54f0372 | 99 | c.time_ms = (time!=NULL) ? time : t.read_ms(); |
andriym | 78:43a6b54f0372 | 100 | contacts.push_front(c); |
andriym | 78:43a6b54f0372 | 101 | |
andriym | 78:43a6b54f0372 | 102 | // Cleanup |
andriym | 78:43a6b54f0372 | 103 | while(contacts.size() > MAX_RECORDS) contacts.pop_back(); |
andriym | 78:43a6b54f0372 | 104 | while(!contacts.empty() && c.time_ms - contacts.back().time_ms > MAX_HISTORY_MS) contacts.pop_back(); |
andriym | 78:43a6b54f0372 | 105 | } |
andriym | 78:43a6b54f0372 | 106 | int16_t get_distance(int &cnt) { |
andriym | 78:43a6b54f0372 | 107 | // Find max RSSI |
andriym | 78:43a6b54f0372 | 108 | uint32_t cur_time = t.read_ms(); |
andriym | 78:43a6b54f0372 | 109 | int16_t max_rssi=-128; |
andriym | 78:43a6b54f0372 | 110 | cnt=0; |
andriym | 78:43a6b54f0372 | 111 | for (list<Contact>::iterator it=contacts.begin(); it != contacts.end(); ++it) { |
andriym | 78:43a6b54f0372 | 112 | if(cur_time - it->time_ms > SIGNALS_VALID_MS) break; |
andriym | 78:43a6b54f0372 | 113 | if(it->rssi > max_rssi) max_rssi = it->rssi; |
andriym | 78:43a6b54f0372 | 114 | cnt++; |
andriym | 78:43a6b54f0372 | 115 | } |
andriym | 78:43a6b54f0372 | 116 | return max_rssi; |
andriym | 78:43a6b54f0372 | 117 | } |
andriym | 78:43a6b54f0372 | 118 | inline bool operator==(const char rhs[]){ return memcmp(name, rhs, NAME_LEN)==0; } |
andriym | 78:43a6b54f0372 | 119 | inline bool operator==(const Player& rhs){ return *this==rhs.name; } |
andriym | 78:43a6b54f0372 | 120 | //inline bool operator!=(const char rhs[]){ return !(*this == rhs); } |
andriym | 78:43a6b54f0372 | 121 | private: |
andriym | 78:43a6b54f0372 | 122 | list<Contact> contacts; |
andriym | 78:43a6b54f0372 | 123 | }; |
andriym | 78:43a6b54f0372 | 124 | |
andriym | 78:43a6b54f0372 | 125 | class Players { |
andriym | 78:43a6b54f0372 | 126 | public: |
andriym | 78:43a6b54f0372 | 127 | list<Player> players; |
andriym | 78:43a6b54f0372 | 128 | |
andriym | 78:43a6b54f0372 | 129 | void update(const char name[], int8_t team, int16_t rssi, uint32_t time_ms=NULL) { |
andriym | 78:43a6b54f0372 | 130 | list<Player>::iterator it; |
andriym | 78:43a6b54f0372 | 131 | for (it=players.begin(); it != players.end(); ++it) { |
andriym | 78:43a6b54f0372 | 132 | if(*it==name) break; |
andriym | 78:43a6b54f0372 | 133 | } |
andriym | 78:43a6b54f0372 | 134 | if(it!=players.end()) { |
andriym | 78:43a6b54f0372 | 135 | it->update(team, rssi, time_ms); |
andriym | 78:43a6b54f0372 | 136 | } else { |
andriym | 78:43a6b54f0372 | 137 | Player p(name); |
andriym | 78:43a6b54f0372 | 138 | p.update(team, rssi, time_ms); |
andriym | 78:43a6b54f0372 | 139 | players.push_front(p); |
andriym | 78:43a6b54f0372 | 140 | } |
andriym | 78:43a6b54f0372 | 141 | } |
andriym | 78:43a6b54f0372 | 142 | |
andriym | 78:43a6b54f0372 | 143 | void show_all(int8_t team) { |
andriym | 78:43a6b54f0372 | 144 | // Show the current information table |
andriym | 78:43a6b54f0372 | 145 | int i=0, contacts, dist; |
andriym | 78:43a6b54f0372 | 146 | list<Player>::iterator it; |
andriym | 78:43a6b54f0372 | 147 | out.clear(); |
andriym | 78:43a6b54f0372 | 148 | for (it=players.begin(); it != players.end(); ++it) { |
andriym | 78:43a6b54f0372 | 149 | dist = it->get_distance(contacts); |
andriym | 78:43a6b54f0372 | 150 | if(dist>-128) { |
andriym | 78:43a6b54f0372 | 151 | out.printf("%d ", ++i); |
andriym | 78:43a6b54f0372 | 152 | out.printf((team==it->team) ? "+" : "-"); // teammate or opponent? |
andriym | 78:43a6b54f0372 | 153 | out.printf("%s ", it->name); |
andriym | 78:43a6b54f0372 | 154 | out.printf("%d/%d\r\n", -dist, contacts); |
andriym | 78:43a6b54f0372 | 155 | } |
andriym | 78:43a6b54f0372 | 156 | } |
andriym | 78:43a6b54f0372 | 157 | if(!i) { |
andriym | 78:43a6b54f0372 | 158 | out.printf("Nobody around\r\n"); |
andriym | 78:43a6b54f0372 | 159 | beep(0.001,0.5); |
andriym | 78:43a6b54f0372 | 160 | } |
andriym | 78:43a6b54f0372 | 161 | } |
andriym | 78:43a6b54f0372 | 162 | }; |
andriym | 78:43a6b54f0372 | 163 | |
andriym | 78:43a6b54f0372 | 164 | /////////////////////////////////// MAIN CODE /////////////////////////////////// |
andriym | 78:43a6b54f0372 | 165 | |
elmbed | 76:6638d83939d5 | 166 | int main() |
andriym | 78:43a6b54f0372 | 167 | { |
elmbed | 76:6638d83939d5 | 168 | char tx_buff[100] = {0}; |
elmbed | 76:6638d83939d5 | 169 | char rx_buff[100] = {0}; |
andriym | 78:43a6b54f0372 | 170 | char rand_name[NAME_LEN+1] = {0}; |
andriym | 78:43a6b54f0372 | 171 | char other_name[NAME_LEN+1] = {0}; |
andriym | 78:43a6b54f0372 | 172 | int8_t team = 1, other_team; |
elmbed | 76:6638d83939d5 | 173 | |
andriym | 78:43a6b54f0372 | 174 | beep(0.002, 0.5); |
andriym | 78:43a6b54f0372 | 175 | |
andriym | 78:43a6b54f0372 | 176 | din.mode(PullUp); |
andriym | 78:43a6b54f0372 | 177 | int button_old = 1, button_new; |
elmbed | 76:6638d83939d5 | 178 | |
andriym | 78:43a6b54f0372 | 179 | char this_node = int(ain.read()*255+17)*int(ain.read()*255+11); // random node value |
andriym | 78:43a6b54f0372 | 180 | out.printf("Node: %d\r\n", this_node); |
andriym | 78:43a6b54f0372 | 181 | |
andriym | 78:43a6b54f0372 | 182 | // Init radio |
andriym | 78:43a6b54f0372 | 183 | radio.initialize(FREQUENCY, this_node, NETWORKID); |
andriym | 78:43a6b54f0372 | 184 | #ifdef HIGH_POWER |
andriym | 78:43a6b54f0372 | 185 | radio.setHighPower(true); |
andriym | 78:43a6b54f0372 | 186 | #endif |
elmbed | 76:6638d83939d5 | 187 | radio.encrypt(0); |
elmbed | 76:6638d83939d5 | 188 | radio.promiscuous(promiscuousMode); |
andriym | 78:43a6b54f0372 | 189 | radio.setFrequency(868000000); |
AntonLS | 11:d3aa5fca2330 | 190 | |
andriym | 78:43a6b54f0372 | 191 | generate_name(rand_name, sizeof(rand_name)); |
andriym | 78:43a6b54f0372 | 192 | out.printf("Name: %s\r\n", rand_name); |
andriym | 78:43a6b54f0372 | 193 | out.sleep(2.0); |
andriym | 78:43a6b54f0372 | 194 | |
elmbed | 76:6638d83939d5 | 195 | t.start(); |
andriym | 78:43a6b54f0372 | 196 | |
andriym | 78:43a6b54f0372 | 197 | Players players; |
andriym | 78:43a6b54f0372 | 198 | |
andriym | 78:43a6b54f0372 | 199 | uint32_t last_send = t.read_ms(); |
andriym | 78:43a6b54f0372 | 200 | uint32_t last_shown = t.read_ms(); |
andriym | 78:43a6b54f0372 | 201 | //uint32_t min_wait = SEND_RATE_MS - 0.5*SEND_RATE_MS*SEND_DESYNC; |
andriym | 78:43a6b54f0372 | 202 | //uint32_t send_wait = min_wait; |
AntonLS | 49:626e84ce5e52 | 203 | |
elmbed | 76:6638d83939d5 | 204 | while (true) |
AntonLS | 19:afcbb425b3cf | 205 | { |
andriym | 78:43a6b54f0372 | 206 | button_new = din; |
andriym | 78:43a6b54f0372 | 207 | if(!button_new && button_old) { |
andriym | 78:43a6b54f0372 | 208 | team = (team==1) ? 2 : 1; |
andriym | 78:43a6b54f0372 | 209 | out.clear(); |
andriym | 78:43a6b54f0372 | 210 | out.printf("New team: %d\r\n", team); |
andriym | 78:43a6b54f0372 | 211 | out.sleep(2); |
andriym | 78:43a6b54f0372 | 212 | } |
andriym | 78:43a6b54f0372 | 213 | button_old = button_new; |
andriym | 78:43a6b54f0372 | 214 | |
elmbed | 76:6638d83939d5 | 215 | unsigned long current_time = t.read_ms(); |
elmbed | 76:6638d83939d5 | 216 | |
andriym | 78:43a6b54f0372 | 217 | if (current_time - last_shown > 2000L) |
andriym | 78:43a6b54f0372 | 218 | { |
andriym | 78:43a6b54f0372 | 219 | players.show_all(team); |
andriym | 78:43a6b54f0372 | 220 | last_shown = current_time; |
andriym | 78:43a6b54f0372 | 221 | } |
andriym | 78:43a6b54f0372 | 222 | |
andriym | 78:43a6b54f0372 | 223 | if (current_time - last_send > SEND_RATE_MS) |
AntonLS | 19:afcbb425b3cf | 224 | { |
elmbed | 76:6638d83939d5 | 225 | // Send message |
andriym | 78:43a6b54f0372 | 226 | snprintf(tx_buff, sizeof(tx_buff), "N=%s,%d", rand_name, team); |
andriym | 78:43a6b54f0372 | 227 | radio.send(EVERY_NODE, tx_buff, strlen(tx_buff)); |
andriym | 78:43a6b54f0372 | 228 | last_send = current_time; |
andriym | 78:43a6b54f0372 | 229 | //send_wait = min_wait + (rand() % SEND_RATE_MS)*SEND_DESYNC; |
andriym | 78:43a6b54f0372 | 230 | |
andriym | 78:43a6b54f0372 | 231 | //out.clear(); |
andriym | 78:43a6b54f0372 | 232 | //out.printf("Sent: %s\r\n", tx_buff); |
andriym | 78:43a6b54f0372 | 233 | //uint8_t tempC = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient |
andriym | 78:43a6b54f0372 | 234 | //uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain |
andriym | 78:43a6b54f0372 | 235 | //uint32_t freq = radio.getFrequency(); |
andriym | 78:43a6b54f0372 | 236 | //out.printf("T: %d, G: %d\r\n", tempC, gain); |
andriym | 78:43a6b54f0372 | 237 | //if(freq!=868000000) out.printf("Freq: %d\r\n", freq); |
elmbed | 76:6638d83939d5 | 238 | |
andriym | 78:43a6b54f0372 | 239 | //beep(0.003, 0.05); |
elmbed | 76:6638d83939d5 | 240 | } |
andriym | 78:43a6b54f0372 | 241 | |
elmbed | 76:6638d83939d5 | 242 | if (radio.receiveDone()) |
AntonLS | 11:d3aa5fca2330 | 243 | { |
elmbed | 76:6638d83939d5 | 244 | memset(rx_buff, 0x00, sizeof(rx_buff)); |
elmbed | 76:6638d83939d5 | 245 | memcpy(rx_buff, (char*)radio.DATA, radio.DATALEN > sizeof(rx_buff)-1 ? sizeof(rx_buff)-1 : radio.DATALEN); |
elmbed | 76:6638d83939d5 | 246 | |
andriym | 78:43a6b54f0372 | 247 | if(rx_buff[0]=='N' && rx_buff[1]=='=') { |
andriym | 78:43a6b54f0372 | 248 | memcpy(other_name, rx_buff+2, NAME_LEN); |
andriym | 78:43a6b54f0372 | 249 | other_name[5] = 0x00; |
andriym | 78:43a6b54f0372 | 250 | if(sizeof(rx_buff)>8 && rx_buff[7]==',') { |
andriym | 78:43a6b54f0372 | 251 | other_team = rx_buff[8]-'0'; |
andriym | 78:43a6b54f0372 | 252 | } else other_team = 1; |
andriym | 78:43a6b54f0372 | 253 | players.update(other_name, other_team, radio.RSSI, t.read_ms()); |
andriym | 78:43a6b54f0372 | 254 | |
andriym | 78:43a6b54f0372 | 255 | //uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain |
andriym | 78:43a6b54f0372 | 256 | //out.clear(); |
andriym | 78:43a6b54f0372 | 257 | //out.printf("Other: %s\r\n", other_name); |
andriym | 78:43a6b54f0372 | 258 | //out.printf("RSSI: %d, G: %d\r\n", radio.RSSI, gain); |
andriym | 78:43a6b54f0372 | 259 | |
andriym | 78:43a6b54f0372 | 260 | //beep(0.001, 0.5); |
andriym | 78:43a6b54f0372 | 261 | } else { // received unknown signal |
andriym | 78:43a6b54f0372 | 262 | uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain |
andriym | 78:43a6b54f0372 | 263 | out.clear(); |
andriym | 78:43a6b54f0372 | 264 | out.printf("Got: %s\r\n", rx_buff); |
andriym | 78:43a6b54f0372 | 265 | out.printf("RSSI: %d, G: %d\r\n", radio.RSSI, gain); |
andriym | 78:43a6b54f0372 | 266 | out.sleep(2.0); |
andriym | 78:43a6b54f0372 | 267 | } |
AntonLS | 11:d3aa5fca2330 | 268 | } |
AntonLS | 0:28ca4562fe1a | 269 | } |
elmbed | 76:6638d83939d5 | 270 | } |