Aloha implementation of LoRa technology

Dependencies:   SX1276Lib mbed

Fork of SX1276PingPong by Semtech

Files at this revision

API Documentation at this revision

Comitter:
rba90
Date:
Wed Jun 08 22:15:29 2016 +0000
Parent:
15:f790f35839db
Commit message:
random stuff

Changed in this revision

Aloha.h Show annotated file Show diff for this revision Revisions of this file
AlohaPacket.cpp Show annotated file Show diff for this revision Revisions of this file
AlohaPacket.h Show annotated file Show diff for this revision Revisions of this file
Buffer.cpp Show diff for this revision Revisions of this file
Buffer.h Show diff for this revision Revisions of this file
crc.c Show diff for this revision Revisions of this file
crc.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r f790f35839db -r c3c6b13c3c42 Aloha.h
--- a/Aloha.h	Tue May 31 09:52:21 2016 +0000
+++ b/Aloha.h	Wed Jun 08 22:15:29 2016 +0000
@@ -3,7 +3,7 @@
 
 #include "mbed.h"
 
-#define ALOHA_MAX_ATTEMPT 3
+#define ALOHA_MAX_ATTEMPT 5
 
 class Aloha
 {
@@ -13,12 +13,13 @@
         IDLE = 0,
         PENDING,
         RETRANSMIT,
-        EXPIRED
+        EXPIRED,
+        ACK_RESP
     } AlohaState_t;
     
 public:
     Timeout AlohaAckTimeout;
-    uint32_t delay;
+    float delay;
     int attempts;
     
     AlohaState_t state;
diff -r f790f35839db -r c3c6b13c3c42 AlohaPacket.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AlohaPacket.cpp	Wed Jun 08 22:15:29 2016 +0000
@@ -0,0 +1,75 @@
+#include "AlohaPacket.h"
+
+uint8_t crc8(const uint8_t *data, int len)
+{
+    unsigned int crc = 0;
+    
+    for (int j = len; j; j--, data++)
+    {
+        crc ^= (*data << 8);
+        for (int i = 8; i; i--)
+        {
+            if (crc & 0x8000)
+            {
+                crc ^= (0x1070 << 3);
+            }
+            crc <<= 1;
+        }
+    }
+    
+    return (uint8_t)(crc >> 8);
+}
+
+bool dissectAlohaPacket(uint8_t *input, HeaderStruct *header, DataStruct *data)
+{
+    // assume user has already prepare memory in *in
+    
+    // get header
+    if (header)
+    {
+        header->fid = input[0] >> 4; // higher four bits
+        header->no = input[0] & 0x0f; // lower four bits
+    }
+    
+    // get data
+    if (data)
+    {
+        data->pd0 = input[1];
+        data->pd1 = input[2];
+    }
+    
+    // check crc
+    if (header && data)
+    {
+        return input[3] == crc8(input, 3);
+    }
+    else
+    {
+        return false;
+    }
+}
+
+void createAlohaPacket(uint8_t *output, HeaderStruct *header, DataStruct *data)
+{
+    // assume user has already allocated memory for output
+    
+    // create header
+    if (header)
+    {
+        output[0] = header->no;
+        output[0] |= header->fid << 4;
+    }
+    
+    // fit data
+    if (data)
+    {
+        output[1] = data->pd0;
+        output[2] = data->pd1;
+    }
+    
+    // calculate CRC
+    if (header && data)
+    {
+        output[3] = crc8(output, 3);
+    }
+}
\ No newline at end of file
diff -r f790f35839db -r c3c6b13c3c42 AlohaPacket.h
--- a/AlohaPacket.h	Tue May 31 09:52:21 2016 +0000
+++ b/AlohaPacket.h	Wed Jun 08 22:15:29 2016 +0000
@@ -2,7 +2,9 @@
 #define ALOHAPACKET_H_
 
 #include "stdint.h"
-#include "crc.h"
+
+
+// TODO: Move everything to Aloha.h
 
 typedef struct 
 {
@@ -16,58 +18,8 @@
     uint8_t pd1;
 } DataStruct;
 
