ENEL400
/
Aloha
Aloha implementation of LoRa technology
Fork of SX1276PingPong by
Revision 16:c3c6b13c3c42, committed 2016-06-08
- Comitter:
- rba90
- Date:
- Wed Jun 08 22:15:29 2016 +0000
- Parent:
- 15:f790f35839db
- Commit message:
- random stuff
Changed in this revision
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; } }