football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

Revision:
78:43a6b54f0372
Parent:
76:6638d83939d5
Child:
79:9db29f41dc9d
--- a/main.cpp	Wed Apr 27 08:41:13 2016 +0000
+++ b/main.cpp	Mon May 09 01:08:01 2016 +0000
@@ -1,54 +1,270 @@
 #include <RFM69.h>
-#include <SPI.h>
+#include <list>
+#include "output.h"
 
-#define NODE_ID 1     // ID of the current node
-#define SEND_TO_ID 2  // ID to send messages to 
+using namespace std;
+
+Timer t;
+Output out;
 
-#define NETWORKID     101   //the same on all nodes that talk to each other
-
-#define FREQUENCY     RF69_915MHZ
+///////////////////////////////////  PINS   ///////////////////////////////////
+#ifdef NORDIC
+//PwmOut speaker(PB_8);     // TODO: add sound for Nordic
+DigitalIn din(BTN1);
+AnalogIn ain(P0_1);       // used for randomizing
+#else // not NORDIC
+#ifdef NUCLEO
+PwmOut speaker(PB_8);
+DigitalIn din(USER_BUTTON);
+AnalogIn ain(A5);       // used for randomizing
+#else // LPC assumed
+PwmOut speaker(p21);
+DigitalIn din(p5);
+AnalogIn ain(p15);      // used for randomizing
+#endif // NUCLEO
+#endif // NORDIC
 
-Serial pc(USBTX, USBRX);
+///////////////////////////////////  RADIO  ///////////////////////////////////
+#ifdef NORDIC
+static RFM69 radio(P0_20,P0_22,P0_25,P0_24,P0_23);      // Update according to your setup
+#else // not NORDIC
+#ifdef NUCLEO
+static RFM69 radio(D11,D12,D13,D10,D9);
+#else // LPC assumed
+static RFM69 radio(p11,p12,p13,p10,p9);
+#endif // NUCLEO
+#endif // NORDIC
 
-static RFM69 radio(P0_24,P0_23,P0_25,P0_28,P0_7);
 static bool promiscuousMode = true; // set 'true' to sniff all packets on the same network
 
+/////////////////////////////////// FUNCTIONS ///////////////////////////////////
+
+void beep(float period, float time) { 
+#ifdef ENABLE_SOUND
+    speaker.period(period);
+    speaker =0.5; //50% duty cycle - max volume
+    wait(time);
+    speaker=0.0; // turn off audio
+#endif
+}
+
+void binary_sound(int z) {
+    // Beeps numbers according to their binary form
+    // (used for debugging in display-less and serial-less environments)
+#ifdef ENABLE_SOUND
+    speaker.period(0.004);
+    while(z) {
+        speaker = 0.5;
+        if(z&1) wait(0.5);
+        else wait(0.25);
+        speaker = 0.0;
+        wait(1.0);
+        z >>= 1;
+    }
+    beep(0.002, 1.0);
+#endif
+}
+
+void generate_name(char rand_name[], uint8_t size) {
+    // Generate random name on the 62 character alphabet
+    memset(rand_name, 0x00, size);
+    char alph[63] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+    uint32_t seed = ((ain.read_u16()+3)/17)*(radio.readTemperature(-1)+37)*((ain.read_u16()+5)/13);
+    srand(seed);
+    for(int i=0;i<size-1;i++) {
+        rand_name[i] = alph[abs(rand()) % 62];
+    }
+}
+
+/////////////////////////////////// CLASSES ///////////////////////////////////
+
+struct Contact {
+    int16_t rssi;
+    uint32_t time_ms;
+};
+
+class Player {
+  public:
+    char name[NAME_LEN+1];
+    int8_t team;
+    Player(const char rand_name[]) {
+        memset(name, 0x00, NAME_LEN+1);
+        memcpy(name, rand_name, NAME_LEN);
+    }
+    void update(int8_t _team, int rssi, uint32_t time=NULL) {
+        // Remember this contact
+        team = _team;
+        Contact c;
+        c.rssi = rssi;
+        c.time_ms = (time!=NULL) ? time : t.read_ms();
+        contacts.push_front(c);
+        
+        // Cleanup
+        while(contacts.size() > MAX_RECORDS) contacts.pop_back();
+        while(!contacts.empty() && c.time_ms - contacts.back().time_ms > MAX_HISTORY_MS) contacts.pop_back();
+    }
+    int16_t get_distance(int &cnt) {
+        // Find max RSSI
+        uint32_t cur_time = t.read_ms();
+        int16_t max_rssi=-128;
+        cnt=0;
+        for (list<Contact>::iterator it=contacts.begin(); it != contacts.end(); ++it) {
+            if(cur_time - it->time_ms > SIGNALS_VALID_MS) break;
+            if(it->rssi > max_rssi) max_rssi = it->rssi;
+            cnt++;
+        }
+        return max_rssi;
+    }
+    inline bool operator==(const char rhs[]){ return memcmp(name, rhs, NAME_LEN)==0; }
+    inline bool operator==(const Player& rhs){ return *this==rhs.name; }
+    //inline bool operator!=(const char rhs[]){ return !(*this == rhs); }
+  private:
+    list<Contact> contacts;
+};
+
+class Players {
+  public:
+    list<Player> players;
+    
+    void update(const char name[], int8_t team, int16_t rssi, uint32_t time_ms=NULL) {
+        list<Player>::iterator it;
+        for (it=players.begin(); it != players.end(); ++it) {
+            if(*it==name) break;
+        }
+        if(it!=players.end()) {
+            it->update(team, rssi, time_ms);
+        } else {
+            Player p(name);
+            p.update(team, rssi, time_ms);
+            players.push_front(p);
+        }
+    }
+    
+    void show_all(int8_t team) {
+        // Show the current information table
+        int i=0, contacts, dist;
+        list<Player>::iterator it;
+        out.clear();
+        for (it=players.begin(); it != players.end(); ++it) {
+            dist = it->get_distance(contacts);
+            if(dist>-128) {
+                out.printf("%d ", ++i);
+                out.printf((team==it->team) ? "+" : "-");       // teammate or opponent?
+                out.printf("%s ", it->name);
+                out.printf("%d/%d\r\n", -dist, contacts);
+            }
+        } 
+        if(!i) {
+            out.printf("Nobody around\r\n");
+            beep(0.001,0.5);
+        }
+    }
+};
+
+/////////////////////////////////// MAIN CODE ///////////////////////////////////
+
 int main()
