ECE 4180 - Final Project Team / Mbed 2 deprecated WalkieTalkie

Dependencies:   mbed 4DGL-uLCD-SE mbed-rtos nRF24L01P

main.cpp

Committer:
Nurchu
Date:
2018-04-22
Revision:
27:08d34e60b6d0
Parent:
26:57731422b129
Child:
28:9413eb50156d
Child:
29:0c6f3c0c992a

File content as of revision 27:08d34e60b6d0:

#include "mbed.h"
#include "rtos.h"

#include "Microphone.h"
#include "Speaker.h"
#include "HUD.h"
#include "nRF24L01P.h"
#include "uLCD_4DGL.h"

#include "CircularBuf.h"
#include "CircularBuf.cpp" // Hack to get templates to work

// How many times larger the buffer should be
#define FIFO_BUFFER_SCALE  4
// How maybe bytes to send over RF
#define DATA_PACKET_SIZE   32
// How quickly to sample the mic / play the speaker
#define SAMPLE_PERIOD   0.1


Serial pc(USBTX, USBRX);
DigitalOut myled1(LED1); // Mic data sent over RF
DigitalOut myled2(LED2); // Speaker data recieved over RF
DigitalOut myled3(LED3); // Sampled mic / played the speaker
DigitalOut myled4(LED4); // Heartbeat

Speaker spkr(p18);
Microphone mic(p16);

uLCD_4DGL uLCD(p27, p28, p30);                      // serial tx, serial rx, reset pin;

nRF24L01P my_nrf24l01p(p5, p6, p7, p8, p9, p10);    // mosi, miso, sck, csn, ce, irq
CircularBuf<uint8_t> txbuff( FIFO_BUFFER_SCALE * DATA_PACKET_SIZE );
CircularBuf<uint8_t> rxbuff( FIFO_BUFFER_SCALE * DATA_PACKET_SIZE );
Ticker sampler; //10:41 am 4/20

InterruptIn button(p18); //changed DitialIn to InterruptIn at 5:54 4/18/18
BusIn channel(p21, p22, p23, p24); // TODO: CHANGE THESE TO THE ACTUAL PINS NEEDED

int rfFreq;
int dataRate;
unsigned long long rxAddr, txAddr;

enum operatingMode {
    RECEIVE = 0,
    TRANSMIT
};

operatingMode mode;

// Cheap nonbranching min function
int min(int a, int b) {
    return a * (int)(a <= b) + b * (int)(b < a);
}

// Sets the frequency of the RF device based on which swtiches are flipped
// TODO: Make sure we don't have to restart the device or anything to change this
void setRFFrequency() {
    int channelNum = channel.read();
    
    // TODO: Don't force it to the default RF frequency
    channelNum = 2;
    
    my_nrf24l01p.setRfFrequency(channelNum + NRF24L01P_MIN_RF_FREQUENCY);
}

// Callback interrupt from the button to shift into transmit mode
void enterTransmitMode() {
    mode = TRANSMIT;
}

// Callback interrupt from the button to shift into receive mode
void enterRecieveMode() {
    mode = RECEIVE;
}

// Called every SAMPLE_PERIOD ms to sample the mic or output data into the speaker
void sampleData()
{
    // Depending on the mode, only sample the mic or output data to the speaker
    if (mode == RECEIVE) {
        // Get speaker sample from buffer
        // If there is no data in the buffer, it will just output 0 to the write function
        uint8_t speakerSample = 0;
        rxbuff.pop(&speakerSample, 1);
        
        // Output into the actual speaker
        spkr.write(speakerSample);
    } else {
        // Get mic sample and place into buffer
        uint8_t micSample = mic.getData();
        txbuff.push(&micSample, 1);

        // Make sure the speaker is actually off
        spkr.turnOff();
    }
    
    // TODO: This will have to be removed later on once we actually crank up the sample rate
    pc.printf("Sampling....\n\r");
    myled3 = !myled3;
}

// Communicates to the other MBED using RF
void commThread()
{
    // We want this in it's own thread so we don't have to worry about the
    // timings screwing anything else up
    // It can't be in an interrupt because of that
    while (true) {
        // Change what we are sending based on what mode we are in
        if (mode == RECEIVE) {
            // Make sure something is there to read
            if (my_nrf24l01p.readable( NRF24L01P_PIPE_P0 )) {
                uint8_t spkrPacket[DATA_PACKET_SIZE];
            
                // Remove entire packet of data from the bus
                int numReceived =  my_nrf24l01p.read( NRF24L01P_PIPE_P0, (char*) spkrPacket, DATA_PACKET_SIZE );
                
                // Place into buffer to play speaker in another thread
                // Only place into the buffer the number of bytes received
                rxbuff.push(spkrPacket, min(DATA_PACKET_SIZE, numReceived));
                
                pc.printf("Receiviing....\n\r");
                myled2 = !myled2;
            }
        } else { // mode == TRANSMIT
            if (txbuff.size() >= DATA_PACKET_SIZE) {
                uint8_t micPacket[DATA_PACKET_SIZE];
                
                // Pull an entire packet of data from the mic sample buffer
                int numPopped = txbuff.pop(micPacket, DATA_PACKET_SIZE);
                
                // Send the entire buffer to the other device
                // TODO: We just assume that DATA_PACKET_SIZE bytes were popped, this may
                //       not be the case
                my_nrf24l01p.write( NRF24L01P_PIPE_P0, (char*) micPacket, DATA_PACKET_SIZE );
                
                pc.printf("Transmitting....\n\r");
                myled1 = !myled1;
            }
        }
        
        Thread::yield();
    }
}

// Displays the current info to the LCD display
void lcdThread()
{
    while (1) {
        uLCD.locate(64, 20);
        uLCD.printf("Frequency: %d MHz", rfFreq);
        uLCD.locate(64, 40);
        uLCD.printf("Data Rate: %d kbps", dataRate);
        uLCD.locate(64, 60);
        uLCD.printf("TX Address: 0x%010llX", txAddr);
        uLCD.locate(64, 80);
        uLCD.printf("RX Address: 0x%010llX", rxAddr);
        uLCD.locate(64, 100);
        
        switch (mode) {
            case RECEIVE:
                uLCD.printf("Mode: Receiving");
                break;
            case TRANSMIT:
                uLCD.printf("Mode: Transmitting");
                break;
        }
        
        // Maybe add some graphics too idk
        Thread::wait(50);
    }
}

int main()
{
    Thread lcd;
    Thread comm;    
    
    // Set up the nrf24l01p
    rfFreq = my_nrf24l01p.getRfFrequency();
    dataRate = my_nrf24l01p.getAirDataRate();
    rxAddr = my_nrf24l01p.getRxAddress();
    txAddr = my_nrf24l01p.getTxAddress();
    
    my_nrf24l01p.setTransferSize(DATA_PACKET_SIZE);

    my_nrf24l01p.setReceiveMode();
    my_nrf24l01p.enable();
    
    pc.printf("Finished starting up....\n\r");
    
    mode = RECEIVE;
    
    // Initialize the uLCD
    uLCD.baudrate(3000000);
    uLCD.background_color(BLACK);
    
    // Spawn threads
    lcd.start(lcdThread);
    comm.start(commThread);
    
    // Setup the button to enter transmit mode when pushed down
    // and recieve when release
    button.mode(PullDown);
    button.fall(&enterTransmitMode);
    button.rise(&enterRecieveMode);
    
    // Setup sampler to sample at a specific frequency
    sampler.attach(&sampleData, SAMPLE_PERIOD);
    
    // Heartbeat thread
    while (1) {
        myled4 = !myled4;
        Thread::wait(100);
    }
}