FaradayRF / Faraday-Firmware

Faraday node firmware
Other
25 stars 10 forks source link

Decouple RF Packet Functions - Avoid Imports #74

Open kb1lqd opened 7 years ago

kb1lqd commented 7 years ago

Decouple the layer stacks by using function pointers that allow interactions between the stacks by pointing to a function rather than full import of the header. This will follow the higher levels of RF and UART stack interactions with applications themselves while allowing easier debugging.

This is a push to both clean, optimize, and potentially fix bugs such as corrupted telemetry data possibly getting sent to proxy.

Correct Method Example - Command Application

The command application "opens" a port from the RF receive stack which just places a function pointer to the command application PUT() function using a standardized FIFO interface. The pointer is stored in an array where the index is the "port".

To assign the command application through a function pointer the initialization in main{} is performed:

//Open RX RF service ports (Transport Layer)
rf_rx_service_open(2, app_command_rf_rx_put, 0); // RF Command Link, not safe for broadcast reception

When a data packet at the transport layer level is received the RF network stack uses the assigned port to call the correct standardized PUT() function in the Command application:

void rf_rx_stack_rx(unsigned char service_number, unsigned char *data, unsigned char payload_len){
    //Recieved a new uart packet from external device
    //ALL APPLICATIONS MUST BUFFER AS FULL UART HIGH LEVEL FRAME
    if((service_number <RF_SERVICE_ELEMENT_COUNT) && (srvc_open_func_ptrs[service_number] != 0)){
            (*srvc_open_func_ptrs[service_number]) (data, service_number);
        }
    else{
        __no_operation(); //Bad service port or registration, not a valid pointer in array.
    }
}

Command Application interacts with RF receive through this PUT() function the is used through a function pointer.

void app_command_rf_rx_put(unsigned char *packet){
//Put into the same local command queue
put_fifo_sram(&app_command_rx_fifo_state_machine, packet);
}

It is important to realize that:

Incorrect Implementation

Note below that the includes for "rf_transport.h" (layer 4) directly imported "rf.h" (layer 2) and this is unwanted and causing both headers to be coupled. This breaks the modular desirement and creates blurred interfaces between layers.

/* -- Includes -- */

/* standard includes */
#include "cc430f6137.h"
#include "rf_transport.h"

/* faraday rf layer 2 include */
#include "rf.h"

/* faraday rf layer 4 service include */
#include "rf_service.h"

/* faraday fifo include */
#include "../Ring_Buffers/FIFO.h"

/* faraday hardware allocation include */
#include "../REVA_Faraday.h"

/* faraday gpio hardware abstraction functions */
#include "../HAL/GPIO.h"

RF Layer 2 (rf.c)

Calls To Layer 4 (rf_transport.h)

Lines

These references are in rf_housekeeping() and simply checking the transport FIFO for new data from Layer 4 to Layer 2.

void rf_housekeeping(void){
    __no_operation();
    unsigned char status;
    if(rf_check_tx_fifo() && !transmitting_flag){
        ReceiveOff();
        rf_get_next_tx_fifo();
        }
    else if(rf_datalink_rx_fifo_state_machine.inwaiting>0){
        //Get packet from queue
        status = get_fifo(&rf_datalink_rx_fifo_state_machine, &rf_datalink_rx_fifo_buffer, rf_rx_datalink_buffer);

        //Parse received packet
        rf_datalink_parse(&rf_rx_datalink_buffer);

        //Determine destination of RX'd packet
        if(strstr((char *)rf_datalink_packet_rx_struct.destination_callsign, (char *)local_callsign) != NULL){
            if(rf_datalink_packet_rx_struct.destination_identifier == local_device_id){
                //__no_operation(); //This device!
                rf_transport_parse((unsigned char *)rf_datalink_packet_rx_struct.payload, 0);
            }
        }

        else if(*strstr((char *)rf_datalink_packet_rx_struct.destination_callsign, (char *)"CQCQCQ")){
            //__no_operation(); //Broadcast
                rf_transport_parse((unsigned char *)rf_datalink_packet_rx_struct.payload, 1);
        }

        else{
            //__no_operation(); //All others
        }
    }
    else{
    }
}

Layer 4 (rf_transport.c)

rf_transport.c includes both layer 2 and rf service headers:

/* faraday rf layer 2 include */
#include "rf.h"

/* faraday rf layer 4 service include */
#include "rf_service.h"

rf.h

Line

rf_service.h

Line

Layer 4 Services (rf_services.h)

This layer doesn't seem to have any of its own import issues but it is also a weird header to have.

kb1lqd commented 7 years ago

I'm going to start with Layer 4 <-> Layer 4 service first.

Line

rf_rx_service_broadcast_rule_get()

Broadcast rule is a method for Faraday to determine if the packet should be accepted if it is not addressed to the specific Faraday (i.e. broadcasted). Unit specific data is determined at layer 2 (datalink) and therefore needs to be filtered to avoid commands from affecting ALL units in an area but allow all units to receive broadcasted telemetry.

Broadcast function argument is determined if the destination callsign is CQCQCQ.

For some reason I keep rf_rx_service_broadcast_rule_get() in services and this is an array where the indexes are the "ports" and if the value is 1 then that port is allowed to accept "broadcasted" data.

This really should be done completely in layer 2.