Demonstration of a message queue + memory pool

Revision:
2:70084af839d3
Parent:
1:4fb27aea76b2
Child:
3:423191a375dc
--- a/main.cpp	Tue Mar 08 12:26:28 2016 +0000
+++ b/main.cpp	Tue Mar 08 20:51:13 2016 +0000
@@ -1,13 +1,77 @@
 #include "mbed.h"
 #include "rtos.h"
+#include "string.h"
+#include <stdio.h>
+#include <ctype.h>
 
 #define RED_DONE 1
 #define YELLOW_DONE 2
 
+//Delays in ms
+#define TUNIT 250
+#define TDOT  TUNIT
+#define TDASH (3*TUNIT)
+#define TGAP TUNIT
+#define TLETTER (3*TUNIT)
+#define TWORD (7*TUNIT)
 
-//Function declarations
-void countUP(void const *args);
-void countDOWN(void const *args);
+//Size of the morse character buffer
+#define BUFFERSIZE 240
+
+
+/* 
+**** Morse Code ***
+
+.               1 unit
+-               3 units
+inter-space     1 unit
+
+between letters 3 units
+between words   7 units
+*/
+
+//Morse code
+const char* const morseAlpha[] = {
+    ".-",   //A
+    "-...", //B
+    "-.-.", //C
+    "-..",  //D
+    ".",    //E
+    "..-.", //F
+    "--.",  //G
+    "....", //H
+    "..",   //I
+    ".---", //J
+    "-.-",  //K
+    ".-..", //L
+    "--",   //M
+    "-.",   //N
+    "---",  //O
+    ".--.", //P
+    "--.-", //Q
+    ".-.",  //R
+    "...",  //S
+    "-",    //T
+    "..-",  //U
+    "...-", //V
+    ".--",  //W
+    "-..-", //X
+    "-.--", //Y
+    "--.."  //Z
+};
+
+const char* const morseNumeric[] = {
+    "-----",    //0
+    ".----",    //1
+    "..---",    //2
+    "...--",    //3
+    "....-",    //4
+    ".....",    //5
+    "-....",    //6
+    "--...",    //7
+    "---..",    //8
+    "----."     //9    
+};
 
 //Digital outputs
 DigitalOut onBoardLED(LED1);
@@ -15,112 +79,168 @@
 DigitalOut yellowLED(D6);
 DigitalOut greenLED(D5);
 
+//Serial Interface
+Serial pc(USBTX, USBRX);
+
 //Digital inputs
 DigitalIn  onBoardSwitch(USER_BUTTON);
 DigitalIn  SW1(D4);
 DigitalIn  SW2(D3);
 
-//MUTEX Lock
-Mutex *countLock;
-
 //Thread ID for the Main function (CMSIS API)
 osThreadId tidMain;
 
-//Stared mutable state
-volatile long long count = 0;
+//Thread sychronisation primatives
+Semaphore *spaceAvailable;
+Semaphore *samplesInBuffer;
+Mutex *bufferLock;
+
+//Output buffer
+char buffer[BUFFERSIZE];
+unsigned int newestIndex = BUFFERSIZE-1;    //First time it is incremented, it will be 0
+unsigned int oldestIndex = BUFFERSIZE-1;          
 
