diff --git a/src/entrypoints/dsgamma-test.cpp b/src/entrypoints/dsgamma-test.cpp
index 3d1f05a3d4d5f53ba5861e047429e700642f3ab4..36d11cbc4d406b28962db5e2a6c3c5b44dc36a56 100644
--- a/src/entrypoints/dsgamma-test.cpp
+++ b/src/entrypoints/dsgamma-test.cpp
@@ -26,12 +26,8 @@
 using namespace std;
 using namespace miosix;
 
-
-/*
- * STRANGE THING #1 (AKA BUG):
- * Stack overflow if PKT_LEN in greater than 24 !!!!!
- */
-#define PKT_LEN 14
+#define CMD_LEN 1
+#define DATA_LEN 64
 
 typedef Gpio<GPIOG_BASE,13> greenLed;
 typedef Gpio<GPIOG_BASE,14> redLed;
@@ -42,10 +38,14 @@ Gamma868 gamma("/dev/auxtty");
 long long sendTime = 0;
 int nTentativi = 0;
 int tot = 0;
+int state = 0; //0 = normal, 1 = sender, 2 = echo receiver
 
-void sender(void *arg);
+void btnClick(void *arg);
+void stdInput(void *arg);
 void receiver();
+
 int main() {
+    gamma.start(); //!!!!!IMPORTANT!!!!!!!!
     
     //Discovery gpio setup
     {
@@ -55,17 +55,17 @@ int main() {
         button::mode(Mode::INPUT);
     }
     
-    Thread::create(sender, STACK_MIN);
-    
+    //STACK_DEFAULT_FOR_PTHREAD is needed for printf())
+    Thread::create(btnClick, STACK_DEFAULT_FOR_PTHREAD);
+    Thread::create(stdInput, STACK_DEFAULT_FOR_PTHREAD);
     receiver();     //Runs in a loop
     
-    
     return 0;
 }
 
-void sender(void *arg){
+void btnClick(void *arg){
     
-    char msg[PKT_LEN];
+    char msg[CMD_LEN];
     
     while(1){
         
@@ -74,55 +74,94 @@ void sender(void *arg){
             if(button::value()==1) break;       
         }
         
-        //Prepare a packet of PKT_LEN chars with all #
-        printf("Writing... \n");
-        for(int i = 0; i < PKT_LEN; i++){
-            msg[i] = '#';
-        }
+        //---------------Send COMMAND----------------
+        printf("Writing CMD... \n");
+        msg[0] = (char) 10;
+        gamma.sendCmd(CMD_LEN, msg);
+        //------------------------------------------
+        state = 1;
+        
+        printf("Ok \n" );
+        Thread::sleep(200);
+    }
+}
+
+void stdInput(void *arg){
+    
+    char msg[DATA_LEN + 1];
+    
+    while(1){
+        
+        //Wait for button
+        scanf("%s", msg);
         
         //Save current time
-        sendTime = miosix::getTick();
-        nTentativi++;
+        if(state == 1){
+            sendTime = miosix::getTick();
+            nTentativi++;
+        }
         
-        //Send
-        gamma.send(msg);
+        //----------------SEND DATA----------------
+        gamma.send(DATA_LEN, msg);
+        //-----------------------------------------
         
         printf("Ok \n" );
         Thread::sleep(200);
     }
 }
 
+/*
+ * Continuosusly reads from the device.
+ */
 void receiver(){
     
-    int len = PKT_LEN;
-    char inputBuf[len];
-    long long arrivalTime;
+    char inputBuf[DATA_LEN];
         
     while(1){ 
         
         //Read PKT_LEN bytes
         printf("Reading: \n");
-        gamma.receive(len, inputBuf);
+        bool cmdReceived = gamma.receive(DATA_LEN, inputBuf);
         
-        //Print received chars
-        for(int i = 0; i < len ; i++){
-            printf("Received: %c\n", inputBuf[i]);
-        }
-        
-        //Calculate Round Trip Time
-        arrivalTime = miosix::getTick();
+        if(cmdReceived) 
+            handleCommand(inputBuf);
+        else
+            handleData(inputBuf);
+    }
+}
+
+void handleCommand(char *cmd){
+    printf("Command received!\n");
+    switch((int)cmd[0]){
+                case 0: 
+                    state = 0;
+                    break;
+                case 10:
+                    state = 2;
+                    break;
+                default:
+                    printf("Unknown command\n");
+            }
+}
+
+void handleData(char *data){
+
+    long long arrivalTime = miosix::getTick();
+    printf("Received: %s\n", data);
+    
+
+    if(state == 2){
+        gamma.send(DATA_LEN, data);
+    }  else if (state == 1) {
         int rtt = arrivalTime - sendTime;
         printf("RTT: %d\n", rtt);
-        
+
         printf("--------------RESULT------------");
         tot += rtt;
-        
+
         //Print Delay calculation
         if(nTentativi > 0)
         printf("Tentativi: %d  Media: %d \n", nTentativi, tot/(2*nTentativi));
-        
-        //------------------ RECEIVER ONLY -----------------
-        gamma.send(inputBuf);
-        //--------------------------------------------------
+
     }
 }
\ No newline at end of file
diff --git a/src/shared/drivers/gamma868/Gamma868.cpp b/src/shared/drivers/gamma868/Gamma868.cpp
index 08760408c8dd221c80fc724281f2cf43ab1ebfdb..5af89b281869ee07756bca3b4f764df189203a12 100644
--- a/src/shared/drivers/gamma868/Gamma868.cpp
+++ b/src/shared/drivers/gamma868/Gamma868.cpp
@@ -24,37 +24,179 @@
 
 using namespace std;
 
-#ifdef _MIOSIX
-
-#include <miosix.h>
-
-using namespace miosix;
-
-#endif //_MIOSIX
-
 Gamma868::Gamma868(const char *serialPath)
 {
     fd=open(serialPath,O_RDWR);
     if(fd<0) printf("Cannot open %s\n", serialPath);
+    led::mode(Mode::INPUT);
 }
 
-bool Gamma868::send(const char *msg)
-{
-    //TODO output buffer and synchronize
-    int length = strlen(msg);
-    write(fd, msg, length);
+
+/*
+ * Adds data to circular buffer (non blocking).
+ * Returns how many cahrs could be effectively stored in the buffer.
+ */
+int Gamma868::send(int msg_len, const char *msg)
+{ 
+    int retVal = 0;
+    if(last == -1) return false;
+    else
+    {
+        int i = 0;
+        pthread_mutex_lock(&bufMutex);
+        printf("Locked buffer mutex (send)\n");
+        for(i = 0; i < msg_len; i++){
+            buffer[last] = msg[last];
+            last++;
+            if(last == MAX_BUFFER) last = 0;
+            if(last == first){
+                last =-1;
+                break;
+            }
+        }
+        pthread_mutex_unlock(&bufMutex);
+        printf("Unocked buffer mutex (send)\n");
+        retVal = i;
+    }
+    return retVal;
+}
+
+/*
+ * Immediately sends command (blocking).
+ */
+bool Gamma868::sendCmd(int cmd_len, const char *cmd){
+    
+    //TODO implement command length
+    char pkt[HEAD_LEN + cmd_len + END_LEN];
+
+    //Prepare packet
+    pkt[0] = START;
+    pkt[1] = CMD;
+    pkt[2] = cmd[0];
+    pkt[HEAD_LEN + CMD_LEN] = END;
+
+    //Send to gamma (synchronized)
+    pthread_mutex_lock(&writingMutex); 
+    printf("Locked writing mutex (sendcmd)\n");
+        write(fd, pkt, HEAD_LEN + cmd_len + END_LEN);
+    pthread_mutex_unlock(&writingMutex);  
+    printf("Unocked writing mutex (sendcmd)\n");
+
     return true;
 }
 
+/*
+ * Reads from the gamma868 serial.
+ */
 bool Gamma868::receive(int bufLen, char *buf)
 {
+    char init = (char) 0;
+    char type = (char) 0;
+    char end = (char) 0;
+    bool cmd = false;
+    
+    //Read what you received (synchronized ?)
     pthread_mutex_lock(&readingMutex);
-    char received[bufLen+1];
-    read(fd, &received, bufLen+1);
+        //First byte: start
+        while(init != START){
+            read(fd, &init, 1);
+        }
+        //Second byte: type of data
+        read(fd, &type, 1);
+        if(type == DATA){
+            read(fd, buf, bufLen);
+        }else if(type == CMD){
+            read(fd, buf, CMD_LEN);
+            cmd = true;
+        }
+        //End byte
+        read(fd, &end, 1);        
+    pthread_mutex_unlock(&readingMutex);
     
-    for(int i = 0; i < bufLen; i++){
-        buf[i] = received[i];
+    if(end!= END) 
+        printf("Did not find end char! stream may be inconsistent\n");
+
+    return cmd;
+}
+
+/*
+ * Reads from the circular buffer and, if there's something in the buffer,
+ *  sends it in packets of fixed dimension, then until the end of transmission.
+ */
+void Gamma868::readFromBuffer(){
+    while(1){
+    if(bufSize() > 0){
+        int nChar = bufSize() > 64 ? 64 : bufSize();
+        
+        //Prepare header
+        char pkt[HEAD_LEN + DATA_LEN + END_LEN];
+        pkt[0] = START;
+        pkt[1] = DATA;
+        //Copy from circular buffer (Synchronized)
+        pthread_mutex_lock(&bufMutex);
+            for(int i = 0; i < nChar; i++){
+                pkt[i+HEAD_LEN] = buffer[first];
+                first++;
+                if(first == MAX_BUFFER)
+                    first = 0;
+                if(first == last){
+                    break;
+                }
+            }    
+        pthread_mutex_unlock(&bufMutex);
+        pkt[DATA_LEN + HEAD_LEN] = END;
+  
+        //Send
+        pthread_mutex_lock(&writingMutex); 
+        printf("Locked writing mutex (cycle)\n");
+            Thread::create(&Gamma868::static_waitForLed, 
+                                STACK_DEFAULT_FOR_PTHREAD,
+                                MAIN_PRIORITY,
+                                reinterpret_cast<void*>(this));
+
+            write(fd, pkt, HEAD_LEN + DATA_LEN + END_LEN);
+            {
+                Lock<FastMutex> l(ledMutex);
+                while(sent==0) ledCond.wait(l);
+                sent = 0;
+            }
+        printf("Unocked writing mutex (cycle)\n");
+        pthread_mutex_unlock(&writingMutex);   
+        
     }
-    pthread_mutex_unlock(&readingMutex);
-    return true;
+    Thread::sleep(200);
+    }
+    
+}
+
+/*
+ * Static wrapper for running it in a thread.
+ */
+
+
+void Gamma868::waitForLed(){
+    bool sending = false;
+    while(1){
+        if(led::value() == 1 && !sending){
+            sending = true;
+        }
+        if(sending && led::value() == 0){
+            Lock<FastMutex> l(ledMutex);
+            sent++;
+            ledCond.signal();
+            break;
+        }
+    }
+}
+
+/*
+ * Calculates the occupied portion of the circular buffer.
+ */
+unsigned int Gamma868::bufSize(){
+    if(last == -1)
+        return MAX_BUFFER;
+    else if(last < first)
+        return MAX_BUFFER - (first - last);
+    else
+        return last - first;
 }
\ No newline at end of file
diff --git a/src/shared/drivers/gamma868/Gamma868.h b/src/shared/drivers/gamma868/Gamma868.h
index 36169b74d0066bdebbce765768256208af8aace8..2512a557a197ea9f3618e0e289c5f4429b9d9410 100644
--- a/src/shared/drivers/gamma868/Gamma868.h
+++ b/src/shared/drivers/gamma868/Gamma868.h
@@ -29,20 +29,45 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <string.h>
+#ifdef _MIOSIX
 
-struct Configuration{
-    int local_addr[3] = {127, 127, 127};
-    int dest_addr[3] = {127, 127, 127};
-    int lora_mode = 6;
-    int lora_pow = 15;
-    int handshake = 0;
-    int baudrate = 4;
-};
+#include <miosix.h>
+
+using namespace miosix;
+
+#endif //_MIOSIX   
+
+#include "gamma_config.h"
 
 class Gamma868 {
     public:
         Gamma868(const char *serialPath);
-        bool send(const char *msg);
+        
+        /*
+         * Starts a thread that reads from the buffer and sends to the gamma module.
+         */
+        void start(){
+            Thread::create(&Gamma868::static_readFromBuffer,
+                              STACK_DEFAULT_FOR_PTHREAD,
+                              MAIN_PRIORITY,
+                              reinterpret_cast<void*>(this));
+        }
+        
+        /*
+         * Message goes in a queue (non blocking).
+         * Returns number of bytes effectively stored in the buffer.
+         */
+        int send(int msg_len, const char *msg);
+        
+        /*
+         * Message is sent as soon as possible (blocking).
+         */
+        bool sendCmd(int cmd_len, const char *cmd);
+        
+        /*
+         * Read from the Blocking.
+         * Returns true if the received stream is a command.
+         */
         bool receive(int bufLen, char *buf);
         //~Gamma868();
         
@@ -54,14 +79,35 @@ class Gamma868 {
          * bool configure(Configuration newConf);
          * void exitLearnMode();
          */
-       
-    private:
         
+    private:
         int fd;
         pthread_t writeThread;
         pthread_mutex_t readingMutex;
         pthread_mutex_t writingMutex;
-        pthread_cond_t writingCond;
+        pthread_mutex_t bufMutex;
+        
+        FastMutex ledMutex;          
+        ConditionVariable ledCond; 
+        int sent=0;
+        
+        int first = 0;
+        int last = 0;
+        char buffer[MAX_BUFFER];
+        
+        unsigned int bufSize();
+        
+        void readFromBuffer();
+        void waitForLed();
+        
+                
+        static void* static_readFromBuffer(void * object){
+            reinterpret_cast<Gamma868*>(object)->readFromBuffer();
+        }
+        
+        static void* static_waitForLed(void * object){
+             reinterpret_cast<Gamma868*>(object)->waitForLed();
+        }
 };
 
 #endif /* GAMMA868_H */
\ No newline at end of file
diff --git a/src/shared/drivers/gamma868/gamma_config.h b/src/shared/drivers/gamma868/gamma_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..a7fdef4b72eff79e77a0bcf251dccb5f9797b19a
--- /dev/null
+++ b/src/shared/drivers/gamma868/gamma_config.h
@@ -0,0 +1,32 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+
+
+#endif /* CONFIG_H */
+
+//Object config
+#define MAX_BUFFER 128
+
+typedef Gpio<GPIOB_BASE,0> led;
+
+struct Configuration{
+    int local_addr[3] = {127, 127, 127};
+    int dest_addr[3] = {127, 127, 127};
+    int lora_mode = 6;
+    int lora_pow = 15;
+    int handshake = 0;
+    int baudrate = 4;
+};
+
+//Protocol config
+#define HEAD_LEN 2
+#define CMD_LEN 1
+#define DATA_LEN 64
+#define END_LEN 1
+
+#define START '#'
+#define CMD '!'
+#define DATA '?'
+#define END  '%'
+