Alejandro Ungria Hirte / GA-Test

Dependencies:   mbed-dev

main_minimal.cpp

Committer:
aungriah
Date:
2017-12-06
Revision:
0:3333b6066adf

File content as of revision 0:3333b6066adf:

#include "mbed.h"


#include "SMConfig.h"
#include "DecaWave.h"                  // DW1000 functions      
//#include "LMMN2WR.h"                   // 2-Way-Ranging
#include "PC.h"                        // Serial Port via USB for debugging with Terminal
#include "Watchdog.h"                  // Resets Program if it gets stuck
#include "nodes.h"

// Function Prototypes
void dwCallbackTx(const dwt_cb_data_t *rxd);
void dwCallbackRx(const dwt_cb_data_t *rxd);
int min (int a, int b);
void configureDW1000(uint8_t dwMode);
void rangeAndDisplayOne(uint8_t addr);
void rangeAndDisplayAll();
void executeOrder(char* command);


// PA_7 MOSI, PA_6 MISO, PA_5 SCLK, PB_6 CS, PB_9 IRQ
SPI         decaWaveSpi(PA_7, PA_6, PA_5);      // Instance of SPI connection to DW1000
DigitalOut  decaWaveCs(PB_6);
InterruptIn decaWaveIrq(PB_9);
DecaWave    decaWave = DecaWave();              // Instance of the DW1000
BusIn       addressInput(PA_10, PB_3, PB_5, PB_4);   // Bit 0-3 of Switches to set the adress.
PC          pc(USBTX, USBRX, 921600);           // USB UART Terminal
DigitalIn   anchorInput(PB_10);                 // Bit 4 of Switches to set the Anchor.
BusIn       modeInput(PA_8, PA_9, PC_7);        // Bit 5-7 Bits of Switches to set the mode.
Watchdog    wdt = Watchdog();
BeaconNode  beaconNode(decaWave);
AnchorNode  anchorNode(decaWave);
BaseStationNode  baseStationNode(decaWave);
Node        *node;


int main() {
  
  decaWaveSpi.frequency(20000000); // Crank up the SPI frequency from 1Mhz to 3Mhz (maybe more?)
  
  // Check if Reset was from Watchdog or externally
  if(RCC->CSR&0x20000000)
    pc.printf("\r\n\r\n --- !!!!WATCHDOG RESET!!!! --- \r\n\r\n", RCC->CSR); 
  else if(RCC->CSR&0x4000000)
    pc.printf("\r\n\r\n --- External Reset --- \r\n\r\n", RCC->CSR);    
    __HAL_RCC_CLEAR_RESET_FLAGS();

  // Set all Switches Pull-Down so that it is zero if Switch is not set   
  addressInput.mode(PullDown);        
  anchorInput.mode(PullDown);
  modeInput.mode(PullDown);
  wait_ms(50);
  
    baseStationNode.setAddress(addressInput & addressInput.mask());  
    anchorNode.setAddress(addressInput & addressInput.mask());  
    beaconNode.setAddress(addressInput & addressInput.mask());  
   uint8_t roomadress = modeInput & modeInput.mask());
    if((addressInput & addressInput.mask()) == BASE_STATION_ADDR){
        node = &baseStationNode; 
        pc.printf("This node is the Base Station, Adress: %d \r\n \r\n \r\n", node->getAddress());                 
    }
    else if(anchorInput){
        node = &anchorNode;  
        pc.printf("This node is an Anchor node, Adress: %d \r\n \r\n \r\n", node->getAddress()); 
        pc.printf("The room id of the anchor is %d", roomadress);
        wdt.kick(2);            // Set up WatchDog         
    }     
    else{
        node = &beaconNode; 
        pc.printf("This node is a Beacon, Adress: %d \r\n \r\n \r\n", node->getAddress());
        wdt.kick(2);            // Set up WatchDog   
    }

    //pc.printf(" Adress: %d \r\n \r\n \r\n", node->getAddress());
       
    configureDW1000(7); 
 
    // TODO turn on RXMode regularly (every couple seconds)
    
    while(1) {
        
        // Choose between what to execte based on whether this device is a:
        // BEACON
        // BASESTATION
        // ANCHOR
        if (!node->isAnchor() && !node->isBaseStation()){
            
            // THE BEACON EXECUTES THIS
            if(beaconNode.getRepetitions() > 0){
                switch(beaconNode.getMode()){
                    case RANGE_ALL: rangeAndDisplayAll(); 
                                    break;
                    case RANGE_ONE: rangeAndDisplayOne(beaconNode.getDestination());
                                    break;
                    default:        break;
                }
                beaconNode.decreaseRepetitions();
            }
            else{
                beaconNode.clearRec();
                wait_ms(8);
            }
            wdt.kick(); 
        } 
        else if (node->isBaseStation()){
             
            pc.printf("Debug Point 1\r\n");
    
             // EXECUTE THIS IF A BASE STATION
             pc.readcommand(executeOrder);
        }
        else { // All Anchor Action is in the Interrupt functions!
            // EXECUTE THIS IF AN ANCHOR
            wait_ms(10);
            wdt.kick(); 
        }
    }  
}


