al w / ARQ-radio

arq.cpp

Committer:
quagga
Date:
2021-05-25
Revision:
0:8e06c9b8b7f6

File content as of revision 0:8e06c9b8b7f6:

#include"arq.h"

Arq::Arq(MicroBit* bit)
{
    uBit=bit;
    //uBit->serial.send("Arq::Arq(MicroBit *)\n");
    power=0;
    timeout=5000;
    maxtries=10;
    mintries=1;
    tries=0;
    rssi=255;
    min_rssi=70;
    uBit->radio.setTransmitPower(power);
}

void Arq::off()
{
    //uBit->serial.send("void Arq::off()\n");
    uBit->messageBus.ignore(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, this, &Arq::listen);
    uBit->radio.disable();
}

void Arq::listen(MicroBitEvent e)
{
    //uBit->serial.send("Arq::receive(MicroBitEvent)\n");
    //message received
    rssi=uBit->radio.getRSSI();
    PacketBuffer s=uBit->radio.datagram.recv();
    if (s[0]==0) //power_test
    {
        #ifdef ARQ_DEBUG
        int pow=(int)s[1];
        uBit->serial.printf("received POWER_TEST at %d\n",pow);
        #endif
        received_power=s[1];
        MicroBitEvent(ARQ_ID,ARQ_POW_RECVD_EVT);
    }
    else //message
    {
        //set packet to received packet buffer minus 1st byte
        packet = PacketBuffer(s.length()-1);
        for (int i=1;i<s.length();i++){packet[i-1]=s[i];}
        #ifdef ARQ_DEBUG
        //uBit->serial.send(packet); //send packet to serial
        #endif
        MicroBitEvent(ARQ_ID,ARQ_MSG_RECVD_EVT);
    }
    s=PacketBuffer(1); //send ACK
    s[0]=(char) rssi;
    s[0] |= 1UL << 7; // set bit 8 for ACK
    uBit->radio.datagram.send(s);
    #ifdef ARQ_DEBUG
    uBit->serial.printf("Sending ACK with %d rssi\n",rssi);
    #endif
}

void Arq::receive()
{
    uBit->messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, this, &Arq::listen);
    uBit->radio.setTransmitPower(7); //max power for ACK
    uBit->radio.enable();
}

void Arq::send(PacketBuffer packet)
{
    //uBit->serial.send("void Arq::send()\n");
    uBit->radio.enable();

    int t,dt;
    int count=0;
    bool ack=false;
    
    while (count<maxtries)
    {
        //clear dataReady queue
        while (uBit->radio.dataReady()>0){uBit->radio.recv();}
        uBit->radio.datagram.send(packet);
        dt=0;
        t=system_timer_current_time_us();
        while (dt<timeout)
        {
            dt=system_timer_current_time_us()-t;
            if (uBit->radio.dataReady()>0){ack=true;break;}
        }
        if (ack){break;}
        count++;
    }
    tries=count;
    if (ack)
    {
        //PacketBuffer s=uBit->radio.datagram.recv();
        FrameBuffer *s=uBit->radio.recv();
        //get rssi reported from receiver
        rssi=(int)((s->payload[0])^128);
        delete s;
        #ifdef ARQ_DEBUG
        uBit->serial.printf("%d rssi reported from ACK ",rssi);
        uBit->serial.printf("after - %d tries\n",tries);
        uBit->serial.printf("after - %d microseconds\n",dt);
        #endif
        if (packet[0]==0){MicroBitEvent(ARQ_ID,ARQ_POW_ACK_RECVD);}
        else {MicroBitEvent(ARQ_ID,ARQ_MSG_ACK_RECVD);}
    }

    else
    {
        #ifdef ARQ_DEBUG
        uBit->serial.printf("Send Failed!\n"); 
        #endif
        if (packet[0]==0){MicroBitEvent(ARQ_ID_POW_SEND_FAIL);}
        else {MicroBitEvent(ARQ_ID,ARQ_MSG_SEND_FAIL);}
    }
    
    //power check?
    if (packet[0]!=0) //make sure not power_test to avoid infinite loop
    {
        if (tries>(mintries-1)){this->incPower();} //if too many attempts power up
        else if (rssi<min_rssi){this->decPower();} //if rssi high reduce power
    }
    
    uBit->radio.disable();
}


void Arq::incPower()
{
    //uBit->serial.send("Arq::incPower()\n");
    //send message if ack not received up power
    uBit->radio.enable();
    while (power<7)
    {
        //send message
        PacketBuffer s(2);
        s[0]=0;
        s[1]=(char)power;
        this->send(s);
        if (tries<mintries){break;}
        power++;
        uBit->radio.setTransmitPower(power);
        #ifdef ARQ_DEBUG
        uBit->serial.printf("Power set to %d\n",power);
        #endif
    }
    uBit->radio.disable();
}

void Arq::decPower()
{
    //uBit->serial.send("Arq::decPower()\n");
    uBit->radio.enable();
    while (power>0)
    {
        //send message
        PacketBuffer s(2);
        s[0]=0;
        s[1]=(char) power;
        //try lower power
        power--;
        uBit->radio.setTransmitPower(power);
        this->send(s);
        if (tries>mintries)//failed at this power,increase power and break
        {
            if (power<7)
            {
                power++;
                uBit->radio.setTransmitPower(power);
                #ifdef ARQ_DEBUG
                uBit->serial.printf("Power set to %d\n",power);
                #endif
            }
            break;
        }
    }
    uBit->radio.disable();
}