Andriy Makukha / Mbed 2 deprecated football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

TA.cpp

Committer:
elmbed
Date:
2015-11-29
Revision:
18:affef3a7db2a
Parent:
17:d8b901d791fd
Child:
23:26f27c462976

File content as of revision 18:affef3a7db2a:

#include "TA.h"

#include <nrf51.h>
#include <mbed.h>
#include <device.h>
#include <vector> 

/* !SR
 * Can't find any boards which use the nrf51822 and have analog output enabled. Currently
 * all analog stuff has been commented out.
 */
 
 #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need //////////////////////DEBUG messages on the console;
                               * it will have an impact on code-size and power consumption. */

#define LOOPBACK_MODE       0  // Loopback mode

#if NEED_CONSOLE_OUTPUT
#define DEBUG(...) { printf(__VA_ARGS__); }
#else
#define DEBUG(...) /* nothing */
#endif /* #if NEED_CONSOLE_OUTPUT */
 

extern unsigned long millis();
extern unsigned long micros();
extern int random(int numberone, int numbertwo);

ByteBuffer TA::send_buffer;
ByteBuffer TA::receive_buffer;

uint8_t TA::node_id;//        1  //network ID used for this unit
uint8_t TA::network_id;//    99  //network ID used for this network
uint8_t TA::gateway_id;//     1  //the ID of the network controller
uint8_t TA::ack_time;//      50  // # of ms to wait for an ack

//encryption is OPTIONAL
//to enable encryption you will need to:
// - provide a 16-byte encryption KEY (same on all nodes that talk encrypted)
// - to call .Encrypt(KEY) to start encrypting
// - to stop encrypting call .Encrypt(NULL)
uint8_t TA::KEY[] = "ABCDABCDABCDABCD";
uint16_t TA::interPacketDelay;// = 1000; //wait this many ms between sending packets

// Need an instance of the Radio Module
//byte TA::sendSize;//=0;
//char TA::payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//bool TA::requestACK;//=true;

//neopixels_spi TA::neopixels;


unsigned long millis();

unsigned long micros();


/** Macro for min() 
 *
 * @param any
 */
#define min(a,b)                  ((a)<(b)?(a):(b))
/** Macro for max()
 *
 * @param any
 */
#define max(a,b)                  ((a)>(b)?(a):(b))

/** generates a random number between two numbers
 *
 * @param numberone minimum value for random number
 * @param numbertwo maximum value for random number
 */
int random(int numberone, int numbertwo) {
    int random = 0;
    if ((numberone < 0) && (numbertwo < 0)) {
        numberone = numberone * -1;
        numbertwo = numbertwo * -1;
        random = -1 * (rand()%(numberone + numbertwo));
    }
    if ((numbertwo < 0) && (numberone >= 0)) {
        numbertwo = numbertwo * -1;
        random = (rand()%(numberone + numbertwo)) - numbertwo;
    }
    if ((numberone < 0) && (numbertwo >= 0)) {
        numberone = numberone * -1;
        random = (rand()%(numberone + numbertwo)) - numberone;
    } else {
        random = (rand()%(numberone + numbertwo)) - min(numberone, numbertwo);
    }
    return random;
}

// ########## End code taken from audrino library ##########

uint8_t TA::mask;

// outputs
//uint8_t TA::buzzPin;
uint8_t TA::red;
uint8_t TA::green;
uint8_t TA::blue;

neopixel_strip_t m_strip;

uint8_t dig_pin_num =  16;
uint8_t leds_per_strip = 18;
uint8_t led_to_enable = 1;

#if 0
DigitalOut TA::enable_1(p4);
DigitalOut TA::enable_2(p7);
DigitalOut TA::enable_3(p8);


DigitalOut TA::cap_enable(A3);
#endif
DigitalOut TA::buzzPin(p20);

#if 0
// inputs
DigitalIn TA::touch_1(A0);
DigitalIn TA::touch_2(A1);
DigitalIn TA::touch_3(A2);
#endif

