ECE 4180 - Final Project Team / Mbed 2 deprecated WalkieTalkie

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

Revision:
27:08d34e60b6d0
Parent:
26:57731422b129
Child:
28:9413eb50156d
Child:
29:0c6f3c0c992a
--- a/main.cpp	Sat Apr 21 17:55:46 2018 +0000
+++ b/main.cpp	Sun Apr 22 00:48:48 2018 +0000
@@ -10,31 +10,32 @@
 #include "CircularBuf.h"
 #include "CircularBuf.cpp" // Hack to get templates to work
 
-#define TRANSFER_SIZE   4 //added 5:54pm 4/18/18
+// 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); // tx, rx
-DigitalOut myled1(LED1);
-DigitalOut myled2(LED2);
-DigitalOut myled3(LED3);
+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 mymicrophone(p16);
+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
-uLCD_4DGL uLCD(p27,p28,p30);                        // serial tx, serial rx, reset pin;
-CircularBuf<uint8_t> txbuff(30);
-CircularBuf<uint8_t> rxbuff(30);
-Ticker t; //10:41 am 4/20
+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
-Thread lcd;
-
-char txData[TRANSFER_SIZE], rxData[TRANSFER_SIZE]; //making these usable by other voids.
-int txDataCnt = 0;//and this.
-int rxDataCnt = 0;//and this. //David Rechtmann 6.24 pm 4/18/18
-uint8_t micvalue[30];
-int micvalcount = 0;
+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;
@@ -47,124 +48,103 @@
 
 operatingMode mode;
 
-
-void startup()
-{
-
-// The nRF24L01+ supports transfers from 1 to 32 bytes, but Sparkfun's
-//  "Nordic Serial Interface Board" (http://www.sparkfun.com/products/9019)
-//  only handles 4 byte transfers in the ATMega code.
-
-//   char txData[TRANSFER_SIZE], rxData[TRANSFER_SIZE]; //making these usable by other voids.
-    // int txDataCnt = 0;//and this.
-    // int rxDataCnt = 0;//and this. //David Rechtmann 6:24 pm 4/18/18
-
-    my_nrf24l01p.powerUp();
+// Cheap nonbranching min function
+int min(int a, int b) {
+    return a * (int)(a <= b) + b * (int)(b < a);
+}
 
-    // Display the (default) setup of the nRF24L01+ chip
-    pc.printf( "nRF24L01+ Frequency    : %d MHz\r\n",  my_nrf24l01p.getRfFrequency() );
-    pc.printf( "nRF24L01+ Output power : %d dBm\r\n",  my_nrf24l01p.getRfOutputPower() );
-    pc.printf( "nRF24L01+ Data Rate    : %d kbps\r\n", my_nrf24l01p.getAirDataRate() );
-    pc.printf( "nRF24L01+ TX Address   : 0x%010llX\r\n", my_nrf24l01p.getTxAddress() );
-    pc.printf( "nRF24L01+ RX Address   : 0x%010llX\r\n", my_nrf24l01p.getRxAddress() );
+// 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);
+}
 
-    pc.printf( "Type keys to test transfers:\r\n  (transfers are grouped into %d characters)\r\n", TRANSFER_SIZE );
+// Callback interrupt from the button to shift into transmit mode
+void enterTransmitMode() {
+    mode = TRANSMIT;
+}
 
-    my_nrf24l01p.setTransferSize( TRANSFER_SIZE );
-
-    my_nrf24l01p.setReceiveMode();
-    my_nrf24l01p.enable();
+// Callback interrupt from the button to shift into receive mode
+void enterRecieveMode() {
+    mode = RECEIVE;
 }
 