-inline void createAlohaPacket(uint8_t *output, HeaderStruct *header, DataStruct *data)
-{
-    // assume user has already allocated memory for output
-    
-    // create header
-    if (header)
-    {
-        output[0] = header->no;
-        output[0] |= header->fid << 4;
-    }
-    
-    // fit data
-    if (data)
-    {
-        output[1] = data->pd0;
-        output[2] = data->pd1;
-    }
-    
-    // calculate CRC
-    if (header && data)
-    {
-        output[3] = crc8(output, 3);
-    }
-}
+void createAlohaPacket(uint8_t *output, HeaderStruct *header, DataStruct *data);
 
-inline bool dissectAlohaPacket(uint8_t *input, HeaderStruct *header, DataStruct *data)
-{
-    // assume user has already prepare memory in *in
-    
-    // get header
-    if (header)
-    {
-        header->fid = input[0] >> 4; // higher four bits
-        header->no = input[0] & 0x0f; // lower four bits
-    }
-    
-    // get data
-    if (data)
-    {
-        data->pd0 = input[1];
-        data->pd1 = input[2];
-    }
-    
-    // check crc
-    if (header && data)
-    {
-        return input[3] == crc8(input, 3);
-    }
-    else
-    {
-        return false;
-    }
-}
+bool dissectAlohaPacket(uint8_t *input, HeaderStruct *header, DataStruct *data);
 
 #endif
\ No newline at end of file
diff -r f790f35839db -r c3c6b13c3c42 Buffer.cpp
--- a/Buffer.cpp	Tue May 31 09:52:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-#include "Buffer.h"
-
-template <typename T>
-CircularBuffer<T>::CircularBuffer(const uint32_t size)
-    :buffer_size(size)
-{
-    read_ptr = 0;
-    write_ptr = 0;
-    count = 0;
-    
-    // mutex lock
-    mux = false; 
-    
-    // overflow
-    is_over_flow = false;
-    
-    // container
-    data = new T[buffer_size];
-}
-
-template <typename T>
-CircularBuffer<T>::~CircularBuffer()
-{
-    delete[] data;
-}
-
-template <typename T>
-bool CircularBuffer<T>::isLocked()
-{
-    return mux;
-}
-
-template <typename T>
-void CircularBuffer<T>::lock()
-{
-    mux = true;
-}
-
-template <typename T>
-void CircularBuffer<T>::unlock()
-{
-    mux = false;
-}
-
-template <typename T>
-void CircularBuffer<T>::enqueue(T in)
-{
-    data[write_ptr++] = in;
-    write_ptr %= buffer_size;
-    
-    count++;
-}
-
-template <typename T>
-T CircularBuffer<T>::dequeue()
-{
-    T temp = data[read_ptr++];
-    read_ptr %= buffer_size;
-    
-    count--;
-    return temp;   
-}
-
-template <typename T>
-uint32_t CircularBuffer<T>::getReadPtr()
-{
-    return read_ptr;
-}
-
-template <typename T>
-uint32_t CircularBuffer<T>::getWritePtr()
-{
-    return write_ptr;
-}
-
-template <typename T>
-uint32_t CircularBuffer<T>::getCounter()
-{
-    return count;
-}
-
-template <typename T>
-bool CircularBuffer<T>::getOverFlow()
-{
-    return is_over_flow;
-}
-
-template <typename T>
-void CircularBuffer<T>::clearOverFlow()
-{
-    is_over_flow = false;  
-}
-
-template <typename T>
-T CircularBuffer<T>::first()
-{
-    if (read_ptr > 0)
-    {
-        return data[read_ptr - 1];   
-    }
-    else
-    {
-        return data[read_ptr];
-    }
-}
-
-template <typename T>
-T CircularBuffer<T>::last()
-{
-    if (write_ptr > 0)
-    {
-        return data[write_ptr - 1];   
-    }
-    else
-    {
-        return data[write_ptr];
-    }
-}
-
-template <typename T>
-T CircularBuffer<T>::operator[](uint32_t idx)
-{
-    return data[idx];
-}
-
-// force compiler to create code for template
-template class CircularBuffer<int>;
-template class CircularBuffer<uint8_t>;
-template class CircularBuffer<uint16_t>;
-template class CircularBuffer<uint32_t>;
\ No newline at end of file
diff -r f790f35839db -r c3c6b13c3c42 Buffer.h
--- a/Buffer.h	Tue May 31 09:52:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-#ifndef BUFFER_H_
-#define BUFFER_H_
-
-#define DEFAULT_MAX_BUFFER_SZ 64
-
-#include "stdint.h"
-
-template <typename T>
-class CircularBuffer
-{
-private:
-    const uint32_t buffer_size;
-    uint32_t read_ptr;
-    uint32_t write_ptr;
-    uint32_t count;
-    
-    // mutex lock
-    bool mux; 
-    
-    // overflow
-    bool is_over_flow;
-    
-    // container
-    T *data;
-    
-    
-public:
-    CircularBuffer(const uint32_t size=DEFAULT_MAX_BUFFER_SZ);
-    ~CircularBuffer();
-    
-    // psudo mutex
-    bool isLocked();
-    void lock();
-    void unlock();
-    
-    // enqueue and dequeue
-    void enqueue(T in);
-    T dequeue();
-    
-    // pointer operation
-    uint32_t getReadPtr();
-    uint32_t getWritePtr();
-    uint32_t getCounter();
-    
-    // overflow
-    bool getOverFlow();
-    void clearOverFlow();
-    
-    // operation
-    T first();
-    T last();
-    
-    // random access
-    T operator[](uint32_t idx);
-};
-
-#endif
\ No newline at end of file
diff -r f790f35839db -r c3c6b13c3c42 crc.c
--- a/crc.c	Tue May 31 09:52:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-#include "crc.h"
-
-uint8_t crc8(const uint8_t *data, int len)
-{
-    unsigned int crc = 0;
-    
-    for (int j = len; j; j--, data++)
-    {
-        crc ^= (*data << 8);
-        for (int i = 8; i; i--)
-        {
-            if (crc & 0x8000)
-            {
-                crc ^= (0x1070 << 3);
-            }
-            crc <<= 1;
-        }
-    }
-    
-    return (uint8_t)(crc >> 8);
-}
\ No newline at end of file
diff -r f790f35839db -r c3c6b13c3c42 crc.h
--- a/crc.h	Tue May 31 09:52:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-#ifndef CRC_H_
-#define CRC_H_
-
-#include "stdint.h"
-
-/**
- * Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial.
- * Reference: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/master/firmware/lib/crc8.c 
- */
-uint8_t crc8(const uint8_t *data, int len);
-
-#endif
\ No newline at end of file
diff -r f790f35839db -r c3c6b13c3c42 main.cpp
--- a/main.cpp	Tue May 31 09:52:21 2016 +0000
+++ b/main.cpp	Wed Jun 08 22:15:29 2016 +0000
@@ -74,6 +74,49 @@
 // aloha protocol
 Aloha aloha;
 
