ECE 4180 - Final Project Team / Mbed 2 deprecated WalkieTalkie

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "uLCD_4DGL.h"
00002 #include "mbed.h"
00003 #include "rtos.h"
00004 
00005 #include "Microphone.h"
00006 #include "Speaker.h"
00007 #include "HUD.h"
00008 #include "nRF24L01P.h"
00009 
00010 #include "CircularBuf.h"
00011 #include "CircularBuf.cpp" // Hack to get templates to work
00012 
00013 // How many times larger the buffer should be
00014 #define FIFO_BUFFER_SCALE  250
00015 // How maybe bytes to send over RF
00016 #define DATA_PACKET_SIZE   32
00017 // How quickly to sample the mic / play the speaker
00018 #define SAMPLE_PERIOD   1/8000.0
00019 
00020 
00021 Serial pc(USBTX, USBRX);
00022 DigitalOut myled1(LED1); // Mic data sent over RF
00023 DigitalOut myled2(LED2); // Speaker data recieved over RF
00024 DigitalOut myled3(LED3); // Sampled mic / played the speaker
00025 DigitalOut myled4(LED4); // Heartbeat
00026 
00027 Speaker spkr(p18);
00028 Microphone mic(p16);
00029 Mutex u;
00030 
00031 uLCD_4DGL uLCD(p28, p27, p29);                      // serial tx, serial rx, reset pin;
00032 
00033 nRF24L01P my_nrf24l01p(p5, p6, p7, p8, p9, p10);    // mosi, miso, sck, csn, ce, irq
00034 CircularBuf<uint8_t> txbuff( FIFO_BUFFER_SCALE * DATA_PACKET_SIZE );
00035 CircularBuf<uint8_t> rxbuff( FIFO_BUFFER_SCALE * DATA_PACKET_SIZE );
00036 Ticker sampler; //10:41 am 4/20
00037 
00038 InterruptIn button(p12); //changed DitialIn to InterruptIn at 5:54 4/18/18
00039 BusIn channel(p21, p22, p23, p24, p25);
00040 
00041 int rfFreq;
00042 int dataRate;
00043 unsigned long long rxAddr, txAddr;
00044 int pipe = 0;
00045 int channelNum = -1;
00046 
00047 enum operatingMode {
00048     RECEIVE = 0,
00049     TRANSMIT
00050 };
00051 
00052 operatingMode mode;
00053 
00054 // Cheap nonbranching min function
00055 int min(int a, int b)
00056 {
00057     return a * (int)(a <= b) + b * (int)(b < a);
00058 }
00059 
00060 // Sets the channel of the RF device based on which swtiches are flipped
00061 // by changing RX/TX pipes
00062 // TODO: Make sure we don't have to restart the device or anything to change this
00063 void setChannel()
00064 {
00065     int oldChannel = channelNum;
00066     //int oldPipe = pipe;
00067     //int width = 5;
00068     switch (channel) {
00069         case 0:      // Channel 0
00070             //rxAddr = txAddr = 0xC2C2C2C2C0;
00071             //pipe = NRF24L01P_PIPE_P0;
00072             channelNum = 0;
00073             if (channelNum != oldChannel) {
00074                 //my_nrf24l01p.setRxAddress(rxAddr, width, pipe);
00075                 //my_nrf24l01p.setTxAddress(txAddr, width);
00076                 rfFreq = channelNum + NRF24L01P_MIN_RF_FREQUENCY;
00077                 my_nrf24l01p.setRfFrequency(rfFreq);
00078                 u.lock();
00079                 uLCD.locate(0, 0);
00080                 uLCD.printf("Freq: %d MHz", rfFreq);
00081                 uLCD.locate(0, 2);
00082                 uLCD.printf("Channel: %d ", channelNum);
00083                 uLCD.locate(0, 10);
00084                 u.unlock();
00085             }
00086             break;
00087         case 1:      // Channel 1
00088             //rxAddr = txAddr = 0xC2C2C2C2C1;
00089             //pipe = NRF24L01P_PIPE_P1;
00090             channelNum = 1;
00091             if (channelNum != oldChannel) {
00092                 //my_nrf24l01p.setRxAddress(rxAddr, width, pipe);
00093                 //my_nrf24l01p.setTxAddress(txAddr, width);
00094                 rfFreq = channelNum + NRF24L01P_MIN_RF_FREQUENCY;
00095                 my_nrf24l01p.setRfFrequency(rfFreq);
00096                 uLCD.locate(0, 0);
00097                 uLCD.printf("Freq: %d MHz", rfFreq);
00098                 uLCD.locate(0, 2);
00099                 uLCD.printf("Channel: %d ", channelNum);
00100                 uLCD.locate(0, 10);
00101                 u.unlock();
00102             }
00103             break;
00104         case 2:      // Channel 2
00105             //rxAddr = txAddr = 0xC2C2C2C2C2;
00106             //pipe = NRF24L01P_PIPE_P2;
00107             channelNum = 2;
00108             if (channelNum != oldChannel) {
00109                 //my_nrf24l01p.setRxAddress(rxAddr, width, pipe);
00110                 //my_nrf24l01p.setTxAddress(txAddr, width);
00111                 rfFreq = channelNum + NRF24L01P_MIN_RF_FREQUENCY;
00112                 my_nrf24l01p.setRfFrequency(rfFreq);
00113                 u.lock();
00114                 uLCD.locate(0, 0);
00115                 uLCD.printf("Freq: %d MHz", rfFreq);
00116                 uLCD.locate(0, 2);
00117                 uLCD.printf("Channel: %d ", channelNum);
00118                 uLCD.locate(0, 10);
00119                 u.unlock();
00120             }
00121             break;
00122         case 4:      // Channel 3
00123             //rxAddr = txAddr = 0xC2C2C2C2C3;
00124             //pipe = NRF24L01P_PIPE_P3;
00125             channelNum = 3;
00126             if (channelNum != oldChannel) {
00127                 //my_nrf24l01p.setRxAddress(rxAddr, width, pipe);
00128                 //my_nrf24l01p.setTxAddress(txAddr, width);
00129                 rfFreq = channelNum + NRF24L01P_MIN_RF_FREQUENCY;
00130                 my_nrf24l01p.setRfFrequency(rfFreq);
00131                 u.lock();
00132                 uLCD.locate(0, 0);
00133                 uLCD.printf("Freq: %d MHz", rfFreq);
00134                 uLCD.locate(0, 2);
00135                 uLCD.printf("Channel: %d ", channelNum);
00136                 uLCD.locate(0, 10);
00137                 u.unlock();
00138             }
00139             break;
00140         case 8:      // Channel 4
00141             //rxAddr = txAddr = 0xC2C2C2C2C4;
00142             //pipe = NRF24L01P_PIPE_P4;
00143             channelNum = 4;
00144             if (channelNum != oldChannel) {
00145                 //my_nrf24l01p.setRxAddress(rxAddr, width, pipe);
00146                 //my_nrf24l01p.setTxAddress(txAddr, width);
00147                 rfFreq = channelNum + NRF24L01P_MIN_RF_FREQUENCY;
00148                 my_nrf24l01p.setRfFrequency(rfFreq);
00149                 u.lock();
00150                 uLCD.locate(0, 0);
00151                 uLCD.printf("Freq: %d MHz", rfFreq);
00152                 uLCD.locate(0, 2);
00153                 uLCD.printf("Channel: %d ", channelNum);
00154                 uLCD.locate(0, 10);
00155                 u.unlock();
00156             }
00157             break;
00158         case 16:     // Channel 5
00159             //rxAddr = txAddr = 0xC2C2C2C2C5;
00160             //pipe = NRF24L01P_PIPE_P5;
00161             channelNum = 5;
00162             if (channelNum != oldChannel) {
00163                 //my_nrf24l01p.setRxAddress(rxAddr, width, pipe);
00164                 //my_nrf24l01p.setTxAddress(txAddr, width);
00165                 rfFreq = channelNum + NRF24L01P_MIN_RF_FREQUENCY;
00166                 my_nrf24l01p.setRfFrequency(rfFreq);
00167                 u.lock();
00168                 uLCD.locate(0, 0);
00169                 uLCD.printf("Freq: %d MHz", rfFreq);
00170                 uLCD.locate(0, 2);
00171                 uLCD.printf("Channel: %d ", channelNum);
00172                 uLCD.locate(0, 10);
00173                 u.unlock();
00174             }
00175             break;
00176         default:
00177             break;
00178     }
00179 
00180     //pc.printf("Pipe = %d\r\n", pipe);
00181 
00182     // TODO: Don't force it to the default RF frequency
00183     //channelNum = 2;
00184 
00185     //my_nrf24l01p.setRfFrequency(channelNum + NRF24L01P_MIN_RF_FREQUENCY);
00186 }
00187 
00188 // Callback interrupt from the button to shift into transmit mode
00189 void enterTransmitMode()
00190 {
00191     mode = TRANSMIT;
00192     txbuff.clear();
00193 //   u.lock();
00194 //    uLCD.locate(0, 10);
00195 //   uLCD.printf("Mode:    Transmitting");
00196 //     u.unlock();
00197 }
00198 
00199 // Callback interrupt from the button to shift into receive mode
00200 void enterRecieveMode()
00201 {
00202     mode = RECEIVE;
00203     rxbuff.clear();
00204     //    u.lock();
00205     //  uLCD.locate(0, 10);
00206 //   uLCD.printf("Mode:    Receiving");
00207     // u.unlock();
00208 }
00209 
00210 // Called every SAMPLE_PERIOD ms to sample the mic or output data into the speaker
00211 void sampleData()
00212 {
00213     // Depending on the mode, only sample the mic or output data to the speaker
00214     if (mode == RECEIVE) {
00215         // Get speaker sample from buffer
00216         // If there is no data in the buffer, it will just output 0 to the write function
00217         uint8_t speakerSample = 0;
00218         rxbuff.pop(&speakerSample, 1);
00219 
00220         // Output into the actual speaker
00221         spkr.write (speakerSample);
00222     } else {
00223         // Get mic sample and place into buffer
00224         uint8_t micSample = mic.getData();
00225         txbuff.push(&micSample, 1);
00226 
00227         // Make sure the speaker is actually off
00228         spkr.turnOff();
00229     }
00230 
00231     // TODO: This will have to be removed later on once we actually crank up the sample rate
00232     myled3 = !myled3;
00233 }
00234 
00235 // Communicates to the other MBED using RF
00236 void commThread()
00237 {
00238     // We want this in it's own thread so we don't have to worry about the
00239     // timings screwing anything else up
00240     // It can't be in an interrupt because of that
00241     while (true) {
00242         // Change what we are sending based on what mode we are in
00243         if (mode == RECEIVE) {
00244             // Make sure something is there to read
00245             if (my_nrf24l01p.readable( NRF24L01P_PIPE_P0 )) {
00246                 uint8_t spkrPacket[DATA_PACKET_SIZE];
00247 
00248                 // Remove entire packet of data from the bus
00249                 int numReceived =  my_nrf24l01p.read( NRF24L01P_PIPE_P0, (char*) spkrPacket, DATA_PACKET_SIZE );
00250 
00251                 // Place into buffer to play speaker in another thread
00252                 // Only place into the buffer the number of bytes received
00253                 rxbuff.push(spkrPacket, min(DATA_PACKET_SIZE, numReceived));
00254 
00255                 //pc.printf("Receiviing....\n\r");
00256                 myled2 = !myled2;
00257             }
00258         } else { // mode == TRANSMIT
00259             if (txbuff.size() >= DATA_PACKET_SIZE) {
00260                 uint8_t micPacket[DATA_PACKET_SIZE];
00261 
00262                 // Pull an entire packet of data from the mic sample buffer
00263                 int numPopped = txbuff.pop(micPacket, DATA_PACKET_SIZE);
00264                 //   rxbuff.push(micPacket, DATA_PACKET_SIZE);
00265 
00266                 // Send the entire buffer to the other device
00267                 // TODO: We just assume that DATA_PACKET_SIZE bytes were popped, this may
00268                 //       not be the case
00269                 my_nrf24l01p.write( NRF24L01P_PIPE_P0, (char*) micPacket, DATA_PACKET_SIZE );
00270 
00271                 myled1 = !myled1;
00272             }
00273         }
00274 
00275         //pc.printf("TX Size %d RX Size%d Mode %d\n\r", txbuff.size(), rxbuff.size(), mode);
00276         Thread::yield();
00277         //Thread::wait(10);
00278     }
00279 }
00280 
00281 // Displays the current info to the LCD display
00282 /*void lcdThread()
00283 {
00284     while (1) {
00285         uLCD.locate(0, 0);
00286         uLCD.printf("Freq: %d MHz", rfFreq);
00287         uLCD.locate(0, 2);
00288         uLCD.printf("Rate: %d kbps", dataRate);
00289         uLCD.locate(0, 4);
00290         uLCD.printf("Addr: 0x%010llX", txAddr);
00291         uLCD.locate(0, 6);
00292         //uLCD.printf("RX: 0x%010llX", rxAddr);
00293         uLCD.printf("Channel: %d", channelNum);
00294         uLCD.locate(0, 10);
00295 
00296         switch (mode) {
00297             case RECEIVE:
00298                 uLCD.printf("Mode:    Receiving");
00299                 break;
00300             case TRANSMIT:
00301                 uLCD.line(0, 8, 127, 8, BLACK);
00302                 uLCD.printf("Mode: Transmitting");
00303                 break;
00304         }
00305 
00306         // Maybe add some graphics too idk
00307         Thread::wait(1000);
00308     }
00309 }*/
00310 
00311 int main()
00312 {
00313     //Thread lcd;
00314     Thread comm;
00315 
00316     // Set up the nrf24l01p
00317     my_nrf24l01p.setAirDataRate(2000);  // 2Mbs
00318     rfFreq = my_nrf24l01p.getRfFrequency();
00319     dataRate = my_nrf24l01p.getAirDataRate();
00320     rxAddr = my_nrf24l01p.getRxAddress();
00321     txAddr = my_nrf24l01p.getTxAddress();
00322 
00323     my_nrf24l01p.setTransferSize(DATA_PACKET_SIZE);
00324 
00325     my_nrf24l01p.setReceiveMode();
00326     my_nrf24l01p.enable();
00327 
00328     pc.printf( "nRF24L01+ Frequency    : %d MHz\r\n",  rfFreq );
00329     pc.printf( "nRF24L01+ Output power : %d dBm\r\n",  my_nrf24l01p.getRfOutputPower() );
00330     pc.printf( "nRF24L01+ Data Rate    : %d kbps\r\n", my_nrf24l01p.getAirDataRate() );
00331     pc.printf( "nRF24L01+ TX Address   : 0x%010llX\r\n", txAddr );
00332     pc.printf( "nRF24L01+ RX Address   : 0x%010llX\r\n", rxAddr );
00333 
00334     pc.printf("Finished starting up....\n\r");
00335 
00336     mode = RECEIVE;
00337 
00338     // Initialize the uLCD
00339     uLCD.baudrate(3000000);
00340     uLCD.background_color(BLACK);
00341 
00342     // Spawn threads
00343     //lcd.start(lcdThread);
00344     comm.start(commThread);
00345 
00346     // Setup the button to enter transmit mode when pushed down
00347     // and recieve when release
00348     button.mode(PullUp);
00349     button.fall(&enterTransmitMode);
00350     button.rise(&enterRecieveMode);
00351 
00352     // Setup sampler to sample at a specific frequency
00353     sampler.attach(&sampleData, SAMPLE_PERIOD);
00354 
00355     // Heartbeat thread
00356     u.lock();
00357     uLCD.locate(0, 0);
00358     uLCD.printf("Freq: %d MHz", rfFreq);
00359     uLCD.locate(0, 2);
00360     uLCD.printf("Channel: %d", channelNum);
00361     uLCD.locate(0, 4);
00362     uLCD.printf("Addr: 0x%010llX", txAddr);
00363     uLCD.locate(0, 6);
00364     uLCD.printf("RX: 0x%010llX", rxAddr);
00365     uLCD.locate(0, 10);
00366     uLCD.printf("Mode: Receiving");
00367     u.unlock();
00368     int oldmode = -1;
00369     
00370     while (1) {
00371         myled4 = !myled4;
00372         setChannel(); // Poll the DIP switch and change channels accordingly
00373         if (mode == 0 && not(oldmode == mode)) {
00374             uLCD.locate(6, 10);
00375             uLCD.printf("Rx");
00376             oldmode = mode;
00377         } else if  (mode == 1 && not(oldmode == mode)) {
00378             uLCD.locate(6, 10);
00379             uLCD.printf("Tx");
00380             oldmode = mode;
00381         }
00382         Thread::wait(100);
00383     }
00384 }