football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

main.cpp

Committer:
andriym
Date:
2016-06-16
Revision:
97:2894fbc2d4f8
Parent:
95:3cc3ae2e5e7f
Child:
98:9241041ec253

File content as of revision 97:2894fbc2d4f8:

#include <list>
#include <DebounceIn.h>
#include "configs.h"

using namespace std;

Timer tmr;
//Output out;

///////////////////////////////////  PINS   ///////////////////////////////////

DebounceIn buttonTeam(BUT_TEAM);
DebounceIn buttonSpace(BUT_SPACE);
DebounceIn buttonVolMore(BUT_VOL_MORE);
DebounceIn buttonVolLess(BUT_VOL_LESS);

DigitalOut ledTeamA(LED_TEAM_A);
DigitalOut ledTeamB(LED_TEAM_B);
DigitalOut ledSpace5(LED_SPACE5);
DigitalOut ledSpace10(LED_SPACE10);
DigitalOut ledSpace15(LED_SPACE15);
DigitalOut ledSpace20(LED_SPACE20);
DigitalOut ledBuzzer(LED_BUZZER_ON);

AnalogIn ain(ANALOG_IN);    // used for randomizing  
#ifdef NORDIC
DigitalOut buzzer(BUZZER);
#ifndef HARD_V2
DigitalOut buzzLow(BUZZ_LOW);
#endif
DigitalOut buzzMed(BUZZ_MED);
DigitalOut buzzHigh(BUZZ_HIGH);
#else
PwmOut speaker(BUZZER);     // passive buzzer
#endif

/////////////////////////////////// FUNCTIONS ///////////////////////////////////

void beep(float period, float time, uint8_t vol) { 
#ifdef ENABLE_SOUND
    if(!vol) return;
#ifdef NORDIC
    if(vol>=3) {
#ifndef HARD_V2
        buzzLow = LOW_ON; 
#endif 
        buzzMed = MED_OFF; buzzHigh = HIGH_OFF;
    } else if(vol>=2) {
#ifndef HARD_V2
        buzzLow = LOW_OFF; 
#endif 
        buzzMed = MED_ON; buzzHigh = HIGH_OFF;
    } else {
#ifndef HARD_V2
        buzzLow = LOW_OFF; 
#endif 
        buzzMed = MED_OFF; buzzHigh = HIGH_ON;
    }
    buzzer = 0;     // P-MOSFET
    wait(time);
    buzzer = 1;
#else
    speaker.period(period);
    if(vol>=3) 
        speaker = 0.5; //50% duty cycle - max volume
    else if(vol>=2) 
        speaker = 0.33;
    else
        speaker = 0.2;
    wait(time);
    speaker=0.0; // turn off audio
#endif
#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
#ifndef NORDIC
    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(NOTE_A4, 1.0, 2);
#endif
#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)*((ain.read_u16()+5)/13);
    srand(seed);
    for(int i=0;i<size-1;i++) {
        rand_name[i] = alph[abs(rand()) % 62];
    }
}

void spaceLEDs(int level) {
    if(level<=0) {
        ledSpace5 = 1; ledSpace10 = 0; ledSpace15 = 0; ledSpace20 = 0;
    } else if(level<=1) {
        ledSpace5 = 0; ledSpace10 = 1; ledSpace15 = 0; ledSpace20 = 0;
    } else if(level<=2) {
        ledSpace5 = 0; ledSpace10 = 0; ledSpace15 = 1; ledSpace20 = 0;
    } else {
        ledSpace5 = 0; ledSpace10 = 0; ledSpace15 = 0; ledSpace20 = 1;
    }
}


/////////////////////////////////// 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 : tmr.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 = tmr.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 showAll(int8_t team, uint8_t level, uint8_t volume) {
        // Output the current state to the user:
        //   - show the current information table and/or
        //   - beep if the user is too close to another one
        int i=0, nContacts, signal, maxTeamSignal = -128;
        list<Player>::iterator it;
        //out.clear();
        for (it=players.begin(); it != players.end(); ++it) {
            signal = it->get_distance(nContacts);
            if(signal>-128) {
                /*
                out.printf("%d ", ++i);
                out.printf((team==it->team) ? "+" : "-");       // teammate or opponent?
                out.printf("%s ", it->name);
                out.printf("%d/%d", -signal, nContacts);
                out.printf((-signal<SPACE[level]) ? "!" : " ");
                out.printf("\r\n");
                */
            }
            if(team==it->team && signal>maxTeamSignal) {
                maxTeamSignal = signal;
            }
        } 
        //if(!i) {
        //    out.printf("Nobody around\r\n");
        //    beep(NOTE_A5,0.5,volume);
        //}
        if(-maxTeamSignal<SPACE[level]) {
            beep(NOTE_A4, 0.33, volume);
        }
    }
};