-//Threads
-void countUP(void const *args)
-{
-    redLED = 1;
-    
-    for (unsigned int n=0; n<10000; n++) {
-        //Take lock
-        countLock->lock();
+
+//Producer
+void addCharacterToQueue(const char c)
+{    
+    //Is there space?
+    spaceAvailable->wait();
+             
+    //Ok, there is space - take the lock
+    bufferLock->lock();
+    redLED = 1;       
         
-        //Critical section(s)
-        count++;
-        count++;        
-        count++;
-        count++;    
-        count++;
-        count++; 
-        count++;
-        count++;
-        count++;
-        count++;   
+    //Update buffer
+    newestIndex = (newestIndex+1) % BUFFERSIZE;  
+    buffer[newestIndex] = c;
+
+    //Release lock
+    bufferLock->unlock();
+    redLED = 0;
+    
+    //Signal that a sample has been added
+    samplesInBuffer->release();
+}
+
+//Consumer
+char takeCharacterFromQueue()
+{    
+    //Are thre any samples in the buffer
+    samplesInBuffer->wait();
         
-        //Release lock
-        countLock->unlock();
-    }
+    //Ok, there are samples - take the lock
+    bufferLock->lock();   
+    yellowLED = 1;
+    
+    //Update buffer - remove oldest
+    oldestIndex = (oldestIndex+1) % BUFFERSIZE;
+    char cc = buffer[oldestIndex];
     
-    redLED = 0;
-    osSignalSet(tidMain, RED_DONE);  //Signal main thread we are done
+    //Release lock
+    bufferLock->unlock();
+    yellowLED = 0;
+    
+    //Signal there is space in the buffer
+    spaceAvailable->release();
+    
+    //return a copy of the result
+    return cc;
 }
 
-void countDOWN(void const *args)
+void morseGenerator( const void* arg ) 
 {
-    yellowLED = 1;
-    
-    for (unsigned int n=0; n<10000; n++) {
-        //Take lock
-        countLock->lock();
+    while (true) {
+        
+        //Are there samples available?
+        char nextChar = takeCharacterFromQueue();  
+        nextChar = tolower(nextChar);
+        
+        //Look up morse code
+        
+        //Space between words - assumes only one
+        if (nextChar == ' ') {
+            Thread::wait(TWORD-TLETTER);
+            continue;   
+        }
+        
+        //Number?
+        const char *nextString;
+        if ((nextChar >= '0') && (nextChar <= '9')) {
+            nextString = morseNumeric[nextChar - '0'];   
+        }
+        //Character?
+        else if ((nextChar >='a') && (nextChar <= 'z')) {
+            nextString = morseAlpha[nextChar - 'a'];   
+        } else {
+            //Invalid
+            continue;   
+        }
         
-        //Critical section(s)        
-        count--;
-        count--;        
-        count--;
-        count--;    
-        count--;
-        count--; 
-        count--;
-        count--;
-        count--;
-        count--;    
+        //Flash morse for this letter
+        for (unsigned int n=0; n<strlen(nextString); n++) {
+            char symb = nextString[n];
+            greenLED = 1;
+            switch (symb) {
+                case '.':
+                    Thread::wait(TDOT);
+                    break;
+                case '-':
+                    Thread::wait(TDASH);
+                    break;
+                default:
+                    break;  
+            }
+            greenLED = 0;
+            
+            //A gap between symbols
+            Thread::wait(TGAP);    
+        } 
         
-        //Release lock
-        countLock->unlock();                   
-    }   
-    
-    osSignalSet(tidMain, YELLOW_DONE); //Signal main thread we are done
-    yellowLED = 0;
+        //Gap between letters
+        Thread::wait(TLETTER-TGAP);
+        
+    }      
 }
 
+void convertToMorseAsync(const char* pString)
+{
+    //Copy each character into the buffer
+    int L = strlen(pString);
+    for (int n=0; n<L; n++) {
+        char c = pString[n];
+        addCharacterToQueue(c);   
+    }
+}  
+
 
 //Main thread
 int main() {
     redLED    = 0;
     yellowLED = 0;
-    greenLED  = 1;
+    greenLED  = 0;
+        
+    //Semaphores
+    bufferLock = new Mutex();
+    spaceAvailable = new Semaphore(BUFFERSIZE);
+    samplesInBuffer = new Semaphore(0);
+        
     
     //Main thread ID
     tidMain = Thread::gettid();  
     
-    //Create lock
-    countLock = new Mutex();
+    
+    //Thread for outputting mors
+    Thread writer(morseGenerator);
     
-    //Press the switch to run concurrently
-    if (onBoardSwitch == 1) {
-        printf("Running sequntially\n");
-        countUP(NULL);
-        countDOWN(NULL);        
-    } else {
-        printf("Running concurrently\n");
-        Thread t1(countUP);           
-        Thread t2(countDOWN);    
-  
-        //Wait for the ALL_ON signal
-        Thread::signal_wait(RED_DONE,osWaitForever);
-        Thread::signal_wait(YELLOW_DONE,osWaitForever);        
+    pc.printf("Type characters to send\n");
+    while (true) {
+        //Read keyboard (serial port)
+        char c = pc.getc();
+        pc.printf("\n");
+        addCharacterToQueue(c);
     }
 
-    printf("Final result = %lld\n", count);
-    if (count == 0) {
-        greenLED = 0;
-    }
-    
-    //Tidy
-    delete countLock;
-    
-    while(true);
 }
+
+