-
-void pctransmit()
+// Called every SAMPLE_PERIOD ms to sample the mic or output data into the speaker
+void sampleData()
 {
-    // If we've received anything over the host serial link...
-    if ( pc.readable() ) {
-
-        // ...add it to the transmit buffer
-        txData[txDataCnt++] = pc.getc();
+    // 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);
 
-        // If the transmit buffer is full
-        if ( txDataCnt >= sizeof( txData ) ) {
-
-            // Send the transmitbuffer via the nRF24L01+
-            my_nrf24l01p.write( NRF24L01P_PIPE_P0, txData, txDataCnt );
-
-            txDataCnt = 0;
-        }
+        // 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;
+}
 
-        // Toggle LED1 (to help debug Host -> nRF24L01+ communication)
-        myled3 = !myled3;
-    }
-
-    // If we've received anything in the nRF24L01+...
-    if ( my_nrf24l01p.readable() ) {
-
-        // ...read the data into the receive buffer
-        rxDataCnt = my_nrf24l01p.read( NRF24L01P_PIPE_P0, rxData, sizeof( rxData ) );
-
-        // Display the receive buffer contents via the host serial link
-        for ( int i = 0; rxDataCnt > 0; rxDataCnt--, i++ ) {
-
-            pc.putc( rxData[i] );
+// 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;
+            }
         }
-
-        // Toggle LED2 (to help debug nRF24L01+ -> Host communication)
-        myled3 = !myled3;
+        
+        Thread::yield();
     }
 }
 
-void receive()   //most of this function added by david at 6:02pm 4/18/18
-{
-    uint8_t spkrarray[30];
-    uint8_t spkrtemp;
-    while (Button.read() == 0) {
-        mode = RECEIVE;
-        if (my_nrf24l01p.readable(0)) {
-   pc.printf("receiving....");
-        my_nrf24l01p.read(0, (char*)spkrarray, 30);
-        rxbuff.push(spkrarray, 30);
-          //  rxbuff.push(spkrarray, 30);
-            rxbuff.pop(&spkrtemp, 1);
-            spkr.write(spkrtemp);
-            myled2 = !myled2;
-        }
-    }
-}
-
-void transmit()
-{
-    //  while   (mymycrophone.getData()) {
-    //     txData[txDataCnt++] = mymicrophone.getData();
-    //    }
-    // txData[txDataCnt++] = ;
-    spkr.turnOff();
-    
-    uint8_t txsendary[30];
-    txbuff.pop(txsendary, 30);
-    while (Button.read()) {
-   //     my_nrf24l01p.write(0, (char *)micvalue, 30);
-   pc.printf("transmitting....");
-   my_nrf24l01p.write( NRF24L01P_PIPE_P0, (char*) txsendary, 30);
-   myled1 = !myled1;
-        mode = TRANSMIT;
-    }
-}
-
-void pollmic()
-{
-    uint8_t txentry = mymicrophone.getData();
-    txbuff.push(&txentry, 1);
-     pc.printf("polling....");
-  //  micvalcount = micvalcount + 1;
-  //  if (micvalcount > 30);
-  //  {
-  //      micvalcount = 0;
-  //  }
-
-}
-
+// Displays the current info to the LCD display
 void lcdThread()
 {
     while (1) {
@@ -177,6 +157,7 @@
         uLCD.locate(64, 80);
         uLCD.printf("RX Address: 0x%010llX", rxAddr);
         uLCD.locate(64, 100);
+        
         switch (mode) {
             case RECEIVE:
                 uLCD.printf("Mode: Receiving");
@@ -185,46 +166,52 @@
                 uLCD.printf("Mode: Transmitting");
                 break;
         }
+        
         // Maybe add some graphics too idk
-        Thread::yield();
+        Thread::wait(50);
     }
 }
 
 int main()
 {
-    startup();
-     pc.printf("starting up....");
-    Button.mode(PullDown);//added 6:23pm 4/18/18
-    Button.rise(&transmit);
-    Button.fall(&receive);
-    t.attach(&pollmic, 0.1);
+    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(TRANSFER_SIZE);
+    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);
     
-    // Register interrupts
-    Button.mode(PullUp);//added 6:23pm 4/18/18
-    t.attach(&pollmic, 0.0001);
-    t.attach(&receive, 0.0001);
-    
     // Spawn threads
     lcd.start(lcdThread);
+    comm.start(commThread);
     
-    // Main thread
+    // 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) {
-        Thread::yield();
+        myled4 = !myled4;
+        Thread::wait(100);
     }
 }
\ No newline at end of file