+// user button
+InterruptIn UserButton(USER_BUTTON);
+static int seqid = 0;
+
+void sendMessage()
+{
+    HeaderStruct header;
+    DataStruct data;
+    
+    memset(&header, 0, sizeof(header));
+    memset(&data, 0, sizeof(data));
+    
+    header.fid = 0x0;
+    header.no = (uint8_t) seqid;
+    data.pd0 = 0xff;
+    data.pd1 = 0xff;
+    
+    uint8_t buffer[4];
+    createAlohaPacket(buffer, &header, &data);
+    
+    Radio.Send(buffer, 4);
+}
+
+void sendAck(int id)
+{
+    HeaderStruct header;
+    DataStruct data;
+    
+    memset(&header, 0, sizeof(header));
+    memset(&data, 0, sizeof(data));
+    
+    header.fid = 0x1;
+    header.no = (uint8_t) id;
+    data.pd0 = 0x00;
+    data.pd1 = 0x00;
+    
+    uint8_t buffer[4];
+    createAlohaPacket(buffer, &header, &data);
+    
+    Radio.Send(buffer, 4);
+}
+
+
 void setExpire()
 {
     if (aloha.attempts >= ALOHA_MAX_ATTEMPT)
@@ -83,10 +126,15 @@
     else
     {
         aloha.state = Aloha::RETRANSMIT;
-        aloha.delay = aloha.delay * aloha.delay;
     }
 }
 
