football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

main.cpp

Committer:
andriym
Date:
2016-05-09
Revision:
78:43a6b54f0372
Parent:
76:6638d83939d5
Child:
79:9db29f41dc9d

File content as of revision 78:43a6b54f0372:

#include <RFM69.h>
#include <list>
#include "output.h"

using namespace std;

Timer t;
Output out;

///////////////////////////////////  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

///////////////////////////////////  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 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()
{    
    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;
    
    beep(0.002, 0.5);

    din.mode(PullUp);    
    int button_old = 1, button_new;
    
    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);

    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_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), "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);
            
            //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);
            
            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);
            }
        }
    }
}