-{
-    unsigned long last_send = 0L;
+{    
     char tx_buff[100] = {0};
     char rx_buff[100] = {0};
+    char rand_name[NAME_LEN+1] = {0};
+    char other_name[NAME_LEN+1] = {0};
+    int8_t team = 1, other_team;
     
-    pc.baud(9600);
-    pc.printf("RFM69 test starting with ID: %d\r\n", NODE_ID);
+    beep(0.002, 0.5);
+
+    din.mode(PullUp);    
+    int button_old = 1, button_new;
     
-    radio.initialize(FREQUENCY, NODE_ID, NETWORKID);
+    char this_node = int(ain.read()*255+17)*int(ain.read()*255+11); // random node value
+    out.printf("Node: %d\r\n", this_node);
+
+    // Init radio    
+    radio.initialize(FREQUENCY, this_node, NETWORKID);
+#ifdef HIGH_POWER
+    radio.setHighPower(true);
+#endif
     radio.encrypt(0);
     radio.promiscuous(promiscuousMode);
+    radio.setFrequency(868000000);
 
-    Timer t;
+    generate_name(rand_name, sizeof(rand_name));
+    out.printf("Name: %s\r\n", rand_name);
+    out.sleep(2.0);
+        
     t.start();
+    
+    Players players;
+    
+    uint32_t last_send = t.read_ms();
+    uint32_t last_shown = t.read_ms();
+    //uint32_t min_wait = SEND_RATE_MS - 0.5*SEND_RATE_MS*SEND_DESYNC;
+    //uint32_t send_wait = min_wait;
 
     while (true)
     {
+        button_new = din;
+        if(!button_new && button_old) {
+            team = (team==1) ? 2 : 1;
+            out.clear();
+            out.printf("New team: %d\r\n", team);
+            out.sleep(2);
+        }
+        button_old = button_new;
+        
         unsigned long current_time = t.read_ms();
         
-        if (current_time - last_send > 2000L)
+        if (current_time - last_shown > 2000L)
+        {
+            players.show_all(team);
+            last_shown = current_time;
+        }
+        
+        if (current_time - last_send > SEND_RATE_MS)
         {
             // Send message
-            snprintf(tx_buff, sizeof(tx_buff), "msg frm: %d at %lu", NODE_ID, current_time);
-            radio.send(SEND_TO_ID, tx_buff, strlen(tx_buff));
-            last_send = current_time;    
+            snprintf(tx_buff, sizeof(tx_buff), "N=%s,%d", rand_name, team);
+            radio.send(EVERY_NODE, tx_buff, strlen(tx_buff));
+            last_send = current_time;
+            //send_wait = min_wait + (rand() % SEND_RATE_MS)*SEND_DESYNC;
+      
+            //out.clear();
+            //out.printf("Sent: %s\r\n", tx_buff);
+            //uint8_t tempC = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient
+            //uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3;   // LNA Current Gain
+            //uint32_t freq = radio.getFrequency();
+            //out.printf("T: %d, G: %d\r\n", tempC, gain);
+            //if(freq!=868000000) out.printf("Freq: %d\r\n", freq);
             
-            pc.printf("Sent: %s\r\n", tx_buff);
+            //beep(0.003, 0.05);
         }
-        
+
         if (radio.receiveDone())
         {
             memset(rx_buff, 0x00, sizeof(rx_buff));
             memcpy(rx_buff, (char*)radio.DATA, radio.DATALEN > sizeof(rx_buff)-1 ? sizeof(rx_buff)-1 : radio.DATALEN);
             
-            pc.printf("Got: %s\r\n", rx_buff);
+            if(rx_buff[0]=='N' && rx_buff[1]=='=') {
+                memcpy(other_name, rx_buff+2, NAME_LEN);
+                other_name[5] = 0x00;
+                if(sizeof(rx_buff)>8 && rx_buff[7]==',') {
+                    other_team = rx_buff[8]-'0';
+                } else other_team = 1;
+                players.update(other_name, other_team, radio.RSSI, t.read_ms());
+
+                //uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3;   // LNA Current Gain
+                //out.clear();
+                //out.printf("Other: %s\r\n", other_name);
+                //out.printf("RSSI: %d, G: %d\r\n", radio.RSSI, gain);
+                
+                //beep(0.001, 0.5);
+            } else {    // received unknown signal 
+                uint8_t gain = (radio.readReg(REG_LNA) & 0b111000)>>3;   // LNA Current Gain
+                out.clear();
+                out.printf("Got: %s\r\n", rx_buff);
+                out.printf("RSSI: %d, G: %d\r\n", radio.RSSI, gain);
+                out.sleep(2.0);
+            }
         }
     }
 }
\ No newline at end of file