+void userButtonHandler()
+{
+    seqid += 1;
+    sendMessage();
+}
+
 void RadioInit()
 {
     // Initialize Radio driver
@@ -126,7 +174,9 @@
 int main() 
 {  
     RadioInit();
+    UserButton.rise(userButtonHandler);
     
+    Radio.Rx( RX_TIMEOUT_VALUE );
     while (1)
     {
         switch( State )
@@ -135,36 +185,104 @@
             // if the receive frame is an ack, then cancel the timer
             // otherwise process the frame
             HeaderStruct header;
+            DataStruct data;
+            
             memset(&header, 0, sizeof(header));
+            memset(&data, 0, sizeof(data));
             
+            // decode data
+            dissectAlohaPacket(Buffer, &header, &data);
+            
+            // process packet
+            switch (header.fid)
+            {
+                case 0x0: // data packet
+                    sendAck(header.no);
+                    break;
+                    
+                case 0x1: // ack received
+                    aloha.AlohaAckTimeout.detach();
+                    aloha.state = Aloha::IDLE;
+                    break;
+                
+                default:
+                    break;
+            }
+                
             if (header.fid == 0x01)
             {
                 aloha.AlohaAckTimeout.detach();
             }
             
             // TODO: process the frame
+            
+            
+            printf("RECV::fid=0x%x, seqid=0x%x, pd0=0x%x, pd1=0x%x\r\n", header.fid, header.no, data.pd0, data.pd1);
+            
+            // enter listening mode
+            Radio.Rx( RX_TIMEOUT_VALUE );
+            
+            State = LOWPOWER;
             break;
         case TX:
             // transmit done
-            // then set state to aloha pending and start the timer
+            // set the state to pending and attach the timer with random delay
+            
+            // we dont need ack for ack
+            if (aloha.state == Aloha::ACK_RESP)
+            {
+                aloha.state =  Aloha::IDLE;
+                break;
+            }
+            
+            // set delay time
+            if (aloha.state == Aloha::IDLE)
+            {
+                aloha.delay = (Radio.Random() % 1000) / 1000.0f;
+            }
+            else if (aloha.state == Aloha::RETRANSMIT)
+            {
+                aloha.delay *= 2;
+            }
+            
+            aloha.AlohaAckTimeout.detach();
+            aloha.AlohaAckTimeout.attach(&setExpire, aloha.delay);
+            
+            // increase the attempt counter
+            aloha.attempts += 1;
+            
+            // enter listening mode
+            Radio.Rx( RX_TIMEOUT_VALUE );
+            
+            // state transition
             aloha.state = Aloha::PENDING;
-            aloha.delay = Radio.Random();
-            aloha.AlohaAckTimeout.detach();
-            aloha.AlohaAckTimeout.attach_us(&setExpire, aloha.delay);
-            aloha.attempts += 1;
+                    
+            State = LOWPOWER;
             break;
         case RX_TIMEOUT:
             // enter listening mode
+            Radio.Rx( RX_TIMEOUT_VALUE );
+            
+            State = LOWPOWER;
             break;
         case RX_ERROR:
             // we don't handle crc failed situation
+            // enter listening mode
+            Radio.Rx( RX_TIMEOUT_VALUE );
+            
+            State = LOWPOWER;
             break;
         case TX_TIMEOUT:
             // we don't handle hardware error
+            // enter listening mode
+            Radio.Rx( RX_TIMEOUT_VALUE );
+            
+            State = LOWPOWER;
             break;
         case LOWPOWER:
             break;
         default:
+            State = LOWPOWER;
             break;
         }
         
@@ -172,22 +290,31 @@
         {
         case Aloha::IDLE:
             // transmit packet if any
+            // printf("Aloha::IDLE\r\n");
             break;
         
         case Aloha::PENDING:
             // set rx time
+            // printf("Aloha::PENDING, delay=%f, attempt=%d\r\n", aloha.delay, aloha.attempts);
             break;
             
         case Aloha::RETRANSMIT:
             // send the packet again
-            // and setup the timer with new backoff delay
-            aloha.AlohaAckTimeout.attach(&setExpire, aloha.delay);
-            aloha.state = Aloha::PENDING;
+            sendMessage();
+            
+            // printf("Aloha::RETRANSMIT\r\n");
             break;
         case Aloha::EXPIRED:
             // give up the transmission
             // back to idle
+            aloha.attempts = 0;
+            
             aloha.state = Aloha::IDLE;
+            // printf("Aloha::EXPIRED\r\n");
+            break;
+        case Aloha::ACK_RESP:
+            break;
+        default:
             break;
         }
     }