Dependencies:   MQTT

Road.cpp

Committer:
micallef25
Date:
2019-12-11
Revision:
6:6cb13ac483e0
Parent:
5:e0d8e5e922f1
Child:
7:fd8e0604faaa

File content as of revision 6:6cb13ac483e0:

#include "Road.h"
#include "mbed.h"

#define ROADLENGTH 100
#define ROAD_TAG "[ROAD] "
//#define ROAD_DEBUG 

Serial road_pc (USBTX, USBRX);

Road::Road(int id, mqtt* mqtt_singleton) 
{    
    this->road_id = id;
    this->singleton = mqtt_singleton;
    this->active_cars = 0;
    this->active_car_bits = 0x00;
    this->road_clock = 0;
    this->msg = new road_msg;
    // clear out our pointer table
    for (int i = 0; i < MAX_CARS_ON_ROAD; ++i)
    {
        this->car_table[i] = NULL;
    }
}
 
void Road::add_acc_car(AccCar* car) {
    
    // make sure all is well on the road
    assert( active_cars < MAX_CARS_ON_ROAD );
    
    car_table[active_cars] = car; 
       
    // no need to lock as main thread is only callee
    active_car_bits = active_car_bits | car->flag;
    active_cars++;
}
 
void Road::let_cars_update() {
    go_flags.set(active_car_bits);
    road_clock++;
}
 
void Road::wait_for_car_update() {
    done_flags.wait_all(active_car_bits);
}

bool Road::can_car_enter(int speed)
{
    // if no cars on the road enter
    if(active_cars == 0)
        return true;
    
    // else make sure you have not exceed the max amount of cars and make sure you can safely enter
    // safely being that you maintain your safety gap with your speed
    AccCar* caboose = car_table[active_cars-1];
    assert( caboose != NULL);    
    if(active_cars < MAX_CARS_ON_ROAD && speed <= caboose->position - 2 ) // 2 is safety gap
    {
        return true;    
    }
    return false;
}

// whats the id of next car
// used to set bit flags really
int Road::get_new_car_id()
{
    return active_cars;   
}

// how many active cars are there
int Road::get_active_cars()
{
    return active_cars;   
}

// get a car pointer based off some id
AccCar* Road::get_car(int id)
{
    assert(id < MAX_CARS_ON_ROAD);
    return car_table[id];    
}

// 0 is the lead car 
// 1 is the second car and so on
AccCar* Road::get_forward_car(int id)
{
    // make sure we don't go out of bounds
    assert( id >= 0 && id <= MAX_CARS_ON_ROAD );
    if( id > 0 )
        return car_table[id-1];
    else
        return NULL;  // return null means there is no forward car 
}  

// manages any clean up
void Road::DESTROY_ALL_CARS()
{
    for( int i = 0; i < active_cars; i++)
    {
        AccCar* car = car_table[i];
        car->stop();
        delete car;
    }   
}

// dumb function to end simulation only returns true when we have 
// 5 cars and the last car is passed 100 or road length
bool Road::simulating()
{
    if(active_cars != MAX_CARS_ON_ROAD )
        return true;
    
    else
    {
        AccCar* car = car_table[active_cars-1];
        assert( car != NULL );
        if(car->position > ROADLENGTH) // TODO use macro 
            return false; 
    }
    return true;
}

// typical getter functions
int Road::get_road_id()
{
    return road_id;   
}

int Road::get_road_clock()
{
    return road_clock;
}

AccCar* Road::get_last_car()
{
    return car_table[active_cars-1];    
}

bool Road::synchronize(bool simulating)
{
#ifdef ROAD_DEBUG
            road_pc.printf(ROAD_TAG "synchronizing  cycle %d complete=%d ..."DELIM, road_clock,simulating);
#endif 

        this->msg->road_id = road_id;
        this->msg->simulating = simulating;
        this->msg->road_clock = road_clock;
        this->singleton->add_to_road_to_network_queue(this->msg);     
    
        //
        road_msg_t* rmsg = this->singleton->get_network_to_road_msg();
        bool rc = rmsg->simulating;
        assert(rmsg->road_clock == road_clock);
        
#ifdef ROAD_DEBUG
            road_pc.printf(ROAD_TAG "clock %d id %d sync complete rc=%d"DELIM,rmsg->road_clock,rmsg->road_id,rmsg->simulating);
#endif 
    delete rmsg;
    return rc;
}