std::vector<Message*> *messages;

//NeoStrip *neo;

TA::TA()
{
    buzzPin = 1;
    neopixel_init(&m_strip, dig_pin_num, leds_per_strip);
    neopixel_clear(&m_strip);
    messages = new std::vector<Message*>();
    
}

void TA::post_color(uint32_t rgb)
{
    if (rgb == 0)
    {
          neopixel_clear(&m_strip);  
          return;
    }
    
    for (int i = 0; i <= leds_per_strip; ++i)
    {
        neopixel_set_color_and_show(&m_strip, i, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
        //neo->setPixel(i, rgb);
    } 
    
    buzzPin = 1;
}

void TA::mask_color(uint32_t rgb)
{
   // enable_1 = 0;
   // enable_2 = 0;
   // enable_3 = 0;
  //neopixels.setRGBStrip1((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
  
  //enable_1 = (mask & 0x01)?1:0;
  //enable_2 = (mask & 0x02)?1:0;
  //enable_3 = (mask & 0x04)?1:0;
  
  for (int i = 0; i <= leds_per_strip; ++i)
    {
 //       neopixel_set_color_and_show(&m_strip, i, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
    } 
}

void TA::beep(uint16_t ms)
{
    beeping = true;
    beep_start = millis();
    beep_duration = ms;
}

void TA::beep_off(void)
{
    beeping = false;   
}

void TA::powerup(uint8_t sound)
{
    powerup_start = millis();
    beeping = false;
    pulsing = false;
    powering_up1 = false;
    powering_up2 = false;

    if(sound == 1)
    {
        powering_up1 = true;
        powerup_toggle = 300;
    }
    
    if(sound == 2)
    {
        powering_up2 = true;
        powerup_toggle = 20;
    }
}

void TA::pulse(uint16_t on_time, uint16_t period, uint16_t ms, uint32_t rgb)
{
    current_color = rgb;
    pulsing = true;
    pulse_start = millis();
    pulse_period = period;
    pulse_on = on_time;
    pulse_duration = ms;   
}

void TA::pulse_off(void)
{
    pulsing = false;
}

int TA::get_buffer_size(void)
{
    return send_buffer.getSize();    
}

bool TA::send(Message *m)
{
    send_immediate(m); 
    return true;   
}

void TA::send_immediate(Message *m)
{
    Message *tmp = new Message;
    DEBUG("in send_imediate: %d '%c'\n", m->cone, m->command);
    
    tmp->command = m->command;
    tmp->cone    = m->cone;
    
    // Fake version of the function, push this onto the reply queue
    if (messages->size() < 50)
    {
        messages->push_back(tmp);
    }
    else
    {
        DEBUG("TA message queue too full!\n");    
    }
}

bool TA::sendRaw(uint8_t *message, uint8_t len, uint8_t cone)
{

    return true;    
}

bool TA::recieve(Message *m)
{
   bool processed = true;
top:
    processed = true;

   //DEBUG("receiving\n");
   if (messages->size() > 0)
   {
       Message *lm = messages->front();
       
       DEBUG("got messaage with command: '%c'\n", lm->command);
       
       // Now populate the outgoing message based on the incoming
       if (lm->command == 'z')
       {
            m->cone = lm->cone;   
        } 
        else
        {
            DEBUG("Unknown command: '%c'\r\n", lm->command);   
            processed = false; 
        }
        
        messages->erase(messages->begin());
        
        if (lm)
        {
           delete lm;    
        }
        
        if (!processed)
        {
            // Clear out the queue if we don't know what
            // to do with the message
            goto top;    
        }
   }
   else
   {
        processed = false;
    }
    
    return processed;   
}

bool TA::waitForAck(int cone) 
{
   
    return true;
}

void TA::spin(void)
{
    #if 0
    static byte payload [6];
    static bool message_in_queue = false;
    static bool waiting_for_ack = false;
    static byte dest_cone = 0;
    static uint16_t index = 0;
    static uint16_t ack_tries = 0;
    static uint8_t send_tries = 0;
    static unsigned long ack_start = 0;
    static unsigned long random_wait = 0;
    static unsigned long random_wait_start = 0;
    static unsigned long mem_monitor_start = 0;

    // if(millis() - mem_monitor_start > 2000){
    //   mem_monitor_start = millis();
    //   Ram_TableDisplay();
    // }

#if 0
    if(tripped())
    {//buttons() && millis() - activated_start > 1000){
        cap_enable = 1;
        wait_ms(100);
        cap_enable = 0;
        //activated_start = millis();
        //Serial.println(F("toggled cap sense power"));
    }
#endif    
    if(powering_up2)
    {
        unsigned long t = millis() - powerup_start;
        
        if(t > powerup_toggle)
        {
            buzzPin = !buzzPin;
            powerup_toggle *= 1.2;
        }
        
        if(t > 1250)
        {
            buzzPin = 0;
            powering_up2 = false;
        }
    }
    else if(powering_up1)
    {
        unsigned long t = millis() - powerup_start;
        
        if(t > powerup_toggle)
        {
            buzzPin = !buzzPin;
            powerup_toggle *= 0.95;
            powerup_start = millis();
        }
    
        if(powerup_toggle < 10)
        {
            buzzPin = 0;
            powering_up1 = false;
        }
    }
    else
    {
        if(beeping && (millis()-beep_start > beep_duration)) 
            beeping = false;
        if(pulsing && (millis()-pulse_start > pulse_duration)) 
            pulsing = false;
        if(beeping)
            buzzPin = 1;
        else if( pulsing && (((millis()-pulse_start) % pulse_period) < pulse_on))
        {
            if(!(mask & SILENT))
                buzzPin = 1;
            mask_color(0);
        }
        else
        {
            if(pulsing)
                mask_color(current_color);
            buzzPin = 0;
        }
    }
/*
    if(!waiting_for_ack && radio.ReceiveComplete())
    {
        if(radio.CRCPass())
        {
            receive_buffer.put(radio.GetSender());
            for(byte i = 0; i < *radio.DataLen; i++)
                receive_buffer.put(radio.Data[i]);
        }
       
        if(radio.ACKRequested())
        {
            wait_us(1300);
            radio.SendACK();
            //Serial.println(F("Sent ACK"));
        }
    }
    */

    //if(index > 4999 || waiting_for_ack){
    if(waiting_for_ack)
    {
        //Serial.println(F("Waiting for ack"));
        bool success = radio.ACKReceived(dest_cone);
        
        if(success || send_tries > 15)
        {
            //Serial.print(F("dequeued: "));
            //Serial.println((uint16_t)payload[1]<<8 + payload[2]);
            message_in_queue = false;
            waiting_for_ack = false;
            unsigned long t = micros() - ack_start;
            //Serial.print(F("Received ACK, microseconds: "));
            //Serial.println(t);
            //ack_tries = 0;
          
            message_in_queue = false;
            send_tries = 0;
                
            /*Serial.print(F("Sent "));
            Serial.print((char)payload[0]);
            Serial.print(F(", to cone "));
            Serial.println(dest_cone);*/
        }
        else
        {
            if(micros() - ack_start > 10000)
            {
                //Serial.println(F("no ACK"));
                waiting_for_ack = false;
                random_wait_start = micros();
                random_wait = random(1500,3000);
                /*if(send_tries > 15){
                Serial.print(F("Failed to deliver message to cone "));
                Serial.println(dest_cone);
                message_in_queue = false;
                send_tries = 0;
                }*/
                if(send_tries > 4) 
                    random_wait = random(3000,9000);
                //Serial.print(F("Failed to deliver message, waiting "));
                //Serial.println(random_wait);
                //ack_tries = 0;
    
                /*if(send_tries%50 == 0){
                Serial.print(send_tries);
                Serial.println(F(" tries"));
                }*/
            }
        }
        // ack_tries++;
    }
    else if(message_in_queue && micros() - random_wait > random_wait_start)
    {// && index%64 == 0){
        requestACK = true;
        //Serial.println(F("sending"));
        radio.Send(dest_cone, payload, 6, requestACK);
        //Serial.println(F("sent"));
        //Serial.print(F("Trying to send: "));
        //uint16_t temp = (uint16_t)payload[1]<<8;
        //temp += (uint8_t)payload[2];
        //Serial.println((uint8_t)payload[0]);
        send_tries++;
        ack_start = micros();
        
        if(!radio.ACKReceived(dest_cone)) 
            waiting_for_ack = true; // the 'if' is here to prevent the radio from going to sleep and missing the ACK
        else 
            message_in_queue = false;
    }
    else 
    {
    /*if(send_buffer.getSize() > 0 && message_in_queue == false){
      payload[0] = send_buffer.get();
      //Serial.print(F("Got from queue: "));
      //Serial.println((char)payload[0]);
      message_in_queue = true;
    }*/
    while(send_buffer.getSize() > 4 && message_in_queue == false)
    {
      payload[0] = send_buffer.get();
      payload[1] = send_buffer.get();
      payload[2] = send_buffer.get();
      payload[3] = send_buffer.get();
      payload[4] = send_buffer.get();
      dest_cone = send_buffer.get();
      payload[5] = send_buffer.get();
      /*Serial.println(F(""));
      Serial.println(F("sending..."));
      Serial.println(payload[0], BIN);
      Serial.println(payload[1], BIN);
      Serial.println(payload[2], BIN);
      Serial.println(payload[3], BIN);
      Serial.println(payload[4], BIN);
      Serial.println(dest_cone, BIN);      
      Serial.println(payload[5], BIN);
      Serial.println(F(""));*/
      if((char)payload[5] == '%')
        message_in_queue = true;
      else 
      {
        while(send_buffer.getSize() > 0 && send_buffer.get() != '%'); // if we didn't land on the end of a message, peel stuff off until we are
      }
    }
  }
  
  #endif
}

bool TA::activated(void)
{
    return true;   
}

bool TA::tripped(void)
{
    return false;
}

uint8_t TA::buttons(void)
{
    uint8_t buttons = 0;

    return buttons;  
}

void TA::setMask(uint8_t the_mask)
{
    mask = the_mask;
}

void TA::initialize(uint8_t address)
{
}

/* Can't find a way of implementing this function.
 *
 * !SR
 */
void TA::Ram_TableDisplay(void)
{
    
}

/* Not sure if this work. Taken from: https://developer.mbed.org/questions/6994/How-to-print-Free-RAM-available-RAM-or-u/
 *
 * !SR
 */
void TA::get_free_memory(void)
{
    char   stackVariable;
    char   *heap;
    unsigned long result;
    heap  = (char*)malloc(4);
    result  = &stackVariable - heap;
    free(heap);
    
    //serial->printf("Free memory: %ul\n\n",result);
}

void TA::check_mem(void)
{
    uint8_t * heapptr, * stackptr;
    unsigned int stack, heap = 0;

    stackptr = (uint8_t *)malloc(4);          // use stackptr temporarily
    heapptr = stackptr;                     // save value of heap pointer
    free(stackptr);      // free up the memory again (sets stackptr to 0)
  
    stack = __current_sp() ;
    heap = (uint16_t)heapptr;
    uint16_t last_call = *(stackptr++);
    
    //serial->printf("Stack: 0x");
    //serial->printf("%x ",stack);
    //serial->printf("Heap: 0x");
    //serial->printf("%x\n",heap);
    //serial->printf("Last call: 0x");
   // serial->printf("%x\n",last_call);
    get_free_memory();
}