football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

Committer:
andriym
Date:
Wed May 25 05:02:53 2016 +0000
Revision:
79:9db29f41dc9d
Parent:
78:43a6b54f0372
Child:
80:8d4f190bd253
Version 1 for Aamir's testing

Who changed what in which revision?

UserRevisionLine numberNew 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 79:9db29f41dc9d 11
andriym 79:9db29f41dc9d 12 DigitalIn buttonTeam(BUT_TEAM);
andriym 79:9db29f41dc9d 13 DigitalIn buttonSpace(BUT_SPACE);
andriym 79:9db29f41dc9d 14 DigitalOut ledTeamA(LED_TEAM_A);
andriym 79:9db29f41dc9d 15 DigitalOut ledTeamB(LED_TEAM_B);
andriym 79:9db29f41dc9d 16 DigitalOut ledSpace5(LED_SPACE5);
andriym 79:9db29f41dc9d 17 DigitalOut ledSpace10(LED_SPACE10);
andriym 79:9db29f41dc9d 18 DigitalOut ledSpace15(LED_SPACE15);
andriym 79:9db29f41dc9d 19 DigitalOut ledSpace20(LED_SPACE20);
andriym 79:9db29f41dc9d 20 AnalogIn ain(ANALOG_IN); // used for randomizing
andriym 78:43a6b54f0372 21 #ifdef NORDIC
andriym 79:9db29f41dc9d 22 DigitalOut buzzer(BUZZER);
andriym 79:9db29f41dc9d 23 DigitalOut buzzLow(BUZZ_LOW);
andriym 79:9db29f41dc9d 24 DigitalOut buzzMed(BUZZ_MED);
andriym 79:9db29f41dc9d 25 DigitalOut buzzHigh(BUZZ_HIGH);
andriym 79:9db29f41dc9d 26 #else
andriym 79:9db29f41dc9d 27 PwmOut speaker(BUZZER); // passive buzzer
andriym 79:9db29f41dc9d 28 #endif
AntonLS 30:c60b0d52b067 29
andriym 78:43a6b54f0372 30 /////////////////////////////////// RADIO ///////////////////////////////////
andriym 79:9db29f41dc9d 31 static RFM69 radio(RFM_MOSI, RFM_MISO, RFM_SCK, RFM_SS, RFM_IRQ);
AntonLS 12:6d313d575f84 32
elmbed 76:6638d83939d5 33 static bool promiscuousMode = true; // set 'true' to sniff all packets on the same network
AntonLS 0:28ca4562fe1a 34
andriym 78:43a6b54f0372 35 /////////////////////////////////// FUNCTIONS ///////////////////////////////////
andriym 78:43a6b54f0372 36
andriym 78:43a6b54f0372 37 void beep(float period, float time) {
andriym 78:43a6b54f0372 38 #ifdef ENABLE_SOUND
andriym 79:9db29f41dc9d 39 #ifdef NORDIC
andriym 79:9db29f41dc9d 40 if(period>=NOTE_A3) {
andriym 79:9db29f41dc9d 41 buzzLow = 1; buzzMed = 0; buzzHigh = 0;
andriym 79:9db29f41dc9d 42 } else if(period>=NOTE_A4) {
andriym 79:9db29f41dc9d 43 buzzLow = 0; buzzMed = 1; buzzHigh = 0;
andriym 79:9db29f41dc9d 44 } else {
andriym 79:9db29f41dc9d 45 buzzLow = 0; buzzMed = 0; buzzHigh = 1;
andriym 79:9db29f41dc9d 46 }
andriym 79:9db29f41dc9d 47 buzzer = 1;
andriym 79:9db29f41dc9d 48 wait(time);
andriym 79:9db29f41dc9d 49 buzzer = 0;
andriym 79:9db29f41dc9d 50 #else
andriym 78:43a6b54f0372 51 speaker.period(period);
andriym 78:43a6b54f0372 52 speaker =0.5; //50% duty cycle - max volume
andriym 78:43a6b54f0372 53 wait(time);
andriym 78:43a6b54f0372 54 speaker=0.0; // turn off audio
andriym 78:43a6b54f0372 55 #endif
andriym 79:9db29f41dc9d 56 #endif
andriym 78:43a6b54f0372 57 }
andriym 78:43a6b54f0372 58
andriym 78:43a6b54f0372 59 void binary_sound(int z) {
andriym 78:43a6b54f0372 60 // Beeps numbers according to their binary form
andriym 78:43a6b54f0372 61 // (used for debugging in display-less and serial-less environments)
andriym 78:43a6b54f0372 62 #ifdef ENABLE_SOUND
andriym 79:9db29f41dc9d 63 #ifndef NORDIC
andriym 78:43a6b54f0372 64 speaker.period(0.004);
andriym 78:43a6b54f0372 65 while(z) {
andriym 78:43a6b54f0372 66 speaker = 0.5;
andriym 78:43a6b54f0372 67 if(z&1) wait(0.5);
andriym 78:43a6b54f0372 68 else wait(0.25);
andriym 78:43a6b54f0372 69 speaker = 0.0;
andriym 78:43a6b54f0372 70 wait(1.0);
andriym 78:43a6b54f0372 71 z >>= 1;
andriym 78:43a6b54f0372 72 }
andriym 79:9db29f41dc9d 73 beep(NOTE_A4, 1.0);
andriym 79:9db29f41dc9d 74 #endif
andriym 78:43a6b54f0372 75 #endif
andriym 78:43a6b54f0372 76 }
andriym 78:43a6b54f0372 77
andriym 78:43a6b54f0372 78 void generate_name(char rand_name[], uint8_t size) {
andriym 78:43a6b54f0372 79 // Generate random name on the 62 character alphabet
andriym 78:43a6b54f0372 80 memset(rand_name, 0x00, size);
andriym 78:43a6b54f0372 81 char alph[63] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
andriym 78:43a6b54f0372 82 uint32_t seed = ((ain.read_u16()+3)/17)*(radio.readTemperature(-1)+37)*((ain.read_u16()+5)/13);
andriym 78:43a6b54f0372 83 srand(seed);
andriym 78:43a6b54f0372 84 for(int i=0;i<size-1;i++) {
andriym 78:43a6b54f0372 85 rand_name[i] = alph[abs(rand()) % 62];
andriym 78:43a6b54f0372 86 }
andriym 78:43a6b54f0372 87 }
andriym 78:43a6b54f0372 88
andriym 78:43a6b54f0372 89 /////////////////////////////////// CLASSES ///////////////////////////////////
andriym 78:43a6b54f0372 90
andriym 78:43a6b54f0372 91 struct Contact {
andriym 78:43a6b54f0372 92 int16_t rssi;
andriym 78:43a6b54f0372 93 uint32_t time_ms;
andriym 78:43a6b54f0372 94 };
andriym 78:43a6b54f0372 95
andriym 78:43a6b54f0372 96 class Player {
andriym 78:43a6b54f0372 97 public:
andriym 78:43a6b54f0372 98 char name[NAME_LEN+1];
andriym 78:43a6b54f0372 99 int8_t team;
andriym 78:43a6b54f0372 100 Player(const char rand_name[]) {
andriym 78:43a6b54f0372 101 memset(name, 0x00, NAME_LEN+1);
andriym 78:43a6b54f0372 102 memcpy(name, rand_name, NAME_LEN);
andriym 78:43a6b54f0372 103 }
andriym 78:43a6b54f0372 104 void update(int8_t _team, int rssi, uint32_t time=NULL) {
andriym 78:43a6b54f0372 105 // Remember this contact
andriym 78:43a6b54f0372 106 team = _team;
andriym 78:43a6b54f0372 107 Contact c;
andriym 78:43a6b54f0372 108 c.rssi = rssi;
andriym 78:43a6b54f0372 109 c.time_ms = (time!=NULL) ? time : t.read_ms();
andriym 78:43a6b54f0372 110 contacts.push_front(c);
andriym 78:43a6b54f0372 111
andriym 78:43a6b54f0372 112 // Cleanup
andriym 78:43a6b54f0372 113 while(contacts.size() > MAX_RECORDS) contacts.pop_back();
andriym 78:43a6b54f0372 114 while(!contacts.empty() && c.time_ms - contacts.back().time_ms > MAX_HISTORY_MS) contacts.pop_back();
andriym 78:43a6b54f0372 115 }
andriym 78:43a6b54f0372 116 int16_t get_distance(int &cnt) {
andriym 78:43a6b54f0372 117 // Find max RSSI
andriym 78:43a6b54f0372 118 uint32_t cur_time = t.read_ms();
andriym 78:43a6b54f0372 119 int16_t max_rssi=-128;
andriym 78:43a6b54f0372 120 cnt=0;
andriym 78:43a6b54f0372 121 for (list<Contact>::iterator it=contacts.begin(); it != contacts.end(); ++it) {
andriym 78:43a6b54f0372 122 if(cur_time - it->time_ms > SIGNALS_VALID_MS) break;
andriym 78:43a6b54f0372 123 if(it->rssi > max_rssi) max_rssi = it->rssi;
andriym 78:43a6b54f0372 124 cnt++;
andriym 78:43a6b54f0372 125 }
andriym 78:43a6b54f0372 126 return max_rssi;
andriym 78:43a6b54f0372 127 }
andriym 78:43a6b54f0372 128 inline bool operator==(const char rhs[]){ return memcmp(name, rhs, NAME_LEN)==0; }
andriym 78:43a6b54f0372 129 inline bool operator==(const Player& rhs){ return *this==rhs.name; }
andriym 78:43a6b54f0372 130 //inline bool operator!=(const char rhs[]){ return !(*this == rhs); }
andriym 78:43a6b54f0372 131 private:
andriym 78:43a6b54f0372 132 list<Contact> contacts;
andriym 78:43a6b54f0372 133 };
andriym 78:43a6b54f0372 134
andriym 78:43a6b54f0372 135 class Players {
andriym 78:43a6b54f0372 136 public:
andriym 78:43a6b54f0372 137 list<Player> players;
andriym 78:43a6b54f0372 138
andriym 78:43a6b54f0372 139 void update(const char name[], int8_t team, int16_t rssi, uint32_t time_ms=NULL) {
andriym 78:43a6b54f0372 140 list<Player>::iterator it;
andriym 78:43a6b54f0372 141 for (it=players.begin(); it != players.end(); ++it) {
andriym 78:43a6b54f0372 142 if(*it==name) break;
andriym 78:43a6b54f0372 143 }
andriym 78:43a6b54f0372 144 if(it!=players.end()) {
andriym 78:43a6b54f0372 145 it->update(team, rssi, time_ms);
andriym 78:43a6b54f0372 146 } else {
andriym 78:43a6b54f0372 147 Player p(name);
andriym 78:43a6b54f0372 148 p.update(team, rssi, time_ms);
andriym 78:43a6b54f0372 149 players.push_front(p);
andriym 78:43a6b54f0372 150 }
andriym 78:43a6b54f0372 151 }
andriym 78:43a6b54f0372 152
andriym 79:9db29f41dc9d 153 void showAll(int8_t team, uint8_t level) {
andriym 79:9db29f41dc9d 154 // Output the current state to the user:
andriym 79:9db29f41dc9d 155 // - show the current information table and/or
andriym 79:9db29f41dc9d 156 // - beep if the user is too close to another one
andriym 79:9db29f41dc9d 157 int i=0, nContacts, signal, maxTeamSignal = -128;
andriym 78:43a6b54f0372 158 list<Player>::iterator it;
andriym 78:43a6b54f0372 159 out.clear();
andriym 78:43a6b54f0372 160 for (it=players.begin(); it != players.end(); ++it) {
andriym 79:9db29f41dc9d 161 signal = it->get_distance(nContacts);
andriym 79:9db29f41dc9d 162 if(signal>-128) {
andriym 78:43a6b54f0372 163 out.printf("%d ", ++i);
andriym 78:43a6b54f0372 164 out.printf((team==it->team) ? "+" : "-"); // teammate or opponent?
andriym 78:43a6b54f0372 165 out.printf("%s ", it->name);
andriym 79:9db29f41dc9d 166 out.printf("%d/%d", -signal, nContacts);
andriym 79:9db29f41dc9d 167 out.printf((-signal<SPACE[level]) ? "!" : " ");
andriym 79:9db29f41dc9d 168 out.printf("\r\n");
andriym 79:9db29f41dc9d 169 }
andriym 79:9db29f41dc9d 170 if(team==it->team && signal>maxTeamSignal) {
andriym 79:9db29f41dc9d 171 maxTeamSignal = signal;
andriym 78:43a6b54f0372 172 }
andriym 78:43a6b54f0372 173 }
andriym 79:9db29f41dc9d 174 //if(!i) {
andriym 79:9db29f41dc9d 175 // out.printf("Nobody around\r\n");
andriym 79:9db29f41dc9d 176 // beep(NOTE_A5,0.5);
andriym 79:9db29f41dc9d 177 //}
andriym 79:9db29f41dc9d 178 if(-maxTeamSignal<SPACE[level]) {
andriym 79:9db29f41dc9d 179 beep(NOTE_A4,0.33);
andriym 78:43a6b54f0372 180 }
andriym 78:43a6b54f0372 181 }
andriym 78:43a6b54f0372 182 };
andriym 78:43a6b54f0372 183
andriym 78:43a6b54f0372 184 /////////////////////////////////// MAIN CODE ///////////////////////////////////
andriym 78:43a6b54f0372 185
elmbed 76:6638d83939d5 186 int main()
andriym 78:43a6b54f0372 187 {
elmbed 76:6638d83939d5 188 char tx_buff[100] = {0};
elmbed 76:6638d83939d5 189 char rx_buff[100] = {0};
andriym 78:43a6b54f0372 190 char rand_name[NAME_LEN+1] = {0};
andriym 78:43a6b54f0372 191 char other_name[NAME_LEN+1] = {0};
andriym 79:9db29f41dc9d 192 int8_t myTeam = 1, otherTeam;
andriym 79:9db29f41dc9d 193 uint8_t level = 1;
elmbed 76:6638d83939d5 194
andriym 79:9db29f41dc9d 195 beep(NOTE_A5, 0.5);
andriym 78:43a6b54f0372 196
andriym 79:9db29f41dc9d 197 buttonSpace.mode(PullDown);
andriym 79:9db29f41dc9d 198 #ifdef NORDIC
andriym 79:9db29f41dc9d 199 buttonTeam.mode(PullDown);
andriym 79:9db29f41dc9d 200 int bTeamOld = 0;
andriym 79:9db29f41dc9d 201 #else
andriym 79:9db29f41dc9d 202 buttonTeam.mode(PullUp);
andriym 79:9db29f41dc9d 203 int bTeamOld = 1;
andriym 79:9db29f41dc9d 204 #endif
andriym 79:9db29f41dc9d 205 int bTeamNew, bSpaceOld=0, bSpaceNew;
elmbed 76:6638d83939d5 206
andriym 78:43a6b54f0372 207 char this_node = int(ain.read()*255+17)*int(ain.read()*255+11); // random node value
andriym 78:43a6b54f0372 208 out.printf("Node: %d\r\n", this_node);
andriym 78:43a6b54f0372 209
andriym 78:43a6b54f0372 210 // Init radio
andriym 78:43a6b54f0372 211 radio.initialize(FREQUENCY, this_node, NETWORKID);
andriym 78:43a6b54f0372 212 #ifdef HIGH_POWER
andriym 78:43a6b54f0372 213 radio.setHighPower(true);
andriym 78:43a6b54f0372 214 #endif
elmbed 76:6638d83939d5 215 radio.encrypt(0);
elmbed 76:6638d83939d5 216 radio.promiscuous(promiscuousMode);
andriym 78:43a6b54f0372 217 radio.setFrequency(868000000);
AntonLS 11:d3aa5fca2330 218
andriym 78:43a6b54f0372 219 generate_name(rand_name, sizeof(rand_name));
andriym 78:43a6b54f0372 220 out.printf("Name: %s\r\n", rand_name);
andriym 78:43a6b54f0372 221 out.sleep(2.0);
andriym 78:43a6b54f0372 222
elmbed 76:6638d83939d5 223 t.start();
andriym 79:9db29f41dc9d 224 ledTeamA = myTeam & 1;
andriym 79:9db29f41dc9d 225 ledTeamB = ~myTeam & 1;
andriym 79:9db29f41dc9d 226 #ifdef NORDIC
andriym 79:9db29f41dc9d 227 buzzMed = 1;
andriym 79:9db29f41dc9d 228 #endif
andriym 78:43a6b54f0372 229
andriym 78:43a6b54f0372 230 Players players;
andriym 78:43a6b54f0372 231
andriym 78:43a6b54f0372 232 uint32_t last_send = t.read_ms();
andriym 78:43a6b54f0372 233 uint32_t last_shown = t.read_ms();
andriym 78:43a6b54f0372 234 //uint32_t min_wait = SEND_RATE_MS - 0.5*SEND_RATE_MS*SEND_DESYNC;
andriym 78:43a6b54f0372 235 //uint32_t send_wait = min_wait;
AntonLS 49:626e84ce5e52 236
elmbed 76:6638d83939d5 237 while (true)
AntonLS 19:afcbb425b3cf 238 {
andriym 79:9db29f41dc9d 239 // Read team button
andriym 79:9db29f41dc9d 240 bTeamNew = buttonTeam;
andriym 79:9db29f41dc9d 241 if(bTeamNew==PRESSED && bTeamOld==RELEASED) {
andriym 79:9db29f41dc9d 242 myTeam = (myTeam==1) ? 2 : 1;
andriym 79:9db29f41dc9d 243 ledTeamA = myTeam & 1;
andriym 79:9db29f41dc9d 244 ledTeamB = ~myTeam & 1;
andriym 78:43a6b54f0372 245 out.clear();
andriym 79:9db29f41dc9d 246 out.printf("New team: %d\r\n", myTeam);
andriym 78:43a6b54f0372 247 out.sleep(2);
andriym 78:43a6b54f0372 248 }
andriym 79:9db29f41dc9d 249 bTeamOld = bTeamNew;
andriym 79:9db29f41dc9d 250
andriym 79:9db29f41dc9d 251 // Read space button
andriym 79:9db29f41dc9d 252 bSpaceNew = buttonSpace;
andriym 79:9db29f41dc9d 253 if(bSpaceNew && !bSpaceOld) {
andriym 79:9db29f41dc9d 254 level = (level+1) & 0b11; // four states
andriym 79:9db29f41dc9d 255 if(level<=0) {
andriym 79:9db29f41dc9d 256 ledSpace5 = 1; ledSpace10 = 0; ledSpace15 = 0; ledSpace20 = 0;
andriym 79:9db29f41dc9d 257 } else if(level<=1) {
andriym 79:9db29f41dc9d 258 ledSpace5 = 0; ledSpace10 = 1; ledSpace15 = 0; ledSpace20 = 0;
andriym 79:9db29f41dc9d 259 } else if(level<=2) {
andriym 79:9db29f41dc9d 260 ledSpace5 = 0; ledSpace10 = 0; ledSpace15 = 1; ledSpace20 = 0;
andriym 79:9db29f41dc9d 261 } else {
andriym 79:9db29f41dc9d 262 ledSpace5 = 0; ledSpace10 = 0; ledSpace15 = 0; ledSpace20 = 1;
andriym 79:9db29f41dc9d 263 }
andriym 79:9db29f41dc9d 264 out.clear();
andriym 79:9db29f41dc9d 265 out.printf("New level: %d\r\n", level);
andriym 79:9db29f41dc9d 266 out.sleep(2);
andriym 79:9db29f41dc9d 267 }
andriym 79:9db29f41dc9d 268 bSpaceOld = bSpaceNew;
andriym 78:43a6b54f0372 269
elmbed 76:6638d83939d5 270 unsigned long current_time = t.read_ms();
elmbed 76:6638d83939d5 271
andriym 79:9db29f41dc9d 272 if (current_time - last_shown > CYCLE_MS)
andriym 78:43a6b54f0372 273 {
andriym 79:9db29f41dc9d 274 players.showAll(myTeam, level);
andriym 78:43a6b54f0372 275 last_shown = current_time;
andriym 78:43a6b54f0372 276 }
andriym 78:43a6b54f0372 277
andriym 78:43a6b54f0372 278 if (current_time - last_send > SEND_RATE_MS)
AntonLS 19:afcbb425b3cf 279 {
elmbed 76:6638d83939d5 280 // Send message
andriym 79:9db29f41dc9d 281 snprintf(tx_buff, sizeof(tx_buff), "N=%s,%d", rand_name, myTeam);
andriym 78:43a6b54f0372 282 radio.send(EVERY_NODE, tx_buff, strlen(tx_buff));
andriym 78:43a6b54f0372 283 last_send = current_time;
andriym 78:43a6b54f0372 284 //send_wait = min_wait + (rand() % SEND_RATE_MS)*SEND_DESYNC;
andriym 78:43a6b54f0372 285
andriym 78:43a6b54f0372 286 //out.clear();
andriym 78:43a6b54f0372 287 //out.printf("Sent: %s\r\n", tx_buff);
andriym 78:43a6b54f0372 288 //uint8_t tempC = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient
andriym 78:43a6b54f0372 289 //uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain
andriym 78:43a6b54f0372 290 //uint32_t freq = radio.getFrequency();
andriym 78:43a6b54f0372 291 //out.printf("T: %d, G: %d\r\n", tempC, gain);
andriym 78:43a6b54f0372 292 //if(freq!=868000000) out.printf("Freq: %d\r\n", freq);
elmbed 76:6638d83939d5 293
andriym 79:9db29f41dc9d 294 //beep(NOTE_A3, 0.05);
elmbed 76:6638d83939d5 295 }
andriym 78:43a6b54f0372 296
elmbed 76:6638d83939d5 297 if (radio.receiveDone())
AntonLS 11:d3aa5fca2330 298 {
elmbed 76:6638d83939d5 299 memset(rx_buff, 0x00, sizeof(rx_buff));
elmbed 76:6638d83939d5 300 memcpy(rx_buff, (char*)radio.DATA, radio.DATALEN > sizeof(rx_buff)-1 ? sizeof(rx_buff)-1 : radio.DATALEN);
elmbed 76:6638d83939d5 301
andriym 78:43a6b54f0372 302 if(rx_buff[0]=='N' && rx_buff[1]=='=') {
andriym 78:43a6b54f0372 303 memcpy(other_name, rx_buff+2, NAME_LEN);
andriym 78:43a6b54f0372 304 other_name[5] = 0x00;
andriym 78:43a6b54f0372 305 if(sizeof(rx_buff)>8 && rx_buff[7]==',') {
andriym 79:9db29f41dc9d 306 otherTeam = rx_buff[8]-'0';
andriym 79:9db29f41dc9d 307 } else otherTeam = 1;
andriym 79:9db29f41dc9d 308 players.update(other_name, otherTeam, radio.RSSI, t.read_ms());
andriym 78:43a6b54f0372 309
andriym 78:43a6b54f0372 310 //uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain
andriym 78:43a6b54f0372 311 //out.clear();
andriym 78:43a6b54f0372 312 //out.printf("Other: %s\r\n", other_name);
andriym 78:43a6b54f0372 313 //out.printf("RSSI: %d, G: %d\r\n", radio.RSSI, gain);
andriym 78:43a6b54f0372 314
andriym 79:9db29f41dc9d 315 //beep(NOTE_A5, 0.5);
andriym 78:43a6b54f0372 316 } else { // received unknown signal
andriym 78:43a6b54f0372 317 uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3; // LNA Current Gain
andriym 78:43a6b54f0372 318 out.clear();
andriym 78:43a6b54f0372 319 out.printf("Got: %s\r\n", rx_buff);
andriym 78:43a6b54f0372 320 out.printf("RSSI: %d, G: %d\r\n", radio.RSSI, gain);
andriym 78:43a6b54f0372 321 out.sleep(2.0);
andriym 78:43a6b54f0372 322 }
AntonLS 11:d3aa5fca2330 323 }
AntonLS 0:28ca4562fe1a 324 }
elmbed 76:6638d83939d5 325 }