/////////////////////////////////// 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 myTeam = 1, otherTeam;
    uint8_t level = 1, volume = 1;      // SPACE10, VOL_LOW
    int bTeamNew, bTeamOld, bSpaceOld, bSpaceNew, bVMNew, bVLNew, bVMOld, bVLOld;
    
    // Blink all the LEDs at startup
    spaceLEDs(0); wait(0.2); spaceLEDs(1); wait(0.2); spaceLEDs(2); wait(0.2);  spaceLEDs(3); wait(0.2); ledSpace20 = 0;
#ifdef TEST_LED_SOUND
    // Test LEDs and sound simultaneously to save time
    buzzMed = MED_OFF; buzzHigh = HIGH_OFF; 
    ledBuzzer = 1; buzzer=0; wait(0.2); buzzer=1; ledBuzzer = 0;
    buzzMed = MED_ON;
    ledTeamA = 1; buzzer=0; wait(0.2); buzzer=1; ledTeamA = 0;  
    buzzMed = MED_OFF; buzzHigh = HIGH_ON; 
    ledTeamB = 1; buzzer=0; wait(0.2); buzzer=1; ledTeamB = 0; 
    buzzHigh = HIGH_OFF;
#else
    ledBuzzer = 1; wait(0.2); ledBuzzer = 0;
    ledTeamA = 1; wait(0.2); ledTeamA = 0;  
    ledTeamB = 1; wait(0.2); ledTeamB = 0; 
    
    // Beep all the levels on startup
    beep(NOTE_A5, 0.2, 1);
    beep(NOTE_A5, 0.2, 2);
    beep(NOTE_A5, 0.2, 3);
#endif
    
    // ...and go to a informative LEDs
    spaceLEDs(level);
    ledBuzzer = volume ? 1 : 0;
    if(myTeam & 1) ledTeamA = 1;
    else ledTeamB = 1;

    // Buttons initialization
    buttonSpace.mode(PullDown);
    buttonVolMore.mode(PullDown);
    buttonVolLess.mode(PullDown);
#ifdef NORDIC
    buttonTeam.mode(PullDown);
    bTeamOld = 0;
#else
    buttonTeam.mode(PullUp);
    bTeamOld = 1;
#endif
    bSpaceOld = 0;
    bVMOld = 0;
    bVLOld = 0;
        
    // Pick node number
    char this_node = int(ain.read()*255+17)*int(ain.read()*255+11); // random node value
    //out.printf("Node: %d\r\n", this_node);

    // Pick node name
    generate_name(rand_name, sizeof(rand_name));
    /*
    out.printf("Name: %s\r\n", rand_name);
    out.sleep(2.0);
    */
        
    tmr.start();
    
    Players players;
    
    uint32_t last_send = tmr.read_ms();
    uint32_t last_shown = tmr.read_ms();
    //uint32_t min_wait = SEND_RATE_MS - 0.5*SEND_RATE_MS*SEND_DESYNC;
    //uint32_t send_wait = min_wait;

    while (true)
    {
        // Read team button
        bTeamNew = buttonTeam;
        if(bTeamNew==PRESSED && bTeamOld==RELEASED) {
            myTeam = (myTeam==1) ? 2 : 1;
            ledTeamA = myTeam & 1;
            ledTeamB = ~myTeam & 1;
            /*
            out.clear();
            out.printf("New team: %d\r\n", myTeam);
            out.sleep(2);
            */
        }
        bTeamOld = bTeamNew;
        
        // Read space button
        bSpaceNew = buttonSpace;
        if(bSpaceNew && !bSpaceOld) {
            level = (level+1) & 0b11;   // four states
            spaceLEDs(level);
            /*
            out.clear();
            out.printf("New level: %d\r\n", level);
            out.sleep(2);
            */
        }
        bSpaceOld = bSpaceNew;

        // Read volume buttons
        bVMNew = buttonVolMore.read();
        bVLNew = buttonVolLess.read();
        if(bVMNew && !bVMOld) {
            volume++;
            if(volume>3) volume=3;
            ledBuzzer = 1;
            /*
            out.clear();
            out.printf("New volume: %d\r\n", volume);
            out.sleep(2);
            */
        }
        if(bVLNew && !bVLOld) {
            if(volume>0) volume--;
            if(!volume) ledBuzzer = 0;
            /*
            out.clear();
            out.printf("New volume: %d\r\n", volume);
            out.sleep(2);
            */
        }
        bVMOld = bVMNew;
        bVLOld = bVLNew;

        // Output
        unsigned long current_time = tmr.read_ms();
        
        if (current_time - last_shown > CYCLE_MS)
        {
            players.showAll(myTeam, level, volume);
            last_shown = current_time;
        }
        
    }
}