Andriy Makukha
/
football_project_wo_output
football_project_wo_output
Fork of football_project by
main.cpp@95:3cc3ae2e5e7f, 2016-06-16 (annotated)
- Committer:
- andriym
- Date:
- Thu Jun 16 05:06:24 2016 +0000
- Revision:
- 95:3cc3ae2e5e7f
- Parent:
- 94:831a7fc2d69a
- Child:
- 97:2894fbc2d4f8
Removed output lib.
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 | 82:1e552cc1a615 | 3 | #include <DebounceIn.h> |
andriym | 89:425369a595c4 | 4 | #ifdef BLE_ENABLE |
andriym | 92:a9ebe6d0a0fa | 5 | #include "ble/BLE.h" |
andriym | 90:b4d53a870147 | 6 | #include "ble/services/DFUService.h" |
andriym | 89:425369a595c4 | 7 | #endif |
AntonLS | 0:28ca4562fe1a | 8 | |
andriym | 78:43a6b54f0372 | 9 | using namespace std; |
andriym | 78:43a6b54f0372 | 10 | |
andriym | 89:425369a595c4 | 11 | Timer tmr; |
andriym | 95:3cc3ae2e5e7f | 12 | //Output out; |
elmbed | 17:d8b901d791fd | 13 | |
andriym | 89:425369a595c4 | 14 | #ifdef BLE_ENABLE |
andriym | 90:b4d53a870147 | 15 | BLEDevice ble; |
andriym | 91:0fc897cccc06 | 16 | |
andriym | 91:0fc897cccc06 | 17 | // Optional: Device Name, add for human read-ability |
andriym | 92:a9ebe6d0a0fa | 18 | //const static char DEVICE_NAME[] = "PassiveCoach"; |
andriym | 90:b4d53a870147 | 19 | |
andriym | 91:0fc897cccc06 | 20 | // You have up to 26 bytes of advertising data to use. |
andriym | 89:425369a595c4 | 21 | //const static uint8_t AdvData[] = {0x01,0x02,0x03,0x04,0x05}; /* Example of hex data */ |
andriym | 92:a9ebe6d0a0fa | 22 | //const static uint8_t AdvData[] = {"Keep the Space!"}; /* Example of character data */ |
andriym | 89:425369a595c4 | 23 | #endif // BLE_ENABLE |
andriym | 89:425369a595c4 | 24 | |
andriym | 78:43a6b54f0372 | 25 | /////////////////////////////////// PINS /////////////////////////////////// |
andriym | 79:9db29f41dc9d | 26 | |
andriym | 82:1e552cc1a615 | 27 | DebounceIn buttonTeam(BUT_TEAM); |
andriym | 82:1e552cc1a615 | 28 | DebounceIn buttonSpace(BUT_SPACE); |
andriym | 82:1e552cc1a615 | 29 | DebounceIn buttonVolMore(BUT_VOL_MORE); |
andriym | 82:1e552cc1a615 | 30 | DebounceIn buttonVolLess(BUT_VOL_LESS); |
andriym | 81:3cd7de5d01ef | 31 | |
andriym | 79:9db29f41dc9d | 32 | DigitalOut ledTeamA(LED_TEAM_A); |
andriym | 79:9db29f41dc9d | 33 | DigitalOut ledTeamB(LED_TEAM_B); |
andriym | 79:9db29f41dc9d | 34 | DigitalOut ledSpace5(LED_SPACE5); |
andriym | 79:9db29f41dc9d | 35 | DigitalOut ledSpace10(LED_SPACE10); |
andriym | 79:9db29f41dc9d | 36 | DigitalOut ledSpace15(LED_SPACE15); |
andriym | 79:9db29f41dc9d | 37 | DigitalOut ledSpace20(LED_SPACE20); |
andriym | 81:3cd7de5d01ef | 38 | DigitalOut ledBuzzer(LED_BUZZER_ON); |
andriym | 81:3cd7de5d01ef | 39 | |
andriym | 79:9db29f41dc9d | 40 | AnalogIn ain(ANALOG_IN); // used for randomizing |
andriym | 78:43a6b54f0372 | 41 | #ifdef NORDIC |
andriym | 79:9db29f41dc9d | 42 | DigitalOut buzzer(BUZZER); |
andriym | 88:d3f0394da5aa | 43 | #ifndef HARD_V2 |
andriym | 79:9db29f41dc9d | 44 | DigitalOut buzzLow(BUZZ_LOW); |
andriym | 88:d3f0394da5aa | 45 | #endif |
andriym | 79:9db29f41dc9d | 46 | DigitalOut buzzMed(BUZZ_MED); |
andriym | 79:9db29f41dc9d | 47 | DigitalOut buzzHigh(BUZZ_HIGH); |
andriym | 79:9db29f41dc9d | 48 | #else |
andriym | 79:9db29f41dc9d | 49 | PwmOut speaker(BUZZER); // passive buzzer |
andriym | 79:9db29f41dc9d | 50 | #endif |
AntonLS | 30:c60b0d52b067 | 51 | |
andriym | 78:43a6b54f0372 | 52 | /////////////////////////////////// RADIO /////////////////////////////////// |
andriym | 83:79cb2ba44b66 | 53 | #ifdef ENABLE_PIN |
andriym | 83:79cb2ba44b66 | 54 | static RFM69 radio(RFM_MOSI, RFM_MISO, RFM_SCK, RFM_SS, RFM_IRQ, RFM_ISM_EN); |
andriym | 83:79cb2ba44b66 | 55 | #else |
andriym | 79:9db29f41dc9d | 56 | static RFM69 radio(RFM_MOSI, RFM_MISO, RFM_SCK, RFM_SS, RFM_IRQ); |
andriym | 83:79cb2ba44b66 | 57 | #endif |
AntonLS | 12:6d313d575f84 | 58 | |
elmbed | 76:6638d83939d5 | 59 | static bool promiscuousMode = true; // set 'true' to sniff all packets on the same network |
AntonLS | 0:28ca4562fe1a | 60 | |
andriym | 78:43a6b54f0372 | 61 | /////////////////////////////////// FUNCTIONS /////////////////////////////////// |
andriym | 78:43a6b54f0372 | 62 | |
andriym | 81:3cd7de5d01ef | 63 | void beep(float period, float time, uint8_t vol) { |
andriym | 78:43a6b54f0372 | 64 | #ifdef ENABLE_SOUND |
andriym | 81:3cd7de5d01ef | 65 | if(!vol) return; |
andriym | 79:9db29f41dc9d | 66 | #ifdef NORDIC |
andriym | 81:3cd7de5d01ef | 67 | if(vol>=3) { |
andriym | 88:d3f0394da5aa | 68 | #ifndef HARD_V2 |
andriym | 88:d3f0394da5aa | 69 | buzzLow = LOW_ON; |
andriym | 88:d3f0394da5aa | 70 | #endif |
andriym | 88:d3f0394da5aa | 71 | buzzMed = MED_OFF; buzzHigh = HIGH_OFF; |
andriym | 81:3cd7de5d01ef | 72 | } else if(vol>=2) { |
andriym | 88:d3f0394da5aa | 73 | #ifndef HARD_V2 |
andriym | 88:d3f0394da5aa | 74 | buzzLow = LOW_OFF; |
andriym | 88:d3f0394da5aa | 75 | #endif |
andriym | 88:d3f0394da5aa | 76 | buzzMed = MED_ON; buzzHigh = HIGH_OFF; |
andriym | 79:9db29f41dc9d | 77 | } else { |
andriym | 88:d3f0394da5aa | 78 | #ifndef HARD_V2 |
andriym | 88:d3f0394da5aa | 79 | buzzLow = LOW_OFF; |
andriym | 88:d3f0394da5aa | 80 | #endif |
andriym | 88:d3f0394da5aa | 81 | buzzMed = MED_OFF; buzzHigh = HIGH_ON; |
andriym | 79:9db29f41dc9d | 82 | } |
andriym | 80:8d4f190bd253 | 83 | buzzer = 0; // P-MOSFET |
andriym | 80:8d4f190bd253 | 84 | wait(time); |
andriym | 79:9db29f41dc9d | 85 | buzzer = 1; |
andriym | 79:9db29f41dc9d | 86 | #else |
andriym | 78:43a6b54f0372 | 87 | speaker.period(period); |
andriym | 81:3cd7de5d01ef | 88 | if(vol>=3) |
andriym | 81:3cd7de5d01ef | 89 | speaker = 0.5; //50% duty cycle - max volume |
andriym | 81:3cd7de5d01ef | 90 | else if(vol>=2) |
andriym | 81:3cd7de5d01ef | 91 | speaker = 0.33; |
andriym | 81:3cd7de5d01ef | 92 | else |
andriym | 81:3cd7de5d01ef | 93 | speaker = 0.2; |
andriym | 78:43a6b54f0372 | 94 | wait(time); |
andriym | 78:43a6b54f0372 | 95 | speaker=0.0; // turn off audio |
andriym | 78:43a6b54f0372 | 96 | #endif |
andriym | 79:9db29f41dc9d | 97 | #endif |
andriym | 78:43a6b54f0372 | 98 | } |
andriym | 78:43a6b54f0372 | 99 | |
andriym | 78:43a6b54f0372 | 100 | void binary_sound(int z) { |
andriym | 78:43a6b54f0372 | 101 | // Beeps numbers according to their binary form |
andriym | 78:43a6b54f0372 | 102 | // (used for debugging in display-less and serial-less environments) |
andriym | 78:43a6b54f0372 | 103 | #ifdef ENABLE_SOUND |
andriym | 79:9db29f41dc9d | 104 | #ifndef NORDIC |
andriym | 78:43a6b54f0372 | 105 | speaker.period(0.004); |
andriym | 78:43a6b54f0372 | 106 | while(z) { |
andriym | 78:43a6b54f0372 | 107 | speaker = 0.5; |
andriym | 78:43a6b54f0372 | 108 | if(z&1) wait(0.5); |
andriym | 78:43a6b54f0372 | 109 | else wait(0.25); |
andriym | 78:43a6b54f0372 | 110 | speaker = 0.0; |
andriym | 78:43a6b54f0372 | 111 | wait(1.0); |
andriym | 78:43a6b54f0372 | 112 | z >>= 1; |
andriym | 78:43a6b54f0372 | 113 | } |
andriym | 81:3cd7de5d01ef | 114 | beep(NOTE_A4, 1.0, 2); |
andriym | 79:9db29f41dc9d | 115 | #endif |
andriym | 78:43a6b54f0372 | 116 | #endif |
andriym | 78:43a6b54f0372 | 117 | } |
andriym | 78:43a6b54f0372 | 118 | |
andriym | 78:43a6b54f0372 | 119 | void generate_name(char rand_name[], uint8_t size) { |
andriym | 78:43a6b54f0372 | 120 | // Generate random name on the 62 character alphabet |
andriym | 78:43a6b54f0372 | 121 | memset(rand_name, 0x00, size); |
andriym | 78:43a6b54f0372 | 122 | char alph[63] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; |
andriym | 78:43a6b54f0372 | 123 | uint32_t seed = ((ain.read_u16()+3)/17)*(radio.readTemperature(-1)+37)*((ain.read_u16()+5)/13); |
andriym | 78:43a6b54f0372 | 124 | srand(seed); |
andriym | 78:43a6b54f0372 | 125 | for(int i=0;i<size-1;i++) { |
andriym | 78:43a6b54f0372 | 126 | rand_name[i] = alph[abs(rand()) % 62]; |
andriym | 78:43a6b54f0372 | 127 | } |
andriym | 78:43a6b54f0372 | 128 | } |
andriym | 78:43a6b54f0372 | 129 | |
andriym | 86:2a569d9e67f5 | 130 | void spaceLEDs(int level) { |
andriym | 85:4692a1790cfa | 131 | if(level<=0) { |
andriym | 85:4692a1790cfa | 132 | ledSpace5 = 1; ledSpace10 = 0; ledSpace15 = 0; ledSpace20 = 0; |
andriym | 85:4692a1790cfa | 133 | } else if(level<=1) { |
andriym | 85:4692a1790cfa | 134 | ledSpace5 = 0; ledSpace10 = 1; ledSpace15 = 0; ledSpace20 = 0; |
andriym | 85:4692a1790cfa | 135 | } else if(level<=2) { |
andriym | 85:4692a1790cfa | 136 | ledSpace5 = 0; ledSpace10 = 0; ledSpace15 = 1; ledSpace20 = 0; |
andriym | 85:4692a1790cfa | 137 | } else { |
andriym | 85:4692a1790cfa | 138 | ledSpace5 = 0; ledSpace10 = 0; ledSpace15 = 0; ledSpace20 = 1; |
andriym | 85:4692a1790cfa | 139 | } |
andriym | 85:4692a1790cfa | 140 | } |
andriym | 85:4692a1790cfa | 141 | |
andriym | 89:425369a595c4 | 142 | #ifdef BLE_ENABLE |
andriym | 92:a9ebe6d0a0fa | 143 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
andriym | 92:a9ebe6d0a0fa | 144 | { |
andriym | 92:a9ebe6d0a0fa | 145 | //pc.printf("Disconnected \r\n"); |
andriym | 92:a9ebe6d0a0fa | 146 | //pc.printf("Restart advertising \r\n"); |
andriym | 92:a9ebe6d0a0fa | 147 | ble.startAdvertising(); |
andriym | 92:a9ebe6d0a0fa | 148 | } |
andriym | 92:a9ebe6d0a0fa | 149 | |
andriym | 90:b4d53a870147 | 150 | // Optional: Restart advertising when peer disconnects |
andriym | 92:a9ebe6d0a0fa | 151 | /* |
andriym | 89:425369a595c4 | 152 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
andriym | 89:425369a595c4 | 153 | { |
andriym | 89:425369a595c4 | 154 | BLE::Instance().gap().startAdvertising(); |
andriym | 89:425369a595c4 | 155 | } |
andriym | 92:a9ebe6d0a0fa | 156 | */ |
andriym | 90:b4d53a870147 | 157 | // This function is called when the ble initialization process has failed |
andriym | 89:425369a595c4 | 158 | void onBleInitError(BLE &ble, ble_error_t error) |
andriym | 89:425369a595c4 | 159 | { |
andriym | 90:b4d53a870147 | 160 | // Avoid compiler warnings |
andriym | 89:425369a595c4 | 161 | (void) ble; |
andriym | 89:425369a595c4 | 162 | (void) error; |
andriym | 89:425369a595c4 | 163 | |
andriym | 90:b4d53a870147 | 164 | // Initialization error handling should go here |
andriym | 89:425369a595c4 | 165 | } |
andriym | 89:425369a595c4 | 166 | |
andriym | 90:b4d53a870147 | 167 | // Callback triggered when the ble initialization process has finished |
andriym | 93:620dd0a7ddc7 | 168 | /* |
andriym | 89:425369a595c4 | 169 | void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) |
andriym | 89:425369a595c4 | 170 | { |
andriym | 89:425369a595c4 | 171 | BLE& ble = params->ble; |
andriym | 89:425369a595c4 | 172 | ble_error_t error = params->error; |
andriym | 89:425369a595c4 | 173 | |
andriym | 89:425369a595c4 | 174 | if (error != BLE_ERROR_NONE) { |
andriym | 90:b4d53a870147 | 175 | // In case of error, forward the error handling to onBleInitError |
andriym | 89:425369a595c4 | 176 | onBleInitError(ble, error); |
andriym | 89:425369a595c4 | 177 | return; |
andriym | 89:425369a595c4 | 178 | } |
andriym | 89:425369a595c4 | 179 | |
andriym | 90:b4d53a870147 | 180 | // Ensure that it is the default instance of BLE |
andriym | 89:425369a595c4 | 181 | if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { |
andriym | 89:425369a595c4 | 182 | return; |
andriym | 89:425369a595c4 | 183 | } |
andriym | 89:425369a595c4 | 184 | |
andriym | 90:b4d53a870147 | 185 | // Set device name characteristic data |
andriym | 89:425369a595c4 | 186 | ble.gap().setDeviceName((const uint8_t *) DEVICE_NAME); |
andriym | 89:425369a595c4 | 187 | |
andriym | 90:b4d53a870147 | 188 | // Optional: add callback for disconnection |
andriym | 89:425369a595c4 | 189 | ble.gap().onDisconnection(disconnectionCallback); |
andriym | 89:425369a595c4 | 190 | |
andriym | 90:b4d53a870147 | 191 | // Sacrifice 3B of 31B to Advertising Flags |
andriym | 89:425369a595c4 | 192 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE ); |
andriym | 89:425369a595c4 | 193 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
andriym | 89:425369a595c4 | 194 | |
andriym | 90:b4d53a870147 | 195 | // Sacrifice 2B of 31B to AdvType overhead, rest goes to AdvData array you define |
andriym | 89:425369a595c4 | 196 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, AdvData, sizeof(AdvData)); |
andriym | 89:425369a595c4 | 197 | |
andriym | 90:b4d53a870147 | 198 | // Optional: Add name to device |
andriym | 89:425369a595c4 | 199 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
andriym | 89:425369a595c4 | 200 | |
andriym | 90:b4d53a870147 | 201 | // Set advertising interval. Longer interval == longer battery life |
andriym | 90:b4d53a870147 | 202 | ble.gap().setAdvertisingInterval(100); // 100ms |
andriym | 89:425369a595c4 | 203 | |
andriym | 90:b4d53a870147 | 204 | // Start advertising |
andriym | 89:425369a595c4 | 205 | ble.gap().startAdvertising(); |
andriym | 89:425369a595c4 | 206 | } |
andriym | 93:620dd0a7ddc7 | 207 | */ |
andriym | 89:425369a595c4 | 208 | #endif // BLE_ENABLE |
andriym | 89:425369a595c4 | 209 | |
andriym | 78:43a6b54f0372 | 210 | /////////////////////////////////// CLASSES /////////////////////////////////// |
andriym | 78:43a6b54f0372 | 211 | |
andriym | 78:43a6b54f0372 | 212 | struct Contact { |
andriym | 78:43a6b54f0372 | 213 | int16_t rssi; |
andriym | 78:43a6b54f0372 | 214 | uint32_t time_ms; |
andriym | 78:43a6b54f0372 | 215 | }; |
andriym | 78:43a6b54f0372 | 216 | |
andriym | 78:43a6b54f0372 | 217 | class Player { |
andriym | 78:43a6b54f0372 | 218 | public: |
andriym | 78:43a6b54f0372 | 219 | char name[NAME_LEN+1]; |
andriym | 78:43a6b54f0372 | 220 | int8_t team; |
andriym | 78:43a6b54f0372 | 221 | Player(const char rand_name[]) { |
andriym | 78:43a6b54f0372 | 222 | memset(name, 0x00, NAME_LEN+1); |
andriym | 78:43a6b54f0372 | 223 | memcpy(name, rand_name, NAME_LEN); |
andriym | 78:43a6b54f0372 | 224 | } |
andriym | 78:43a6b54f0372 | 225 | void update(int8_t _team, int rssi, uint32_t time=NULL) { |
andriym | 78:43a6b54f0372 | 226 | // Remember this contact |
andriym | 78:43a6b54f0372 | 227 | team = _team; |
andriym | 78:43a6b54f0372 | 228 | Contact c; |
andriym | 78:43a6b54f0372 | 229 | c.rssi = rssi; |
andriym | 89:425369a595c4 | 230 | c.time_ms = (time!=NULL) ? time : tmr.read_ms(); |
andriym | 78:43a6b54f0372 | 231 | contacts.push_front(c); |
andriym | 78:43a6b54f0372 | 232 | |
andriym | 78:43a6b54f0372 | 233 | // Cleanup |
andriym | 78:43a6b54f0372 | 234 | while(contacts.size() > MAX_RECORDS) contacts.pop_back(); |
andriym | 78:43a6b54f0372 | 235 | while(!contacts.empty() && c.time_ms - contacts.back().time_ms > MAX_HISTORY_MS) contacts.pop_back(); |
andriym | 78:43a6b54f0372 | 236 | } |
andriym | 78:43a6b54f0372 | 237 | int16_t get_distance(int &cnt) { |
andriym | 78:43a6b54f0372 | 238 | // Find max RSSI |
andriym | 89:425369a595c4 | 239 | uint32_t cur_time = tmr.read_ms(); |
andriym | 78:43a6b54f0372 | 240 | int16_t max_rssi=-128; |
andriym | 78:43a6b54f0372 | 241 | cnt=0; |
andriym | 78:43a6b54f0372 | 242 | for (list<Contact>::iterator it=contacts.begin(); it != contacts.end(); ++it) { |
andriym | 78:43a6b54f0372 | 243 | if(cur_time - it->time_ms > SIGNALS_VALID_MS) break; |
andriym | 78:43a6b54f0372 | 244 | if(it->rssi > max_rssi) max_rssi = it->rssi; |
andriym | 78:43a6b54f0372 | 245 | cnt++; |
andriym | 78:43a6b54f0372 | 246 | } |
andriym | 78:43a6b54f0372 | 247 | return max_rssi; |
andriym | 78:43a6b54f0372 | 248 | } |
andriym | 78:43a6b54f0372 | 249 | inline bool operator==(const char rhs[]){ return memcmp(name, rhs, NAME_LEN)==0; } |
andriym | 78:43a6b54f0372 | 250 | inline bool operator==(const Player& rhs){ return *this==rhs.name; } |
andriym | 78:43a6b54f0372 | 251 | //inline bool operator!=(const char rhs[]){ return !(*this == rhs); } |
andriym | 78:43a6b54f0372 | 252 | private: |
andriym | 78:43a6b54f0372 | 253 | list<Contact> contacts; |
andriym | 78:43a6b54f0372 | 254 | }; |
andriym | 78:43a6b54f0372 | 255 | |
andriym | 78:43a6b54f0372 | 256 | class Players { |
andriym | 78:43a6b54f0372 | 257 | public: |
andriym | 78:43a6b54f0372 | 258 | list<Player> players; |
andriym | 78:43a6b54f0372 | 259 | |
andriym | 78:43a6b54f0372 | 260 | void update(const char name[], int8_t team, int16_t rssi, uint32_t time_ms=NULL) { |
andriym | 78:43a6b54f0372 | 261 | list<Player>::iterator it; |
andriym | 78:43a6b54f0372 | 262 | for (it=players.begin(); it != players.end(); ++it) { |
andriym | 78:43a6b54f0372 | 263 | if(*it==name) break; |
andriym | 78:43a6b54f0372 | 264 | } |
andriym | 78:43a6b54f0372 | 265 | if(it!=players.end()) { |
andriym | 78:43a6b54f0372 | 266 | it->update(team, rssi, time_ms); |
andriym | 78:43a6b54f0372 | 267 | } else { |
andriym | 78:43a6b54f0372 | 268 | Player p(name); |
andriym | 78:43a6b54f0372 | 269 | p.update(team, rssi, time_ms); |
andriym | 78:43a6b54f0372 | 270 | players.push_front(p); |
andriym | 78:43a6b54f0372 | 271 | } |
andriym | 78:43a6b54f0372 | 272 | } |
andriym | 78:43a6b54f0372 | 273 | |
andriym | 81:3cd7de5d01ef | 274 | void showAll(int8_t team, uint8_t level, uint8_t volume) { |
andriym | 79:9db29f41dc9d | 275 | // Output the current state to the user: |
andriym | 79:9db29f41dc9d | 276 | // - show the current information table and/or |
andriym | 79:9db29f41dc9d | 277 | // - beep if the user is too close to another one |
andriym | 79:9db29f41dc9d | 278 | int i=0, nContacts, signal, maxTeamSignal = -128; |
andriym | 78:43a6b54f0372 | 279 | list<Player>::iterator it; |
andriym | 95:3cc3ae2e5e7f | 280 | //out.clear(); |
andriym | 78:43a6b54f0372 | 281 | for (it=players.begin(); it != players.end(); ++it) { |
andriym | 79:9db29f41dc9d | 282 | signal = it->get_distance(nContacts); |
andriym | 79:9db29f41dc9d | 283 | if(signal>-128) { |
andriym | 95:3cc3ae2e5e7f | 284 | /* |
andriym | 78:43a6b54f0372 | 285 | out.printf("%d ", ++i); |
andriym | 78:43a6b54f0372 | 286 | out.printf((team==it->team) ? "+" : "-"); // teammate or opponent? |
andriym | 78:43a6b54f0372 | 287 | out.printf("%s ", it->name); |
andriym | 79:9db29f41dc9d | 288 | out.printf("%d/%d", -signal, nContacts); |
andriym | 79:9db29f41dc9d | 289 | out.printf((-signal<SPACE[level]) ? "!" : " "); |
andriym | 79:9db29f41dc9d | 290 | out.printf("\r\n"); |
andriym | 95:3cc3ae2e5e7f | 291 | */ |
andriym | 79:9db29f41dc9d | 292 | } |
andriym | 79:9db29f41dc9d | 293 | if(team==it->team && signal>maxTeamSignal) { |
andriym | 79:9db29f41dc9d | 294 | maxTeamSignal = signal; |
andriym | 78:43a6b54f0372 | 295 | } |
andriym | 78:43a6b54f0372 | 296 | } |
andriym | 79:9db29f41dc9d | 297 | //if(!i) { |
andriym | 79:9db29f41dc9d | 298 | // out.printf("Nobody around\r\n"); |
andriym | 81:3cd7de5d01ef | 299 | // beep(NOTE_A5,0.5,volume); |
andriym | 79:9db29f41dc9d | 300 | //} |
andriym | 79:9db29f41dc9d | 301 | if(-maxTeamSignal<SPACE[level]) { |
andriym | 81:3cd7de5d01ef | 302 | beep(NOTE_A4, 0.33, volume); |
andriym | 78:43a6b54f0372 | 303 | } |
andriym | 78:43a6b54f0372 | 304 | } |
andriym | 78:43a6b54f0372 | 305 | }; |
andriym | 78:43a6b54f0372 | 306 | |
andriym | 78:43a6b54f0372 | 307 | /////////////////////////////////// MAIN CODE /////////////////////////////////// |
andriym | 78:43a6b54f0372 | 308 | |
elmbed | 76:6638d83939d5 | 309 | int main() |
andriym | 78:43a6b54f0372 | 310 | { |
andriym | 92:a9ebe6d0a0fa | 311 | #ifdef BLE_ENABLE |
andriym | 92:a9ebe6d0a0fa | 312 | // BLE initialization |
andriym | 92:a9ebe6d0a0fa | 313 | ble.init(); |
andriym | 92:a9ebe6d0a0fa | 314 | ble.onDisconnection(disconnectionCallback); |
andriym | 92:a9ebe6d0a0fa | 315 | #endif // BLE_ENABLE |
andriym | 92:a9ebe6d0a0fa | 316 | |
elmbed | 76:6638d83939d5 | 317 | char tx_buff[100] = {0}; |
elmbed | 76:6638d83939d5 | 318 | char rx_buff[100] = {0}; |
andriym | 78:43a6b54f0372 | 319 | char rand_name[NAME_LEN+1] = {0}; |
andriym | 78:43a6b54f0372 | 320 | char other_name[NAME_LEN+1] = {0}; |
andriym | 79:9db29f41dc9d | 321 | int8_t myTeam = 1, otherTeam; |
andriym | 87:a9870d513fcf | 322 | uint8_t level = 1, volume = 1; // SPACE10, VOL_LOW |
andriym | 89:425369a595c4 | 323 | int bTeamNew, bTeamOld, bSpaceOld, bSpaceNew, bVMNew, bVLNew, bVMOld, bVLOld; |
elmbed | 76:6638d83939d5 | 324 | |
andriym | 94:831a7fc2d69a | 325 | // Blink all the LEDs at startup |
andriym | 94:831a7fc2d69a | 326 | spaceLEDs(0); wait(0.2); spaceLEDs(1); wait(0.2); spaceLEDs(2); wait(0.2); spaceLEDs(3); wait(0.2); ledSpace20 = 0; |
andriym | 94:831a7fc2d69a | 327 | #ifdef TEST_LED_SOUND |
andriym | 94:831a7fc2d69a | 328 | // Test LEDs and sound simultaneously to save time |
andriym | 94:831a7fc2d69a | 329 | buzzMed = MED_OFF; buzzHigh = HIGH_OFF; |
andriym | 94:831a7fc2d69a | 330 | ledBuzzer = 1; buzzer=0; wait(0.2); buzzer=1; ledBuzzer = 0; |
andriym | 94:831a7fc2d69a | 331 | buzzMed = MED_ON; |
andriym | 94:831a7fc2d69a | 332 | ledTeamA = 1; buzzer=0; wait(0.2); buzzer=1; ledTeamA = 0; |
andriym | 94:831a7fc2d69a | 333 | buzzMed = MED_OFF; buzzHigh = HIGH_ON; |
andriym | 94:831a7fc2d69a | 334 | ledTeamB = 1; buzzer=0; wait(0.2); buzzer=1; ledTeamB = 0; |
andriym | 94:831a7fc2d69a | 335 | buzzHigh = HIGH_OFF; |
andriym | 94:831a7fc2d69a | 336 | #else |
andriym | 94:831a7fc2d69a | 337 | ledBuzzer = 1; wait(0.2); ledBuzzer = 0; |
andriym | 94:831a7fc2d69a | 338 | ledTeamA = 1; wait(0.2); ledTeamA = 0; |
andriym | 94:831a7fc2d69a | 339 | ledTeamB = 1; wait(0.2); ledTeamB = 0; |
andriym | 89:425369a595c4 | 340 | |
andriym | 94:831a7fc2d69a | 341 | // Beep all the levels on startup |
andriym | 94:831a7fc2d69a | 342 | beep(NOTE_A5, 0.2, 1); |
andriym | 94:831a7fc2d69a | 343 | beep(NOTE_A5, 0.2, 2); |
andriym | 94:831a7fc2d69a | 344 | beep(NOTE_A5, 0.2, 3); |
andriym | 94:831a7fc2d69a | 345 | #endif |
andriym | 94:831a7fc2d69a | 346 | |
andriym | 94:831a7fc2d69a | 347 | // ...and go to a informative LEDs |
andriym | 94:831a7fc2d69a | 348 | spaceLEDs(level); |
andriym | 81:3cd7de5d01ef | 349 | ledBuzzer = volume ? 1 : 0; |
andriym | 94:831a7fc2d69a | 350 | if(myTeam & 1) ledTeamA = 1; |
andriym | 94:831a7fc2d69a | 351 | else ledTeamB = 1; |
andriym | 89:425369a595c4 | 352 | |
andriym | 89:425369a595c4 | 353 | // Buttons initialization |
andriym | 79:9db29f41dc9d | 354 | buttonSpace.mode(PullDown); |
andriym | 81:3cd7de5d01ef | 355 | buttonVolMore.mode(PullDown); |
andriym | 81:3cd7de5d01ef | 356 | buttonVolLess.mode(PullDown); |
andriym | 79:9db29f41dc9d | 357 | #ifdef NORDIC |
andriym | 79:9db29f41dc9d | 358 | buttonTeam.mode(PullDown); |
andriym | 89:425369a595c4 | 359 | bTeamOld = 0; |
andriym | 79:9db29f41dc9d | 360 | #else |
andriym | 79:9db29f41dc9d | 361 | buttonTeam.mode(PullUp); |
andriym | 89:425369a595c4 | 362 | bTeamOld = 1; |
andriym | 79:9db29f41dc9d | 363 | #endif |
andriym | 89:425369a595c4 | 364 | bSpaceOld = 0; |
andriym | 89:425369a595c4 | 365 | bVMOld = 0; |
andriym | 89:425369a595c4 | 366 | bVLOld = 0; |
elmbed | 76:6638d83939d5 | 367 | |
andriym | 89:425369a595c4 | 368 | #ifdef BLE_ENABLE |
andriym | 92:a9ebe6d0a0fa | 369 | // setup advertising |
andriym | 92:a9ebe6d0a0fa | 370 | ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); |
andriym | 92:a9ebe6d0a0fa | 371 | ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
andriym | 92:a9ebe6d0a0fa | 372 | ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
andriym | 92:a9ebe6d0a0fa | 373 | (const uint8_t *)"KeepTheSpace", sizeof("KeepTheSpace") - 1); |
andriym | 92:a9ebe6d0a0fa | 374 | //ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, |
andriym | 92:a9ebe6d0a0fa | 375 | // (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid)); |
andriym | 92:a9ebe6d0a0fa | 376 | |
andriym | 92:a9ebe6d0a0fa | 377 | // 100ms; in multiples of 0.625ms. |
andriym | 92:a9ebe6d0a0fa | 378 | ble.setAdvertisingInterval(160); |
andriym | 92:a9ebe6d0a0fa | 379 | |
andriym | 93:620dd0a7ddc7 | 380 | //ble.addService(uartService); |
andriym | 92:a9ebe6d0a0fa | 381 | |
andriym | 92:a9ebe6d0a0fa | 382 | DFUService dfu(ble); |
andriym | 92:a9ebe6d0a0fa | 383 | |
andriym | 92:a9ebe6d0a0fa | 384 | ble.startAdvertising(); |
andriym | 92:a9ebe6d0a0fa | 385 | //pc.printf("Advertising Start \r\n"); |
andriym | 92:a9ebe6d0a0fa | 386 | |
andriym | 92:a9ebe6d0a0fa | 387 | /* |
andriym | 92:a9ebe6d0a0fa | 388 | // GAP version |
andriym | 89:425369a595c4 | 389 | BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE); |
andriym | 89:425369a595c4 | 390 | ble.init(bleInitComplete); // Initialize BLE baselayer |
andriym | 91:0fc897cccc06 | 391 | DFUService dfu( ble ); |
andriym | 92:a9ebe6d0a0fa | 392 | */ |
andriym | 89:425369a595c4 | 393 | #endif // BLE_ENABLE |
andriym | 89:425369a595c4 | 394 | |
andriym | 89:425369a595c4 | 395 | // Pick node number |
andriym | 78:43a6b54f0372 | 396 | char this_node = int(ain.read()*255+17)*int(ain.read()*255+11); // random node value |
andriym | 95:3cc3ae2e5e7f | 397 | //out.printf("Node: %d\r\n", this_node); |
andriym | 78:43a6b54f0372 | 398 | |
andriym | 89:425369a595c4 | 399 | // Initialize the radio |
andriym | 78:43a6b54f0372 | 400 | radio.initialize(FREQUENCY, this_node, NETWORKID); |
andriym | 78:43a6b54f0372 | 401 | #ifdef HIGH_POWER |
andriym | 78:43a6b54f0372 | 402 | radio.setHighPower(true); |
andriym | 78:43a6b54f0372 | 403 | #endif |
elmbed | 76:6638d83939d5 | 404 | radio.encrypt(0); |
elmbed | 76:6638d83939d5 | 405 | radio.promiscuous(promiscuousMode); |
andriym | 85:4692a1790cfa | 406 | if(FREQUENCY == RF69_868MHZ) |
andriym | 85:4692a1790cfa | 407 | radio.setFrequency(868000000); |
andriym | 85:4692a1790cfa | 408 | else if(FREQUENCY == RF69_915MHZ) |
andriym | 85:4692a1790cfa | 409 | radio.setFrequency(915000000); |
AntonLS | 11:d3aa5fca2330 | 410 | |
andriym | 89:425369a595c4 | 411 | // Pick node name |
andriym | 78:43a6b54f0372 | 412 | generate_name(rand_name, sizeof(rand_name)); |
andriym | 95:3cc3ae2e5e7f | 413 | /* |
andriym | 78:43a6b54f0372 | 414 | out.printf("Name: %s\r\n", rand_name); |
andriym | 78:43a6b54f0372 | 415 | out.sleep(2.0); |
andriym | 95:3cc3ae2e5e7f | 416 | */ |
andriym | 78:43a6b54f0372 | 417 | |
andriym | 89:425369a595c4 | 418 | tmr.start(); |
andriym | 78:43a6b54f0372 | 419 | |
andriym | 78:43a6b54f0372 | 420 | Players players; |
andriym | 78:43a6b54f0372 | 421 | |
andriym | 89:425369a595c4 | 422 | uint32_t last_send = tmr.read_ms(); |
andriym | 89:425369a595c4 | 423 | uint32_t last_shown = tmr.read_ms(); |
andriym | 78:43a6b54f0372 | 424 | //uint32_t min_wait = SEND_RATE_MS - 0.5*SEND_RATE_MS*SEND_DESYNC; |
andriym | 78:43a6b54f0372 | 425 | //uint32_t send_wait = min_wait; |
AntonLS | 49:626e84ce5e52 | 426 | |
elmbed | 76:6638d83939d5 | 427 | while (true) |
AntonLS | 19:afcbb425b3cf | 428 | { |
andriym | 79:9db29f41dc9d | 429 | // Read team button |
andriym | 79:9db29f41dc9d | 430 | bTeamNew = buttonTeam; |
andriym | 79:9db29f41dc9d | 431 | if(bTeamNew==PRESSED && bTeamOld==RELEASED) { |
andriym | 79:9db29f41dc9d | 432 | myTeam = (myTeam==1) ? 2 : 1; |
andriym | 79:9db29f41dc9d | 433 | ledTeamA = myTeam & 1; |
andriym | 79:9db29f41dc9d | 434 | ledTeamB = ~myTeam & 1; |
andriym | 95:3cc3ae2e5e7f | 435 | /* |
andriym | 78:43a6b54f0372 | 436 | out.clear(); |
andriym | 79:9db29f41dc9d | 437 | out.printf("New team: %d\r\n", myTeam); |
andriym | 78:43a6b54f0372 | 438 | out.sleep(2); |
andriym | 95:3cc3ae2e5e7f | 439 | */ |
andriym | 78:43a6b54f0372 | 440 | } |
andriym | 79:9db29f41dc9d | 441 | bTeamOld = bTeamNew; |
andriym | 79:9db29f41dc9d | 442 | |
andriym | 79:9db29f41dc9d | 443 | // Read space button |
andriym | 79:9db29f41dc9d | 444 | bSpaceNew = buttonSpace; |
andriym | 79:9db29f41dc9d | 445 | if(bSpaceNew && !bSpaceOld) { |
andriym | 79:9db29f41dc9d | 446 | level = (level+1) & 0b11; // four states |
andriym | 85:4692a1790cfa | 447 | spaceLEDs(level); |
andriym | 95:3cc3ae2e5e7f | 448 | /* |
andriym | 79:9db29f41dc9d | 449 | out.clear(); |
andriym | 79:9db29f41dc9d | 450 | out.printf("New level: %d\r\n", level); |
andriym | 79:9db29f41dc9d | 451 | out.sleep(2); |
andriym | 95:3cc3ae2e5e7f | 452 | */ |
andriym | 79:9db29f41dc9d | 453 | } |
andriym | 79:9db29f41dc9d | 454 | bSpaceOld = bSpaceNew; |
andriym | 81:3cd7de5d01ef | 455 | |
andriym | 81:3cd7de5d01ef | 456 | // Read volume buttons |
andriym | 82:1e552cc1a615 | 457 | bVMNew = buttonVolMore.read(); |
andriym | 82:1e552cc1a615 | 458 | bVLNew = buttonVolLess.read(); |
andriym | 81:3cd7de5d01ef | 459 | if(bVMNew && !bVMOld) { |
andriym | 81:3cd7de5d01ef | 460 | volume++; |
andriym | 81:3cd7de5d01ef | 461 | if(volume>3) volume=3; |
andriym | 81:3cd7de5d01ef | 462 | ledBuzzer = 1; |
andriym | 95:3cc3ae2e5e7f | 463 | /* |
andriym | 81:3cd7de5d01ef | 464 | out.clear(); |
andriym | 81:3cd7de5d01ef | 465 | out.printf("New volume: %d\r\n", volume); |
andriym | 81:3cd7de5d01ef | 466 | out.sleep(2); |
andriym | 95:3cc3ae2e5e7f | 467 | */ |
andriym | 81:3cd7de5d01ef | 468 | } |
andriym | 81:3cd7de5d01ef | 469 | if(bVLNew && !bVLOld) { |
andriym | 81:3cd7de5d01ef | 470 | if(volume>0) volume--; |
andriym | 81:3cd7de5d01ef | 471 | if(!volume) ledBuzzer = 0; |
andriym | 95:3cc3ae2e5e7f | 472 | /* |
andriym | 81:3cd7de5d01ef | 473 | out.clear(); |
andriym | 81:3cd7de5d01ef | 474 | out.printf("New volume: %d\r\n", volume); |
andriym | 81:3cd7de5d01ef | 475 | out.sleep(2); |
andriym | 95:3cc3ae2e5e7f | 476 | */ |
andriym | 81:3cd7de5d01ef | 477 | } |
andriym | 81:3cd7de5d01ef | 478 | bVMOld = bVMNew; |
andriym | 81:3cd7de5d01ef | 479 | bVLOld = bVLNew; |
andriym | 81:3cd7de5d01ef | 480 | |
andriym | 81:3cd7de5d01ef | 481 | // Output |
andriym | 89:425369a595c4 | 482 | unsigned long current_time = tmr.read_ms(); |
elmbed | 76:6638d83939d5 | 483 | |
andriym | 79:9db29f41dc9d | 484 | if (current_time - last_shown > CYCLE_MS) |
andriym | 78:43a6b54f0372 | 485 | { |
andriym | 81:3cd7de5d01ef | 486 | players.showAll(myTeam, level, volume); |
andriym | 78:43a6b54f0372 | 487 | last_shown = current_time; |
andriym | 78:43a6b54f0372 | 488 | } |
andriym | 78:43a6b54f0372 | 489 | |
andriym | 81:3cd7de5d01ef | 490 | // Radios |
andriym | 78:43a6b54f0372 | 491 | if (current_time - last_send > SEND_RATE_MS) |
AntonLS | 19:afcbb425b3cf | 492 | { |
elmbed | 76:6638d83939d5 | 493 | // Send message |
andriym | 79:9db29f41dc9d | 494 | snprintf(tx_buff, sizeof(tx_buff), "N=%s,%d", rand_name, myTeam); |
andriym | 78:43a6b54f0372 | 495 | radio.send(EVERY_NODE, tx_buff, strlen(tx_buff)); |
andriym | 78:43a6b54f0372 | 496 | last_send = current_time; |
andriym | 78:43a6b54f0372 | 497 | //send_wait = min_wait + (rand() % SEND_RATE_MS)*SEND_DESYNC; |
andriym | 78:43a6b54f0372 | 498 | |
andriym | 89:425369a595c4 | 499 | //// Some debugging info I used to display |
andriym | 78:43a6b54f0372 | 500 | //out.clear(); |
andriym | 78:43a6b54f0372 | 501 | //out.printf("Sent: %s\r\n", tx_buff); |
andriym | 78:43a6b54f0372 | 502 | //uint8_t tempC = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient |
andriym | 78:43a6b54f0372 | 503 | //uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain |
andriym | 78:43a6b54f0372 | 504 | //uint32_t freq = radio.getFrequency(); |
andriym | 78:43a6b54f0372 | 505 | //out.printf("T: %d, G: %d\r\n", tempC, gain); |
andriym | 78:43a6b54f0372 | 506 | //if(freq!=868000000) out.printf("Freq: %d\r\n", freq); |
elmbed | 76:6638d83939d5 | 507 | |
andriym | 81:3cd7de5d01ef | 508 | //beep(NOTE_A3, 0.05, volume); |
elmbed | 76:6638d83939d5 | 509 | } |
andriym | 78:43a6b54f0372 | 510 | |
elmbed | 76:6638d83939d5 | 511 | if (radio.receiveDone()) |
AntonLS | 11:d3aa5fca2330 | 512 | { |
elmbed | 76:6638d83939d5 | 513 | memset(rx_buff, 0x00, sizeof(rx_buff)); |
elmbed | 76:6638d83939d5 | 514 | memcpy(rx_buff, (char*)radio.DATA, radio.DATALEN > sizeof(rx_buff)-1 ? sizeof(rx_buff)-1 : radio.DATALEN); |
elmbed | 76:6638d83939d5 | 515 | |
andriym | 78:43a6b54f0372 | 516 | if(rx_buff[0]=='N' && rx_buff[1]=='=') { |
andriym | 78:43a6b54f0372 | 517 | memcpy(other_name, rx_buff+2, NAME_LEN); |
andriym | 78:43a6b54f0372 | 518 | other_name[5] = 0x00; |
andriym | 78:43a6b54f0372 | 519 | if(sizeof(rx_buff)>8 && rx_buff[7]==',') { |
andriym | 79:9db29f41dc9d | 520 | otherTeam = rx_buff[8]-'0'; |
andriym | 79:9db29f41dc9d | 521 | } else otherTeam = 1; |
andriym | 89:425369a595c4 | 522 | players.update(other_name, otherTeam, radio.RSSI, tmr.read_ms()); |
andriym | 78:43a6b54f0372 | 523 | |
andriym | 78:43a6b54f0372 | 524 | //uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain |
andriym | 78:43a6b54f0372 | 525 | //out.clear(); |
andriym | 78:43a6b54f0372 | 526 | //out.printf("Other: %s\r\n", other_name); |
andriym | 78:43a6b54f0372 | 527 | //out.printf("RSSI: %d, G: %d\r\n", radio.RSSI, gain); |
andriym | 78:43a6b54f0372 | 528 | |
andriym | 81:3cd7de5d01ef | 529 | //beep(NOTE_A5, 0.5, volume); |
andriym | 78:43a6b54f0372 | 530 | } else { // received unknown signal |
andriym | 78:43a6b54f0372 | 531 | uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain |
andriym | 95:3cc3ae2e5e7f | 532 | /* |
andriym | 78:43a6b54f0372 | 533 | out.clear(); |
andriym | 78:43a6b54f0372 | 534 | out.printf("Got: %s\r\n", rx_buff); |
andriym | 78:43a6b54f0372 | 535 | out.printf("RSSI: %d, G: %d\r\n", radio.RSSI, gain); |
andriym | 78:43a6b54f0372 | 536 | out.sleep(2.0); |
andriym | 95:3cc3ae2e5e7f | 537 | */ |
andriym | 78:43a6b54f0372 | 538 | } |
AntonLS | 11:d3aa5fca2330 | 539 | } |
andriym | 89:425369a595c4 | 540 | |
andriym | 89:425369a595c4 | 541 | #ifdef BLE_ENABLE |
andriym | 92:a9ebe6d0a0fa | 542 | // ble.waitForEvent(); |
andriym | 91:0fc897cccc06 | 543 | #endif // BLE_ENABLE |
AntonLS | 0:28ca4562fe1a | 544 | } |
elmbed | 76:6638d83939d5 | 545 | } |