void executeOrder(char* command){

    int repetitions = command[3]*100 + command[4]*10 + command[5] - 5328;
    uint8_t dest1 = command[7] - 48;
    uint8_t dest2 = command[8] - 48;
    uint8_t dest3 = command[9] - 48;
    
    pc.printf("Debug Point 2 to destination 1: %d, repetitions: %d \r\n", dest1, repetitions);
    
    if (strncmp(command, "all", 3) == 0){
        baseStationNode.sendOrder(0, NOT_USED, RANGE_ALL, repetitions, Node::BASE_ORDER); 
       // pc.printf("Mode: Range all \r\n");
    }
    else if (strncmp(command, "one", 3) == 0){
        
        pc.printf("Debug Point 3\r\n");
        
        if(dest1 < 15)
        {
            pc.printf("Debug Point 6\r\n");
            baseStationNode.sendOrder(0, dest1, RANGE_ONE, repetitions, Node::BASE_ORDER); 
        }
        else
        {
            baseStationNode.sendOrder(0, 1, RANGE_ONE, repetitions, Node::BASE_ORDER); 
        }
    }
    
    else if (strncmp(command, "bea", 3) == 0){
        if(dest1 < 15)        
            baseStationNode.sendOrder(dest1, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
        else
            baseStationNode.sendOrder(0, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
         
    }
    
    else if (strncmp(command, "anc", 3) == 0){
        if(dest1 < 15)   
            baseStationNode.sendOrder(dest1, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE); 
        else
            baseStationNode.sendOrder(0, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE); 
    }
    
    else if (strncmp(command, "tri", 3) == 0){
        // Switch them in correct modes (should already be the case)
        baseStationNode.sendOrder(dest1, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
        baseStationNode.sendOrder(dest2, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);  
        baseStationNode.sendOrder(dest3, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);  
        
        // Ranging from first node
        baseStationNode.sendOrder(dest1, dest2, RANGE_ONE, repetitions, Node::BASE_ORDER); 
        wait_ms(10*repetitions);
        baseStationNode.sendOrder(dest1, dest3, RANGE_ONE, repetitions, Node::BASE_ORDER); 
        wait_ms(10*repetitions);
        
        // Mode Switches
        baseStationNode.sendOrder(dest2, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);  
        baseStationNode.sendOrder(dest1, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
        
        // Rangings
        baseStationNode.sendOrder(dest2, dest1, RANGE_ONE, repetitions, Node::BASE_ORDER); 
        wait_ms(10*repetitions);        
        baseStationNode.sendOrder(dest2, dest3, RANGE_ONE, repetitions, Node::BASE_ORDER); 
        wait_ms(10*repetitions);
        
        // Mode Switches
        baseStationNode.sendOrder(dest3, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);  
        baseStationNode.sendOrder(dest2, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
        
        // Rangings
        baseStationNode.sendOrder(dest3, dest1, RANGE_ONE, repetitions, Node::BASE_ORDER); 
        wait_ms(10*repetitions);        
        baseStationNode.sendOrder(dest3, dest2, RANGE_ONE, repetitions, Node::BASE_ORDER); 
        wait_ms(10*repetitions);        
        
        // Back to original modes
        baseStationNode.sendOrder(dest1, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
        baseStationNode.sendOrder(dest2, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);  
        baseStationNode.sendOrder(dest3, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
        
    } 
}

#pragma Otime // Compiler optimize Runtime at the cost of image size
// Called after Frame was received
void dwCallbackRx(const dwt_cb_data_t *rxd) {
  int64_t rxTimeStamp = 0;  
  dwt_readrxdata(node->getRecFrameRef(), min(node->getRecFrameLength(), rxd->datalength), 0);  // Read Data Frame from Registers 

  dwt_readrxtimestamp((uint8_t*) &rxTimeStamp);  // Read Timestamp when the frame was received exactly
  rxTimeStamp &= MASK_40BIT; //Mask the 40 Bits of the timestamp
  
  node->callbackRX(rxTimeStamp); // Two Way Ranging Function
}


#pragma Otime // Compiler optimize Runtime at the cost of image size
// Called after Frame was transmitted
void dwCallbackTx(const dwt_cb_data_t *txd) {
  int64_t txTimeStamp = 0;
  dwt_readtxtimestamp((uint8_t*) &txTimeStamp);  // Read Timestamp when the frame was transmitted exactly
  txTimeStamp &= MASK_40BIT; // Delete the most significant 8 Bits because the timestamp has only 40 Bits

  node->callbackTX(txTimeStamp); // Two Way Ranging Function
}


int min (int a, int b){
    if(a<=b) return a;
    return b;
}

void configureDW1000(uint8_t dwMode){
  dwt_config_t dwConfig;
  dwt_txconfig_t dwConfigTx;
    
  SMsetconfig(dwMode, &dwConfig, &dwConfigTx);

  decaWave.setup(dwConfig, dwConfigTx, rfDelays[dwConfig.prf - DWT_PRF_16M], dwCallbackTx, dwCallbackRx);

  pc.printf("%s\r\n", DW1000_DEVICE_DRIVER_VER_STRING);
  {
    uint16_t tempvbat = dwt_readtempvbat(1);
    if (tempvbat>0) {
      float tempC = 1.13f * (float) (tempvbat >> 8) - 113.0f;
      float vbatV = 0.0057f * (float) (tempvbat & 0xFF) + 2.3f;

      pc.printf("  Voltage: %f, Temperature: %f\r\n", vbatV, tempC);
    } else {
      pc.printf("ERROR: Cannot read voltage/temperature\r\n");
    }
  }
  pc.printf("  Device Lot ID %lu, Part ID %lu\r\n", dwt_getlotid(), dwt_getpartid());

  uint16_t DWID = (dwt_getpartid() & 0xFFFF);

  pc.printf(
      "  Settings %i: \r\n    Channel %u (%1.3f GHz w/ %1.3f GHz BW), Datarate %s, \r\n    PRF %s, Preamble Code %u, PreambleLength %u symbols, \r\n    PAC Size %u, %s SFD, SDF timeout %ul symbols\r\n",
      dwMode, dwConfig.chan, ChannelFrequency[dwConfig.chan],
    ChannelBandwidth[dwConfig.chan], ChannelBitrate[dwConfig.dataRate], ChannelPRF[dwConfig.prf],
      dwConfig.txCode, ChannelPLEN(dwConfig.txPreambLength), ChannelPAC[dwConfig.rxPAC],
      dwConfig.nsSFD==0?"standard":"non-standard", dwConfig.sfdTO);
  pc.printf("    Power: NORM %2.1f dB, BOOST: 0.125ms %2.1f dB, 0.25ms %2.1f dB, 0.5ms %2.1f dB\r\n",
    SMgain(dwConfigTx.power& 0xFF), SMgain((dwConfigTx.power>>24)& 0xFF), SMgain((dwConfigTx.power>>16)& 0xFF),
    SMgain((dwConfigTx.power>>8)& 0xFF));
  pc.printf("  Frame length: %d us\r\n", decaWave.computeFrameLength_us());
  pc.printf("  Antenna Delay set to: %d \r\n", decaWave.getAntennaDelay());

  decaWave.turnonrx();   // start listening       
}

void rangeAndDisplayOne(uint8_t addr){
    beaconNode.requestRanging(addr); 
    pc.printf("%f(%f) \r\n", beaconNode.getDistance(addr), beaconNode.getSignalStrength(addr));
}



void rangeAndDisplayAll(){
    beaconNode.requestRangingAll(); 
    for(int i = 0; i < ADRESSES_COUNT; i++){
        /*if(beaconNode.getDistance(i) > -10){
            pc.printf("#%d %f(%f), ", i, beaconNode.getDistance(i), beaconNode.getSignalStrength(i));
        }*/
    }
    pc.printf("\r\n");
}