Para o mario
Dependencies: mbed USBDevice Buffer
Revision 0:dcbbdc06fcd5, committed 2018-12-13
- Comitter:
- diogo966
- Date:
- Thu Dec 13 23:19:23 2018 +0000
- Commit message:
- para o mario;
Changed in this revision
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/.hg_archival.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/.hg_archival.txt Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,6 @@ +repo: c43b6919ae15d4d48467c881902de5e812eb634d +node: 02d779e8c4f6e74ec850830dc72f2ff80266ee43 +branch: default +latesttag: null +latesttagdistance: 13 +changessincelatesttag: 13
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/BufferedSerial/Buffer.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/BufferedSerial/Buffer.lib Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/sam_grove/code/Buffer/#89564915f2a7
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/BufferedSerial/BufferedSerial.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/BufferedSerial/BufferedSerial.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,158 @@ +/** + * @file BufferedSerial.cpp + * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BufferedSerial.h" +#include <stdarg.h> + +BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name) + : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size)) +{ + RawSerial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq); + this->_buf_size = buf_size; + this->_tx_multiple = tx_multiple; + return; +} + +BufferedSerial::~BufferedSerial(void) +{ + RawSerial::attach(NULL, RawSerial::RxIrq); + RawSerial::attach(NULL, RawSerial::TxIrq); + + return; +} + +int BufferedSerial::readable(void) +{ + return _rxbuf.available(); // note: look if things are in the buffer +} + +int BufferedSerial::writeable(void) +{ + return 1; // buffer allows overwriting by design, always true +} + +int BufferedSerial::getc(void) +{ + return _rxbuf; +} + +int BufferedSerial::putc(int c) +{ + _txbuf = (char)c; + BufferedSerial::prime(); + + return c; +} + +int BufferedSerial::puts(const char *s) +{ + if (s != NULL) { + const char* ptr = s; + + while(*(ptr) != 0) { + _txbuf = *(ptr++); + } + _txbuf = '\n'; // done per puts definition + BufferedSerial::prime(); + + return (ptr - s) + 1; + } + return 0; +} + +int BufferedSerial::printf(const char* format, ...) +{ + char buffer[this->_buf_size]; + memset(buffer,0,this->_buf_size); + int r = 0; + + va_list arg; + va_start(arg, format); + r = vsprintf(buffer, format, arg); + // this may not hit the heap but should alert the user anyways + if(r > this->_buf_size) { + error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__,this->_buf_size,r); + va_end(arg); + return 0; + } + va_end(arg); + r = BufferedSerial::write(buffer, r); + + return r; +} + +ssize_t BufferedSerial::write(const void *s, size_t length) +{ + if (s != NULL && length > 0) { + const char* ptr = (const char*)s; + const char* end = ptr + length; + + while (ptr != end) { + _txbuf = *(ptr++); + } + BufferedSerial::prime(); + + return ptr - (const char*)s; + } + return 0; +} + + +void BufferedSerial::rxIrq(void) +{ + // read from the peripheral and make sure something is available + if(serial_readable(&_serial)) { + _rxbuf = serial_getc(&_serial); // if so load them into a buffer + } + + return; +} + +void BufferedSerial::txIrq(void) +{ + // see if there is room in the hardware fifo and if something is in the software fifo + while(serial_writable(&_serial)) { + if(_txbuf.available()) { + serial_putc(&_serial, (int)_txbuf.get()); + } else { + // disable the TX interrupt when there is nothing left to send + RawSerial::attach(NULL, RawSerial::TxIrq); + break; + } + } + + return; +} + +void BufferedSerial::prime(void) +{ + // if already busy then the irq will pick this up + if(serial_writable(&_serial)) { + RawSerial::attach(NULL, RawSerial::TxIrq); // make sure not to cause contention in the irq + BufferedSerial::txIrq(); // only write to hardware in one place + RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq); + } + + return; +} + +
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/BufferedSerial/BufferedSerial.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/BufferedSerial/BufferedSerial.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,140 @@ + +/** + * @file BufferedSerial.h + * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BUFFEREDSERIAL_H +#define BUFFEREDSERIAL_H + +#include "mbed.h" +#include "MyBuffer.h" + +/** A serial port (UART) for communication with other serial devices + * + * Can be used for Full Duplex communication, or Simplex by specifying + * one pin as NC (Not Connected) + * + * Example: + * @code + * #include "mbed.h" + * #include "BufferedSerial.h" + * + * BufferedSerial pc(USBTX, USBRX); + * + * int main() + * { + * while(1) + * { + * Timer s; + * + * s.start(); + * pc.printf("Hello World - buffered\n"); + * int buffered_time = s.read_us(); + * wait(0.1f); // give time for the buffer to empty + * + * s.reset(); + * printf("Hello World - blocking\n"); + * int polled_time = s.read_us(); + * s.stop(); + * wait(0.1f); // give time for the buffer to empty + * + * pc.printf("printf buffered took %d us\n", buffered_time); + * pc.printf("printf blocking took %d us\n", polled_time); + * wait(0.5f); + * } + * } + * @endcode + */ + +/** + * @class BufferedSerial + * @brief Software buffers and interrupt driven tx and rx for Serial + */ +class BufferedSerial : public RawSerial +{ +private: + MyBuffer <char> _rxbuf; + MyBuffer <char> _txbuf; + uint32_t _buf_size; + uint32_t _tx_multiple; + + void rxIrq(void); + void txIrq(void); + void prime(void); + +public: + /** Create a BufferedSerial port, connected to the specified transmit and receive pins + * @param tx Transmit pin + * @param rx Receive pin + * @param buf_size printf() buffer size + * @param tx_multiple amount of max printf() present in the internal ring buffer at one time + * @param name optional name + * @note Either tx or rx may be specified as NC if unused + */ + BufferedSerial(PinName tx, PinName rx, uint32_t buf_size = 256, uint32_t tx_multiple = 4,const char* name=NULL); + + /** Destroy a BufferedSerial port + */ + virtual ~BufferedSerial(void); + + /** Check on how many bytes are in the rx buffer + * @return 1 if something exists, 0 otherwise + */ + virtual int readable(void); + + /** Check to see if the tx buffer has room + * @return 1 always has room and can overwrite previous content if too small / slow + */ + virtual int writeable(void); + + /** Get a single byte from the BufferedSerial Port. + * Should check readable() before calling this. + * @return A byte that came in on the Serial Port + */ + virtual int getc(void); + + /** Write a single byte to the BufferedSerial Port. + * @param c The byte to write to the Serial Port + * @return The byte that was written to the Serial Port Buffer + */ + virtual int putc(int c); + + /** Write a string to the BufferedSerial Port. Must be NULL terminated + * @param s The string to write to the Serial Port + * @return The number of bytes written to the Serial Port Buffer + */ + virtual int puts(const char *s); + + /** Write a formatted string to the BufferedSerial Port. + * @param format The string + format specifiers to write to the Serial Port + * @return The number of bytes written to the Serial Port Buffer + */ + virtual int printf(const char* format, ...); + + /** Write data to the Buffered Serial Port + * @param s A pointer to data to send + * @param length The amount of data being pointed to + * @return The number of bytes written to the Serial Port Buffer + */ + virtual ssize_t write(const void *s, std::size_t length); +}; + +#endif
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/PinMap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/PinMap.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + * Licensed under the Apache License, Version 2.0); + */ + + + +#ifdef TARGET_NUCLEO_L476RG + #define FEATURE_LORA 1 +#elif TARGET_DISCO_L072CZ_LRWAN1 +#define FEATURE_LORA 1 +#endif + + + +#if defined(TARGET_DISCO_L072CZ_LRWAN1) + +#define LORA_SPI_MOSI PA_7 +#define LORA_SPI_MISO PA_6 +#define LORA_SPI_SCLK PB_3 +#define LORA_CS PA_15 +#define LORA_RESET PC_0 +#define LORA_DIO0 PB_4 +#define LORA_DIO1 PB_1 +#define LORA_DIO2 PB_0 +#define LORA_DIO3 PC_13 +#define LORA_DIO4 PA_5 +#define LORA_DIO5 PA_4 +#define LORA_ANT_RX PA_1 +#define LORA_ANT_TX PC_2 +#define LORA_ANT_BOOST PC_1 +#define LORA_TCXO PA_12 // 32 MHz + + + +#elif defined(TARGET_NUCLEO_L476RG) // using the RFM95 board + +#define LORA_SPI_MOSI PC_12 +#define LORA_SPI_MISO PC_11 +#define LORA_SPI_SCLK PC_10 +#define LORA_CS PA_0 +#define LORA_RESET PA_1 +#define LORA_DIO0 PD_2 // DIO0=TxDone/RXDone +#define LORA_DIO1 PB_7 // +#define LORA_DIO2 PC_14 // DIO2=FhssChangeChannel +#define LORA_DIO3 PC_15 // DIO3=CADDone +#define LORA_DIO4 PH_0 // ???? +#define LORA_DIO5 NC // unused? + +#endif
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/Callback-A.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/Callback-A.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,4228 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef ARDUINO + +#ifndef MBED_CALLBACK_H +#define MBED_CALLBACK_H + + +#include <string.h> +#include <stdint.h> +#include <new> +//#include "platform/mbed_assert.h" +//#include "platform/mbed_toolchain.h" +#ifdef ARDUINO +#undef F +#endif + +// namespace mbed { +/** \addtogroup platform */ + + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + * @ingroup platform + */ +template <typename F> +class Callback; + +// Internal sfinae declarations +// +// These are used to eliminate overloads based on type attributes +// 1. Does a function object have a call operator +// 2. Does a function object fit in the available storage +// +// These eliminations are handled cleanly by the compiler and avoid +// massive and misleading error messages when confronted with an +// invalid type (or worse, runtime failures) +namespace detail { + struct nil {}; + + template <bool B, typename R = nil> + struct enable_if { typedef R type; }; + + template <typename R> + struct enable_if<false, R> {}; + + template <typename M, M> + struct is_type { + static const bool value = true; + }; +} + +#define MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M) \ + typename detail::enable_if< \ + detail::is_type<M, &F::operator()>::value && \ + sizeof(F) <= sizeof(uintptr_t) \ + >::type = detail::nil() + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + * @ingroup platform + */ +template <typename R> +class Callback<R()> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R (*func)() = 0) { + if (!func) { + _ops = 0; + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R()> &func) { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R (T::*method)()) { + generate(method_context<T, R (T::*)()>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R (T::*method)() const) { + generate(method_context<const T, R (T::*)() const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R (T::*method)() volatile) { + generate(method_context<volatile T, R (T::*)() volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (T::*method)() const volatile) { + generate(method_context<const volatile T, R (T::*)() const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(T*), U *arg) { + generate(function_context<R (*)(T*), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const T*), const U *arg) { + generate(function_context<R (*)(const T*), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(volatile T*), volatile U *arg) { + generate(function_context<R (*)(volatile T*), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const volatile T*), const volatile U *arg) { + generate(function_context<R (*)(const volatile T*), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)())) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)() const)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)() volatile)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)() const volatile)) { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(U *obj, R (*func)(T*)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const U *obj, R (*func)(const T*)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(volatile U *obj, R (*func)(volatile T*)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (*func)(const volatile T*)) { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(R (*func)()) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(const Callback<R()> &func) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(U *obj, R (T::*method)()) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const U *obj, R (T::*method)() const) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(volatile U *obj, R (T::*method)() volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const volatile U *obj, R (T::*method)() const volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(T*), U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const T*), const U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(volatile T*), volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const volatile T*), const volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)())) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)() const)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)() volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)() const volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(U *obj, R (*func)(T*)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const U *obj, R (*func)(const T*)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(volatile U *obj, R (*func)(volatile T*)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const volatile U *obj, R (*func)(const volatile T*)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call() const { + return _ops->call(this); + } + + /** Call the attached function + */ + R operator()() const { + return call(); + } + + /** Test if function has been attached + */ + operator bool() const { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @return the value as determined by func which is of + * type and determined by the signiture of func + */ + static R thunk(void *func) { + return static_cast<Callback*>(func)->call(); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to garuntee proper size and alignment + struct _class; + union { + void (*_staticfunc)(); + void (*_boundfunc)(_class*); + void (_class::*_methodfunc)(); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R (*call)(const void*); + void (*move)(void*, const void*); + void (*dtor)(void*); + } *_ops; + + + // Generate operations for function object + template <typename F> + void generate(const F &f) { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + //MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F), + // "Type F must not exceed the size of the Callback class"); + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p) { + return (*(F*)p)(); + } + + template <typename F> + static void function_move(void *d, const void *p) { + new (d) F(*(F*)p); + } + + template <typename F> + static void function_dtor(void *p) { + ((F*)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()() const { + return (obj->*method)(); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()() const { + return func(arg); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + * @ingroup platform + */ +template <typename R, typename A0> +class Callback<R(A0)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R (*func)(A0) = 0) { + if (!func) { + _ops = 0; + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0)> &func) { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R (T::*method)(A0)) { + generate(method_context<T, R (T::*)(A0)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R (T::*method)(A0) const) { + generate(method_context<const T, R (T::*)(A0) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R (T::*method)(A0) volatile) { + generate(method_context<volatile T, R (T::*)(A0) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (T::*method)(A0) const volatile) { + generate(method_context<const volatile T, R (T::*)(A0) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(T*, A0), U *arg) { + generate(function_context<R (*)(T*, A0), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const T*, A0), const U *arg) { + generate(function_context<R (*)(const T*, A0), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(volatile T*, A0), volatile U *arg) { + generate(function_context<R (*)(volatile T*, A0), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const volatile T*, A0), const volatile U *arg) { + generate(function_context<R (*)(const volatile T*, A0), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0))) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0) const)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0) volatile)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0) const volatile)) { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(U *obj, R (*func)(T*, A0)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const U *obj, R (*func)(const T*, A0)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(volatile U *obj, R (*func)(volatile T*, A0)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (*func)(const volatile T*, A0)) { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(R (*func)(A0)) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(const Callback<R(A0)> &func) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(U *obj, R (T::*method)(A0)) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const U *obj, R (T::*method)(A0) const) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(volatile U *obj, R (T::*method)(A0) volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const volatile U *obj, R (T::*method)(A0) const volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(T*, A0), U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const T*, A0), const U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(volatile T*, A0), volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const volatile T*, A0), const volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0))) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0) const)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0) volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0) const volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(U *obj, R (*func)(T*, A0)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const U *obj, R (*func)(const T*, A0)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(volatile U *obj, R (*func)(volatile T*, A0)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const volatile U *obj, R (*func)(const volatile T*, A0)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0) const { + MBED_ASSERT(_ops); + return _ops->call(this, a0); + } + + /** Call the attached function + */ + R operator()(A0 a0) const { + return call(a0); + } + + /** Test if function has been attached + */ + operator bool() const { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signiture of func + */ + static R thunk(void *func, A0 a0) { + return static_cast<Callback*>(func)->call(a0); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to garuntee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0); + void (*_boundfunc)(_class*, A0); + void (_class::*_methodfunc)(A0); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R (*call)(const void*, A0); + void (*move)(void*, const void*); + void (*dtor)(void*); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0) { + return (*(F*)p)(a0); + } + + template <typename F> + static void function_move(void *d, const void *p) { + new (d) F(*(F*)p); + } + + template <typename F> + static void function_dtor(void *p) { + ((F*)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0) const { + return (obj->*method)(a0); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0) const { + return func(arg, a0); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + * @ingroup platform + */ +template <typename R, typename A0, typename A1> +class Callback<R(A0, A1)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R (*func)(A0, A1) = 0) { + if (!func) { + _ops = 0; + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0, A1)> &func) { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R (T::*method)(A0, A1)) { + generate(method_context<T, R (T::*)(A0, A1)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R (T::*method)(A0, A1) const) { + generate(method_context<const T, R (T::*)(A0, A1) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R (T::*method)(A0, A1) volatile) { + generate(method_context<volatile T, R (T::*)(A0, A1) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (T::*method)(A0, A1) const volatile) { + generate(method_context<const volatile T, R (T::*)(A0, A1) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(T*, A0, A1), U *arg) { + generate(function_context<R (*)(T*, A0, A1), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const T*, A0, A1), const U *arg) { + generate(function_context<R (*)(const T*, A0, A1), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(volatile T*, A0, A1), volatile U *arg) { + generate(function_context<R (*)(volatile T*, A0, A1), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const volatile T*, A0, A1), const volatile U *arg) { + generate(function_context<R (*)(const volatile T*, A0, A1), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1))) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1) const)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1) volatile)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1) const volatile)) { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(U *obj, R (*func)(T*, A0, A1)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const U *obj, R (*func)(const T*, A0, A1)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(volatile U *obj, R (*func)(volatile T*, A0, A1)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (*func)(const volatile T*, A0, A1)) { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(R (*func)(A0, A1)) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(const Callback<R(A0, A1)> &func) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(U *obj, R (T::*method)(A0, A1)) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const U *obj, R (T::*method)(A0, A1) const) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(volatile U *obj, R (T::*method)(A0, A1) volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const volatile U *obj, R (T::*method)(A0, A1) const volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(T*, A0, A1), U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const T*, A0, A1), const U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(volatile T*, A0, A1), volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const volatile T*, A0, A1), const volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1))) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1) const)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1) volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1) const volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(U *obj, R (*func)(T*, A0, A1)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const U *obj, R (*func)(const T*, A0, A1)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(volatile U *obj, R (*func)(volatile T*, A0, A1)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const volatile U *obj, R (*func)(const volatile T*, A0, A1)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1) const { + MBED_ASSERT(_ops); + return _ops->call(this, a0, a1); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1) const { + return call(a0, a1); + } + + /** Test if function has been attached + */ + operator bool() const { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @param a1 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signiture of func + */ + static R thunk(void *func, A0 a0, A1 a1) { + return static_cast<Callback*>(func)->call(a0, a1); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to garuntee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0, A1); + void (*_boundfunc)(_class*, A0, A1); + void (_class::*_methodfunc)(A0, A1); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R (*call)(const void*, A0, A1); + void (*move)(void*, const void*); + void (*dtor)(void*); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0, A1 a1) { + return (*(F*)p)(a0, a1); + } + + template <typename F> + static void function_move(void *d, const void *p) { + new (d) F(*(F*)p); + } + + template <typename F> + static void function_dtor(void *p) { + ((F*)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0, A1 a1) const { + return (obj->*method)(a0, a1); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0, A1 a1) const { + return func(arg, a0, a1); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + * @ingroup platform + */ +template <typename R, typename A0, typename A1, typename A2> +class Callback<R(A0, A1, A2)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R (*func)(A0, A1, A2) = 0) { + if (!func) { + _ops = 0; + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0, A1, A2)> &func) { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R (T::*method)(A0, A1, A2)) { + generate(method_context<T, R (T::*)(A0, A1, A2)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R (T::*method)(A0, A1, A2) const) { + generate(method_context<const T, R (T::*)(A0, A1, A2) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R (T::*method)(A0, A1, A2) volatile) { + generate(method_context<volatile T, R (T::*)(A0, A1, A2) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (T::*method)(A0, A1, A2) const volatile) { + generate(method_context<const volatile T, R (T::*)(A0, A1, A2) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(T*, A0, A1, A2), U *arg) { + generate(function_context<R (*)(T*, A0, A1, A2), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const T*, A0, A1, A2), const U *arg) { + generate(function_context<R (*)(const T*, A0, A1, A2), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(volatile T*, A0, A1, A2), volatile U *arg) { + generate(function_context<R (*)(volatile T*, A0, A1, A2), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const volatile T*, A0, A1, A2), const volatile U *arg) { + generate(function_context<R (*)(const volatile T*, A0, A1, A2), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2))) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2) const)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2) volatile)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2) const volatile)) { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(U *obj, R (*func)(T*, A0, A1, A2)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const U *obj, R (*func)(const T*, A0, A1, A2)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(volatile U *obj, R (*func)(volatile T*, A0, A1, A2)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2)) { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(R (*func)(A0, A1, A2)) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(const Callback<R(A0, A1, A2)> &func) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(U *obj, R (T::*method)(A0, A1, A2)) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const U *obj, R (T::*method)(A0, A1, A2) const) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(volatile U *obj, R (T::*method)(A0, A1, A2) volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const volatile U *obj, R (T::*method)(A0, A1, A2) const volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(T*, A0, A1, A2), U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const T*, A0, A1, A2), const U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(volatile T*, A0, A1, A2), volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const volatile T*, A0, A1, A2), const volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2))) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2) const)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2) volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2) const volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(U *obj, R (*func)(T*, A0, A1, A2)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const U *obj, R (*func)(const T*, A0, A1, A2)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(volatile U *obj, R (*func)(volatile T*, A0, A1, A2)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2) const { + MBED_ASSERT(_ops); + return _ops->call(this, a0, a1, a2); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2) const { + return call(a0, a1, a2); + } + + /** Test if function has been attached + */ + operator bool() const { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @param a1 An argument to be called with function func + * @param a2 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signiture of func + */ + static R thunk(void *func, A0 a0, A1 a1, A2 a2) { + return static_cast<Callback*>(func)->call(a0, a1, a2); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to garuntee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0, A1, A2); + void (*_boundfunc)(_class*, A0, A1, A2); + void (_class::*_methodfunc)(A0, A1, A2); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R (*call)(const void*, A0, A1, A2); + void (*move)(void*, const void*); + void (*dtor)(void*); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0, A1 a1, A2 a2) { + return (*(F*)p)(a0, a1, a2); + } + + template <typename F> + static void function_move(void *d, const void *p) { + new (d) F(*(F*)p); + } + + template <typename F> + static void function_dtor(void *p) { + ((F*)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0, A1 a1, A2 a2) const { + return (obj->*method)(a0, a1, a2); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0, A1 a1, A2 a2) const { + return func(arg, a0, a1, a2); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + * @ingroup platform + */ +template <typename R, typename A0, typename A1, typename A2, typename A3> +class Callback<R(A0, A1, A2, A3)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R (*func)(A0, A1, A2, A3) = 0) { + if (!func) { + _ops = 0; + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0, A1, A2, A3)> &func) { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R (T::*method)(A0, A1, A2, A3)) { + generate(method_context<T, R (T::*)(A0, A1, A2, A3)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R (T::*method)(A0, A1, A2, A3) const) { + generate(method_context<const T, R (T::*)(A0, A1, A2, A3) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R (T::*method)(A0, A1, A2, A3) volatile) { + generate(method_context<volatile T, R (T::*)(A0, A1, A2, A3) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (T::*method)(A0, A1, A2, A3) const volatile) { + generate(method_context<const volatile T, R (T::*)(A0, A1, A2, A3) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(T*, A0, A1, A2, A3), U *arg) { + generate(function_context<R (*)(T*, A0, A1, A2, A3), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const T*, A0, A1, A2, A3), const U *arg) { + generate(function_context<R (*)(const T*, A0, A1, A2, A3), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(volatile T*, A0, A1, A2, A3), volatile U *arg) { + generate(function_context<R (*)(volatile T*, A0, A1, A2, A3), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const volatile T*, A0, A1, A2, A3), const volatile U *arg) { + generate(function_context<R (*)(const volatile T*, A0, A1, A2, A3), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3))) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3) const)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3) volatile)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3) const volatile)) { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(U *obj, R (*func)(T*, A0, A1, A2, A3)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const U *obj, R (*func)(const T*, A0, A1, A2, A3)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(volatile U *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(R (*func)(A0, A1, A2, A3)) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(const Callback<R(A0, A1, A2, A3)> &func) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(U *obj, R (T::*method)(A0, A1, A2, A3)) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const U *obj, R (T::*method)(A0, A1, A2, A3) const) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(volatile U *obj, R (T::*method)(A0, A1, A2, A3) volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const volatile U *obj, R (T::*method)(A0, A1, A2, A3) const volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(T*, A0, A1, A2, A3), U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const T*, A0, A1, A2, A3), const U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(volatile T*, A0, A1, A2, A3), volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const volatile T*, A0, A1, A2, A3), const volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3))) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3) const)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3) volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3) const volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(U *obj, R (*func)(T*, A0, A1, A2, A3)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const U *obj, R (*func)(const T*, A0, A1, A2, A3)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(volatile U *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2, A3 a3) const { + MBED_ASSERT(_ops); + return _ops->call(this, a0, a1, a2, a3); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { + return call(a0, a1, a2, a3); + } + + /** Test if function has been attached + */ + operator bool() const { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @param a1 An argument to be called with function func + * @param a2 An argument to be called with function func + * @param a3 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signiture of func + */ + static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return static_cast<Callback*>(func)->call(a0, a1, a2, a3); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to garuntee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0, A1, A2, A3); + void (*_boundfunc)(_class*, A0, A1, A2, A3); + void (_class::*_methodfunc)(A0, A1, A2, A3); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R (*call)(const void*, A0, A1, A2, A3); + void (*move)(void*, const void*); + void (*dtor)(void*); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*(F*)p)(a0, a1, a2, a3); + } + + template <typename F> + static void function_move(void *d, const void *p) { + new (d) F(*(F*)p); + } + + template <typename F> + static void function_dtor(void *p) { + ((F*)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { + return (obj->*method)(a0, a1, a2, a3); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { + return func(arg, a0, a1, a2, a3); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + * @ingroup platform + */ +template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +class Callback<R(A0, A1, A2, A3, A4)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R (*func)(A0, A1, A2, A3, A4) = 0) { + if (!func) { + _ops = 0; + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0, A1, A2, A3, A4)> &func) { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R (T::*method)(A0, A1, A2, A3, A4)) { + generate(method_context<T, R (T::*)(A0, A1, A2, A3, A4)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R (T::*method)(A0, A1, A2, A3, A4) const) { + generate(method_context<const T, R (T::*)(A0, A1, A2, A3, A4) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R (T::*method)(A0, A1, A2, A3, A4) volatile) { + generate(method_context<volatile T, R (T::*)(A0, A1, A2, A3, A4) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (T::*method)(A0, A1, A2, A3, A4) const volatile) { + generate(method_context<const volatile T, R (T::*)(A0, A1, A2, A3, A4) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(T*, A0, A1, A2, A3, A4), U *arg) { + generate(function_context<R (*)(T*, A0, A1, A2, A3, A4), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const T*, A0, A1, A2, A3, A4), const U *arg) { + generate(function_context<R (*)(const T*, A0, A1, A2, A3, A4), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(volatile T*, A0, A1, A2, A3, A4), volatile U *arg) { + generate(function_context<R (*)(volatile T*, A0, A1, A2, A3, A4), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R (*func)(const volatile T*, A0, A1, A2, A3, A4), const volatile U *arg) { + generate(function_context<R (*)(const volatile T*, A0, A1, A2, A3, A4), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3, A4))) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3, A4) const)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3, A4) volatile)) { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3, A4) const volatile)) { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(U *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const U *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(volatile U *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + Callback(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(R (*func)(A0, A1, A2, A3, A4)) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + void attach(const Callback<R(A0, A1, A2, A3, A4)> &func) { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(U *obj, R (T::*method)(A0, A1, A2, A3, A4)) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const U *obj, R (T::*method)(A0, A1, A2, A3, A4) const) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(volatile U *obj, R (T::*method)(A0, A1, A2, A3, A4) volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + void attach(const volatile U *obj, R (T::*method)(A0, A1, A2, A3, A4) const volatile) { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(T*, A0, A1, A2, A3, A4), U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const T*, A0, A1, A2, A3, A4), const U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(volatile T*, A0, A1, A2, A3, A4), volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + void attach(R (*func)(const volatile T*, A0, A1, A2, A3, A4), const volatile U *arg) { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3, A4))) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3, A4) const)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3, A4) volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R (F::*)(A0, A1, A2, A3, A4) const volatile)) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(U *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const U *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(volatile U *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + void attach(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { + MBED_ASSERT(_ops); + return _ops->call(this, a0, a1, a2, a3, a4); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { + return call(a0, a1, a2, a3, a4); + } + + /** Test if function has been attached + */ + operator bool() const { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @param a1 An argument to be called with function func + * @param a2 An argument to be called with function func + * @param a3 An argument to be called with function func + * @param a4 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signiture of func + */ + static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return static_cast<Callback*>(func)->call(a0, a1, a2, a3, a4); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to garuntee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0, A1, A2, A3, A4); + void (*_boundfunc)(_class*, A0, A1, A2, A3, A4); + void (_class::*_methodfunc)(A0, A1, A2, A3, A4); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R (*call)(const void*, A0, A1, A2, A3, A4); + void (*move)(void*, const void*); + void (*dtor)(void*); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*(F*)p)(a0, a1, a2, a3, a4); + } + + template <typename F> + static void function_move(void *d, const void *p) { + new (d) F(*(F*)p); + } + + template <typename F> + static void function_dtor(void *p) { + ((F*)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { + return (obj->*method)(a0, a1, a2, a3, a4); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { + return func(arg, a0, a1, a2, a3, a4); + } + }; +}; + +// Internally used event type +typedef Callback<void(int)> event_callback_t; + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R> +Callback<R()> callback(R (*func)() = 0) { + return Callback<R()>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R> +Callback<R()> callback(const Callback<R()> &func) { + return Callback<R()>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R> +Callback<R()> callback(U *obj, R (T::*method)()) { + return Callback<R()>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R> +Callback<R()> callback(const U *obj, R (T::*method)() const) { + return Callback<R()>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R> +Callback<R()> callback(volatile U *obj, R (T::*method)() volatile) { + return Callback<R()>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R> +Callback<R()> callback(const volatile U *obj, R (T::*method)() const volatile) { + return Callback<R()>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R> +Callback<R()> callback(R (*func)(T*), U *arg) { + return Callback<R()>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R> +Callback<R()> callback(R (*func)(const T*), const U *arg) { + return Callback<R()>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R> +Callback<R()> callback(R (*func)(volatile T*), volatile U *arg) { + return Callback<R()>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R> +Callback<R()> callback(R (*func)(const volatile T*), const volatile U *arg) { + return Callback<R()>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R> +Callback<R()> callback(U *obj, R (*func)(T*)) { + return Callback<R()>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R> +Callback<R()> callback(const U *obj, R (*func)(const T*)) { + return Callback<R()>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R> +Callback<R()> callback(volatile U *obj, R (*func)(volatile T*)) { + return Callback<R()>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R> +Callback<R()> callback(const volatile U *obj, R (*func)(const volatile T*)) { + return Callback<R()>(func, obj); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0> +Callback<R(A0)> callback(R (*func)(A0) = 0) { + return Callback<R(A0)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0> +Callback<R(A0)> callback(const Callback<R(A0)> &func) { + return Callback<R(A0)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(U *obj, R (T::*method)(A0)) { + return Callback<R(A0)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(const U *obj, R (T::*method)(A0) const) { + return Callback<R(A0)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(volatile U *obj, R (T::*method)(A0) volatile) { + return Callback<R(A0)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(const volatile U *obj, R (T::*method)(A0) const volatile) { + return Callback<R(A0)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(R (*func)(T*, A0), U *arg) { + return Callback<R(A0)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(R (*func)(const T*, A0), const U *arg) { + return Callback<R(A0)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(R (*func)(volatile T*, A0), volatile U *arg) { + return Callback<R(A0)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(R (*func)(const volatile T*, A0), const volatile U *arg) { + return Callback<R(A0)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(U *obj, R (*func)(T*, A0)) { + return Callback<R(A0)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(const U *obj, R (*func)(const T*, A0)) { + return Callback<R(A0)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(volatile U *obj, R (*func)(volatile T*, A0)) { + return Callback<R(A0)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(const volatile U *obj, R (*func)(const volatile T*, A0)) { + return Callback<R(A0)>(func, obj); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R (*func)(A0, A1) = 0) { + return Callback<R(A0, A1)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const Callback<R(A0, A1)> &func) { + return Callback<R(A0, A1)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(U *obj, R (T::*method)(A0, A1)) { + return Callback<R(A0, A1)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const U *obj, R (T::*method)(A0, A1) const) { + return Callback<R(A0, A1)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(volatile U *obj, R (T::*method)(A0, A1) volatile) { + return Callback<R(A0, A1)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const volatile U *obj, R (T::*method)(A0, A1) const volatile) { + return Callback<R(A0, A1)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R (*func)(T*, A0, A1), U *arg) { + return Callback<R(A0, A1)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R (*func)(const T*, A0, A1), const U *arg) { + return Callback<R(A0, A1)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R (*func)(volatile T*, A0, A1), volatile U *arg) { + return Callback<R(A0, A1)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R (*func)(const volatile T*, A0, A1), const volatile U *arg) { + return Callback<R(A0, A1)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(U *obj, R (*func)(T*, A0, A1)) { + return Callback<R(A0, A1)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const U *obj, R (*func)(const T*, A0, A1)) { + return Callback<R(A0, A1)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(volatile U *obj, R (*func)(volatile T*, A0, A1)) { + return Callback<R(A0, A1)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const volatile U *obj, R (*func)(const volatile T*, A0, A1)) { + return Callback<R(A0, A1)>(func, obj); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R (*func)(A0, A1, A2) = 0) { + return Callback<R(A0, A1, A2)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const Callback<R(A0, A1, A2)> &func) { + return Callback<R(A0, A1, A2)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(U *obj, R (T::*method)(A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const U *obj, R (T::*method)(A0, A1, A2) const) { + return Callback<R(A0, A1, A2)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(volatile U *obj, R (T::*method)(A0, A1, A2) volatile) { + return Callback<R(A0, A1, A2)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const volatile U *obj, R (T::*method)(A0, A1, A2) const volatile) { + return Callback<R(A0, A1, A2)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R (*func)(T*, A0, A1, A2), U *arg) { + return Callback<R(A0, A1, A2)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R (*func)(const T*, A0, A1, A2), const U *arg) { + return Callback<R(A0, A1, A2)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R (*func)(volatile T*, A0, A1, A2), volatile U *arg) { + return Callback<R(A0, A1, A2)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R (*func)(const volatile T*, A0, A1, A2), const volatile U *arg) { + return Callback<R(A0, A1, A2)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(U *obj, R (*func)(T*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const U *obj, R (*func)(const T*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(volatile U *obj, R (*func)(volatile T*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(func, obj); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R (*func)(A0, A1, A2, A3) = 0) { + return Callback<R(A0, A1, A2, A3)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const Callback<R(A0, A1, A2, A3)> &func) { + return Callback<R(A0, A1, A2, A3)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(U *obj, R (T::*method)(A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const U *obj, R (T::*method)(A0, A1, A2, A3) const) { + return Callback<R(A0, A1, A2, A3)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(volatile U *obj, R (T::*method)(A0, A1, A2, A3) volatile) { + return Callback<R(A0, A1, A2, A3)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const volatile U *obj, R (T::*method)(A0, A1, A2, A3) const volatile) { + return Callback<R(A0, A1, A2, A3)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R (*func)(T*, A0, A1, A2, A3), U *arg) { + return Callback<R(A0, A1, A2, A3)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R (*func)(const T*, A0, A1, A2, A3), const U *arg) { + return Callback<R(A0, A1, A2, A3)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R (*func)(volatile T*, A0, A1, A2, A3), volatile U *arg) { + return Callback<R(A0, A1, A2, A3)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R (*func)(const volatile T*, A0, A1, A2, A3), const volatile U *arg) { + return Callback<R(A0, A1, A2, A3)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(U *obj, R (*func)(T*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const U *obj, R (*func)(const T*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(volatile U *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(func, obj); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R (*func)(A0, A1, A2, A3, A4) = 0) { + return Callback<R(A0, A1, A2, A3, A4)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const Callback<R(A0, A1, A2, A3, A4)> &func) { + return Callback<R(A0, A1, A2, A3, A4)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(U *obj, R (T::*method)(A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const U *obj, R (T::*method)(A0, A1, A2, A3, A4) const) { + return Callback<R(A0, A1, A2, A3, A4)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(volatile U *obj, R (T::*method)(A0, A1, A2, A3, A4) volatile) { + return Callback<R(A0, A1, A2, A3, A4)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with infered type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const volatile U *obj, R (T::*method)(A0, A1, A2, A3, A4) const volatile) { + return Callback<R(A0, A1, A2, A3, A4)>(obj, method); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R (*func)(T*, A0, A1, A2, A3, A4), U *arg) { + return Callback<R(A0, A1, A2, A3, A4)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R (*func)(const T*, A0, A1, A2, A3, A4), const U *arg) { + return Callback<R(A0, A1, A2, A3, A4)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R (*func)(volatile T*, A0, A1, A2, A3, A4), volatile U *arg) { + return Callback<R(A0, A1, A2, A3, A4)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with infered type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R (*func)(const volatile T*, A0, A1, A2, A3, A4), const volatile U *arg) { + return Callback<R(A0, A1, A2, A3, A4)>(func, arg); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(U *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const U *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(volatile U *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(func, obj); +} + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const volatile U *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(func, obj); +} + + +// } // namespace mbed + +#endif +#endif // Arduino
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-d21.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-d21.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,424 @@ +/* + * The file is Licensed under the Apache License, Version 2.0 + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#ifdef ARDUINO + +using namespace std; + +#include "arduino-mbed.h" +#include "arduino-util.h" + + + +#if defined(__SAMD21G18A__) || defined(__SAMD21J18A__) +/* + * __SAMD21J18A__ is the SamD21 Explained Board + * __SAMD21G18A__ is Genuino Zero-Board (compatible with the LoRa board) + */ + +int +CPUID(uint8_t *buf, int maxSize, uint32_t xorval) +{ + int f1 = 0x55d5f559; // D21 128-bit UUID, first 32 bit. + int f2 = 0x55d5f515; // D21 128-bit UUID, next 96 bit. + + if (maxSize >= 16 ) { + int cnt = 0; + int fa = f1 ^ xorval; + uint32_t *first = (uint32_t *)fa; + uint8_t *dst = (uint8_t *)first; + for (int i = 0; i < (int)sizeof(uint32_t); i++) + *buf++ = *dst++; + cnt += 4; + int fb = f2 ^ xorval; + uint32_t *next = (uint32_t *)fb; + dst = (uint8_t *)next; + for (int i = 0; i < (int)sizeof(uint32_t)*3; i++) + *buf++ = *dst++; + cnt += 12; + return cnt; + } + + return 0; +} + +/* + * see tcc.h is automatically included from: + * Arduino15/packages/arduino/tools/CMSIS-Atmel/1.1.0/CMSIS/ + * Device/ATMEL/samd21/include/component/tcc.h + * See also tcc.c (ASF/mbed, e.g. Tcc_get_count_value) + */ +static void initTimer(Tcc *t); +static uint32_t getTimerCount(Tcc *t); + +/* + * The Atmel D21 has three TCC timer, other models have more. + */ +const struct TCC_config { + Tcc *tcc_ptr; + IRQn_Type tcc_irq; + uint8_t nbits; +} TCC_data[] { + { TCC0, TCC0_IRQn, 24 }, + { TCC1, TCC1_IRQn, 24 }, + { TCC2, TCC2_IRQn, 16 }, + { NULL, (IRQn_Type)NULL, 0 } +}; + +/* + * We preferably use the TCC timers because it supports 24-bit counters + * versus TC Timer which supports only 8 or 16 bit counters only. + * TCC0/1/2 timer work on the D21 using Arduino Zero. + */ +#define USE_TCC_TIMEOUT 0 // 0=TCC0, 1=TTC1, 2=TTC2 (see TCC_data) +#define USE_TCC_TICKER 1 + + +/* + * every 21333 ns equals one tick (1/(48000000/1024)) // prescaler 1024, 48 MHz + * every 61035 ns equals one tick (1/(32768/2)) // prescaler 2, 32 kHz + * COUNT*DIVIDER*SECS until interrupt + * CPU 48 MHz = (65536*1024)/1.398636s + * RTC 32 kHz = (65536*2)/4.0s + */ +#define NS_PER_CLOCK_CPU 21333 // ns secs per clock +#define NS_PER_CLOCK_RTC 61035 // ns secs per clock + +#define NS_PER_CLOCK NS_PER_CLOCK_RTC + +/* ----------------- TICKER TIMER CODE ----------------------*/ + +/* + * The global ns_counter contains the time in ns from the last time + * the counter has been wrapped. It cannot be used directly because the + * current counter has to be added fore using it. Use instead + * ns_getTicker(), us_ ns_getTicker(), ms_getTicker() + */ + +uint64_t ticker_ns; +static bool initTickerDone = false; + +uint64_t ns_getTicker(void) +{ + Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr; + if (!initTickerDone) { + initTimer(t); + initTickerDone = true; + + // set counter top to max 16 bit for testing + // t->PER.bit.PER = 0xffff; + // while (t->SYNCBUSY.bit.PER == 1); // wait for sync + + t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC + while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync + } + + /* + * if we are called from the interrupt level, the counter contains + * somehow wrong data, therfore we needs to read it twice. + * Another option was to add a little wait (loop 500x) + * in the TCC_TIMEOUT interrupt handler. + */ + if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) // check if we are in the interrupt + getTimerCount(t); + + uint64_t counter_us = (uint64_t)NS_PER_CLOCK * (uint64_t)getTimerCount(t); + uint64_t ns = ticker_ns + counter_us; + + return ns; +} + +#if USE_TCC_TICKER == 0 +void TCC0_Handler() +#elif USE_TCC_TICKER == 1 +void TCC1_Handler() +#elif USE_TCC_TICKER == 2 +void TCC2_Handler() +#endif +{ + Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr; + /* + * Overflow means the timer top exeeded + */ + if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt + t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag + // ser->println("T_OVF"); + + /* + * reading the count once is needed, otherwise + * it will not wrap correct. + */ + getTimerCount(t); + + int bits = TCC_data[USE_TCC_TICKER].nbits; + int maxCounts = (uint32_t)(1<<bits); + + ticker_ns += (uint64_t)NS_PER_CLOCK * (uint64_t)maxCounts; + } + if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt + t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag + // ser->println("T_MC0"); + } +} + +/* ----------------- SUPPORT CODE FOR TCC TIMERS----------------------*/ + +static bool initTimerDone = false; + +static void initTimer(Tcc *t) +{ + + /* + * enable clock for TCC, see gclk.h + * GCLK_CLKCTRL_GEN_GCLK0 for 48 Mhz CPU + * GCLK_CLKCTRL_GEN_GCLK1 for 32k extern crystal XOSC32K (ifdef CRYSTALLESS) + * GCLK_CLKCTRL_GEN_GCLK1 for 32k internal OSC32K + * see Arduino: arduino/hardware/samd/1.6.15/cores/arduino/startup.c + * Use TCC_CTRLA_PRESCALER_DIV1024 for for 48 Mhz clock + * Use TCC_CTRLA_PRESCALER_DIV2 for 32k clock + */ + if (t == TCC0 || t == TCC1) { + REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_TCC0_TCC1); + } else if (t == TCC2) { + REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_TCC2_TC3_Val); + } + while (GCLK->STATUS.bit.SYNCBUSY == 1); // wait for sync + + t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TCC + while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync + + t->CTRLA.reg |= (TCC_CTRLA_PRESCALER_DIV2 | TCC_CTRLA_RUNSTDBY); // Set perscaler + + t->WAVE.reg |= TCC_WAVE_WAVEGEN_NFRQ; // Set wave form configuration + while (t->SYNCBUSY.bit.WAVE == 1); // wait for sync + + t->PER.bit.PER = 0xffffff; // set counter top to max 24 bit + while (t->SYNCBUSY.bit.PER == 1); // wait for sync + + // the compare counter TC->CC[0].reg will be set in the startTimer + // after the timeout calculation is known. + + // Interrupts + t->INTENSET.reg = 0; // disable all interrupts + t->INTENSET.bit.OVF = 1; // enable overfollow + t->INTENSET.bit.MC0 = 1; // enable compare match to CC0 + + const struct TCC_config *cp = &TCC_data[0]; + while (cp->tcc_ptr) { + if (cp->tcc_ptr == t) { + NVIC_EnableIRQ(cp->tcc_irq); // Enable InterruptVector + break; + } + cp++; + } +} + + +#if 0 +// Atmel ASF Code +static uint32_t getTimerCount(Tcc *t) +{ + uint32_t last_cmd; + /* Wait last command done */ + do { + while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */ + + last_cmd = t->CTRLBSET.reg & TCC_CTRLBSET_CMD_Msk; + if (TCC_CTRLBSET_CMD_NONE == last_cmd) { + /* Issue read command and break */ + t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val; + break; + } else if (TCC_CTRLBSET_CMD_READSYNC == last_cmd) { + /* Command have been issued */ + break; + } + } while (1); + + while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */ + + return t->COUNT.reg; +} +#endif + + +static uint32_t getTimerCount(Tcc *t) +{ + + noInterrupts(); + + while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */ + + t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val; /* Issue read command and break */ + + while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */ + + uint32_t count = t->COUNT.reg; + + interrupts(); + + return count; +} + + +Tcc *getTimeout_tcc(void) +{ + return TCC_data[USE_TCC_TIMEOUT].tcc_ptr; +} + + +void stopTimer(Tcc *t) +{ + t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC + while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync +} + + +/* ----------------- TIMEOUT TIMER CODE ----------------------*/ + +void startTimer(Tcc *t, uint64_t delay_ns) +{ + if (!initTimerDone) { + initTimer(t); // initial setup with stopped timer + initTimerDone = true; + } + + stopTimer(t); // avoid timer interrupts while calculating + + /* + * every 21333 ns equals one tick (1/(48000000/1024)) + * COUNT*DIVIDER*SECS until interrupt + * 48 Mhz = (65536*1024)/1.398636s + */ + uint64_t nclocks = (uint64_t)delay_ns; + nclocks /= (uint64_t)NS_PER_CLOCK; + int nCounts = nclocks; + + int bits = TCC_data[USE_TCC_TIMEOUT].nbits; + int maxCounts = (uint32_t)(1<<bits)-1; + + if (nCounts > maxCounts) // if count exceeds timer capacity + nCounts = maxCounts; // set the largest posible count. + if (nCounts <= 0) + nCounts = 1; + t->CC[0].bit.CC = nCounts; + while (t->SYNCBUSY.bit.CC0 == 1); // wait for sync + + t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC + while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync +#if 0 + ser->print(ms_getTicker(), DEC); + ser->print(" startTimer: nCounts="); + ser->println(nCounts, DEC); +#endif +} + + +#if USE_TCC_TIMEOUT == 0 +void TCC0_Handler() +#elif USE_TCC_TIMEOUT == 1 +void TCC1_Handler() +#elif USE_TCC_TIMEOUT == 2 +void TCC2_Handler() +#endif +{ + Tcc *t = TCC_data[USE_TCC_TIMEOUT].tcc_ptr; + uint64_t nsecs = ns_getTicker(); + + /* + * Overflow means the max timer exeeded, we need restart the timer + * Interrupts and + */ + if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt + t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag + } + + if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt + //ser->print("MC0\r\n"); + t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag + } + + t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC + while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync + + for (int i = 0; i < MAX_TIMEOUTS-1; i++) { + struct TimeoutVector *tvp = &TimeOuts[i]; + if (tvp->timer && nsecs >= tvp->timer->_timeout) { + Timeout *saveTimer = tvp->timer; + tvp->timer = NULL; + Timeout::_irq_handler(saveTimer); + } + } + /* + * we need to restart the timer for remaining interrupts + * Another reason is that we stopped this counter, in case there are + * remaining counts, we need to re-schedule the counter. + */ + Timeout::restart(); +} + + +/* ----------------- D21 sleep() and deepsleep() code ----------------------*/ + +void sleep(void) +{ + /* + * If we use the native USB port our Serial is SerialUSB + * and if the SerialUSB and connected we should + * not enter into sleep mode because this kills the Arduino USB emulation + */ + SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // disbale SysTick + uint32_t saved_ms = ms_getTicker(); + + if (SerialUSB_active) { + __DSB(); // ensures the completion of memory accesses + __WFI(); // wait for interrupt + } else { +#if 0 // (SAMD20 || SAMD21) + /* Errata: Make sure that the Flash does not power all the way down + * when in sleep mode. */ + NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; +#endif + + SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; // clear deep sleep + PM->SLEEP.reg = 2; // SYSTEM_SLEEPMODE_IDLE_2 IDLE 2 sleep mode. + + __DSB(); // ensures the completion of memory accesses + __WFI(); // wait for interrupt + } + + int count = ms_getTicker() - saved_ms; + if (count > 0) { // update the Arduino Systicks + for (int i = 0; i < count; i++) { + SysTick_Handler(); + } + } + SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // enable SysTick +} + +/* + * TODO + * Check if we need to disable the USB GCLK->CLKCTRL.reg (see USBCore.cpp) + * Check what else we need to disable? + */ + +void deepsleep(void) +{ +#if 0 // (SAMD20 || SAMD21) + /* Errata: Make sure that the Flash does not power all the way down + * when in sleep mode. */ + NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; +#endif + + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // standby mode + //EIC->WAKEUP.bit.WAKEUPEN3 = 1; // enable wakeup on Pin 12/PA19/EXTINT[3] see variants.h + + __DSB(); // ensures the completion of memory accesses + __WFI(); // wait for interrupt +} + +#endif // D21 TCC Timer, sleep, etc- + +#endif // ARDUINO
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-mbed.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-mbed.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,335 @@ +/* + * The file is Licensed under the Apache License, Version 2.0 + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#ifdef ARDUINO + +using namespace std; + +#include "arduino-mbed.h" +#include "arduino-util.h" + +Stream *ser; +bool SerialUSB_active = false; + +void InitSerial(Stream *serial, int timeout_ms) { + ser = serial; + if (serial == (Stream *)&SerialUSB) { + uint32_t start = ms_getTicker(); + + SerialUSB_active = true; + while(!SerialUSB) { + if (ms_getTicker() > start + timeout_ms) { + SerialUSB_active = false; + break; + } + } + if (!SerialUSB_active) { + USB->DEVICE.CTRLA.bit.SWRST = 1; // disconnect the USB Port + while (USB->DEVICE.CTRLA.bit.SWRST == 1); + } + } +} + +static void pinInt00(void); +static void pinInt01(void); +static void pinInt02(void); +static void pinInt03(void); +static void pinInt04(void); +static void pinInt05(void); +static void pinInt06(void); +static void pinInt07(void); +static void pinInt08(void); +static void pinInt09(void); +static void pinInt10(void); +static void pinInt11(void); +static void pinInt12(void); +static void pinInt13(void); +static void pinInt14(void); +static void pinInt15(void); +static void pinInt16(void); +static void pinInt17(void); +static void pinInt18(void); +static void pinInt19(void); +static void pinInt20(void); +static void pinInt21(void); +static void pinInt22(void); +static void pinInt23(void); +static void pinInt24(void); +static void pinInt25(void); +static void pinInt26(void); +static void pinInt27(void); +static void pinInt28(void); +static void pinInt29(void); +static void pinInt30(void); +static void pinInt31(void); +static void pinInt32(void); +static void pinInt33(void); +static void pinInt34(void); +static void pinInt35(void); +static void pinInt36(void); +static void pinInt37(void); +static void pinInt38(void); +static void pinInt39(void); +static void pinInt40(void); +static void pinInt41(void); +static void pinInt42(void); +static void pinInt43(void); +static void pinInt44(void); +static void pinInt45(void); +static void pinInt46(void); +static void pinInt47(void); + + + +#define MAX_MCU_PINS 48 +class InterruptIn; +struct intPtrTable { + void (*func)(void); + InterruptIn *context; +} intPtrTable[MAX_MCU_PINS] = { + { pinInt00, NULL }, + { pinInt01, NULL }, + { pinInt02, NULL }, + { pinInt03, NULL }, + { pinInt04, NULL }, + { pinInt05, NULL }, + { pinInt06, NULL }, + { pinInt07, NULL }, + { pinInt08, NULL }, + { pinInt09, NULL }, + { pinInt10, NULL }, + { pinInt11, NULL }, + { pinInt12, NULL }, + { pinInt13, NULL }, + { pinInt14, NULL }, + { pinInt15, NULL }, + { pinInt16, NULL }, + { pinInt17, NULL }, + { pinInt18, NULL }, + { pinInt19, NULL }, + { pinInt20, NULL }, + { pinInt21, NULL }, + { pinInt22, NULL }, + { pinInt23, NULL }, + { pinInt24, NULL }, + { pinInt25, NULL }, + { pinInt26, NULL }, + { pinInt27, NULL }, + { pinInt28, NULL }, + { pinInt29, NULL }, + { pinInt30, NULL }, + { pinInt31, NULL }, + { pinInt32, NULL }, + { pinInt33, NULL }, + { pinInt34, NULL }, + { pinInt35, NULL }, + { pinInt36, NULL }, + { pinInt37, NULL }, + { pinInt38, NULL }, + { pinInt39, NULL }, + { pinInt40, NULL }, + { pinInt41, NULL }, + { pinInt42, NULL }, + { pinInt43, NULL }, + { pinInt44, NULL }, + { pinInt45, NULL }, + { pinInt46, NULL }, + { pinInt47, NULL } +}; // our max MCUs pins + + + +static void pinInt00(void) { InterruptIn::_irq_handler(intPtrTable[0].context); } +static void pinInt01(void) { InterruptIn::_irq_handler(intPtrTable[1].context); } +static void pinInt02(void) { InterruptIn::_irq_handler(intPtrTable[2].context); } +static void pinInt03(void) { InterruptIn::_irq_handler(intPtrTable[3].context); } +static void pinInt04(void) { InterruptIn::_irq_handler(intPtrTable[4].context); } +static void pinInt05(void) { InterruptIn::_irq_handler(intPtrTable[5].context); } +static void pinInt06(void) { InterruptIn::_irq_handler(intPtrTable[6].context); } +static void pinInt07(void) { InterruptIn::_irq_handler(intPtrTable[7].context); } +static void pinInt08(void) { InterruptIn::_irq_handler(intPtrTable[8].context); } +static void pinInt09(void) { InterruptIn::_irq_handler(intPtrTable[9].context); } +static void pinInt10(void) { InterruptIn::_irq_handler(intPtrTable[10].context); } +static void pinInt11(void) { InterruptIn::_irq_handler(intPtrTable[11].context); } +static void pinInt12(void) { InterruptIn::_irq_handler(intPtrTable[12].context); } +static void pinInt13(void) { InterruptIn::_irq_handler(intPtrTable[13].context); } +static void pinInt14(void) { InterruptIn::_irq_handler(intPtrTable[14].context); } +static void pinInt15(void) { InterruptIn::_irq_handler(intPtrTable[15].context); } +static void pinInt16(void) { InterruptIn::_irq_handler(intPtrTable[16].context); } +static void pinInt17(void) { InterruptIn::_irq_handler(intPtrTable[17].context); } +static void pinInt18(void) { InterruptIn::_irq_handler(intPtrTable[18].context); } +static void pinInt19(void) { InterruptIn::_irq_handler(intPtrTable[19].context); } +static void pinInt20(void) { InterruptIn::_irq_handler(intPtrTable[20].context); } +static void pinInt21(void) { InterruptIn::_irq_handler(intPtrTable[21].context); } +static void pinInt22(void) { InterruptIn::_irq_handler(intPtrTable[22].context); } +static void pinInt23(void) { InterruptIn::_irq_handler(intPtrTable[23].context); } +static void pinInt24(void) { InterruptIn::_irq_handler(intPtrTable[24].context); } +static void pinInt25(void) { InterruptIn::_irq_handler(intPtrTable[25].context); } +static void pinInt26(void) { InterruptIn::_irq_handler(intPtrTable[26].context); } +static void pinInt27(void) { InterruptIn::_irq_handler(intPtrTable[27].context); } +static void pinInt28(void) { InterruptIn::_irq_handler(intPtrTable[28].context); } +static void pinInt29(void) { InterruptIn::_irq_handler(intPtrTable[29].context); } +static void pinInt30(void) { InterruptIn::_irq_handler(intPtrTable[30].context); } +static void pinInt31(void) { InterruptIn::_irq_handler(intPtrTable[31].context); } +static void pinInt32(void) { InterruptIn::_irq_handler(intPtrTable[32].context); } +static void pinInt33(void) { InterruptIn::_irq_handler(intPtrTable[33].context); } +static void pinInt34(void) { InterruptIn::_irq_handler(intPtrTable[34].context); } +static void pinInt35(void) { InterruptIn::_irq_handler(intPtrTable[35].context); } +static void pinInt36(void) { InterruptIn::_irq_handler(intPtrTable[36].context); } +static void pinInt37(void) { InterruptIn::_irq_handler(intPtrTable[37].context); } +static void pinInt38(void) { InterruptIn::_irq_handler(intPtrTable[38].context); } +static void pinInt39(void) { InterruptIn::_irq_handler(intPtrTable[39].context); } +static void pinInt40(void) { InterruptIn::_irq_handler(intPtrTable[40].context); } +static void pinInt41(void) { InterruptIn::_irq_handler(intPtrTable[41].context); } +static void pinInt42(void) { InterruptIn::_irq_handler(intPtrTable[42].context); } +static void pinInt43(void) { InterruptIn::_irq_handler(intPtrTable[43].context); } +static void pinInt44(void) { InterruptIn::_irq_handler(intPtrTable[44].context); } +static void pinInt45(void) { InterruptIn::_irq_handler(intPtrTable[45].context); } +static void pinInt46(void) { InterruptIn::_irq_handler(intPtrTable[46].context); } +static void pinInt47(void) { InterruptIn::_irq_handler(intPtrTable[47].context); } + + +void wait_ms(uint32_t ms) +{ + uint32_t start = ms_getTicker(); + + while (true) { + uint32_t t = ms_getTicker(); + if (t < start) // warp. + start = 0; + if (t > (start + ms)) + break; + } +} + +struct TimeoutVector TimeOuts[MAX_TIMEOUTS]; + +void +InterruptIn::rise(Callback<void()> func) { + if (_gpioPin >= MAX_MCU_PINS-1) + return; + if (func) { + _func = func; + intPtrTable[_gpioPin].context = this; + attachInterrupt(MYdigitalPinToInterrupt(_gpioPin), intPtrTable[_gpioPin].func, RISING); + } else { + _func = InterruptIn::donothing; + intPtrTable[_gpioPin].context = NULL; + detachInterrupt(_gpioPin); + } +}; + +void +InterruptIn::fall(Callback<void()> func) { + if (func) { + _func = func; + intPtrTable[_gpioPin].context = this; + attachInterrupt(MYdigitalPinToInterrupt(_gpioPin), intPtrTable[_gpioPin].func, FALLING); + } else { + _func = InterruptIn::donothing; + intPtrTable[_gpioPin].context = NULL; + detachInterrupt(_gpioPin); + } +} + + +uint32_t s_getTicker(void) +{ + long long ns = ns_getTicker(); + ns /= (long long)1000000000; // to secs + + int secs = ns; + return secs; +} + + +uint32_t ms_getTicker(void) +{ + uint32_t us = us_getTicker(); + + us /= 1000; // to ms + return us; +} + +uint32_t us_getTicker(void) +{ + long long ns = ns_getTicker(); + + ns /= (long long)1000; // to us + uint32_t us = ns & 0xffffffff; + + return us; +} + + +void +Timeout::insert(void) +{ + noInterrupts(); + for (int i = 0; i < MAX_TIMEOUTS-1; i++) { + struct TimeoutVector *tvp = &TimeOuts[i]; + if (tvp->timer == this) // already here, timer has been restartet. + break; + if (tvp->timer == NULL) { + tvp->timer = this; + break; + } + } + interrupts(); +} + +void +Timeout::remove(void) +{ + noInterrupts(); + for (int i = 0; i < MAX_TIMEOUTS-1; i++) { + struct TimeoutVector *tvp = &TimeOuts[i]; + if (tvp->timer == this) { + tvp->timer = NULL; + break; + } + } + interrupts(); +} + + +void +Timeout::restart() +{ + Tcc *t = getTimeout_tcc(); + uint64_t timeout = ~0; + + /* + * find the lowest timeout value which is our the next timeout + * zero means stop the timer. + */ + noInterrupts(); + for (int i = 0; i < MAX_TIMEOUTS-1; i++) { + struct TimeoutVector *tvp = &TimeOuts[i]; + if (tvp->timer) { + if (tvp->timer->_timeout < timeout) { + timeout = tvp->timer->_timeout; + } + } + } + interrupts(); + + if (timeout == (uint64_t)~0) { + stopTimer(t); + return; + } + + uint64_t nsecs = ns_getTicker(); + + if (timeout > nsecs) { + startTimer(t, (uint64_t)timeout - (uint64_t)nsecs); + return; + } else { + startTimer(t, (uint64_t)1); // just one nsec to trigger interrrupt + } +} + +#endif // ARDUINO
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-mbed.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-mbed.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,330 @@ +/* + * The file is Licensed under the Apache License, Version 2.0 + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + + + +#ifdef ARDUINO +#ifndef __ARDUINO_MBED_H__ +#define __ARDUINO_MBED_H__ + +#include <arduino.h> +#include "Callback-A.h" +#include <SPI.h> +#undef min +#undef max +#undef map + +typedef int PinName; +#define NC -1 +/* we need to redefine out dprintf because stdio.h uses the same name */ +#define dprint dxprintf +#if ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10606 + #define MYdigitalPinToInterrupt(x) digitalPinToInterrupt(x) +#else + #define MYdigitalPinToInterrupt(x) (x) +#endif + +void InitSerial(Stream *serial, int timeout_ms); +extern Stream *ser; +extern bool SerialUSB_active; + +/* + * Arduino_d21.cpp + */ +extern void startTimer(Tcc *t, uint64_t delay_ns); +extern void stopTimer(Tcc *t); +extern uint64_t ns_getTicker(void); +extern Tcc *getTimeout_tcc(void); +extern int CPUID(uint8_t *buf, int maxSize, uint32_t xorval); + + +extern void sleep(void); +extern void deepsleep(void); + +#define MAX_TIMEOUTS 10 +class Timeout; +struct TimeoutVector { + Timeout *timer; +}; +extern TimeoutVector TimeOuts[]; + + +/* + * Arduino-mbed.cpp + */ +extern uint32_t s_getTicker(void); +extern uint32_t ms_getTicker(void); +extern uint32_t us_getTicker(void); +extern void wait_ms(uint32_t ms); + + +enum PinMode { + PullUp = 1, + PullDown = 2, +}; + +class DigitalInOut { +public: + DigitalInOut(PinName pin) { + _gpioPin = pin; + } + void write(int value) { + digitalWrite(_gpioPin, value == 0 ? LOW : HIGH); + }; + + void output() { + pinMode(_gpioPin, OUTPUT); + }; + + void input() { + pinMode(_gpioPin, INPUT); + }; + + void mode(PinMode pull) { + switch(pull) { + case PullUp: + pinMode(_gpioPin, INPUT_PULLUP); + break; + case PullDown: + pinMode(_gpioPin, INPUT_PULLDOWN); + break; + } + } + + int read() { + if (digitalRead(_gpioPin) == HIGH) + return 1; + else + return 0; + }; + operator int() { + return read(); + }; + + DigitalInOut& operator= (int value) { + // Underlying write is thread safe + write(value); + return *this; + } + + DigitalInOut& operator= (DigitalInOut& rhs) { + write(rhs.read()); + return *this; + } + +private: + int _gpioPin; +}; + +class DigitalOut : public DigitalInOut { +public: + + DigitalOut(PinName pin) : DigitalInOut(pin) { + output(); + } + + DigitalOut& operator= (int value) { + write(value); + return *this; + } + +}; + +class DigitalIn : public DigitalInOut { +public: + + DigitalIn(PinName pin) : DigitalInOut(pin) { + input(); + } +}; + +class XSPI { +public: + XSPI(PinName mosi, PinName miso, PinName sclk) { + _mosi = mosi; + _miso = miso; + _sclk = sclk; + if (mosi == PIN_SPI_MOSI && miso == PIN_SPI_MISO && sclk == PIN_SPI_SCK) + _spi = &SPI; +#if SPI_INTERFACES_COUNT > 1 + else if (mosi == PIN_SPI1_MOSI && miso == PIN_SPI1_MISO && sclk == PIN_SPI1_SCK) + _spi = &SPI1; +#endif +#if SPI_INTERFACES_COUNT > 2 + else if (mosi == PIN_SPI2_MOSI && miso == PIN_SPI2_MISO && sclk == PIN_SPI2_SCK) + _spi = &SPI2; +#endif + else { + _spi = NULL; + return; + } + _hz = 1000000; + _mode = SPI_MODE0; + _spi->beginTransaction(SPISettings(_hz, MSBFIRST, _mode)); + } + ~XSPI() { + _spi->endTransaction(); + }; + + void format(int bits, int mode = 0) { + if (mode == 0) + _mode = SPI_MODE0; + else if (mode == 1) + _mode = SPI_MODE1; + else if (mode == 2) + _mode = SPI_MODE2; + else if (mode == 3) + _mode = SPI_MODE3; + else + _mode = SPI_MODE0; + _bits = bits; + _spi->endTransaction(); + _spi->beginTransaction(SPISettings(_hz, MSBFIRST, _mode)); + } + void frequency(int hz) { + _hz = hz; + _spi->endTransaction(); + _spi->beginTransaction(SPISettings(_hz, MSBFIRST, _mode)); + } + + int write(int value) { + int ret = _spi->transfer(value); + return ret; + } + +private: + SPIClass *_spi; + int _hz; + int _mode; + int _bits; + int _mosi, _miso, _sclk; +}; + +class InterruptIn { +public: + static void donothing(void) { + } + + InterruptIn(PinName pin) : _func() { + _gpioPin = pin; + _func = InterruptIn::donothing; + pinMode(_gpioPin, INPUT); + } + + ~InterruptIn() { + detachInterrupt(MYdigitalPinToInterrupt(_gpioPin)); + }; + + static void _irq_handler(InterruptIn *id) { + if (id) + id->_func(); + } + + void rise(Callback<void()> func); + + void fall(Callback<void()> func); + + void mode(PinMode pull) { + switch(pull) { + case PullUp: + pinMode(_gpioPin, INPUT_PULLUP); + break; + case PullDown: + pinMode(_gpioPin, INPUT_PULLDOWN); + break; + } + } +private: + int _gpioPin; + Callback<void()> _func; +}; + + + +class Timer { +public: + void start(void) { + _time = ns_getTicker(); + } + uint32_t read_sec(void) { + int64_t n = ns_getTicker() - (uint64_t)_time; + n /= (uint64_t)1000000000; + return n; + } + uint32_t read_ms(void) { + int64_t n = ns_getTicker() - (uint64_t)_time; + n /= (uint64_t)1000000; + return n; + } + uint32_t read_us(void) { + int64_t n = ns_getTicker() - (uint64_t)_time; + n /= (uint64_t)1000; + return n; + } +private: + uint64_t _time; +}; + + +class Timeout { +public: + Timeout() : _func() { + } + ~Timeout() { + detach(); + } + + void attach_sec(Callback<void()> func, uint32_t secs) { + if (secs == 0) + return detach(); + _func = func; + _timeout = ns_getTicker() + (uint64_t)secs * (uint64_t)1000000000; + insert(); + restart(); + } + + void attach(Callback<void()> func, uint32_t msecs) { + if (msecs == 0) + return detach(); + _func = func; + _timeout = ns_getTicker() + (uint64_t)msecs * (uint64_t)1000000; + insert(); + restart(); + } + + void attach_us(Callback<void()> func, long usecs) { + if (usecs == 0) + return detach(); + _func = func; + _timeout = ns_getTicker() + (uint64_t)usecs * (uint64_t)1000; + insert(); + restart(); + } + + void detach(void) { + _func = NULL; + remove(); + restart(); + } + + static void _irq_handler(Timeout *tp) { + if (tp) { + tp->_func(); + } + } + + static void restart(void); + uint64_t _timeout; // in ns this lasts for 539 years. +protected: + void insert(void); + void remove(void); +private: + Callback<void()> _func; +}; + +#endif // __ARDUINO_MBED_H__ + +#endif // ARDUINO
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-util.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-util.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,99 @@ +#ifdef ARDUINO + +#include <Arduino.h> +#include "arduino-util.h" +#include <cstdarg> +#include <stdio.h> + + +char tmpbuf[160]; +extern int us_getTicker(void); +extern int s_getTicker(void); +extern Stream *ser; + +void +dprintf(const char *format, ...) +{ + static volatile bool busy; + if (busy) + return; + busy = true; + + int secs = s_getTicker(); + int s = secs % 60; + int m = secs / 60; + int h = secs / 3600; + int us = us_getTicker() % 1000000; + + snprintf(tmpbuf, sizeof(tmpbuf)-1, "%02d:%02d:%02d.%.06d ", h, m, s, us); + ser->write(tmpbuf, (int) sizeof "00:00:34.3436868 " -1); + + va_list arg; + va_start(arg, format); + int len = vsnprintf(tmpbuf, sizeof(tmpbuf)-3, format, arg); + tmpbuf[len] = '\r'; + tmpbuf[len+1] = '\n'; + tmpbuf[len+2] = 0; + ser->write(tmpbuf, len+3); + va_end(arg); + busy = false; +} + +void +rprintf(const char *format, ...) +{ + va_list arg; + va_start(arg, format); + int len = vsnprintf(tmpbuf, sizeof(tmpbuf)-3, format, arg); + tmpbuf[len] = 0; + ser->write(tmpbuf, len+1); + va_end(arg); +} + +void +dump(const char *title, const void *data, int len) +{ + dprintf("dump(\"%s\", 0x%x, %d bytes)", title, data, len); + + int i, j, cnt; + unsigned char *u; + const int width = 16; + const int seppos = 7; + + cnt = 0; + u = (unsigned char *)data; + while (len > 0) { + rprintf("%08x: ", (unsigned int)data + cnt); + cnt += width; + j = len < width ? len : width; + for (i = 0; i < j; i++) { + rprintf("%2.2x ", *(u + i)); + if (i == seppos) + ser->write(' '); + } + ser->write(' '); + if (j < width) { + i = width - j; + if (i > seppos + 1) + ser->write(' '); + while (i--) { + ser->print(" "); + } + } + for (i = 0; i < j; i++) { + int c = *(u + i); + if (c >= ' ' && c <= '~') + ser->write(c); + else + ser->write('.'); + if (i == seppos) + ser->write(' '); + } + len -= width; + u += width; + ser->print("\r\n"); + } + ser->print("--\r\n"); + +} +#endif
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/arduino-util.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,18 @@ +/* + * The file is Licensed under the Apache License, Version 2.0 + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#ifdef ARDUINO +#ifndef __ARDUINO_UTIL_H__ +#define __ARDUINO_UTIL_H__ + + +extern void dprintf(const char *format, ...); + +extern void dump(const char *title, const void *data, int len); + +#endif // __ARDUINO_UTIL_H__ + +#endif
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/examples/TimerTest/TimerTest.ino --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/examples/TimerTest/TimerTest.ino Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,73 @@ + +#include "arduino-mbed.h" + +void TestTimeoutFunc(void); +void TestTimeoutFunc55(void); +void TestTimeoutFunc10(void); +void TestTimeoutFunc1m(void); +void SwitchInput(void); + +#define SW0 3 // switch needs pullup +#define LED LED_BUILTIN +#define MYSERIAL Serial + +DigitalOut led(LED); +InterruptIn intr(SW0); +Timeout tp; +Timeout tp2; +Timeout tp3; +Timeout tp4; + +void setup() { + MYSERIAL.begin(230400); + InitSerial(&MYSERIAL); + + ser->println("TimerTest"); + + tp.attach(callback(&TestTimeoutFunc), 1000); + tp2.attach(callback(&TestTimeoutFunc55), 5500); + tp3.attach(callback(&TestTimeoutFunc10), 10000); + // tp4.attach(callback(&TestTimeoutFunc1m), 1); + + intr.mode(PullUp); + intr.fall(callback(&SwitchInput)); +} + +void loop() { + led = !led; + + sleep(); // or deepsleep() +} + + + +void TestTimeoutFunc(void) { + tp.attach(callback(&TestTimeoutFunc), 1000); + led = !led; + ser->print(ms_getTicker(), DEC); + ser->println(" TestTimeoutFunc 1 sec"); +} + +void TestTimeoutFunc55(void) { + tp2.attach(callback(&TestTimeoutFunc55), 5500); + ser->print(ms_getTicker(), DEC); + ser->println(" TestTimeoutFunc 5.5 sec"); +} + + +void TestTimeoutFunc10(void) { + tp3.attach(callback(&TestTimeoutFunc10), 10000); + ser->print(ms_getTicker(), DEC); + ser->println(" TestTimeoutFunc 10 sec"); +} + + +void TestTimeoutFunc1m(void) { + tp4.attach(callback(&TestTimeoutFunc1m), 1); +} + +void SwitchInput(void) { + ser->print(ms_getTicker(), DEC); + ser->println(" SwitchInput"); + led = !led; +}
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/library.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/Arduino-mbed-APIs/library.properties Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,9 @@ +name=Arduino-mbed-APIs +version=1.0.0 +author=Helmut Tschemernjak <helmut2009@me.com> +maintainer=Helmut Tschemernjak <helmut2009@me.com> +sentence=Arduino-mbed-APIs to support mbed like APIs including Timer, Timeout, SPI, InterruptIn, DigialIn, DigitalOut, DigitalInOut, sleep, deepsleep, it also includes a SAMD TCC based Timer implementation for correct timestamps and timeouts. +paragraph= +category=Other +url=http://www.radioshuttle.de +architectures=samd
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/LICENSE.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/LICENSE.txt Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,25 @@ +--- Revised BSD License --- +Copyright (c) 2013, SEMTECH S.A. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Semtech corporation nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/LoRa_TODO.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/LoRa_TODO.txt Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,50 @@ + +Move finished tasks to Done section: + +TODOs: +- add support for Linux - add sx1276-Linux-hal.h/cpp +- Add support to provide the send/receive packet buffer, + no need to allocate packet data in the sx1276 driver. Can be provided + Rx/Tx parameters, this avoids double memory usage +- Add support for larger Lora packets (can be up to 2048 bytes) + this feature is not so important, however the current implementation + is very basic. +- It is a little bit strange that RX/TX/Cad Timeout Timer calling the + some handler OnTimeoutIrq. Maybe we just need a single timer, or + it is a good idea to split the OnTimeoutIrq function into separate + callbacks for RX/TX/Cad timeouts +- Test if the SX1276 timeouts. Does rx/tx/sync really uses three different + timers or just one at a time. +- Add API to set the LNA gain + + + +Done: +- Started a Generic SX1276 driver to support all SX1276 modules (May-2017 Helmut) +- Migrated typedefs code into sx1276.h (7-May-2017 Helmut) +- Migrated enum code into sx1276.h/radio.h (7-May-2017 Helmut) +- Verify the Murata ANT Switch code +- MURATA PA_BOOST case,is _antSwitchTXBoost right? (Same as STM sample code) +- Check of the MURATA TCXO config is correct (implemented, check JP9 on STM L0 board) +- Make the timers more generic and move the OS code into the HAL layer. (May 2017 Helmut) +- Removed pull down on dio=-dio5 for L151 &LPC11U6X which make no sense to me. May 2017 Helmut +- Added radio API support to receive the MaxMTUSize (May 2017 Helmut) +- Added Send optional Send() parameter to include a header, + this saves additional buffers. (May 2017 Helmut) +- Added proper void * type from sending data, uint8_t * is not appropriate (May 2017 Helmut) +- Use also void pointer for FiFo Write/Read and regular SPI Read/Write +- Added return value to Init, we check for a radio availability (May 2017 Helmut) +- Added a RxSignalPending which verifies if we have a signal pending in receive state. (May 2017 Helmut) +- Added LoRa bandwidth mapping table, now the SetRx/Tx frequency is in Hz. (May 2017 Helmut) +- Enabled MURATA_SX1276 for the MURATA_SX1276 chip (May 2017 Helmut) +- Made SetRfTxPower public to allow easily power TX changes (May 2017 Helmut) +- Added userData and userThisPtr into the radio events, this allows to call C++ + functions and in can include a context via the userData +- Add support for Cad detection before sending a packet, already done in higher + level protocols +- Added initial Arduino support, needs more testing/completion. +- Support for Arduino completed, initial version works. +- Added GetFrequency support + The Murata’s Frequency shift using an TCXO us about 58 Hz + The RFM95 against Murata is about 3300 Hz + RFM95 against RFM95 testing will follow.
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/README.md Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,53 @@ +# SX1276Generic Driver +/* +* (c) 2017 Helmut Tschemernjak (Helmut64 on mbed). +* 30826 Garbsen (Hannover) Germany +*/ + +This library represents a common SX1276 module driver supporting SX1276 +based modules. The approach is to support multiple OS versions including +mbed, Arduino and Linux using the same driver code and little +adjustments for the different OS version. The SX1276 driver is based on +the Semtech 1276 code which can be seen in the revisions of this library +repository. + +## Supported LoRa Modules + +The following Lora modules are supported: +- HopeRF RFM95 +- Murata MURATA_SX1276 (CMWX1ZZABZ-078, used the STM B_L072Z_LRWAN1 board) +- SX1276MB1MAS (433, 868 MHz version) +- SX1276MB1LAS (433, 915 MHz version) + +## Getting Started for Developers +Import the mbed sample project: +http://developer.mbed.org/users/Helmut64/code/STM32L0_LoRa +- It includes a PingPong sample code +- It includes a PinMap.h which allows to define the LoRa SPI, +DIO interrupt, reset and antenna pins. +The STM32L0_LoRa is a turnkey sample application for the STM B_L072Z_LRWAN1, +however it will work with all other mbed based boards by adjusting the PinMap.h + +## Developers help needed +A list of tasks is documented in the file: LoRa_TODO.txt +I (Helmut Tschemernjak) spend a very significant time to complete the +initial version of the SX1276Generic packet driver. Enhancements, +further module support and tuning is more than welcome. Please send me +your patches via mbed. Also questions can be submitted in the mbed +“Questions” area or a personal message via mbed. + +## Future developments +I work in a advanced private protocol using basic LoRa modules to +communicate between simple nodes (battery powered) and stations +(permanent power). The station should support thousands of nodes running +on an Linux based OS using this 1276Generic driver or the LoRa +concentrator module. The station should also work on mbed or Arduino +assuming sufficient memory is provided. I believe there is an +opportunity to do a better protocol compared to the official LoRa +protocol which requires an Concentrator, a LoRa server and an +application server. The idea is to over only efficient, reliable and +secure communication between the nodes and the stations. Further +forwarding to MQTT and other network services can be handled separately +on the station. + +
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/radio/radio.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/radio/radio.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,20 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: Interface for the radios, contains the main functions that a radio needs, and 5 callback functions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#include "radio.h" + +Radio::Radio( RadioEvents_t *events ) +{ + this->RadioEvents = events; +}
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/radio/radio.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/radio/radio.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,516 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: Interface for the radios, contains the main functions that a radio needs, and 5 callback functions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#ifndef __RADIO_H__ +#define __RADIO_H__ + +#ifdef __MBED__ +#include "mbed.h" +#endif +#ifdef ARDUINO +#include <arduino.h> +#endif + +/*! + * Radio driver internal state machine states definition + */ +typedef enum RadioState +{ + RF_IDLE = 0, + RF_RX_RUNNING, + RF_TX_RUNNING, + RF_CAD, +} RadioState_t; + + +/*! + * Type of the modem. [LORA / FSK] + */ +typedef enum ModemType +{ + MODEM_FSK = 0, + MODEM_LORA +}RadioModems_t; + + +/*! + * Radio LoRa modem parameters + */ +typedef struct +{ + int8_t Power; + uint32_t Bandwidth; + uint32_t Datarate; + bool LowDatarateOptimize; + uint8_t Coderate; + uint16_t PreambleLen; + bool FixLen; + uint8_t PayloadLen; + bool CrcOn; + bool FreqHopOn; + uint8_t HopPeriod; + bool IqInverted; + bool RxContinuous; + uint32_t TxTimeout; + bool PublicNetwork; +}RadioLoRaSettings_t; + +/*! + * Radio FSK modem parameters + */ +typedef struct +{ + int8_t Power; + uint32_t Fdev; + uint32_t Bandwidth; + uint32_t BandwidthAfc; + uint32_t Datarate; + uint16_t PreambleLen; + bool FixLen; + uint8_t PayloadLen; + bool CrcOn; + bool IqInverted; + bool RxContinuous; + uint32_t TxTimeout; + uint32_t RxSingleTimeout; +}RadioFskSettings_t; + +/*! + * Radio FSK packet handler state + */ +typedef struct +{ + uint8_t PreambleDetected; + uint8_t SyncWordDetected; + int8_t RssiValue; + int32_t AfcValue; + uint8_t RxGain; + uint16_t Size; + uint16_t NbBytes; + uint8_t FifoThresh; + uint8_t ChunkSize; +}RadioFskPacketHandler_t; + +/*! + * Radio LoRa packet handler state + */ +typedef struct +{ + int8_t SnrValue; + int8_t RssiValue; + uint8_t Size; +}RadioLoRaPacketHandler_t; + +/*! + * Radio Settings + */ +typedef struct +{ + RadioState State; + ModemType Modem; + uint32_t Channel; + RadioFskSettings_t Fsk; + RadioFskPacketHandler_t FskPacketHandler; + RadioLoRaSettings_t LoRa; + RadioLoRaPacketHandler_t LoRaPacketHandler; +}RadioSettings_t; + +/*! + * @brief Radio driver callback functions + */ +typedef struct +{ + /*! + * @brief Tx Done callback prototype. + */ + void ( *TxDone )(void *radio, void *userThisPtr, void *userData); + /*! + * @brief Tx Timeout callback prototype. + */ + void ( *TxTimeout )(void *radio, void *userThisPtr, void *userData); + /*! + * @brief Rx Done callback prototype. + * + * @param [IN] payload Received buffer pointer + * @param [IN] size Received buffer size + * @param [IN] rssi RSSI value computed while receiving the frame [dBm] + * @param [IN] snr Raw SNR value given by the radio hardware + * FSK : N/A ( set to 0 ) + * LoRa: SNR value in dB + */ + void ( *RxDone )(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); + /*! + * @brief Rx Timeout callback prototype. + */ + void ( *RxTimeout )(void *radio, void *userThisPtr, void *userData); + /*! + * @brief Rx Error callback prototype. + */ + void ( *RxError )(void *radio, void *userThisPtr, void *userData); + /*! + * \brief FHSS Change Channel callback prototype. + * + * \param [IN] currentChannel Index number of the current channel + */ + void ( *FhssChangeChannel )(void *radio, void *userThisPtr, void *userData, uint8_t currentChannel ); + + /*! + * @brief CAD Done callback prototype. + * + * @param [IN] channelDetected Channel Activity detected during the CAD + */ + void ( *CadDone ) (void *radio, void *userThisPtr, void *userData, bool channelActivityDetected ); + + /* + * Optional data which is being provided in callbacks + * can be used e.g. for the C++ this pointer. + */ + void *userThisPtr; + + /* + * Optional data which allows to bring in data structures pointer + * for a given radio. As callbacks are being called in interrupt level + * the userData is perfect to know the context without iterating this + * data structures. + */ + void *userData; + +}RadioEvents_t; + +/*! + * Interface for the radios, contains the main functions that a radio needs, and 5 callback functions + */ +class Radio +{ +protected: + RadioEvents_t* RadioEvents; + +public: + //------------------------------------------------------------------------- + // Constructor + //------------------------------------------------------------------------- + /*! + * @brief Constructor of the radio object, the parameters are the callback functions described in the header. + * + * @param [IN] events Structure containing the driver callback functions + */ + Radio( RadioEvents_t *events ); + virtual ~Radio( ) {}; + + //------------------------------------------------------------------------- + // Pure virtual functions + //------------------------------------------------------------------------- + + /*! + * @brief Initializes the radio + * + * @param [IN] events Structure containing the driver callback functions + */ + virtual bool Init( RadioEvents_t *events ) = 0; + + /*! + * @brief Return current radio status, returns true if a radios has been found. + * + * @param status Radio status. [RF_IDLE, RX_RUNNING, TX_RUNNING, CAD_RUNNING] + */ + virtual RadioState GetStatus( void ) = 0; + + /*! + * @brief Configures the radio with the given modem + * + * @param [IN] modem Modem to be used [0: FSK, 1: LoRa] + */ + virtual void SetModem( RadioModems_t modem ) = 0; + + /*! + * @brief Sets the channel frequency + * + * @param [IN] freq Channel RF frequency + */ + virtual void SetChannel( uint32_t freq ) = 0; + + /*! + * @brief Sets the channels configuration + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] freq Channel RF frequency + * @param [IN] rssiThresh RSSI threshold + * + * @retval isFree [true: Channel is free, false: Channel is not free] + */ + virtual bool IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ) = 0; + + /*! + * @brief Generates a 32 bits random value based on the RSSI readings + * + * \remark This function sets the radio in LoRa modem mode and disables + * all interrupts. + * After calling this function either Radio.SetRxConfig or + * Radio.SetTxConfig functions must be called. + * + * @retval randomValue 32 bits random value + */ + virtual uint32_t Random( void )= 0; + + /*! + * @brief Sets the reception parameters + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] bandwidth Sets the bandwidth + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * @param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * @param [IN] coderate Sets the coding rate ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * @param [IN] bandwidthAfc Sets the AFC Bandwidth ( FSK only ) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * @param [IN] preambleLen Sets the Preamble length ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: Length in symbols ( the hardware adds 4 more symbols ) + * @param [IN] symbTimeout Sets the RxSingle timeout value + * FSK : timeout number of bytes + * LoRa: timeout in symbols + * @param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * @param [IN] payloadLen Sets payload length when fixed lenght is used + * @param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * @param [IN] freqHopOn Enables disables the intra-packet frequency hopping [0: OFF, 1: ON] (LoRa only) + * @param [IN] hopPeriod Number of symbols bewteen each hop (LoRa only) + * @param [IN] iqInverted Inverts IQ signals ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * @param [IN] rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ + virtual void SetRxConfig ( RadioModems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ) = 0; + + /*! + * @brief Sets the transmission parameters + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] power Sets the output power [dBm] + * @param [IN] fdev Sets the frequency deviation ( FSK only ) + * FSK : [Hz] + * LoRa: 0 + * @param [IN] bandwidth Sets the bandwidth ( LoRa only ) + * FSK : 0 + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * @param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * @param [IN] coderate Sets the coding rate ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * @param [IN] preambleLen Sets the preamble length + * @param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * @param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * @param [IN] freqHopOn Enables disables the intra-packet frequency hopping [0: OFF, 1: ON] (LoRa only) + * @param [IN] hopPeriod Number of symbols bewteen each hop (LoRa only) + * @param [IN] iqInverted Inverts IQ signals ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * @param [IN] timeout Transmission timeout [us] + */ + virtual void SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ) = 0; + + /*! + * @brief Checks if the given RF frequency is supported by the hardware + * + * @param [IN] frequency RF frequency to be checked + * @retval isSupported [true: supported, false: unsupported] + */ + virtual bool CheckRfFrequency( uint32_t frequency ) = 0; + + /*! + * @brief Computes the packet time on air for the given payload + * + * \Remark Can only be called once SetRxConfig or SetTxConfig have been called + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] pktLen Packet payload length + * + * @retval airTime Computed airTime for the given packet payload length + */ + virtual uint32_t TimeOnAir ( RadioModems_t modem, int16_t pktLen ) = 0; + + /*! + * @brief Sends the buffer of size. Prepares the packet to be sent and sets + * the radio in transmission + * + * @param [IN]: buffer Buffer pointer + * @param [IN]: size Buffer size + * @param [IN]: buffer Header pointer + * @param [IN]: size Header size + */ + virtual void Send( void *buffer, int16_t size, void *header = NULL, int16_t hsize = 0) = 0; + + /*! + * @brief Sets the radio in sleep mode + */ + virtual void Sleep( void ) = 0; + + /*! + * @brief Sets the radio in standby mode + */ + virtual void Standby( void ) = 0; + + /*! + * @brief Sets the radio in CAD mode + */ + virtual void StartCad( void ) = 0; + + /*! + * @brief Sets the radio in reception mode for the given time + * @param [IN] timeout Reception timeout [us] + * [0: continuous, others timeout] + */ + virtual void Rx( uint32_t timeout ) = 0; + + /*! + * @brief Check is radio receives a signal + */ + virtual bool RxSignalPending() = 0; + + + /*! + * @brief Sets the radio in transmission mode for the given time + * @param [IN] timeout Transmission timeout [us] + * [0: continuous, others timeout] + */ + virtual void Tx( uint32_t timeout ) = 0; + + /*! + * @brief Sets the radio in continuous wave transmission mode + * + * @param [IN]: freq Channel RF frequency + * @param [IN]: power Sets the output power [dBm] + * @param [IN]: time Transmission mode timeout [s] + */ + virtual void SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ) = 0; + + /*! + * @brief Returns the maximal transfer unit for a given modem + * + * @retval MTU size in bytes + */ + virtual int16_t MaxMTUSize( RadioModems_t modem ) = 0; + + /*! + * @brief Reads the current RSSI value + * + * @retval rssiValue Current RSSI value in [dBm] + */ + virtual int16_t GetRssi ( RadioModems_t modem ) = 0; + + /*! + * @brief Reads the current frequency error + * + * @retval frequency error value in [Hz] + */ + virtual int32_t GetFrequencyError( RadioModems_t modem ) = 0; + + /*! + * @brief Writes the radio register at the specified address + * + * @param [IN]: addr Register address + * @param [IN]: data New register value + */ + virtual void Write ( uint8_t addr, uint8_t data ) = 0; + + /*! + * @brief Reads the radio register at the specified address + * + * @param [IN]: addr Register address + * @retval data Register value + */ + virtual uint8_t Read ( uint8_t addr ) = 0; + + /*! + * @brief Writes multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [IN] buffer Buffer containing the new register's values + * @param [IN] size Number of registers to be written + */ + virtual void Write( uint8_t addr, void *buffer, uint8_t size ) = 0; + + /*! + * @brief Reads multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [OUT] buffer Buffer where to copy the registers data + * @param [IN] size Number of registers to be read + */ + virtual void Read ( uint8_t addr, void *buffer, uint8_t size ) = 0; + + /*! + * @brief Writes the buffer contents to the Radio FIFO + * + * @param [IN] buffer Buffer containing data to be put on the FIFO. + * @param [IN] size Number of bytes to be written to the FIFO + */ + virtual void WriteFifo( void *buffer, uint8_t size ) = 0; + + /*! + * @brief Reads the contents of the Radio FIFO + * + * @param [OUT] buffer Buffer where to copy the FIFO read data. + * @param [IN] size Number of bytes to be read from the FIFO + */ + virtual void ReadFifo( void *buffer, uint8_t size ) = 0; + + /*! + * @brief Sets the maximum payload length. + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] max Maximum payload length in bytes + */ + virtual void SetMaxPayloadLength( RadioModems_t modem, uint8_t max ) = 0; + + /*! + * @brief Sets the network to public or private. Updates the sync byte. + * + * @remark Applies to LoRa modem only + * + * @param [IN] enable if true, it enables a public network + */ + virtual void SetPublicNetwork( bool enable ) = 0; + + /*! + * \brief Sets the radio output power. + * + * @param [IN] power Sets the RF output power + */ + virtual void SetRfTxPower( int8_t power ) = 0; + +}; + +#endif // __RADIO_H__
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/registers/sx1276Regs-Fsk.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/registers/sx1276Regs-Fsk.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,1134 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: SX1276 FSK modem registers and bits definitions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __SX1276_REGS_FSK_H__ +#define __SX1276_REGS_FSK_H__ + +/*! + * ============================================================================ + * SX1276 Internal registers Address + * ============================================================================ + */ +#define REG_FIFO 0x00 +// Common settings +#define REG_OPMODE 0x01 +#define REG_BITRATEMSB 0x02 +#define REG_BITRATELSB 0x03 +#define REG_FDEVMSB 0x04 +#define REG_FDEVLSB 0x05 +#define REG_FRFMSB 0x06 +#define REG_FRFMID 0x07 +#define REG_FRFLSB 0x08 +// Tx settings +#define REG_PACONFIG 0x09 +#define REG_PARAMP 0x0A +#define REG_OCP 0x0B +// Rx settings +#define REG_LNA 0x0C +#define REG_RXCONFIG 0x0D +#define REG_RSSICONFIG 0x0E +#define REG_RSSICOLLISION 0x0F +#define REG_RSSITHRESH 0x10 +#define REG_RSSIVALUE 0x11 +#define REG_RXBW 0x12 +#define REG_AFCBW 0x13 +#define REG_OOKPEAK 0x14 +#define REG_OOKFIX 0x15 +#define REG_OOKAVG 0x16 +#define REG_RES17 0x17 +#define REG_RES18 0x18 +#define REG_RES19 0x19 +#define REG_AFCFEI 0x1A +#define REG_AFCMSB 0x1B +#define REG_AFCLSB 0x1C +#define REG_FEIMSB 0x1D +#define REG_FEILSB 0x1E +#define REG_PREAMBLEDETECT 0x1F +#define REG_RXTIMEOUT1 0x20 +#define REG_RXTIMEOUT2 0x21 +#define REG_RXTIMEOUT3 0x22 +#define REG_RXDELAY 0x23 +// Oscillator settings +#define REG_OSC 0x24 +// Packet handler settings +#define REG_PREAMBLEMSB 0x25 +#define REG_PREAMBLELSB 0x26 +#define REG_SYNCCONFIG 0x27 +#define REG_SYNCVALUE1 0x28 +#define REG_SYNCVALUE2 0x29 +#define REG_SYNCVALUE3 0x2A +#define REG_SYNCVALUE4 0x2B +#define REG_SYNCVALUE5 0x2C +#define REG_SYNCVALUE6 0x2D +#define REG_SYNCVALUE7 0x2E +#define REG_SYNCVALUE8 0x2F +#define REG_PACKETCONFIG1 0x30 +#define REG_PACKETCONFIG2 0x31 +#define REG_PAYLOADLENGTH 0x32 +#define REG_NODEADRS 0x33 +#define REG_BROADCASTADRS 0x34 +#define REG_FIFOTHRESH 0x35 +// SM settings +#define REG_SEQCONFIG1 0x36 +#define REG_SEQCONFIG2 0x37 +#define REG_TIMERRESOL 0x38 +#define REG_TIMER1COEF 0x39 +#define REG_TIMER2COEF 0x3A +// Service settings +#define REG_IMAGECAL 0x3B +#define REG_TEMP 0x3C +#define REG_LOWBAT 0x3D +// Status +#define REG_IRQFLAGS1 0x3E +#define REG_IRQFLAGS2 0x3F +// I/O settings +#define REG_DIOMAPPING1 0x40 +#define REG_DIOMAPPING2 0x41 +// Version +#define REG_VERSION 0x42 +// Additional settings +#define REG_PLLHOP 0x44 +#define REG_TCXO 0x4B +#define REG_PADAC 0x4D +#define REG_FORMERTEMP 0x5B +#define REG_BITRATEFRAC 0x5D +#define REG_AGCREF 0x61 +#define REG_AGCTHRESH1 0x62 +#define REG_AGCTHRESH2 0x63 +#define REG_AGCTHRESH3 0x64 +#define REG_PLL 0x70 + +/*! + * ============================================================================ + * SX1276 FSK bits control definition + * ============================================================================ + */ + +/*! + * RegFifo + */ + +/*! + * RegOpMode + */ +#define RF_OPMODE_LONGRANGEMODE_MASK 0x7F +#define RF_OPMODE_LONGRANGEMODE_OFF 0x00 +#define RF_OPMODE_LONGRANGEMODE_ON 0x80 + +#define RF_OPMODE_MODULATIONTYPE_MASK 0x9F +#define RF_OPMODE_MODULATIONTYPE_FSK 0x00 // Default +#define RF_OPMODE_MODULATIONTYPE_OOK 0x20 + +#define RF_OPMODE_MODULATIONSHAPING_MASK 0xE7 +#define RF_OPMODE_MODULATIONSHAPING_00 0x00 // Default +#define RF_OPMODE_MODULATIONSHAPING_01 0x08 +#define RF_OPMODE_MODULATIONSHAPING_10 0x10 +#define RF_OPMODE_MODULATIONSHAPING_11 0x18 + +#define RF_OPMODE_MASK 0xF8 +#define RF_OPMODE_SLEEP 0x00 +#define RF_OPMODE_STANDBY 0x01 // Default +#define RF_OPMODE_SYNTHESIZER_TX 0x02 +#define RF_OPMODE_TRANSMITTER 0x03 +#define RF_OPMODE_SYNTHESIZER_RX 0x04 +#define RF_OPMODE_RECEIVER 0x05 + +/*! + * RegBitRate (bits/sec) + */ +#define RF_BITRATEMSB_1200_BPS 0x68 +#define RF_BITRATELSB_1200_BPS 0x2B +#define RF_BITRATEMSB_2400_BPS 0x34 +#define RF_BITRATELSB_2400_BPS 0x15 +#define RF_BITRATEMSB_4800_BPS 0x1A // Default +#define RF_BITRATELSB_4800_BPS 0x0B // Default +#define RF_BITRATEMSB_9600_BPS 0x0D +#define RF_BITRATELSB_9600_BPS 0x05 +#define RF_BITRATEMSB_15000_BPS 0x08 +#define RF_BITRATELSB_15000_BPS 0x55 +#define RF_BITRATEMSB_19200_BPS 0x06 +#define RF_BITRATELSB_19200_BPS 0x83 +#define RF_BITRATEMSB_38400_BPS 0x03 +#define RF_BITRATELSB_38400_BPS 0x41 +#define RF_BITRATEMSB_76800_BPS 0x01 +#define RF_BITRATELSB_76800_BPS 0xA1 +#define RF_BITRATEMSB_153600_BPS 0x00 +#define RF_BITRATELSB_153600_BPS 0xD0 +#define RF_BITRATEMSB_57600_BPS 0x02 +#define RF_BITRATELSB_57600_BPS 0x2C +#define RF_BITRATEMSB_115200_BPS 0x01 +#define RF_BITRATELSB_115200_BPS 0x16 +#define RF_BITRATEMSB_12500_BPS 0x0A +#define RF_BITRATELSB_12500_BPS 0x00 +#define RF_BITRATEMSB_25000_BPS 0x05 +#define RF_BITRATELSB_25000_BPS 0x00 +#define RF_BITRATEMSB_50000_BPS 0x02 +#define RF_BITRATELSB_50000_BPS 0x80 +#define RF_BITRATEMSB_100000_BPS 0x01 +#define RF_BITRATELSB_100000_BPS 0x40 +#define RF_BITRATEMSB_150000_BPS 0x00 +#define RF_BITRATELSB_150000_BPS 0xD5 +#define RF_BITRATEMSB_200000_BPS 0x00 +#define RF_BITRATELSB_200000_BPS 0xA0 +#define RF_BITRATEMSB_250000_BPS 0x00 +#define RF_BITRATELSB_250000_BPS 0x80 +#define RF_BITRATEMSB_32768_BPS 0x03 +#define RF_BITRATELSB_32768_BPS 0xD1 + +/*! + * RegFdev (Hz) + */ +#define RF_FDEVMSB_2000_HZ 0x00 +#define RF_FDEVLSB_2000_HZ 0x21 +#define RF_FDEVMSB_5000_HZ 0x00 // Default +#define RF_FDEVLSB_5000_HZ 0x52 // Default +#define RF_FDEVMSB_10000_HZ 0x00 +#define RF_FDEVLSB_10000_HZ 0xA4 +#define RF_FDEVMSB_15000_HZ 0x00 +#define RF_FDEVLSB_15000_HZ 0xF6 +#define RF_FDEVMSB_20000_HZ 0x01 +#define RF_FDEVLSB_20000_HZ 0x48 +#define RF_FDEVMSB_25000_HZ 0x01 +#define RF_FDEVLSB_25000_HZ 0x9A +#define RF_FDEVMSB_30000_HZ 0x01 +#define RF_FDEVLSB_30000_HZ 0xEC +#define RF_FDEVMSB_35000_HZ 0x02 +#define RF_FDEVLSB_35000_HZ 0x3D +#define RF_FDEVMSB_40000_HZ 0x02 +#define RF_FDEVLSB_40000_HZ 0x8F +#define RF_FDEVMSB_45000_HZ 0x02 +#define RF_FDEVLSB_45000_HZ 0xE1 +#define RF_FDEVMSB_50000_HZ 0x03 +#define RF_FDEVLSB_50000_HZ 0x33 +#define RF_FDEVMSB_55000_HZ 0x03 +#define RF_FDEVLSB_55000_HZ 0x85 +#define RF_FDEVMSB_60000_HZ 0x03 +#define RF_FDEVLSB_60000_HZ 0xD7 +#define RF_FDEVMSB_65000_HZ 0x04 +#define RF_FDEVLSB_65000_HZ 0x29 +#define RF_FDEVMSB_70000_HZ 0x04 +#define RF_FDEVLSB_70000_HZ 0x7B +#define RF_FDEVMSB_75000_HZ 0x04 +#define RF_FDEVLSB_75000_HZ 0xCD +#define RF_FDEVMSB_80000_HZ 0x05 +#define RF_FDEVLSB_80000_HZ 0x1F +#define RF_FDEVMSB_85000_HZ 0x05 +#define RF_FDEVLSB_85000_HZ 0x71 +#define RF_FDEVMSB_90000_HZ 0x05 +#define RF_FDEVLSB_90000_HZ 0xC3 +#define RF_FDEVMSB_95000_HZ 0x06 +#define RF_FDEVLSB_95000_HZ 0x14 +#define RF_FDEVMSB_100000_HZ 0x06 +#define RF_FDEVLSB_100000_HZ 0x66 +#define RF_FDEVMSB_110000_HZ 0x07 +#define RF_FDEVLSB_110000_HZ 0x0A +#define RF_FDEVMSB_120000_HZ 0x07 +#define RF_FDEVLSB_120000_HZ 0xAE +#define RF_FDEVMSB_130000_HZ 0x08 +#define RF_FDEVLSB_130000_HZ 0x52 +#define RF_FDEVMSB_140000_HZ 0x08 +#define RF_FDEVLSB_140000_HZ 0xF6 +#define RF_FDEVMSB_150000_HZ 0x09 +#define RF_FDEVLSB_150000_HZ 0x9A +#define RF_FDEVMSB_160000_HZ 0x0A +#define RF_FDEVLSB_160000_HZ 0x3D +#define RF_FDEVMSB_170000_HZ 0x0A +#define RF_FDEVLSB_170000_HZ 0xE1 +#define RF_FDEVMSB_180000_HZ 0x0B +#define RF_FDEVLSB_180000_HZ 0x85 +#define RF_FDEVMSB_190000_HZ 0x0C +#define RF_FDEVLSB_190000_HZ 0x29 +#define RF_FDEVMSB_200000_HZ 0x0C +#define RF_FDEVLSB_200000_HZ 0xCD + +/*! + * RegFrf (MHz) + */ +#define RF_FRFMSB_863_MHZ 0xD7 +#define RF_FRFMID_863_MHZ 0xC0 +#define RF_FRFLSB_863_MHZ 0x00 +#define RF_FRFMSB_864_MHZ 0xD8 +#define RF_FRFMID_864_MHZ 0x00 +#define RF_FRFLSB_864_MHZ 0x00 +#define RF_FRFMSB_865_MHZ 0xD8 +#define RF_FRFMID_865_MHZ 0x40 +#define RF_FRFLSB_865_MHZ 0x00 +#define RF_FRFMSB_866_MHZ 0xD8 +#define RF_FRFMID_866_MHZ 0x80 +#define RF_FRFLSB_866_MHZ 0x00 +#define RF_FRFMSB_867_MHZ 0xD8 +#define RF_FRFMID_867_MHZ 0xC0 +#define RF_FRFLSB_867_MHZ 0x00 +#define RF_FRFMSB_868_MHZ 0xD9 +#define RF_FRFMID_868_MHZ 0x00 +#define RF_FRFLSB_868_MHZ 0x00 +#define RF_FRFMSB_869_MHZ 0xD9 +#define RF_FRFMID_869_MHZ 0x40 +#define RF_FRFLSB_869_MHZ 0x00 +#define RF_FRFMSB_870_MHZ 0xD9 +#define RF_FRFMID_870_MHZ 0x80 +#define RF_FRFLSB_870_MHZ 0x00 + +#define RF_FRFMSB_902_MHZ 0xE1 +#define RF_FRFMID_902_MHZ 0x80 +#define RF_FRFLSB_902_MHZ 0x00 +#define RF_FRFMSB_903_MHZ 0xE1 +#define RF_FRFMID_903_MHZ 0xC0 +#define RF_FRFLSB_903_MHZ 0x00 +#define RF_FRFMSB_904_MHZ 0xE2 +#define RF_FRFMID_904_MHZ 0x00 +#define RF_FRFLSB_904_MHZ 0x00 +#define RF_FRFMSB_905_MHZ 0xE2 +#define RF_FRFMID_905_MHZ 0x40 +#define RF_FRFLSB_905_MHZ 0x00 +#define RF_FRFMSB_906_MHZ 0xE2 +#define RF_FRFMID_906_MHZ 0x80 +#define RF_FRFLSB_906_MHZ 0x00 +#define RF_FRFMSB_907_MHZ 0xE2 +#define RF_FRFMID_907_MHZ 0xC0 +#define RF_FRFLSB_907_MHZ 0x00 +#define RF_FRFMSB_908_MHZ 0xE3 +#define RF_FRFMID_908_MHZ 0x00 +#define RF_FRFLSB_908_MHZ 0x00 +#define RF_FRFMSB_909_MHZ 0xE3 +#define RF_FRFMID_909_MHZ 0x40 +#define RF_FRFLSB_909_MHZ 0x00 +#define RF_FRFMSB_910_MHZ 0xE3 +#define RF_FRFMID_910_MHZ 0x80 +#define RF_FRFLSB_910_MHZ 0x00 +#define RF_FRFMSB_911_MHZ 0xE3 +#define RF_FRFMID_911_MHZ 0xC0 +#define RF_FRFLSB_911_MHZ 0x00 +#define RF_FRFMSB_912_MHZ 0xE4 +#define RF_FRFMID_912_MHZ 0x00 +#define RF_FRFLSB_912_MHZ 0x00 +#define RF_FRFMSB_913_MHZ 0xE4 +#define RF_FRFMID_913_MHZ 0x40 +#define RF_FRFLSB_913_MHZ 0x00 +#define RF_FRFMSB_914_MHZ 0xE4 +#define RF_FRFMID_914_MHZ 0x80 +#define RF_FRFLSB_914_MHZ 0x00 +#define RF_FRFMSB_915_MHZ 0xE4 // Default +#define RF_FRFMID_915_MHZ 0xC0 // Default +#define RF_FRFLSB_915_MHZ 0x00 // Default +#define RF_FRFMSB_916_MHZ 0xE5 +#define RF_FRFMID_916_MHZ 0x00 +#define RF_FRFLSB_916_MHZ 0x00 +#define RF_FRFMSB_917_MHZ 0xE5 +#define RF_FRFMID_917_MHZ 0x40 +#define RF_FRFLSB_917_MHZ 0x00 +#define RF_FRFMSB_918_MHZ 0xE5 +#define RF_FRFMID_918_MHZ 0x80 +#define RF_FRFLSB_918_MHZ 0x00 +#define RF_FRFMSB_919_MHZ 0xE5 +#define RF_FRFMID_919_MHZ 0xC0 +#define RF_FRFLSB_919_MHZ 0x00 +#define RF_FRFMSB_920_MHZ 0xE6 +#define RF_FRFMID_920_MHZ 0x00 +#define RF_FRFLSB_920_MHZ 0x00 +#define RF_FRFMSB_921_MHZ 0xE6 +#define RF_FRFMID_921_MHZ 0x40 +#define RF_FRFLSB_921_MHZ 0x00 +#define RF_FRFMSB_922_MHZ 0xE6 +#define RF_FRFMID_922_MHZ 0x80 +#define RF_FRFLSB_922_MHZ 0x00 +#define RF_FRFMSB_923_MHZ 0xE6 +#define RF_FRFMID_923_MHZ 0xC0 +#define RF_FRFLSB_923_MHZ 0x00 +#define RF_FRFMSB_924_MHZ 0xE7 +#define RF_FRFMID_924_MHZ 0x00 +#define RF_FRFLSB_924_MHZ 0x00 +#define RF_FRFMSB_925_MHZ 0xE7 +#define RF_FRFMID_925_MHZ 0x40 +#define RF_FRFLSB_925_MHZ 0x00 +#define RF_FRFMSB_926_MHZ 0xE7 +#define RF_FRFMID_926_MHZ 0x80 +#define RF_FRFLSB_926_MHZ 0x00 +#define RF_FRFMSB_927_MHZ 0xE7 +#define RF_FRFMID_927_MHZ 0xC0 +#define RF_FRFLSB_927_MHZ 0x00 +#define RF_FRFMSB_928_MHZ 0xE8 +#define RF_FRFMID_928_MHZ 0x00 +#define RF_FRFLSB_928_MHZ 0x00 + +/*! + * RegPaConfig + */ +#define RF_PACONFIG_PASELECT_MASK 0x7F +#define RF_PACONFIG_PASELECT_PABOOST 0x80 +#define RF_PACONFIG_PASELECT_RFO 0x00 // Default + +#define RF_PACONFIG_MAX_POWER_MASK 0x8F + +#define RF_PACONFIG_OUTPUTPOWER_MASK 0xF0 + +/*! + * RegPaRamp + */ +#define RF_PARAMP_MODULATIONSHAPING_MASK 0x9F +#define RF_PARAMP_MODULATIONSHAPING_00 0x00 // Default +#define RF_PARAMP_MODULATIONSHAPING_01 0x20 +#define RF_PARAMP_MODULATIONSHAPING_10 0x40 +#define RF_PARAMP_MODULATIONSHAPING_11 0x60 + +#define RF_PARAMP_LOWPNTXPLL_MASK 0xEF +#define RF_PARAMP_LOWPNTXPLL_OFF 0x10 +#define RF_PARAMP_LOWPNTXPLL_ON 0x00 // Default + +#define RF_PARAMP_MASK 0xF0 +#define RF_PARAMP_3400_US 0x00 +#define RF_PARAMP_2000_US 0x01 +#define RF_PARAMP_1000_US 0x02 +#define RF_PARAMP_0500_US 0x03 +#define RF_PARAMP_0250_US 0x04 +#define RF_PARAMP_0125_US 0x05 +#define RF_PARAMP_0100_US 0x06 +#define RF_PARAMP_0062_US 0x07 +#define RF_PARAMP_0050_US 0x08 +#define RF_PARAMP_0040_US 0x09 // Default +#define RF_PARAMP_0031_US 0x0A +#define RF_PARAMP_0025_US 0x0B +#define RF_PARAMP_0020_US 0x0C +#define RF_PARAMP_0015_US 0x0D +#define RF_PARAMP_0012_US 0x0E +#define RF_PARAMP_0010_US 0x0F + +/*! + * RegOcp + */ +#define RF_OCP_MASK 0xDF +#define RF_OCP_ON 0x20 // Default +#define RF_OCP_OFF 0x00 + +#define RF_OCP_TRIM_MASK 0xE0 +#define RF_OCP_TRIM_045_MA 0x00 +#define RF_OCP_TRIM_050_MA 0x01 +#define RF_OCP_TRIM_055_MA 0x02 +#define RF_OCP_TRIM_060_MA 0x03 +#define RF_OCP_TRIM_065_MA 0x04 +#define RF_OCP_TRIM_070_MA 0x05 +#define RF_OCP_TRIM_075_MA 0x06 +#define RF_OCP_TRIM_080_MA 0x07 +#define RF_OCP_TRIM_085_MA 0x08 +#define RF_OCP_TRIM_090_MA 0x09 +#define RF_OCP_TRIM_095_MA 0x0A +#define RF_OCP_TRIM_100_MA 0x0B // Default +#define RF_OCP_TRIM_105_MA 0x0C +#define RF_OCP_TRIM_110_MA 0x0D +#define RF_OCP_TRIM_115_MA 0x0E +#define RF_OCP_TRIM_120_MA 0x0F +#define RF_OCP_TRIM_130_MA 0x10 +#define RF_OCP_TRIM_140_MA 0x11 +#define RF_OCP_TRIM_150_MA 0x12 +#define RF_OCP_TRIM_160_MA 0x13 +#define RF_OCP_TRIM_170_MA 0x14 +#define RF_OCP_TRIM_180_MA 0x15 +#define RF_OCP_TRIM_190_MA 0x16 +#define RF_OCP_TRIM_200_MA 0x17 +#define RF_OCP_TRIM_210_MA 0x18 +#define RF_OCP_TRIM_220_MA 0x19 +#define RF_OCP_TRIM_230_MA 0x1A +#define RF_OCP_TRIM_240_MA 0x1B + +/*! + * RegLna + */ +#define RF_LNA_GAIN_MASK 0x1F +#define RF_LNA_GAIN_G1 0x20 // Default +#define RF_LNA_GAIN_G2 0x40 +#define RF_LNA_GAIN_G3 0x60 +#define RF_LNA_GAIN_G4 0x80 +#define RF_LNA_GAIN_G5 0xA0 +#define RF_LNA_GAIN_G6 0xC0 + +#define RF_LNA_BOOST_MASK 0xFC +#define RF_LNA_BOOST_OFF 0x00 // Default +#define RF_LNA_BOOST_ON 0x03 + +/*! + * RegRxConfig + */ +#define RF_RXCONFIG_RESTARTRXONCOLLISION_MASK 0x7F +#define RF_RXCONFIG_RESTARTRXONCOLLISION_ON 0x80 +#define RF_RXCONFIG_RESTARTRXONCOLLISION_OFF 0x00 // Default + +#define RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK 0x40 // Write only + +#define RF_RXCONFIG_RESTARTRXWITHPLLLOCK 0x20 // Write only + +#define RF_RXCONFIG_AFCAUTO_MASK 0xEF +#define RF_RXCONFIG_AFCAUTO_ON 0x10 +#define RF_RXCONFIG_AFCAUTO_OFF 0x00 // Default + +#define RF_RXCONFIG_AGCAUTO_MASK 0xF7 +#define RF_RXCONFIG_AGCAUTO_ON 0x08 // Default +#define RF_RXCONFIG_AGCAUTO_OFF 0x00 + +#define RF_RXCONFIG_RXTRIGER_MASK 0xF8 +#define RF_RXCONFIG_RXTRIGER_OFF 0x00 +#define RF_RXCONFIG_RXTRIGER_RSSI 0x01 +#define RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT 0x06 // Default +#define RF_RXCONFIG_RXTRIGER_RSSI_PREAMBLEDETECT 0x07 + +/*! + * RegRssiConfig + */ +#define RF_RSSICONFIG_OFFSET_MASK 0x07 +#define RF_RSSICONFIG_OFFSET_P_00_DB 0x00 // Default +#define RF_RSSICONFIG_OFFSET_P_01_DB 0x08 +#define RF_RSSICONFIG_OFFSET_P_02_DB 0x10 +#define RF_RSSICONFIG_OFFSET_P_03_DB 0x18 +#define RF_RSSICONFIG_OFFSET_P_04_DB 0x20 +#define RF_RSSICONFIG_OFFSET_P_05_DB 0x28 +#define RF_RSSICONFIG_OFFSET_P_06_DB 0x30 +#define RF_RSSICONFIG_OFFSET_P_07_DB 0x38 +#define RF_RSSICONFIG_OFFSET_P_08_DB 0x40 +#define RF_RSSICONFIG_OFFSET_P_09_DB 0x48 +#define RF_RSSICONFIG_OFFSET_P_10_DB 0x50 +#define RF_RSSICONFIG_OFFSET_P_11_DB 0x58 +#define RF_RSSICONFIG_OFFSET_P_12_DB 0x60 +#define RF_RSSICONFIG_OFFSET_P_13_DB 0x68 +#define RF_RSSICONFIG_OFFSET_P_14_DB 0x70 +#define RF_RSSICONFIG_OFFSET_P_15_DB 0x78 +#define RF_RSSICONFIG_OFFSET_M_16_DB 0x80 +#define RF_RSSICONFIG_OFFSET_M_15_DB 0x88 +#define RF_RSSICONFIG_OFFSET_M_14_DB 0x90 +#define RF_RSSICONFIG_OFFSET_M_13_DB 0x98 +#define RF_RSSICONFIG_OFFSET_M_12_DB 0xA0 +#define RF_RSSICONFIG_OFFSET_M_11_DB 0xA8 +#define RF_RSSICONFIG_OFFSET_M_10_DB 0xB0 +#define RF_RSSICONFIG_OFFSET_M_09_DB 0xB8 +#define RF_RSSICONFIG_OFFSET_M_08_DB 0xC0 +#define RF_RSSICONFIG_OFFSET_M_07_DB 0xC8 +#define RF_RSSICONFIG_OFFSET_M_06_DB 0xD0 +#define RF_RSSICONFIG_OFFSET_M_05_DB 0xD8 +#define RF_RSSICONFIG_OFFSET_M_04_DB 0xE0 +#define RF_RSSICONFIG_OFFSET_M_03_DB 0xE8 +#define RF_RSSICONFIG_OFFSET_M_02_DB 0xF0 +#define RF_RSSICONFIG_OFFSET_M_01_DB 0xF8 + +#define RF_RSSICONFIG_SMOOTHING_MASK 0xF8 +#define RF_RSSICONFIG_SMOOTHING_2 0x00 +#define RF_RSSICONFIG_SMOOTHING_4 0x01 +#define RF_RSSICONFIG_SMOOTHING_8 0x02 // Default +#define RF_RSSICONFIG_SMOOTHING_16 0x03 +#define RF_RSSICONFIG_SMOOTHING_32 0x04 +#define RF_RSSICONFIG_SMOOTHING_64 0x05 +#define RF_RSSICONFIG_SMOOTHING_128 0x06 +#define RF_RSSICONFIG_SMOOTHING_256 0x07 + +/*! + * RegRssiCollision + */ +#define RF_RSSICOLISION_THRESHOLD 0x0A // Default + +/*! + * RegRssiThresh + */ +#define RF_RSSITHRESH_THRESHOLD 0xFF // Default + +/*! + * RegRssiValue (Read Only) + */ + +/*! + * RegRxBw + */ +#define RF_RXBW_MANT_MASK 0xE7 +#define RF_RXBW_MANT_16 0x00 +#define RF_RXBW_MANT_20 0x08 +#define RF_RXBW_MANT_24 0x10 // Default + +#define RF_RXBW_EXP_MASK 0xF8 +#define RF_RXBW_EXP_0 0x00 +#define RF_RXBW_EXP_1 0x01 +#define RF_RXBW_EXP_2 0x02 +#define RF_RXBW_EXP_3 0x03 +#define RF_RXBW_EXP_4 0x04 +#define RF_RXBW_EXP_5 0x05 // Default +#define RF_RXBW_EXP_6 0x06 +#define RF_RXBW_EXP_7 0x07 + +/*! + * RegAfcBw + */ +#define RF_AFCBW_MANTAFC_MASK 0xE7 +#define RF_AFCBW_MANTAFC_16 0x00 +#define RF_AFCBW_MANTAFC_20 0x08 // Default +#define RF_AFCBW_MANTAFC_24 0x10 + +#define RF_AFCBW_EXPAFC_MASK 0xF8 +#define RF_AFCBW_EXPAFC_0 0x00 +#define RF_AFCBW_EXPAFC_1 0x01 +#define RF_AFCBW_EXPAFC_2 0x02 +#define RF_AFCBW_EXPAFC_3 0x03 // Default +#define RF_AFCBW_EXPAFC_4 0x04 +#define RF_AFCBW_EXPAFC_5 0x05 +#define RF_AFCBW_EXPAFC_6 0x06 +#define RF_AFCBW_EXPAFC_7 0x07 + +/*! + * RegOokPeak + */ +#define RF_OOKPEAK_BITSYNC_MASK 0xDF // Default +#define RF_OOKPEAK_BITSYNC_ON 0x20 // Default +#define RF_OOKPEAK_BITSYNC_OFF 0x00 + +#define RF_OOKPEAK_OOKTHRESHTYPE_MASK 0xE7 +#define RF_OOKPEAK_OOKTHRESHTYPE_FIXED 0x00 +#define RF_OOKPEAK_OOKTHRESHTYPE_PEAK 0x08 // Default +#define RF_OOKPEAK_OOKTHRESHTYPE_AVERAGE 0x10 + +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_MASK 0xF8 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_0_5_DB 0x00 // Default +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_1_0_DB 0x01 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_1_5_DB 0x02 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_2_0_DB 0x03 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_3_0_DB 0x04 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_4_0_DB 0x05 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_5_0_DB 0x06 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_6_0_DB 0x07 + +/*! + * RegOokFix + */ +#define RF_OOKFIX_OOKFIXEDTHRESHOLD 0x0C // Default + +/*! + * RegOokAvg + */ +#define RF_OOKAVG_OOKPEAKTHRESHDEC_MASK 0x1F +#define RF_OOKAVG_OOKPEAKTHRESHDEC_000 0x00 // Default +#define RF_OOKAVG_OOKPEAKTHRESHDEC_001 0x20 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_010 0x40 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_011 0x60 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_100 0x80 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_101 0xA0 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_110 0xC0 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_111 0xE0 + +#define RF_OOKAVG_AVERAGEOFFSET_MASK 0xF3 +#define RF_OOKAVG_AVERAGEOFFSET_0_DB 0x00 // Default +#define RF_OOKAVG_AVERAGEOFFSET_2_DB 0x04 +#define RF_OOKAVG_AVERAGEOFFSET_4_DB 0x08 +#define RF_OOKAVG_AVERAGEOFFSET_6_DB 0x0C + +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_MASK 0xFC +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_00 0x00 +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_01 0x01 +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_10 0x02 // Default +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_11 0x03 + +/*! + * RegAfcFei + */ +#define RF_AFCFEI_AGCSTART 0x10 + +#define RF_AFCFEI_AFCCLEAR 0x02 + +#define RF_AFCFEI_AFCAUTOCLEAR_MASK 0xFE +#define RF_AFCFEI_AFCAUTOCLEAR_ON 0x01 +#define RF_AFCFEI_AFCAUTOCLEAR_OFF 0x00 // Default + +/*! + * RegAfcMsb (Read Only) + */ + +/*! + * RegAfcLsb (Read Only) + */ + +/*! + * RegFeiMsb (Read Only) + */ + +/*! + * RegFeiLsb (Read Only) + */ + +/*! + * RegPreambleDetect + */ +#define RF_PREAMBLEDETECT_DETECTOR_MASK 0x7F +#define RF_PREAMBLEDETECT_DETECTOR_ON 0x80 // Default +#define RF_PREAMBLEDETECT_DETECTOR_OFF 0x00 + +#define RF_PREAMBLEDETECT_DETECTORSIZE_MASK 0x9F +#define RF_PREAMBLEDETECT_DETECTORSIZE_1 0x00 +#define RF_PREAMBLEDETECT_DETECTORSIZE_2 0x20 // Default +#define RF_PREAMBLEDETECT_DETECTORSIZE_3 0x40 +#define RF_PREAMBLEDETECT_DETECTORSIZE_4 0x60 + +#define RF_PREAMBLEDETECT_DETECTORTOL_MASK 0xE0 +#define RF_PREAMBLEDETECT_DETECTORTOL_0 0x00 +#define RF_PREAMBLEDETECT_DETECTORTOL_1 0x01 +#define RF_PREAMBLEDETECT_DETECTORTOL_2 0x02 +#define RF_PREAMBLEDETECT_DETECTORTOL_3 0x03 +#define RF_PREAMBLEDETECT_DETECTORTOL_4 0x04 +#define RF_PREAMBLEDETECT_DETECTORTOL_5 0x05 +#define RF_PREAMBLEDETECT_DETECTORTOL_6 0x06 +#define RF_PREAMBLEDETECT_DETECTORTOL_7 0x07 +#define RF_PREAMBLEDETECT_DETECTORTOL_8 0x08 +#define RF_PREAMBLEDETECT_DETECTORTOL_9 0x09 +#define RF_PREAMBLEDETECT_DETECTORTOL_10 0x0A // Default +#define RF_PREAMBLEDETECT_DETECTORTOL_11 0x0B +#define RF_PREAMBLEDETECT_DETECTORTOL_12 0x0C +#define RF_PREAMBLEDETECT_DETECTORTOL_13 0x0D +#define RF_PREAMBLEDETECT_DETECTORTOL_14 0x0E +#define RF_PREAMBLEDETECT_DETECTORTOL_15 0x0F +#define RF_PREAMBLEDETECT_DETECTORTOL_16 0x10 +#define RF_PREAMBLEDETECT_DETECTORTOL_17 0x11 +#define RF_PREAMBLEDETECT_DETECTORTOL_18 0x12 +#define RF_PREAMBLEDETECT_DETECTORTOL_19 0x13 +#define RF_PREAMBLEDETECT_DETECTORTOL_20 0x14 +#define RF_PREAMBLEDETECT_DETECTORTOL_21 0x15 +#define RF_PREAMBLEDETECT_DETECTORTOL_22 0x16 +#define RF_PREAMBLEDETECT_DETECTORTOL_23 0x17 +#define RF_PREAMBLEDETECT_DETECTORTOL_24 0x18 +#define RF_PREAMBLEDETECT_DETECTORTOL_25 0x19 +#define RF_PREAMBLEDETECT_DETECTORTOL_26 0x1A +#define RF_PREAMBLEDETECT_DETECTORTOL_27 0x1B +#define RF_PREAMBLEDETECT_DETECTORTOL_28 0x1C +#define RF_PREAMBLEDETECT_DETECTORTOL_29 0x1D +#define RF_PREAMBLEDETECT_DETECTORTOL_30 0x1E +#define RF_PREAMBLEDETECT_DETECTORTOL_31 0x1F + +/*! + * RegRxTimeout1 + */ +#define RF_RXTIMEOUT1_TIMEOUTRXRSSI 0x00 // Default + +/*! + * RegRxTimeout2 + */ +#define RF_RXTIMEOUT2_TIMEOUTRXPREAMBLE 0x00 // Default + +/*! + * RegRxTimeout3 + */ +#define RF_RXTIMEOUT3_TIMEOUTSIGNALSYNC 0x00 // Default + +/*! + * RegRxDelay + */ +#define RF_RXDELAY_INTERPACKETRXDELAY 0x00 // Default + +/*! + * RegOsc + */ +#define RF_OSC_RCCALSTART 0x08 + +#define RF_OSC_CLKOUT_MASK 0xF8 +#define RF_OSC_CLKOUT_32_MHZ 0x00 +#define RF_OSC_CLKOUT_16_MHZ 0x01 +#define RF_OSC_CLKOUT_8_MHZ 0x02 +#define RF_OSC_CLKOUT_4_MHZ 0x03 +#define RF_OSC_CLKOUT_2_MHZ 0x04 +#define RF_OSC_CLKOUT_1_MHZ 0x05 // Default +#define RF_OSC_CLKOUT_RC 0x06 +#define RF_OSC_CLKOUT_OFF 0x07 + +/*! + * RegPreambleMsb/RegPreambleLsb + */ +#define RF_PREAMBLEMSB_SIZE 0x00 // Default +#define RF_PREAMBLELSB_SIZE 0x03 // Default + +/*! + * RegSyncConfig + */ +#define RF_SYNCCONFIG_AUTORESTARTRXMODE_MASK 0x3F +#define RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_ON 0x80 // Default +#define RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_OFF 0x40 +#define RF_SYNCCONFIG_AUTORESTARTRXMODE_OFF 0x00 + + +#define RF_SYNCCONFIG_PREAMBLEPOLARITY_MASK 0xDF +#define RF_SYNCCONFIG_PREAMBLEPOLARITY_55 0x20 +#define RF_SYNCCONFIG_PREAMBLEPOLARITY_AA 0x00 // Default + +#define RF_SYNCCONFIG_SYNC_MASK 0xEF +#define RF_SYNCCONFIG_SYNC_ON 0x10 // Default +#define RF_SYNCCONFIG_SYNC_OFF 0x00 + + +#define RF_SYNCCONFIG_SYNCSIZE_MASK 0xF8 +#define RF_SYNCCONFIG_SYNCSIZE_1 0x00 +#define RF_SYNCCONFIG_SYNCSIZE_2 0x01 +#define RF_SYNCCONFIG_SYNCSIZE_3 0x02 +#define RF_SYNCCONFIG_SYNCSIZE_4 0x03 // Default +#define RF_SYNCCONFIG_SYNCSIZE_5 0x04 +#define RF_SYNCCONFIG_SYNCSIZE_6 0x05 +#define RF_SYNCCONFIG_SYNCSIZE_7 0x06 +#define RF_SYNCCONFIG_SYNCSIZE_8 0x07 + +/*! + * RegSyncValue1-8 + */ +#define RF_SYNCVALUE1_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE2_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE3_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE4_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE5_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE6_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE7_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE8_SYNCVALUE 0x01 // Default + +/*! + * RegPacketConfig1 + */ +#define RF_PACKETCONFIG1_PACKETFORMAT_MASK 0x7F +#define RF_PACKETCONFIG1_PACKETFORMAT_FIXED 0x00 +#define RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE 0x80 // Default + +#define RF_PACKETCONFIG1_DCFREE_MASK 0x9F +#define RF_PACKETCONFIG1_DCFREE_OFF 0x00 // Default +#define RF_PACKETCONFIG1_DCFREE_MANCHESTER 0x20 +#define RF_PACKETCONFIG1_DCFREE_WHITENING 0x40 + +#define RF_PACKETCONFIG1_CRC_MASK 0xEF +#define RF_PACKETCONFIG1_CRC_ON 0x10 // Default +#define RF_PACKETCONFIG1_CRC_OFF 0x00 + +#define RF_PACKETCONFIG1_CRCAUTOCLEAR_MASK 0xF7 +#define RF_PACKETCONFIG1_CRCAUTOCLEAR_ON 0x00 // Default +#define RF_PACKETCONFIG1_CRCAUTOCLEAR_OFF 0x08 + +#define RF_PACKETCONFIG1_ADDRSFILTERING_MASK 0xF9 +#define RF_PACKETCONFIG1_ADDRSFILTERING_OFF 0x00 // Default +#define RF_PACKETCONFIG1_ADDRSFILTERING_NODE 0x02 +#define RF_PACKETCONFIG1_ADDRSFILTERING_NODEBROADCAST 0x04 + +#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_MASK 0xFE +#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_CCITT 0x00 // Default +#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_IBM 0x01 + +/*! + * RegPacketConfig2 + */ + +#define RF_PACKETCONFIG2_WMBUS_CRC_ENABLE_MASK 0x7F +#define RF_PACKETCONFIG2_WMBUS_CRC_ENABLE 0x80 +#define RF_PACKETCONFIG2_WMBUS_CRC_DISABLE 0x00 // Default + +#define RF_PACKETCONFIG2_DATAMODE_MASK 0xBF +#define RF_PACKETCONFIG2_DATAMODE_CONTINUOUS 0x00 +#define RF_PACKETCONFIG2_DATAMODE_PACKET 0x40 // Default + +#define RF_PACKETCONFIG2_IOHOME_MASK 0xDF +#define RF_PACKETCONFIG2_IOHOME_ON 0x20 +#define RF_PACKETCONFIG2_IOHOME_OFF 0x00 // Default + +#define RF_PACKETCONFIG2_BEACON_MASK 0xF7 +#define RF_PACKETCONFIG2_BEACON_ON 0x08 +#define RF_PACKETCONFIG2_BEACON_OFF 0x00 // Default + +#define RF_PACKETCONFIG2_PAYLOADLENGTH_MSB_MASK 0xF8 + +/*! + * RegPayloadLength + */ +#define RF_PAYLOADLENGTH_LENGTH 0x40 // Default + +/*! + * RegNodeAdrs + */ +#define RF_NODEADDRESS_ADDRESS 0x00 + +/*! + * RegBroadcastAdrs + */ +#define RF_BROADCASTADDRESS_ADDRESS 0x00 + +/*! + * RegFifoThresh + */ +#define RF_FIFOTHRESH_TXSTARTCONDITION_MASK 0x7F +#define RF_FIFOTHRESH_TXSTARTCONDITION_FIFOTHRESH 0x00 // Default +#define RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY 0x80 + +#define RF_FIFOTHRESH_FIFOTHRESHOLD_MASK 0xC0 +#define RF_FIFOTHRESH_FIFOTHRESHOLD_THRESHOLD 0x0F // Default + +/*! + * RegSeqConfig1 + */ +#define RF_SEQCONFIG1_SEQUENCER_START 0x80 + +#define RF_SEQCONFIG1_SEQUENCER_STOP 0x40 + +#define RF_SEQCONFIG1_IDLEMODE_MASK 0xDF +#define RF_SEQCONFIG1_IDLEMODE_SLEEP 0x20 +#define RF_SEQCONFIG1_IDLEMODE_STANDBY 0x00 // Default + +#define RF_SEQCONFIG1_FROMSTART_MASK 0xE7 +#define RF_SEQCONFIG1_FROMSTART_TOLPS 0x00 // Default +#define RF_SEQCONFIG1_FROMSTART_TORX 0x08 +#define RF_SEQCONFIG1_FROMSTART_TOTX 0x10 +#define RF_SEQCONFIG1_FROMSTART_TOTX_ONFIFOLEVEL 0x18 + +#define RF_SEQCONFIG1_LPS_MASK 0xFB +#define RF_SEQCONFIG1_LPS_SEQUENCER_OFF 0x00 // Default +#define RF_SEQCONFIG1_LPS_IDLE 0x04 + +#define RF_SEQCONFIG1_FROMIDLE_MASK 0xFD +#define RF_SEQCONFIG1_FROMIDLE_TOTX 0x00 // Default +#define RF_SEQCONFIG1_FROMIDLE_TORX 0x02 + +#define RF_SEQCONFIG1_FROMTX_MASK 0xFE +#define RF_SEQCONFIG1_FROMTX_TOLPS 0x00 // Default +#define RF_SEQCONFIG1_FROMTX_TORX 0x01 + +/*! + * RegSeqConfig2 + */ +#define RF_SEQCONFIG2_FROMRX_MASK 0x1F +#define RF_SEQCONFIG2_FROMRX_TOUNUSED_000 0x00 // Default +#define RF_SEQCONFIG2_FROMRX_TORXPKT_ONPLDRDY 0x20 +#define RF_SEQCONFIG2_FROMRX_TOLPS_ONPLDRDY 0x40 +#define RF_SEQCONFIG2_FROMRX_TORXPKT_ONCRCOK 0x60 +#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONRSSI 0x80 +#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONSYNC 0xA0 +#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONPREAMBLE 0xC0 +#define RF_SEQCONFIG2_FROMRX_TOUNUSED_111 0xE0 + +#define RF_SEQCONFIG2_FROMRXTIMEOUT_MASK 0xE7 +#define RF_SEQCONFIG2_FROMRXTIMEOUT_TORXRESTART 0x00 // Default +#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOTX 0x08 +#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOLPS 0x10 +#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOSEQUENCEROFF 0x18 + +#define RF_SEQCONFIG2_FROMRXPKT_MASK 0xF8 +#define RF_SEQCONFIG2_FROMRXPKT_TOSEQUENCEROFF 0x00 // Default +#define RF_SEQCONFIG2_FROMRXPKT_TOTX_ONFIFOEMPTY 0x01 +#define RF_SEQCONFIG2_FROMRXPKT_TOLPS 0x02 +#define RF_SEQCONFIG2_FROMRXPKT_TOSYNTHESIZERRX 0x03 +#define RF_SEQCONFIG2_FROMRXPKT_TORX 0x04 + +/*! + * RegTimerResol + */ +#define RF_TIMERRESOL_TIMER1RESOL_MASK 0xF3 +#define RF_TIMERRESOL_TIMER1RESOL_OFF 0x00 // Default +#define RF_TIMERRESOL_TIMER1RESOL_000064_US 0x04 +#define RF_TIMERRESOL_TIMER1RESOL_004100_US 0x08 +#define RF_TIMERRESOL_TIMER1RESOL_262000_US 0x0C + +#define RF_TIMERRESOL_TIMER2RESOL_MASK 0xFC +#define RF_TIMERRESOL_TIMER2RESOL_OFF 0x00 // Default +#define RF_TIMERRESOL_TIMER2RESOL_000064_US 0x01 +#define RF_TIMERRESOL_TIMER2RESOL_004100_US 0x02 +#define RF_TIMERRESOL_TIMER2RESOL_262000_US 0x03 + +/*! + * RegTimer1Coef + */ +#define RF_TIMER1COEF_TIMER1COEFFICIENT 0xF5 // Default + +/*! + * RegTimer2Coef + */ +#define RF_TIMER2COEF_TIMER2COEFFICIENT 0x20 // Default + +/*! + * RegImageCal + */ +#define RF_IMAGECAL_AUTOIMAGECAL_MASK 0x7F +#define RF_IMAGECAL_AUTOIMAGECAL_ON 0x80 +#define RF_IMAGECAL_AUTOIMAGECAL_OFF 0x00 // Default + +#define RF_IMAGECAL_IMAGECAL_MASK 0xBF +#define RF_IMAGECAL_IMAGECAL_START 0x40 + +#define RF_IMAGECAL_IMAGECAL_RUNNING 0x20 +#define RF_IMAGECAL_IMAGECAL_DONE 0x00 // Default + +#define RF_IMAGECAL_TEMPCHANGE_HIGHER 0x08 +#define RF_IMAGECAL_TEMPCHANGE_LOWER 0x00 + +#define RF_IMAGECAL_TEMPTHRESHOLD_MASK 0xF9 +#define RF_IMAGECAL_TEMPTHRESHOLD_05 0x00 +#define RF_IMAGECAL_TEMPTHRESHOLD_10 0x02 // Default +#define RF_IMAGECAL_TEMPTHRESHOLD_15 0x04 +#define RF_IMAGECAL_TEMPTHRESHOLD_20 0x06 + +#define RF_IMAGECAL_TEMPMONITOR_MASK 0xFE +#define RF_IMAGECAL_TEMPMONITOR_ON 0x00 // Default +#define RF_IMAGECAL_TEMPMONITOR_OFF 0x01 + +/*! + * RegTemp (Read Only) + */ + +/*! + * RegLowBat + */ +#define RF_LOWBAT_MASK 0xF7 +#define RF_LOWBAT_ON 0x08 +#define RF_LOWBAT_OFF 0x00 // Default + +#define RF_LOWBAT_TRIM_MASK 0xF8 +#define RF_LOWBAT_TRIM_1695 0x00 +#define RF_LOWBAT_TRIM_1764 0x01 +#define RF_LOWBAT_TRIM_1835 0x02 // Default +#define RF_LOWBAT_TRIM_1905 0x03 +#define RF_LOWBAT_TRIM_1976 0x04 +#define RF_LOWBAT_TRIM_2045 0x05 +#define RF_LOWBAT_TRIM_2116 0x06 +#define RF_LOWBAT_TRIM_2185 0x07 + +/*! + * RegIrqFlags1 + */ +#define RF_IRQFLAGS1_MODEREADY 0x80 + +#define RF_IRQFLAGS1_RXREADY 0x40 + +#define RF_IRQFLAGS1_TXREADY 0x20 + +#define RF_IRQFLAGS1_PLLLOCK 0x10 + +#define RF_IRQFLAGS1_RSSI 0x08 + +#define RF_IRQFLAGS1_TIMEOUT 0x04 + +#define RF_IRQFLAGS1_PREAMBLEDETECT 0x02 + +#define RF_IRQFLAGS1_SYNCADDRESSMATCH 0x01 + +/*! + * RegIrqFlags2 + */ +#define RF_IRQFLAGS2_FIFOFULL 0x80 + +#define RF_IRQFLAGS2_FIFOEMPTY 0x40 + +#define RF_IRQFLAGS2_FIFOLEVEL 0x20 + +#define RF_IRQFLAGS2_FIFOOVERRUN 0x10 + +#define RF_IRQFLAGS2_PACKETSENT 0x08 + +#define RF_IRQFLAGS2_PAYLOADREADY 0x04 + +#define RF_IRQFLAGS2_CRCOK 0x02 + +#define RF_IRQFLAGS2_LOWBAT 0x01 + +/*! + * RegDioMapping1 + */ +#define RF_DIOMAPPING1_DIO0_MASK 0x3F +#define RF_DIOMAPPING1_DIO0_00 0x00 // Default +#define RF_DIOMAPPING1_DIO0_01 0x40 +#define RF_DIOMAPPING1_DIO0_10 0x80 +#define RF_DIOMAPPING1_DIO0_11 0xC0 + +#define RF_DIOMAPPING1_DIO1_MASK 0xCF +#define RF_DIOMAPPING1_DIO1_00 0x00 // Default +#define RF_DIOMAPPING1_DIO1_01 0x10 +#define RF_DIOMAPPING1_DIO1_10 0x20 +#define RF_DIOMAPPING1_DIO1_11 0x30 + +#define RF_DIOMAPPING1_DIO2_MASK 0xF3 +#define RF_DIOMAPPING1_DIO2_00 0x00 // Default +#define RF_DIOMAPPING1_DIO2_01 0x04 +#define RF_DIOMAPPING1_DIO2_10 0x08 +#define RF_DIOMAPPING1_DIO2_11 0x0C + +#define RF_DIOMAPPING1_DIO3_MASK 0xFC +#define RF_DIOMAPPING1_DIO3_00 0x00 // Default +#define RF_DIOMAPPING1_DIO3_01 0x01 +#define RF_DIOMAPPING1_DIO3_10 0x02 +#define RF_DIOMAPPING1_DIO3_11 0x03 + +/*! + * RegDioMapping2 + */ +#define RF_DIOMAPPING2_DIO4_MASK 0x3F +#define RF_DIOMAPPING2_DIO4_00 0x00 // Default +#define RF_DIOMAPPING2_DIO4_01 0x40 +#define RF_DIOMAPPING2_DIO4_10 0x80 +#define RF_DIOMAPPING2_DIO4_11 0xC0 + +#define RF_DIOMAPPING2_DIO5_MASK 0xCF +#define RF_DIOMAPPING2_DIO5_00 0x00 // Default +#define RF_DIOMAPPING2_DIO5_01 0x10 +#define RF_DIOMAPPING2_DIO5_10 0x20 +#define RF_DIOMAPPING2_DIO5_11 0x30 + +#define RF_DIOMAPPING2_MAP_MASK 0xFE +#define RF_DIOMAPPING2_MAP_PREAMBLEDETECT 0x01 +#define RF_DIOMAPPING2_MAP_RSSI 0x00 // Default + +/*! + * RegVersion (Read Only) + */ + +/*! + * RegPllHop + */ +#define RF_PLLHOP_FASTHOP_MASK 0x7F +#define RF_PLLHOP_FASTHOP_ON 0x80 +#define RF_PLLHOP_FASTHOP_OFF 0x00 // Default + +/*! + * RegTcxo + */ +#define RF_TCXO_TCXOINPUT_MASK 0xEF +#define RF_TCXO_TCXOINPUT_ON 0x10 +#define RF_TCXO_TCXOINPUT_OFF 0x00 // Default + +/*! + * RegPaDac + */ +#define RF_PADAC_20DBM_MASK 0xF8 +#define RF_PADAC_20DBM_ON 0x07 +#define RF_PADAC_20DBM_OFF 0x04 // Default + +/*! + * RegFormerTemp + */ + +/*! + * RegBitrateFrac + */ +#define RF_BITRATEFRAC_MASK 0xF0 + +/*! + * RegAgcRef + */ + +/*! + * RegAgcThresh1 + */ + +/*! + * RegAgcThresh2 + */ + +/*! + * RegAgcThresh3 + */ + +/*! + * RegPll + */ +#define RF_PLL_BANDWIDTH_MASK 0x3F +#define RF_PLL_BANDWIDTH_75 0x00 +#define RF_PLL_BANDWIDTH_150 0x40 +#define RF_PLL_BANDWIDTH_225 0x80 +#define RF_PLL_BANDWIDTH_300 0xC0 // Default + +#endif // __SX1276_REGS_FSK_H__
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/registers/sx1276Regs-LoRa.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/registers/sx1276Regs-LoRa.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,571 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: SX1276 LoRa modem registers and bits definitions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __SX1276_REGS_LORA_H__ +#define __SX1276_REGS_LORA_H__ + +/*! + * ============================================================================ + * SX1276 Internal registers Address + * ============================================================================ + */ +#define REG_LR_FIFO 0x00 +// Common settings +#define REG_LR_OPMODE 0x01 +#define REG_LR_FRFMSB 0x06 +#define REG_LR_FRFMID 0x07 +#define REG_LR_FRFLSB 0x08 +// Tx settings +#define REG_LR_PACONFIG 0x09 +#define REG_LR_PARAMP 0x0A +#define REG_LR_OCP 0x0B +// Rx settings +#define REG_LR_LNA 0x0C +// LoRa registers +#define REG_LR_FIFOADDRPTR 0x0D +#define REG_LR_FIFOTXBASEADDR 0x0E +#define REG_LR_FIFORXBASEADDR 0x0F +#define REG_LR_FIFORXCURRENTADDR 0x10 +#define REG_LR_IRQFLAGSMASK 0x11 +#define REG_LR_IRQFLAGS 0x12 +#define REG_LR_RXNBBYTES 0x13 +#define REG_LR_RXHEADERCNTVALUEMSB 0x14 +#define REG_LR_RXHEADERCNTVALUELSB 0x15 +#define REG_LR_RXPACKETCNTVALUEMSB 0x16 +#define REG_LR_RXPACKETCNTVALUELSB 0x17 +#define REG_LR_MODEMSTAT 0x18 +#define REG_LR_PKTSNRVALUE 0x19 +#define REG_LR_PKTRSSIVALUE 0x1A +#define REG_LR_RSSIVALUE 0x1B +#define REG_LR_HOPCHANNEL 0x1C +#define REG_LR_MODEMCONFIG1 0x1D +#define REG_LR_MODEMCONFIG2 0x1E +#define REG_LR_SYMBTIMEOUTLSB 0x1F +#define REG_LR_PREAMBLEMSB 0x20 +#define REG_LR_PREAMBLELSB 0x21 +#define REG_LR_PAYLOADLENGTH 0x22 +#define REG_LR_PAYLOADMAXLENGTH 0x23 +#define REG_LR_HOPPERIOD 0x24 +#define REG_LR_FIFORXBYTEADDR 0x25 +#define REG_LR_MODEMCONFIG3 0x26 +#define REG_LR_FEIMSB 0x28 +#define REG_LR_FEIMID 0x29 +#define REG_LR_FEILSB 0x2A +#define REG_LR_RSSIWIDEBAND 0x2C +#define REG_LR_TEST2F 0x2F +#define REG_LR_TEST30 0x30 +#define REG_LR_DETECTOPTIMIZE 0x31 +#define REG_LR_INVERTIQ 0x33 +#define REG_LR_TEST36 0x36 +#define REG_LR_DETECTIONTHRESHOLD 0x37 +#define REG_LR_SYNCWORD 0x39 +#define REG_LR_TEST3A 0x3A +#define REG_LR_INVERTIQ2 0x3B + +// end of documented register in datasheet +// I/O settings +#define REG_LR_DIOMAPPING1 0x40 +#define REG_LR_DIOMAPPING2 0x41 +// Version +#define REG_LR_VERSION 0x42 +// Additional settings +#define REG_LR_PLLHOP 0x44 +#define REG_LR_TCXO 0x4B +#define REG_LR_PADAC 0x4D +#define REG_LR_FORMERTEMP 0x5B +#define REG_LR_BITRATEFRAC 0x5D +#define REG_LR_AGCREF 0x61 +#define REG_LR_AGCTHRESH1 0x62 +#define REG_LR_AGCTHRESH2 0x63 +#define REG_LR_AGCTHRESH3 0x64 +#define REG_LR_PLL 0x70 + +/*! + * ============================================================================ + * SX1276 LoRa bits control definition + * ============================================================================ + */ + +/*! + * RegFifo + */ + +/*! + * RegOpMode + */ +#define RFLR_OPMODE_LONGRANGEMODE_MASK 0x7F +#define RFLR_OPMODE_LONGRANGEMODE_OFF 0x00 // Default +#define RFLR_OPMODE_LONGRANGEMODE_ON 0x80 + +#define RFLR_OPMODE_ACCESSSHAREDREG_MASK 0xBF +#define RFLR_OPMODE_ACCESSSHAREDREG_ENABLE 0x40 +#define RFLR_OPMODE_ACCESSSHAREDREG_DISABLE 0x00 // Default + +#define RFLR_OPMODE_FREQMODE_ACCESS_MASK 0xF7 +#define RFLR_OPMODE_FREQMODE_ACCESS_LF 0x08 // Default +#define RFLR_OPMODE_FREQMODE_ACCESS_HF 0x00 + +#define RFLR_OPMODE_MASK 0xF8 +#define RFLR_OPMODE_SLEEP 0x00 +#define RFLR_OPMODE_STANDBY 0x01 // Default +#define RFLR_OPMODE_SYNTHESIZER_TX 0x02 +#define RFLR_OPMODE_TRANSMITTER 0x03 +#define RFLR_OPMODE_SYNTHESIZER_RX 0x04 +#define RFLR_OPMODE_RECEIVER 0x05 +// LoRa specific modes +#define RFLR_OPMODE_RECEIVER_SINGLE 0x06 +#define RFLR_OPMODE_CAD 0x07 + +/*! + * RegFrf (MHz) + */ +#define RFLR_FRFMSB_434_MHZ 0x6C // Default +#define RFLR_FRFMID_434_MHZ 0x80 // Default +#define RFLR_FRFLSB_434_MHZ 0x00 // Default + +/*! + * RegPaConfig + */ +#define RFLR_PACONFIG_PASELECT_MASK 0x7F +#define RFLR_PACONFIG_PASELECT_PABOOST 0x80 +#define RFLR_PACONFIG_PASELECT_RFO 0x00 // Default + +#define RFLR_PACONFIG_MAX_POWER_MASK 0x8F + +#define RFLR_PACONFIG_OUTPUTPOWER_MASK 0xF0 + +/*! + * RegPaRamp + */ +#define RFLR_PARAMP_TXBANDFORCE_MASK 0xEF +#define RFLR_PARAMP_TXBANDFORCE_BAND_SEL 0x10 +#define RFLR_PARAMP_TXBANDFORCE_AUTO 0x00 // Default + +#define RFLR_PARAMP_MASK 0xF0 +#define RFLR_PARAMP_3400_US 0x00 +#define RFLR_PARAMP_2000_US 0x01 +#define RFLR_PARAMP_1000_US 0x02 +#define RFLR_PARAMP_0500_US 0x03 +#define RFLR_PARAMP_0250_US 0x04 +#define RFLR_PARAMP_0125_US 0x05 +#define RFLR_PARAMP_0100_US 0x06 +#define RFLR_PARAMP_0062_US 0x07 +#define RFLR_PARAMP_0050_US 0x08 +#define RFLR_PARAMP_0040_US 0x09 // Default +#define RFLR_PARAMP_0031_US 0x0A +#define RFLR_PARAMP_0025_US 0x0B +#define RFLR_PARAMP_0020_US 0x0C +#define RFLR_PARAMP_0015_US 0x0D +#define RFLR_PARAMP_0012_US 0x0E +#define RFLR_PARAMP_0010_US 0x0F + +/*! + * RegOcp + */ +#define RFLR_OCP_MASK 0xDF +#define RFLR_OCP_ON 0x20 // Default +#define RFLR_OCP_OFF 0x00 + +#define RFLR_OCP_TRIM_MASK 0xE0 +#define RFLR_OCP_TRIM_045_MA 0x00 +#define RFLR_OCP_TRIM_050_MA 0x01 +#define RFLR_OCP_TRIM_055_MA 0x02 +#define RFLR_OCP_TRIM_060_MA 0x03 +#define RFLR_OCP_TRIM_065_MA 0x04 +#define RFLR_OCP_TRIM_070_MA 0x05 +#define RFLR_OCP_TRIM_075_MA 0x06 +#define RFLR_OCP_TRIM_080_MA 0x07 +#define RFLR_OCP_TRIM_085_MA 0x08 +#define RFLR_OCP_TRIM_090_MA 0x09 +#define RFLR_OCP_TRIM_095_MA 0x0A +#define RFLR_OCP_TRIM_100_MA 0x0B // Default +#define RFLR_OCP_TRIM_105_MA 0x0C +#define RFLR_OCP_TRIM_110_MA 0x0D +#define RFLR_OCP_TRIM_115_MA 0x0E +#define RFLR_OCP_TRIM_120_MA 0x0F +#define RFLR_OCP_TRIM_130_MA 0x10 +#define RFLR_OCP_TRIM_140_MA 0x11 +#define RFLR_OCP_TRIM_150_MA 0x12 +#define RFLR_OCP_TRIM_160_MA 0x13 +#define RFLR_OCP_TRIM_170_MA 0x14 +#define RFLR_OCP_TRIM_180_MA 0x15 +#define RFLR_OCP_TRIM_190_MA 0x16 +#define RFLR_OCP_TRIM_200_MA 0x17 +#define RFLR_OCP_TRIM_210_MA 0x18 +#define RFLR_OCP_TRIM_220_MA 0x19 +#define RFLR_OCP_TRIM_230_MA 0x1A +#define RFLR_OCP_TRIM_240_MA 0x1B + +/*! + * RegLna + */ +#define RFLR_LNA_GAIN_MASK 0x1F +#define RFLR_LNA_GAIN_G1 0x20 // Default +#define RFLR_LNA_GAIN_G2 0x40 +#define RFLR_LNA_GAIN_G3 0x60 +#define RFLR_LNA_GAIN_G4 0x80 +#define RFLR_LNA_GAIN_G5 0xA0 +#define RFLR_LNA_GAIN_G6 0xC0 + +#define RFLR_LNA_BOOST_LF_MASK 0xE7 +#define RFLR_LNA_BOOST_LF_DEFAULT 0x00 // Default + +#define RFLR_LNA_BOOST_HF_MASK 0xFC +#define RFLR_LNA_BOOST_HF_OFF 0x00 // Default +#define RFLR_LNA_BOOST_HF_ON 0x03 + +/*! + * RegFifoAddrPtr + */ +#define RFLR_FIFOADDRPTR 0x00 // Default + +/*! + * RegFifoTxBaseAddr + */ +#define RFLR_FIFOTXBASEADDR 0x80 // Default + +/*! + * RegFifoTxBaseAddr + */ +#define RFLR_FIFORXBASEADDR 0x00 // Default + +/*! + * RegFifoRxCurrentAddr (Read Only) + */ + +/*! + * RegIrqFlagsMask + */ +#define RFLR_IRQFLAGS_RXTIMEOUT_MASK 0x80 +#define RFLR_IRQFLAGS_RXDONE_MASK 0x40 +#define RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK 0x20 +#define RFLR_IRQFLAGS_VALIDHEADER_MASK 0x10 +#define RFLR_IRQFLAGS_TXDONE_MASK 0x08 +#define RFLR_IRQFLAGS_CADDONE_MASK 0x04 +#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL_MASK 0x02 +#define RFLR_IRQFLAGS_CADDETECTED_MASK 0x01 + +/*! + * RegIrqFlags + */ +#define RFLR_IRQFLAGS_RXTIMEOUT 0x80 +#define RFLR_IRQFLAGS_RXDONE 0x40 +#define RFLR_IRQFLAGS_PAYLOADCRCERROR 0x20 +#define RFLR_IRQFLAGS_VALIDHEADER 0x10 +#define RFLR_IRQFLAGS_TXDONE 0x08 +#define RFLR_IRQFLAGS_CADDONE 0x04 +#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL 0x02 +#define RFLR_IRQFLAGS_CADDETECTED 0x01 + +/*! + * RegFifoRxNbBytes (Read Only) + */ + +/*! + * RegRxHeaderCntValueMsb (Read Only) + */ + +/*! + * RegRxHeaderCntValueLsb (Read Only) + */ + +/*! + * RegRxPacketCntValueMsb (Read Only) + */ + +/*! + * RegRxPacketCntValueLsb (Read Only) + */ + +/*! + * RegModemStat (Read Only) + */ +#define RFLR_MODEMSTAT_RX_CR_MASK 0x1F +#define RFLR_MODEMSTAT_MODEM_STATUS_MASK 0xE0 + +#define RFLR_MODEMSTAT_MODEM_CLEAR 0x10 +#define RFLR_MODEMSTAT_HEADERINFO_VALID 0x08 +#define RFLR_MODEMSTAT_RX_ONGOING 0x04 +#define RFLR_MODEMSTAT_SIGNAL_SYNCRONIZED 0x02 +#define RFLR_MODEMSTAT_SIGNAL_DETECTED 0x01 + +/*! + * RegPktSnrValue (Read Only) + */ + +/*! + * RegPktRssiValue (Read Only) + */ + +/*! + * RegRssiValue (Read Only) + */ + +/*! + * RegHopChannel (Read Only) + */ +#define RFLR_HOPCHANNEL_PLL_LOCK_TIMEOUT_MASK 0x7F +#define RFLR_HOPCHANNEL_PLL_LOCK_FAIL 0x80 +#define RFLR_HOPCHANNEL_PLL_LOCK_SUCCEED 0x00 // Default + +#define RFLR_HOPCHANNEL_CRCONPAYLOAD_MASK 0xBF +#define RFLR_HOPCHANNEL_CRCONPAYLOAD_ON 0x40 +#define RFLR_HOPCHANNEL_CRCONPAYLOAD_OFF 0x00 // Default + +#define RFLR_HOPCHANNEL_CHANNEL_MASK 0x3F + +/*! + * RegModemConfig1 + */ +#define RFLR_MODEMCONFIG1_BW_MASK 0x0F +#define RFLR_MODEMCONFIG1_BW_7_81_KHZ 0x00 +#define RFLR_MODEMCONFIG1_BW_10_41_KHZ 0x10 +#define RFLR_MODEMCONFIG1_BW_15_62_KHZ 0x20 +#define RFLR_MODEMCONFIG1_BW_20_83_KHZ 0x30 +#define RFLR_MODEMCONFIG1_BW_31_25_KHZ 0x40 +#define RFLR_MODEMCONFIG1_BW_41_66_KHZ 0x50 +#define RFLR_MODEMCONFIG1_BW_62_50_KHZ 0x60 +#define RFLR_MODEMCONFIG1_BW_125_KHZ 0x70 // Default +#define RFLR_MODEMCONFIG1_BW_250_KHZ 0x80 +#define RFLR_MODEMCONFIG1_BW_500_KHZ 0x90 + +#define RFLR_MODEMCONFIG1_CODINGRATE_MASK 0xF1 +#define RFLR_MODEMCONFIG1_CODINGRATE_4_5 0x02 +#define RFLR_MODEMCONFIG1_CODINGRATE_4_6 0x04 // Default +#define RFLR_MODEMCONFIG1_CODINGRATE_4_7 0x06 +#define RFLR_MODEMCONFIG1_CODINGRATE_4_8 0x08 + +#define RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK 0xFE +#define RFLR_MODEMCONFIG1_IMPLICITHEADER_ON 0x01 +#define RFLR_MODEMCONFIG1_IMPLICITHEADER_OFF 0x00 // Default + +/*! + * RegModemConfig2 + */ +#define RFLR_MODEMCONFIG2_SF_MASK 0x0F +#define RFLR_MODEMCONFIG2_SF_6 0x60 +#define RFLR_MODEMCONFIG2_SF_7 0x70 // Default +#define RFLR_MODEMCONFIG2_SF_8 0x80 +#define RFLR_MODEMCONFIG2_SF_9 0x90 +#define RFLR_MODEMCONFIG2_SF_10 0xA0 +#define RFLR_MODEMCONFIG2_SF_11 0xB0 +#define RFLR_MODEMCONFIG2_SF_12 0xC0 + +#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_MASK 0xF7 +#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_ON 0x08 +#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_OFF 0x00 + +#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK 0xFB +#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_ON 0x04 +#define RFLR_MODEMCONFIG2_RXPAYLOADCRC_OFF 0x00 // Default + +#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK 0xFC +#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB 0x00 // Default + +/*! + * RegSymbTimeoutLsb + */ +#define RFLR_SYMBTIMEOUTLSB_SYMBTIMEOUT 0x64 // Default + +/*! + * RegPreambleLengthMsb + */ +#define RFLR_PREAMBLELENGTHMSB 0x00 // Default + +/*! + * RegPreambleLengthLsb + */ +#define RFLR_PREAMBLELENGTHLSB 0x08 // Default + +/*! + * RegPayloadLength + */ +#define RFLR_PAYLOADLENGTH 0x0E // Default + +/*! + * RegPayloadMaxLength + */ +#define RFLR_PAYLOADMAXLENGTH 0xFF // Default + +/*! + * RegHopPeriod + */ +#define RFLR_HOPPERIOD_FREQFOPPINGPERIOD 0x00 // Default + +/*! + * RegFifoRxByteAddr (Read Only) + */ + +/*! + * RegModemConfig3 + */ +#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK 0xF7 +#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_ON 0x08 +#define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_OFF 0x00 // Default + +#define RFLR_MODEMCONFIG3_AGCAUTO_MASK 0xFB +#define RFLR_MODEMCONFIG3_AGCAUTO_ON 0x04 // Default +#define RFLR_MODEMCONFIG3_AGCAUTO_OFF 0x00 + +/*! + * RegFeiMsb (Read Only) + */ + +/*! + * RegFeiMid (Read Only) + */ + +/*! + * RegFeiLsb (Read Only) + */ + +/*! + * RegRssiWideband (Read Only) + */ + +/*! + * RegDetectOptimize + */ +#define RFLR_DETECTIONOPTIMIZE_MASK 0xF8 +#define RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 0x03 // Default +#define RFLR_DETECTIONOPTIMIZE_SF6 0x05 + +/*! + * RegInvertIQ + */ +#define RFLR_INVERTIQ_RX_MASK 0xBF +#define RFLR_INVERTIQ_RX_OFF 0x00 +#define RFLR_INVERTIQ_RX_ON 0x40 +#define RFLR_INVERTIQ_TX_MASK 0xFE +#define RFLR_INVERTIQ_TX_OFF 0x01 +#define RFLR_INVERTIQ_TX_ON 0x00 + +/*! + * RegDetectionThreshold + */ +#define RFLR_DETECTIONTHRESH_SF7_TO_SF12 0x0A // Default +#define RFLR_DETECTIONTHRESH_SF6 0x0C + +/*! + * RegInvertIQ2 + */ +#define RFLR_INVERTIQ2_ON 0x19 +#define RFLR_INVERTIQ2_OFF 0x1D + +/*! + * RegDioMapping1 + */ +#define RFLR_DIOMAPPING1_DIO0_MASK 0x3F +#define RFLR_DIOMAPPING1_DIO0_00 0x00 // Default +#define RFLR_DIOMAPPING1_DIO0_01 0x40 +#define RFLR_DIOMAPPING1_DIO0_10 0x80 +#define RFLR_DIOMAPPING1_DIO0_11 0xC0 + +#define RFLR_DIOMAPPING1_DIO1_MASK 0xCF +#define RFLR_DIOMAPPING1_DIO1_00 0x00 // Default +#define RFLR_DIOMAPPING1_DIO1_01 0x10 +#define RFLR_DIOMAPPING1_DIO1_10 0x20 +#define RFLR_DIOMAPPING1_DIO1_11 0x30 + +#define RFLR_DIOMAPPING1_DIO2_MASK 0xF3 +#define RFLR_DIOMAPPING1_DIO2_00 0x00 // Default +#define RFLR_DIOMAPPING1_DIO2_01 0x04 +#define RFLR_DIOMAPPING1_DIO2_10 0x08 +#define RFLR_DIOMAPPING1_DIO2_11 0x0C + +#define RFLR_DIOMAPPING1_DIO3_MASK 0xFC +#define RFLR_DIOMAPPING1_DIO3_00 0x00 // Default +#define RFLR_DIOMAPPING1_DIO3_01 0x01 +#define RFLR_DIOMAPPING1_DIO3_10 0x02 +#define RFLR_DIOMAPPING1_DIO3_11 0x03 + +/*! + * RegDioMapping2 + */ +#define RFLR_DIOMAPPING2_DIO4_MASK 0x3F +#define RFLR_DIOMAPPING2_DIO4_00 0x00 // Default +#define RFLR_DIOMAPPING2_DIO4_01 0x40 +#define RFLR_DIOMAPPING2_DIO4_10 0x80 +#define RFLR_DIOMAPPING2_DIO4_11 0xC0 + +#define RFLR_DIOMAPPING2_DIO5_MASK 0xCF +#define RFLR_DIOMAPPING2_DIO5_00 0x00 // Default +#define RFLR_DIOMAPPING2_DIO5_01 0x10 +#define RFLR_DIOMAPPING2_DIO5_10 0x20 +#define RFLR_DIOMAPPING2_DIO5_11 0x30 + +#define RFLR_DIOMAPPING2_MAP_MASK 0xFE +#define RFLR_DIOMAPPING2_MAP_PREAMBLEDETECT 0x01 +#define RFLR_DIOMAPPING2_MAP_RSSI 0x00 // Default + +/*! + * RegVersion (Read Only) + */ + +/*! + * RegPllHop + */ +#define RFLR_PLLHOP_FASTHOP_MASK 0x7F +#define RFLR_PLLHOP_FASTHOP_ON 0x80 +#define RFLR_PLLHOP_FASTHOP_OFF 0x00 // Default + +/*! + * RegTcxo + */ +#define RFLR_TCXO_TCXOINPUT_MASK 0xEF +#define RFLR_TCXO_TCXOINPUT_ON 0x10 +#define RFLR_TCXO_TCXOINPUT_OFF 0x00 // Default + +/*! + * RegPaDac + */ +#define RFLR_PADAC_20DBM_MASK 0xF8 +#define RFLR_PADAC_20DBM_ON 0x07 +#define RFLR_PADAC_20DBM_OFF 0x04 // Default + +/*! + * RegFormerTemp + */ + +/*! + * RegBitrateFrac + */ +#define RF_BITRATEFRAC_MASK 0xF0 + +/*! + * RegAgcRef + */ + +/*! + * RegAgcThresh1 + */ + +/*! + * RegAgcThresh2 + */ + +/*! + * RegAgcThresh3 + */ + +/*! + * RegPll + */ +#define RF_PLL_BANDWIDTH_MASK 0x3F +#define RF_PLL_BANDWIDTH_75 0x00 +#define RF_PLL_BANDWIDTH_150 0x40 +#define RF_PLL_BANDWIDTH_225 0x80 +#define RF_PLL_BANDWIDTH_300 0xC0 // Default + +#endif // __SX1276_REGS_LORA_H__
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/sx1276/library.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/sx1276/library.properties Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,9 @@ +name=SX1276GenericLib +version=1.0.0 +author=Semtech Inc, Helmut Tschemernjak <helmut2009@me.com> +maintainer=Helmut Tschemernjak <helmut2009@me.com> +sentence=SX1276GenericLib to support sx1276 bassed LoRa modules, including HopeRF RFM95, Murata CMWX1ZZABZ and Semtech SX1276MB1MAS/SX1276MB1LAS modules +paragraph= +category=Communication +url=http://www.radioshuttle.de +architectures=samd
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/sx1276/sx1276-linux-hal.cpp
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/sx1276/sx1276-linux-hal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/sx1276/sx1276-linux-hal.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,18 @@ + +/* + * This file contains a copy of the master content sx1276-mbed-hal.h + * with adaption for the Linux environment (PI or similar + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ +#ifdef __linux__ + + + + + + + + + +#endif // __linux__
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/sx1276/sx1276-mbed-hal.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/sx1276/sx1276-mbed-hal.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,442 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: - + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ + +/* + * additional development to make it more generic across multiple OS versions + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#ifdef ARDUINO + #include "arduino-mbed.h" +#endif + +#include "sx1276-mbed-hal.h" + + + +SX1276Generic::SX1276Generic( RadioEvents_t *events, BoardType_t board, + PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, + PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5, + PinName antSwitch, PinName antSwitchTX, PinName antSwitchTXBoost, PinName tcxo) + : SX1276( events) +{ + Sleep_ms( 10 ); + this->RadioEvents = events; + boardConnected = board; + + _antSwitch = NULL; + _antSwitchTX = NULL; + _antSwitchTXBoost = NULL; + + _tcxo = NULL; + if (tcxo != NC) + _tcxo = new DigitalOut(tcxo); + + switch(boardConnected) { + case SX1276MB1MAS: + case SX1276MB1LAS: + _antSwitch = new DigitalOut(antSwitch); + break; + case RFM95_SX1276: + break; + case MURATA_SX1276: + _antSwitch = new DigitalOut(antSwitch); + _antSwitchTX = new DigitalOut(antSwitchTX); + _antSwitchTXBoost = new DigitalOut(antSwitchTXBoost); + break; + default: + break; + } + _spi = new XSPI(mosi, miso, sclk ); + _nss = new DigitalOut(nss); + + _reset = new DigitalInOut(reset); + + _dio0 = NULL; + _dio1 = NULL; + _dio2 = NULL; + _dio3 = NULL; + _dio4 = NULL; + _dio5 = NULL; + if (dio0 != NC) + _dio0 = new InterruptIn(dio0); + if (dio1 != NC) + _dio1 = new InterruptIn(dio1); + if (dio2 != NC) + _dio2 = new InterruptIn(dio2); + if (dio3 != NC) + _dio3 = new InterruptIn(dio3); + if (dio4 != NC) + _dio4 = new InterruptIn(dio4); + if (dio5 != NC) + _dio5 = new DigitalIn(dio5); + + Reset( ); + + IoInit( ); + + RxChainCalibration( ); + + SetOpMode( RF_OPMODE_SLEEP ); + + IoIrqInit( dioIrq ); + + RadioRegistersInit( ); + + SetModem( MODEM_FSK ); +} + +SX1276Generic::~SX1276Generic() +{ + if (_antSwitch) + delete _antSwitch; + if (_antSwitchTX) + delete _antSwitchTX; + if (_antSwitchTXBoost) + delete _antSwitchTXBoost; + + if (_tcxo) { + *_tcxo = 0; + delete (_tcxo); + } + delete _reset; + delete _spi; + delete _nss; + + if (_dio0) + delete _dio0; + if (_dio1) + delete _dio1; + if (_dio2) + delete _dio2; + if (_dio3) + delete _dio3; + if (_dio4) + delete _dio4; + if (_dio5) + delete _dio5; +} + + +//------------------------------------------------------------------------- +// Board relative functions +//------------------------------------------------------------------------- +uint8_t SX1276Generic::DetectBoardType( void ) +{ + return boardConnected; +} + +void SX1276Generic::IoInit( void ) +{ + if (_tcxo) + *_tcxo = 1; + AntSwInit( ); + SpiInit( ); +} + + +void SX1276Generic::SpiInit( void ) +{ + *_nss = 1; + _spi->format( 8,0 ); + uint32_t frequencyToSet = 8000000; +#ifdef TARGET_KL25Z //busclock frequency is halved -> double the spi frequency to compensate + _spi->frequency( frequencyToSet * 2 ); +#else + _spi->frequency( frequencyToSet ); +#endif + wait_ms(100); +} + +void SX1276Generic::IoIrqInit( DioIrqHandler *irqHandlers ) +{ + if (_dio0) + _dio0->rise(callback(this, static_cast< Trigger > ( irqHandlers[0] ))); + if (_dio1) + _dio1->rise(callback(this, static_cast< Trigger > ( irqHandlers[1] ))); + if (_dio2) + _dio2->rise(callback(this, static_cast< Trigger > ( irqHandlers[2] ))); + if (_dio3) + _dio3->rise(callback(this, static_cast< Trigger > ( irqHandlers[3] ))); + if (_dio4) + _dio4->rise(callback(this, static_cast< Trigger > ( irqHandlers[4] ))); +} + +void SX1276Generic::IoDeInit( void ) +{ + //nothing +} + +void SX1276Generic::SetRfTxPower( int8_t power ) +{ + uint8_t paConfig = 0; + uint8_t paDac = 0; + + paConfig = Read( REG_PACONFIG ); + paDac = Read( REG_PADAC ); + + paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | GetPaSelect( this->settings.Channel ); + paConfig = ( paConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70; + + if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST ) + { + if( power > 17 ) + { + paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON; + } + else + { + paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF; + } + if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON ) + { + if( power < 5 ) + { + power = 5; + } + if( power > 20 ) + { + power = 20; + } + paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F ); + } + else + { + if( power < 2 ) + { + power = 2; + } + if( power > 17 ) + { + power = 17; + } + paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F ); + } + } + else + { + if( power < -1 ) + { + power = -1; + } + if( power > 14 ) + { + power = 14; + } + paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F ); + } + Write( REG_PACONFIG, paConfig ); + Write( REG_PADAC, paDac ); +} + + +uint8_t SX1276Generic::GetPaSelect( uint32_t channel ) +{ + if( channel > RF_MID_BAND_THRESH ) + { + if (boardConnected == SX1276MB1LAS || boardConnected == RFM95_SX1276 || boardConnected == MURATA_SX1276) + { + return RF_PACONFIG_PASELECT_PABOOST; + } + else + { + return RF_PACONFIG_PASELECT_RFO; + } + } + else + { + return RF_PACONFIG_PASELECT_RFO; + } +} + +void SX1276Generic::SetAntSwLowPower( bool status ) +{ + if( isRadioActive != status ) + { + isRadioActive = status; + + if( status == false ) + { + AntSwInit( ); + } + else + { + AntSwDeInit( ); + } + } +} + +void SX1276Generic::AntSwInit( void ) +{ + if (_antSwitch) + *_antSwitch = 0; + if (boardConnected == MURATA_SX1276) { + *_antSwitchTX = 0; + *_antSwitchTXBoost = 0; + } +} + +void SX1276Generic::AntSwDeInit( void ) +{ + if (_antSwitch) + *_antSwitch = 0; + if (boardConnected == MURATA_SX1276) { + *_antSwitchTX = 0; + *_antSwitchTXBoost = 0; + } +} + + +void SX1276Generic::SetAntSw( uint8_t opMode ) +{ + switch( opMode ) + { + case RFLR_OPMODE_TRANSMITTER: + if (boardConnected == MURATA_SX1276) { + *_antSwitch = 0;// Murata-RX + if (Read( REG_PACONFIG) & RF_PACONFIG_PASELECT_PABOOST) + *_antSwitchTXBoost = 1; + else + *_antSwitchTX = 1; // alternate: antSwitchTXBoost = 1 + } else { + if (_antSwitch) + *_antSwitch = 1; + } + break; + case RFLR_OPMODE_RECEIVER: + case RFLR_OPMODE_RECEIVER_SINGLE: + case RFLR_OPMODE_CAD: + if (boardConnected == MURATA_SX1276) { + *_antSwitch = 1; // Murata-RX + *_antSwitchTX = 0; + *_antSwitchTXBoost = 0; + } else { + if (_antSwitch) + _antSwitch = 0; + } + break; + case RFLR_OPMODE_SLEEP: + case RFLR_OPMODE_STANDBY: + default: + if (boardConnected == MURATA_SX1276) { + *_antSwitch = 0; //Murata-RX + *_antSwitchTX = 0; + *_antSwitchTXBoost = 0; + } else { + if (_antSwitch) + *_antSwitch = 0; + } + break; + } +} + +void SX1276Generic::SetTimeout(TimeoutTimer_t timer, timeoutFuncPtr func, int timeout_ms) +{ + switch(timer) { + case RXTimeoutTimer: + if (func) + rxTimeoutTimer.attach_us(callback(this, func), timeout_ms); + else + rxTimeoutTimer.detach(); + break; + case TXTimeoutTimer: + if (func) + txTimeoutTimer.attach_us(callback(this, func), timeout_ms); + else + txTimeoutTimer.detach(); + break; + case RXTimeoutSyncWordTimer: + if (func) + rxTimeoutSyncWord.attach_us(callback(this, func), timeout_ms); + else + rxTimeoutSyncWord.detach(); + break; + } +} + +void +SX1276Generic::Sleep_ms(int ms) +{ + wait_ms(ms); +} + +bool SX1276Generic::CheckRfFrequency( uint32_t frequency ) +{ + if (frequency > 1200000) + return false; + // Implement check. Currently all frequencies are supported + return true; +} + +void SX1276Generic::Reset( void ) +{ + _reset->output(); + *_reset = 0; + wait_ms( 1 ); + *_reset = 1; + _reset->input(); // I don't know my input again, maybe to save power (Helmut T) + wait_ms( 6 ); +} + +void SX1276Generic::Write( uint8_t addr, uint8_t data ) +{ + Write( addr, &data, 1 ); +} + +uint8_t SX1276Generic::Read( uint8_t addr ) +{ + uint8_t data; + Read( addr, &data, 1 ); + return data; +} + +void SX1276Generic::Write( uint8_t addr, void *buffer, uint8_t size ) +{ + uint8_t i; + uint8_t *p = (uint8_t *)buffer; + + *_nss = 0; // what about SPI hold/release timing on fast MCUs? Helmut + _spi->write( addr | 0x80 ); + for( i = 0; i < size; i++ ) + { + _spi->write(*p++); + } + *_nss = 1; +} + +void SX1276Generic::Read( uint8_t addr, void *buffer, uint8_t size ) +{ + uint8_t i; + uint8_t *p = (uint8_t *)buffer; + + *_nss = 0; // what about SPI hold/release timing on fast MCUs? Helmut + _spi->write( addr & 0x7F ); + for( i = 0; i < size; i++ ) + { + *p++ = _spi->write( 0 ); + } + *_nss = 1; +} + +void SX1276Generic::WriteFifo( void *buffer, uint8_t size ) +{ + Write( 0, buffer, size ); +} + +void SX1276Generic::ReadFifo( void *buffer, uint8_t size ) +{ + Read( 0, buffer, size ); +}
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/sx1276/sx1276-mbed-hal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/sx1276/sx1276-mbed-hal.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,251 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: - + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ + +/* + * additional development to make it more generic across multiple OS versions + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#ifndef __SX1276_MBED_HAL_H__ +#define __SX1276_MBED_HAL_H__ + + +#include "sx1276.h" + + +#ifdef __MBED__ +#define XSPI SPI +#endif + + +/*! + * Actual implementation of a SX1276 radio, includes some modifications to make it + * compatible with the MB1 LAS board + */ +class SX1276Generic : public SX1276 +{ +protected: + /*! + * Antenna switch GPIO pins objects + */ + DigitalOut *_antSwitch; + DigitalOut *_antSwitchTX; + DigitalOut *_antSwitchTXBoost; + + /*! + * SX1276 Reset pin + */ + DigitalInOut *_reset; + + /*! + * TCXO being used with the Murata Module + */ + DigitalOut *_tcxo; + + /*! + * SPI Interface + */ + XSPI *_spi; // mosi, miso, sclk + DigitalOut *_nss; + + /*! + * SX1276 DIO pins + */ + InterruptIn *_dio0; + InterruptIn *_dio1; + InterruptIn *_dio2; + InterruptIn *_dio3; + InterruptIn *_dio4; + DigitalIn *_dio5; + + /*! + * Tx and Rx timers + */ + Timeout txTimeoutTimer; + Timeout rxTimeoutTimer; + Timeout rxTimeoutSyncWord; + + +private: + /*! + * triggers definition + */ + typedef void (SX1276Generic::*Trigger)(void); + + +public: + SX1276Generic( RadioEvents_t *events, BoardType_t board, + PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, + PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5, + PinName antSwitch = NC, PinName antSwitchTX= NC, PinName antSwitchTXBoost = NC, PinName tcxo = NC); + + + SX1276Generic( RadioEvents_t *events ); + + virtual ~SX1276Generic(); + +protected: + /*! + * @brief Initializes the radio I/Os pins interface + */ + virtual void IoInit( void ); + + /*! + * @brief Initializes the radio SPI + */ + virtual void SpiInit( void ); + + /*! + * @brief Initializes DIO IRQ handlers + * + * @param [IN] irqHandlers Array containing the IRQ callback functions + */ + virtual void IoIrqInit( DioIrqHandler *irqHandlers ); + + /*! + * @brief De-initializes the radio I/Os pins interface. + * + * \remark Useful when going in MCU lowpower modes + */ + virtual void IoDeInit( void ); + + /*! + * @brief Gets the board PA selection configuration + * + * @param [IN] channel Channel frequency in Hz + * @retval PaSelect RegPaConfig PaSelect value + */ + virtual uint8_t GetPaSelect( uint32_t channel ); + + /*! + * @brief Set the RF Switch I/Os pins in Low Power mode + * + * @param [IN] status enable or disable + */ + virtual void SetAntSwLowPower( bool status ); + + /*! + * @brief Initializes the RF Switch I/Os pins interface + */ + virtual void AntSwInit( void ); + + /*! + * @brief De-initializes the RF Switch I/Os pins interface + * + * @remark Needed to decrease the power consumption in MCU lowpower modes + */ + virtual void AntSwDeInit( void ); + + /*! + * @brief Controls the antena switch if necessary. + * + * @remark see errata note + * + * @param [IN] opMode Current radio operating mode + */ + virtual void SetAntSw( uint8_t opMode ); + + /* + * The the Timeout for a given Timer. + */ + virtual void SetTimeout(TimeoutTimer_t timer, timeoutFuncPtr, int timeout_ms = 0); + + /* + * A simple ms sleep + */ + virtual void Sleep_ms(int ms); + + +public: + + /*! + * @brief Detect the board connected by reading the value of the antenna switch pin + */ + virtual uint8_t DetectBoardType( void ); + + /*! + * @brief Checks if the given RF frequency is supported by the hardware + * + * @param [IN] frequency RF frequency to be checked + * @retval isSupported [true: supported, false: unsupported] + */ + virtual bool CheckRfFrequency( uint32_t frequency ); + + /*! + * @brief Writes the radio register at the specified address + * + * @param [IN]: addr Register address + * @param [IN]: data New register value + */ + virtual void Write ( uint8_t addr, uint8_t data ) ; + + /*! + * @brief Reads the radio register at the specified address + * + * @param [IN]: addr Register address + * @retval data Register value + */ + virtual uint8_t Read ( uint8_t addr ) ; + + /*! + * @brief Writes multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [IN] buffer Buffer containing the new register's values + * @param [IN] size Number of registers to be written + */ + virtual void Write( uint8_t addr, void *buffer, uint8_t size ) ; + + /*! + * @brief Reads multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [OUT] buffer Buffer where to copy the registers data + * @param [IN] size Number of registers to be read + */ + virtual void Read ( uint8_t addr, void *buffer, uint8_t size ) ; + + /*! + * @brief Writes the buffer contents to the SX1276 FIFO + * + * @param [IN] buffer Buffer containing data to be put on the FIFO. + * @param [IN] size Number of bytes to be written to the FIFO + */ + virtual void WriteFifo( void *buffer, uint8_t size ) ; + + /*! + * @brief Reads the contents of the SX1276 FIFO + * + * @param [OUT] buffer Buffer where to copy the FIFO read data. + * @param [IN] size Number of bytes to be read from the FIFO + */ + virtual void ReadFifo( void *buffer, uint8_t size ) ; + + /*! + * @brief Reset the SX1276 + */ + virtual void Reset( void ); + + /*! + * \brief Sets the radio output power. + * + * @param [IN] power Sets the RF output power + */ + virtual void SetRfTxPower( int8_t power ); + +}; + +#endif // __SX1276_MBED_HAL_H__
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/sx1276/sx1276.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/sx1276/sx1276.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,1711 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: Actual implementation of a SX1276 radio, inherits Radio + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ + +/* + * additional development to make it more generic across multiple OS versions + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#include "sx1276.h" + + + +const SX1276::BandwidthMap SX1276::FskBandwidths[] = +{ + { 2600 , 0x17 }, + { 3100 , 0x0F }, + { 3900 , 0x07 }, + { 5200 , 0x16 }, + { 6300 , 0x0E }, + { 7800 , 0x06 }, + { 10400 , 0x15 }, + { 12500 , 0x0D }, + { 15600 , 0x05 }, + { 20800 , 0x14 }, + { 25000 , 0x0C }, + { 31300 , 0x04 }, + { 41700 , 0x13 }, + { 50000 , 0x0B }, + { 62500 , 0x03 }, + { 83333 , 0x12 }, + { 100000, 0x0A }, + { 125000, 0x02 }, + { 166700, 0x11 }, + { 200000, 0x09 }, + { 250000, 0x01 }, + { 300000, 0x00 }, // Invalid Bandwidth +}; + +const SX1276::BandwidthMap SX1276::LoRaBandwidths[] = +{ + { 7800, 0 }, // 7.8 kHz requires TCXO + { 10400, 1 }, // 10.4 kHz requires TCXO + { 15600, 2 }, // 15.6 kHz requires TCXO + { 20800, 3 }, // 20.8 kHz requires TCXO + { 31250, 4 }, // 31.25 kHz requires TCXO + { 41700, 5 }, // 41.7 kHz requires TCXO + { 62500, 6 }, // 62.5 kHz requires TCXO + { 125000, 7 }, // 125 kHz the LoRa protocol default + { 250000, 8 }, // 250 kHz + { 500000, 9 }, // 500 kHz + { 600000, 10 }, // Invalid Bandwidth, reserved + }; + + + +/*! + * @brief Radio hardware registers initialization definition + * + * @remark Can be automatically generated by the SX1276 GUI (not yet implemented) + */ + +const SX1276::RadioRegisters SX1276::RadioRegsInit[] = { + { MODEM_FSK , REG_LNA , 0x23 }, + { MODEM_FSK , REG_RXCONFIG , 0x1E }, + { MODEM_FSK , REG_RSSICONFIG , 0xD2 }, + { MODEM_FSK , REG_AFCFEI , 0x01 }, + { MODEM_FSK , REG_PREAMBLEDETECT , 0xAA }, + { MODEM_FSK , REG_OSC , 0x07 }, + { MODEM_FSK , REG_SYNCCONFIG , 0x12 }, + { MODEM_FSK , REG_SYNCVALUE1 , 0xC1 }, + { MODEM_FSK , REG_SYNCVALUE2 , 0x94 }, + { MODEM_FSK , REG_SYNCVALUE3 , 0xC1 }, + { MODEM_FSK , REG_PACKETCONFIG1 , 0xD8 }, + { MODEM_FSK , REG_FIFOTHRESH , 0x8F }, + { MODEM_FSK , REG_IMAGECAL , 0x02 }, + { MODEM_FSK , REG_DIOMAPPING1 , 0x00 }, + { MODEM_FSK , REG_DIOMAPPING2 , 0x30 }, + { MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40 }, + +}; + + +SX1276::SX1276( RadioEvents_t *events) : Radio( events ), isRadioActive( false ) +{ + this->rxtxBuffer = new uint8_t[RX_BUFFER_SIZE]; + + this->RadioEvents = events; + + this->dioIrq = new DioIrqHandler[6]; + + this->dioIrq[0] = &SX1276::OnDio0Irq; + this->dioIrq[1] = &SX1276::OnDio1Irq; + this->dioIrq[2] = &SX1276::OnDio2Irq; + this->dioIrq[3] = &SX1276::OnDio3Irq; + this->dioIrq[4] = &SX1276::OnDio4Irq; + this->dioIrq[5] = NULL; + + this->settings.State = RF_IDLE; +} + +SX1276::~SX1276( ) +{ + delete this->rxtxBuffer; + delete this->dioIrq; +} + +bool SX1276::Init( RadioEvents_t *events ) +{ + if (Read(REG_VERSION) == 0x00) + return false; + + this->RadioEvents = events; + return true; +} + + +void SX1276::RadioRegistersInit( ) +{ + uint8_t i = 0; + for( i = 0; i < sizeof( RadioRegsInit ) / sizeof( RadioRegisters ); i++ ) + { + SetModem( RadioRegsInit[i].Modem ); + Write( RadioRegsInit[i].Addr, RadioRegsInit[i].Value ); + } +} + + +RadioState SX1276::GetStatus( void ) +{ + return this->settings.State; +} + +void SX1276::SetChannel( uint32_t freq ) +{ + this->settings.Channel = freq; + freq = ( uint32_t )( ( double )freq / ( double )FREQ_STEP ); + Write( REG_FRFMSB, ( uint8_t )( ( freq >> 16 ) & 0xFF ) ); + Write( REG_FRFMID, ( uint8_t )( ( freq >> 8 ) & 0xFF ) ); + Write( REG_FRFLSB, ( uint8_t )( freq & 0xFF ) ); +} + +bool SX1276::IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ) +{ + int16_t rssi = 0; + + SetModem( modem ); + + SetChannel( freq ); + + SetOpMode( RF_OPMODE_RECEIVER ); + + Sleep_ms( 1 ); + + rssi = GetRssi( modem ); + + Sleep( ); + + if( rssi > rssiThresh ) + { + return false; + } + return true; +} + +uint32_t SX1276::Random( void ) +{ + uint8_t i; + uint32_t rnd = 0; + + /* + * Radio setup for random number generation + */ + // Set LoRa modem ON + SetModem( MODEM_LORA ); + + // Disable LoRa modem interrupts + Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // Set radio in continuous reception + SetOpMode( RF_OPMODE_RECEIVER ); + + for( i = 0; i < 32; i++ ) + { + Sleep_ms( 1 ); + // Unfiltered RSSI value reading. Only takes the LSB value + rnd |= ( ( uint32_t )Read( REG_LR_RSSIWIDEBAND ) & 0x01 ) << i; + } + + Sleep( ); + + return rnd; +} + +/*! + * Performs the Rx chain calibration for LF and HF bands + * \remark Must be called just after the reset so all registers are at their + * default values + */ +void SX1276::RxChainCalibration( void ) +{ + uint8_t regPaConfigInitVal; + uint32_t initialFreq; + + // Save context + regPaConfigInitVal = this->Read( REG_PACONFIG ); + initialFreq = ( double )( ( ( uint32_t )this->Read( REG_FRFMSB ) << 16 ) | + ( ( uint32_t )this->Read( REG_FRFMID ) << 8 ) | + ( ( uint32_t )this->Read( REG_FRFLSB ) ) ) * ( double )FREQ_STEP; + + // Cut the PA just in case, RFO output, power = -1 dBm + this->Write( REG_PACONFIG, 0x00 ); + + // Launch Rx chain calibration for LF band + Write ( REG_IMAGECAL, ( Read( REG_IMAGECAL ) & RF_IMAGECAL_IMAGECAL_MASK ) | RF_IMAGECAL_IMAGECAL_START ); + while( ( Read( REG_IMAGECAL ) & RF_IMAGECAL_IMAGECAL_RUNNING ) == RF_IMAGECAL_IMAGECAL_RUNNING ) + { + } + + // Sets a Frequency in HF band + SetChannel( 868000000 ); + + // Launch Rx chain calibration for HF band + Write ( REG_IMAGECAL, ( Read( REG_IMAGECAL ) & RF_IMAGECAL_IMAGECAL_MASK ) | RF_IMAGECAL_IMAGECAL_START ); + while( ( Read( REG_IMAGECAL ) & RF_IMAGECAL_IMAGECAL_RUNNING ) == RF_IMAGECAL_IMAGECAL_RUNNING ) + { + } + + // Restore context + this->Write( REG_PACONFIG, regPaConfigInitVal ); + SetChannel( initialFreq ); +} + +/*! + * Returns the known FSK bandwidth registers value + * + * \param [IN] bandwidth Bandwidth value in Hz + * \retval regValue Bandwidth register value. + */ +uint8_t SX1276::GetFskBandwidthRegValue( uint32_t bandwidth ) +{ + uint8_t i; + + for( i = 0; i < ( sizeof( FskBandwidths ) / sizeof( BandwidthMap ) ) - 1; i++ ) + { + if( ( bandwidth >= FskBandwidths[i].bandwidth ) && ( bandwidth < FskBandwidths[i + 1].bandwidth ) ) + { + return FskBandwidths[i].RegValue; + } + } + // ERROR: Value not found + while( 1 ); +} + +/*! + * Returns the known LoRa bandwidth registers value + * + * \param [IN] bandwidth Bandwidth value in Hz + * \retval regValue Bandwidth register value. + */ +uint8_t SX1276::GetLoRaBandwidthRegValue( uint32_t bandwidth ) +{ + uint8_t i; + + for( i = 0; i < ( sizeof( LoRaBandwidths ) / sizeof( BandwidthMap ) ) - 1; i++ ) + { + if( ( bandwidth >= LoRaBandwidths[i].bandwidth ) && ( bandwidth < LoRaBandwidths[i + 1].bandwidth ) ) + { + return LoRaBandwidths[i].RegValue; + } + } + // ERROR: Value not found + while( 1 ); +} + +void SX1276::SetRxConfig( RadioModems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ) +{ + SetModem( modem ); + + switch( modem ) + { + case MODEM_FSK: + { + this->settings.Fsk.Bandwidth = bandwidth; + this->settings.Fsk.Datarate = datarate; + this->settings.Fsk.BandwidthAfc = bandwidthAfc; + this->settings.Fsk.FixLen = fixLen; + this->settings.Fsk.PayloadLen = payloadLen; + this->settings.Fsk.CrcOn = crcOn; + this->settings.Fsk.IqInverted = iqInverted; + this->settings.Fsk.RxContinuous = rxContinuous; + this->settings.Fsk.PreambleLen = preambleLen; + this->settings.Fsk.RxSingleTimeout = symbTimeout * ( ( 1.0 / ( double )datarate ) * 8.0 ) * 1e3; + + + datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate ); + Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) ); + Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) ); + + Write( REG_RXBW, GetFskBandwidthRegValue( bandwidth ) ); + Write( REG_AFCBW, GetFskBandwidthRegValue( bandwidthAfc ) ); + + Write( REG_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); + Write( REG_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); + + if( fixLen == 1 ) + { + Write( REG_PAYLOADLENGTH, payloadLen ); + } + else + { + Write( REG_PAYLOADLENGTH, 0xFF ); // Set payload length to the maximum + } + + Write( REG_PACKETCONFIG1, + ( Read( REG_PACKETCONFIG1 ) & + RF_PACKETCONFIG1_CRC_MASK & + RF_PACKETCONFIG1_PACKETFORMAT_MASK ) | + ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) | + ( crcOn << 4 ) ); + Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) ); + } + break; + case MODEM_LORA: + { + if (bandwidth > 11) // specified in Hz, needs mapping + bandwidth = GetLoRaBandwidthRegValue(bandwidth); + if( bandwidth > LORA_BANKWIDTH_500kHz ) + { + // Fatal error: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported + while( 1 ); + } + this->settings.LoRa.Bandwidth = bandwidth; + this->settings.LoRa.Datarate = datarate; + this->settings.LoRa.Coderate = coderate; + this->settings.LoRa.PreambleLen = preambleLen; + this->settings.LoRa.FixLen = fixLen; + this->settings.LoRa.PayloadLen = payloadLen; + this->settings.LoRa.CrcOn = crcOn; + this->settings.LoRa.FreqHopOn = freqHopOn; + this->settings.LoRa.HopPeriod = hopPeriod; + this->settings.LoRa.IqInverted = iqInverted; + this->settings.LoRa.RxContinuous = rxContinuous; + + if( datarate > LORA_SF12 ) + { + datarate = LORA_SF12; + } + else if( datarate < LORA_SF6 ) + { + datarate = LORA_SF6; + } + + if( ( ( bandwidth == LORA_BANKWIDTH_125kHz ) && ( ( datarate == LORA_SF11 ) || ( datarate == LORA_SF12 ) ) ) || + ( ( bandwidth == LORA_BANKWIDTH_250kHz ) && ( datarate == LORA_SF12 ) ) ) + { + this->settings.LoRa.LowDatarateOptimize = 0x01; + } + else + { + this->settings.LoRa.LowDatarateOptimize = 0x00; + } + + Write( REG_LR_MODEMCONFIG1, + ( Read( REG_LR_MODEMCONFIG1 ) & + RFLR_MODEMCONFIG1_BW_MASK & + RFLR_MODEMCONFIG1_CODINGRATE_MASK & + RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK ) | + ( bandwidth << 4 ) | ( coderate << 1 ) | + fixLen ); + + Write( REG_LR_MODEMCONFIG2, + ( Read( REG_LR_MODEMCONFIG2 ) & + RFLR_MODEMCONFIG2_SF_MASK & + RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK & + RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK ) | + ( datarate << 4 ) | ( crcOn << 2 ) | + ( ( symbTimeout >> 8 ) & ~RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK ) ); + + Write( REG_LR_MODEMCONFIG3, + ( Read( REG_LR_MODEMCONFIG3 ) & + RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK ) | + ( this->settings.LoRa.LowDatarateOptimize << 3 ) ); + + Write( REG_LR_SYMBTIMEOUTLSB, ( uint8_t )( symbTimeout & 0xFF ) ); + + Write( REG_LR_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); + Write( REG_LR_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); + + if( fixLen == 1 ) + { + Write( REG_LR_PAYLOADLENGTH, payloadLen ); + } + + if( this->settings.LoRa.FreqHopOn == true ) + { + Write( REG_LR_PLLHOP, ( Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON ); + Write( REG_LR_HOPPERIOD, this->settings.LoRa.HopPeriod ); + } + + if( ( bandwidth == LORA_BANKWIDTH_500kHz ) && ( this->settings.Channel > RF_MID_BAND_THRESH ) ) + { + // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth + Write( REG_LR_TEST36, 0x02 ); + Write( REG_LR_TEST3A, 0x64 ); + } + else if( bandwidth == LORA_BANKWIDTH_500kHz ) + { + // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth + Write( REG_LR_TEST36, 0x02 ); + Write( REG_LR_TEST3A, 0x7F ); + } + else + { + // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth + Write( REG_LR_TEST36, 0x03 ); + } + + if( datarate == LORA_SF6 ) + { + Write( REG_LR_DETECTOPTIMIZE, + ( Read( REG_LR_DETECTOPTIMIZE ) & + RFLR_DETECTIONOPTIMIZE_MASK ) | + RFLR_DETECTIONOPTIMIZE_SF6 ); + Write( REG_LR_DETECTIONTHRESHOLD, + RFLR_DETECTIONTHRESH_SF6 ); + } + else + { + Write( REG_LR_DETECTOPTIMIZE, + ( Read( REG_LR_DETECTOPTIMIZE ) & + RFLR_DETECTIONOPTIMIZE_MASK ) | + RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 ); + Write( REG_LR_DETECTIONTHRESHOLD, + RFLR_DETECTIONTHRESH_SF7_TO_SF12 ); + } + } + break; + } +} + +void SX1276::SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ) +{ + SetModem( modem ); + SetRfTxPower( power ); + + switch( modem ) + { + case MODEM_FSK: + { + this->settings.Fsk.Power = power; + this->settings.Fsk.Fdev = fdev; + this->settings.Fsk.Bandwidth = bandwidth; + this->settings.Fsk.Datarate = datarate; + this->settings.Fsk.PreambleLen = preambleLen; + this->settings.Fsk.FixLen = fixLen; + this->settings.Fsk.CrcOn = crcOn; + this->settings.Fsk.IqInverted = iqInverted; + this->settings.Fsk.TxTimeout = timeout; + + fdev = ( uint16_t )( ( double )fdev / ( double )FREQ_STEP ); + Write( REG_FDEVMSB, ( uint8_t )( fdev >> 8 ) ); + Write( REG_FDEVLSB, ( uint8_t )( fdev & 0xFF ) ); + + datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate ); + Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) ); + Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) ); + + Write( REG_PREAMBLEMSB, ( preambleLen >> 8 ) & 0x00FF ); + Write( REG_PREAMBLELSB, preambleLen & 0xFF ); + + Write( REG_PACKETCONFIG1, + ( Read( REG_PACKETCONFIG1 ) & + RF_PACKETCONFIG1_CRC_MASK & + RF_PACKETCONFIG1_PACKETFORMAT_MASK ) | + ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) | + ( crcOn << 4 ) ); + Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) ); + } + break; + case MODEM_LORA: + { + this->settings.LoRa.Power = power; + if (bandwidth > 11) // specified in Hz, needs mapping + bandwidth = GetLoRaBandwidthRegValue(bandwidth); + if( bandwidth > LORA_BANKWIDTH_500kHz ) + { + // Fatal error: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported + while( 1 ); + } + this->settings.LoRa.Bandwidth = bandwidth; + this->settings.LoRa.Datarate = datarate; + this->settings.LoRa.Coderate = coderate; + this->settings.LoRa.PreambleLen = preambleLen; + this->settings.LoRa.FixLen = fixLen; + this->settings.LoRa.FreqHopOn = freqHopOn; + this->settings.LoRa.HopPeriod = hopPeriod; + this->settings.LoRa.CrcOn = crcOn; + this->settings.LoRa.IqInverted = iqInverted; + this->settings.LoRa.TxTimeout = timeout; + + if( datarate > LORA_SF12 ) + { + datarate = LORA_SF12; + } + else if( datarate < LORA_SF6 ) + { + datarate = LORA_SF6; + } + if( ( ( bandwidth == LORA_BANKWIDTH_125kHz ) && ( ( datarate == LORA_SF11 ) || ( datarate == LORA_SF12 ) ) ) || + ( ( bandwidth == LORA_BANKWIDTH_250kHz ) && ( datarate == LORA_SF12 ) ) ) + { + this->settings.LoRa.LowDatarateOptimize = 0x01; + } + else + { + this->settings.LoRa.LowDatarateOptimize = 0x00; + } + + if( this->settings.LoRa.FreqHopOn == true ) + { + Write( REG_LR_PLLHOP, ( Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON ); + Write( REG_LR_HOPPERIOD, this->settings.LoRa.HopPeriod ); + } + + Write( REG_LR_MODEMCONFIG1, + ( Read( REG_LR_MODEMCONFIG1 ) & + RFLR_MODEMCONFIG1_BW_MASK & + RFLR_MODEMCONFIG1_CODINGRATE_MASK & + RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK ) | + ( bandwidth << 4 ) | ( coderate << 1 ) | + fixLen ); + + Write( REG_LR_MODEMCONFIG2, + ( Read( REG_LR_MODEMCONFIG2 ) & + RFLR_MODEMCONFIG2_SF_MASK & + RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK ) | + ( datarate << 4 ) | ( crcOn << 2 ) ); + + Write( REG_LR_MODEMCONFIG3, + ( Read( REG_LR_MODEMCONFIG3 ) & + RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK ) | + ( this->settings.LoRa.LowDatarateOptimize << 3 ) ); + + Write( REG_LR_PREAMBLEMSB, ( preambleLen >> 8 ) & 0x00FF ); + Write( REG_LR_PREAMBLELSB, preambleLen & 0xFF ); + + if( datarate == LORA_SF6 ) + { + Write( REG_LR_DETECTOPTIMIZE, + ( Read( REG_LR_DETECTOPTIMIZE ) & + RFLR_DETECTIONOPTIMIZE_MASK ) | + RFLR_DETECTIONOPTIMIZE_SF6 ); + Write( REG_LR_DETECTIONTHRESHOLD, + RFLR_DETECTIONTHRESH_SF6 ); + } + else + { + Write( REG_LR_DETECTOPTIMIZE, + ( Read( REG_LR_DETECTOPTIMIZE ) & + RFLR_DETECTIONOPTIMIZE_MASK ) | + RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 ); + Write( REG_LR_DETECTIONTHRESHOLD, + RFLR_DETECTIONTHRESH_SF7_TO_SF12 ); + } + } + break; + } +} + +uint32_t SX1276::TimeOnAir( RadioModems_t modem, int16_t pktLen ) +{ + uint32_t airTime = 0; + + switch( modem ) + { + case MODEM_FSK: + { + airTime = rint( ( 8 * ( this->settings.Fsk.PreambleLen + + ( ( Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) + + ( ( this->settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) + + ( ( ( Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) + + pktLen + + ( ( this->settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) / + this->settings.Fsk.Datarate ) * 1e3 ); + } + break; + case MODEM_LORA: + { + double bw = 0.0; + // REMARK: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported + switch( this->settings.LoRa.Bandwidth ) + { + case LORA_BANKWIDTH_7kHz: // 7.8 kHz + bw = 78e2; + break; + case LORA_BANKWIDTH_10kHz: // 10.4 kHz + bw = 104e2; + break; + case LORA_BANKWIDTH_15kHz: // 15.6 kHz + bw = 156e2; + break; + case LORA_BANKWIDTH_20kHz: // 20.8 kHz + bw = 208e2; + break; + case LORA_BANKWIDTH_31kHz: // 31.25 kHz + bw = 312e2; + break; + case LORA_BANKWIDTH_41kHz: // 41.7 kHz + bw = 414e2; + break; + case LORA_BANKWIDTH_62kHz: // 62.5 kHz + bw = 625e2; + break; + case LORA_BANKWIDTH_125kHz: // 125 kHz + bw = 125e3; + break; + case LORA_BANKWIDTH_250kHz: // 250 kHz + bw = 250e3; + break; + case LORA_BANKWIDTH_500kHz: // 500 kHz + bw = 500e3; + break; + } + + // Symbol rate : time for one symbol (secs) + double rs = bw / ( 1 << this->settings.LoRa.Datarate ); + double ts = 1 / rs; + // time of preamble + double tPreamble = ( this->settings.LoRa.PreambleLen + 4.25 ) * ts; + // Symbol length of payload and time + double tmp = ceil( ( 8 * pktLen - 4 * this->settings.LoRa.Datarate + + 28 + 16 * this->settings.LoRa.CrcOn - + ( this->settings.LoRa.FixLen ? 20 : 0 ) ) / + ( double )( 4 * ( this->settings.LoRa.Datarate - + ( ( this->settings.LoRa.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * + ( this->settings.LoRa.Coderate + 4 ); + double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); + double tPayload = nPayload * ts; + // Time on air + double tOnAir = tPreamble + tPayload; + // return ms secs + airTime = floor( tOnAir * 1e3 + 0.999 ); + } + break; + } + return airTime; +} + +void SX1276::Send( void *buffer, int16_t size, void *header, int16_t hsize ) +{ + uint32_t txTimeout = 0; + + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = size + hsize; + + if( this->settings.Fsk.FixLen == false ) + { + uint8_t tmpsize = size + hsize; + WriteFifo( ( uint8_t* )&tmpsize, 1 ); + } + else + { + Write( REG_PAYLOADLENGTH, size + hsize); + } + + if( ( size + hsize > 0 ) && ( size + hsize <= 64 ) ) + { + this->settings.FskPacketHandler.ChunkSize = size + hsize; + } + else + { + if (header) { + WriteFifo( header, hsize ); + memcpy( rxtxBuffer, header, hsize ); + } + memcpy( rxtxBuffer+hsize, (uint8_t *)buffer+hsize, size ); + this->settings.FskPacketHandler.ChunkSize = 32; + } + + // Write payload buffer + if (header) + WriteFifo( header, hsize ); + WriteFifo( buffer, this->settings.FskPacketHandler.ChunkSize ); + this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.ChunkSize; + txTimeout = this->settings.Fsk.TxTimeout; + } + break; + case MODEM_LORA: + { + if( this->settings.LoRa.IqInverted == true ) + { + Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_ON ) ); + Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON ); + } + else + { + Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) ); + Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF ); + } + + this->settings.LoRaPacketHandler.Size = size + hsize; + + // Initializes the payload size + Write( REG_LR_PAYLOADLENGTH, size + hsize); + + // Full buffer used for Tx + Write( REG_LR_FIFOTXBASEADDR, 0 ); + Write( REG_LR_FIFOADDRPTR, 0 ); + + // FIFO operations can not take place in Sleep mode + if( ( Read( REG_OPMODE ) & ~RF_OPMODE_MASK ) == RF_OPMODE_SLEEP ) + { + Standby( ); + Sleep_ms( 1 ); + } + // Write payload buffer + if (header) + WriteFifo( header, hsize ); + WriteFifo( buffer, size ); + txTimeout = this->settings.LoRa.TxTimeout; + } + break; + } + + Tx( txTimeout ); +} + +void SX1276::Sleep( void ) +{ + SetTimeout(TXTimeoutTimer, NULL); + SetTimeout(RXTimeoutTimer, NULL); + + SetOpMode( RF_OPMODE_SLEEP ); + this->settings.State = RF_IDLE; +} + +void SX1276::Standby( void ) +{ + SetTimeout(TXTimeoutTimer, NULL); + SetTimeout(RXTimeoutTimer, NULL); + + SetOpMode( RF_OPMODE_STANDBY ); + this->settings.State = RF_IDLE; +} + +void SX1276::Rx( uint32_t timeout ) +{ + bool rxContinuous = false; + + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + rxContinuous = this->settings.Fsk.RxContinuous; + + // DIO0=PayloadReady + // DIO1=FifoLevel + // DIO2=SyncAddr + // DIO3=FifoEmpty + // DIO4=Preamble + // DIO5=ModeReady + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK & + RF_DIOMAPPING1_DIO1_MASK & + RF_DIOMAPPING1_DIO2_MASK ) | + RF_DIOMAPPING1_DIO0_00 | + RF_DIOMAPPING1_DIO1_00 | + RF_DIOMAPPING1_DIO2_11 ); + + Write( REG_DIOMAPPING2, ( Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK & + RF_DIOMAPPING2_MAP_MASK ) | + RF_DIOMAPPING2_DIO4_11 | + RF_DIOMAPPING2_MAP_PREAMBLEDETECT ); + + this->settings.FskPacketHandler.FifoThresh = Read( REG_FIFOTHRESH ) & 0x3F; + + Write( REG_RXCONFIG, RF_RXCONFIG_AFCAUTO_ON | RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT ); + + this->settings.FskPacketHandler.PreambleDetected = false; + this->settings.FskPacketHandler.SyncWordDetected = false; + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = 0; + } + break; + case MODEM_LORA: + { + if( this->settings.LoRa.IqInverted == true ) + { + Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_ON | RFLR_INVERTIQ_TX_OFF ) ); + Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON ); + } + else + { + Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) ); + Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF ); + } + + // ERRATA 2.3 - Receiver Spurious Reception of a LoRa Signal + if( this->settings.LoRa.Bandwidth < LORA_BANKWIDTH_500kHz ) + { + Write( REG_LR_DETECTOPTIMIZE, Read( REG_LR_DETECTOPTIMIZE ) & 0x7F ); + Write( REG_LR_TEST30, 0x00 ); + switch( this->settings.LoRa.Bandwidth ) + { + case LORA_BANKWIDTH_7kHz: // 7.8 kHz + Write( REG_LR_TEST2F, 0x48 ); + SetChannel(this->settings.Channel + 7.81e3 ); + break; + case LORA_BANKWIDTH_10kHz: // 10.4 kHz + Write( REG_LR_TEST2F, 0x44 ); + SetChannel(this->settings.Channel + 10.42e3 ); + break; + case LORA_BANKWIDTH_15kHz: // 15.6 kHz + Write( REG_LR_TEST2F, 0x44 ); + SetChannel(this->settings.Channel + 15.62e3 ); + break; + case LORA_BANKWIDTH_20kHz: // 20.8 kHz + Write( REG_LR_TEST2F, 0x44 ); + SetChannel(this->settings.Channel + 20.83e3 ); + break; + case LORA_BANKWIDTH_31kHz: // 31.25 kHz + Write( REG_LR_TEST2F, 0x44 ); + SetChannel(this->settings.Channel + 31.25e3 ); + break; + case LORA_BANKWIDTH_41kHz: // 41.4 kHz + Write( REG_LR_TEST2F, 0x44 ); + SetChannel(this->settings.Channel + 41.67e3 ); + break; + case LORA_BANKWIDTH_62kHz: // 62.5 kHz + Write( REG_LR_TEST2F, 0x40 ); + break; + case LORA_BANKWIDTH_125kHz: // 125 kHz + Write( REG_LR_TEST2F, 0x40 ); + break; + case LORA_BANKWIDTH_250kHz: // 250 kHz + Write( REG_LR_TEST2F, 0x40 ); + break; + } + } + else + { + Write( REG_LR_DETECTOPTIMIZE, Read( REG_LR_DETECTOPTIMIZE ) | 0x80 ); + } + + rxContinuous = this->settings.LoRa.RxContinuous; + + if( this->settings.LoRa.FreqHopOn == true ) + { + Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | + //RFLR_IRQFLAGS_RXDONE | + //RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=RxDone, DIO2=FhssChangeChannel + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO2_00 ); + } + else + { + Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | + //RFLR_IRQFLAGS_RXDONE | + //RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=RxDone + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 ); + } + Write( REG_LR_FIFORXBASEADDR, 0 ); + Write( REG_LR_FIFOADDRPTR, 0 ); + } + break; + } + + this->settings.State = RF_RX_RUNNING; + if( timeout != 0 ) + { + SetTimeout(RXTimeoutTimer, &SX1276::OnTimeoutIrq, timeout * 1e3); + } + + if( this->settings.Modem == MODEM_FSK ) + { + SetOpMode( RF_OPMODE_RECEIVER ); + + if( rxContinuous == false ) + { + SetTimeout(RXTimeoutSyncWordTimer, &SX1276::OnTimeoutIrq, this->settings.Fsk.RxSingleTimeout * 1e3); + } + } + else + { + if( rxContinuous == true ) + { + SetOpMode( RFLR_OPMODE_RECEIVER ); + } + else + { + SetOpMode( RFLR_OPMODE_RECEIVER_SINGLE ); + } + } +} + +bool SX1276::RxSignalPending() +{ + if (this->settings.State != RF_RX_RUNNING) + return false; + + switch( this->settings.Modem ) + { + case MODEM_FSK: + break; + case MODEM_LORA: + if (Read(REG_LR_MODEMSTAT) & (RFLR_MODEMSTAT_SIGNAL_DETECTED|RFLR_MODEMSTAT_SIGNAL_SYNCRONIZED|RFLR_MODEMSTAT_HEADERINFO_VALID|RFLR_MODEMSTAT_MODEM_CLEAR)) + return true; + break; + } + return false; +} + +void SX1276::Tx( uint32_t timeout ) +{ + + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + // DIO0=PacketSent + // DIO1=FifoEmpty + // DIO2=FifoFull + // DIO3=FifoEmpty + // DIO4=LowBat + // DIO5=ModeReady + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK & + RF_DIOMAPPING1_DIO1_MASK & + RF_DIOMAPPING1_DIO2_MASK ) | + RF_DIOMAPPING1_DIO1_01 ); + + Write( REG_DIOMAPPING2, ( Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK & + RF_DIOMAPPING2_MAP_MASK ) ); + this->settings.FskPacketHandler.FifoThresh = Read( REG_FIFOTHRESH ) & 0x3F; + } + break; + case MODEM_LORA: + { + if( this->settings.LoRa.FreqHopOn == true ) + { + Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + //RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=TxDone, DIO2=FhssChangeChannel + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_01 | RFLR_DIOMAPPING1_DIO2_00 ); + } + else + { + Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + //RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=TxDone + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_01 ); + } + } + break; + } + + this->settings.State = RF_TX_RUNNING; + SetTimeout(TXTimeoutTimer, &SX1276::OnTimeoutIrq, timeout * 1e3); + SetOpMode( RF_OPMODE_TRANSMITTER ); +} + +void SX1276::StartCad( void ) +{ + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + + } + break; + case MODEM_LORA: + { + Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + //RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL // | + //RFLR_IRQFLAGS_CADDETECTED + ); + + // DIO3=CADDone + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO3_MASK ) | RFLR_DIOMAPPING1_DIO3_00 ); + + this->settings.State = RF_CAD; + SetOpMode( RFLR_OPMODE_CAD ); + } + break; + default: + break; + } +} + +void SX1276::SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ) +{ + uint32_t timeout = ( uint32_t )( time * 1e6 ); + + SetChannel( freq ); + + SetTxConfig( MODEM_FSK, power, 0, 0, 4800, 0, 5, false, false, 0, 0, 0, timeout ); + + Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) & RF_PACKETCONFIG2_DATAMODE_MASK ) ); + // Disable radio interrupts + Write( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 | RF_DIOMAPPING1_DIO1_11 ); + Write( REG_DIOMAPPING2, RF_DIOMAPPING2_DIO4_10 | RF_DIOMAPPING2_DIO5_10 ); + + this->settings.State = RF_TX_RUNNING; + SetTimeout(TXTimeoutTimer, &SX1276::OnTimeoutIrq, timeout); + SetOpMode( RF_OPMODE_TRANSMITTER ); +} + +int16_t SX1276::MaxMTUSize( RadioModems_t modem ) +{ + int16_t mtuSize = 0; + + switch( modem ) + { + case MODEM_FSK: + mtuSize = RX_BUFFER_SIZE; + case MODEM_LORA: + mtuSize = RX_BUFFER_SIZE; + break; + default: + mtuSize = -1; + break; + } + return mtuSize; +} + +int16_t SX1276::GetRssi( RadioModems_t modem ) +{ + int16_t rssi = 0; + + switch( modem ) + { + case MODEM_FSK: + rssi = -( Read( REG_RSSIVALUE ) >> 1 ); + break; + case MODEM_LORA: + if( this->settings.Channel > RF_MID_BAND_THRESH ) + { + rssi = RSSI_OFFSET_HF + Read( REG_LR_RSSIVALUE ); + } + else + { + rssi = RSSI_OFFSET_LF + Read( REG_LR_RSSIVALUE ); + } + break; + default: + rssi = -1; + break; + } + return rssi; +} + +int32_t SX1276::GetFrequencyError(RadioModems_t modem ) +{ + int32_t val = 0; + + if (modem != MODEM_LORA) + return 0; + + val = (Read(REG_LR_FEIMSB) & 0b1111) << 16; // high word, 4 valid bits only + val |= (Read(REG_LR_FEIMID) << 8) | Read(REG_LR_FEILSB); // high byte, low byte + if (val & 0x8000) //sconvert ign bit + val |= 0xfff00000; + + int32_t bandwidth = 0; + for (int i = 0; i < (int)(sizeof(LoRaBandwidths) / sizeof(BandwidthMap)) -1; i++ ) { + if (LoRaBandwidths[i].RegValue == this->settings.LoRa.Bandwidth) { + bandwidth = LoRaBandwidths[i].bandwidth; + break; + } + } + if (!bandwidth) + return 0; + + float bandWidthkHz = (float)bandwidth/1000; + + int32_t hz = (((float)val * (float)(1<<24)) / ((float)XTAL_FREQ)) * (bandWidthkHz / 500.0); + + return hz; +} + + +void SX1276::SetOpMode( uint8_t opMode ) +{ + if( opMode == RF_OPMODE_SLEEP ) + { + SetAntSwLowPower( true ); + } + else + { + SetAntSwLowPower( false ); + SetAntSw( opMode ); + } + Write( REG_OPMODE, ( Read( REG_OPMODE ) & RF_OPMODE_MASK ) | opMode ); +} + +void SX1276::SetModem( RadioModems_t modem ) +{ + if( ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_ON ) != 0 ) + { + this->settings.Modem = MODEM_LORA; + } + else + { + this->settings.Modem = MODEM_FSK; + } + + if( this->settings.Modem == modem ) + { + return; + } + + this->settings.Modem = modem; + switch( this->settings.Modem ) + { + default: + case MODEM_FSK: + Sleep( ); + Write( REG_OPMODE, ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_OFF ); + + Write( REG_DIOMAPPING1, 0x00 ); + Write( REG_DIOMAPPING2, 0x30 ); // DIO5=ModeReady + break; + case MODEM_LORA: + Sleep( ); + Write( REG_OPMODE, ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_ON ); + + Write( REG_DIOMAPPING1, 0x00 ); + Write( REG_DIOMAPPING2, 0x00 ); + break; + } +} + +void SX1276::SetMaxPayloadLength( RadioModems_t modem, uint8_t max ) +{ + this->SetModem( modem ); + + switch( modem ) + { + case MODEM_FSK: + if( this->settings.Fsk.FixLen == false ) + { + this->Write( REG_PAYLOADLENGTH, max ); + } + break; + case MODEM_LORA: + this->Write( REG_LR_PAYLOADMAXLENGTH, max ); + break; + } +} + +void SX1276::SetPublicNetwork( bool enable ) +{ + SetModem( MODEM_LORA ); + this->settings.LoRa.PublicNetwork = enable; + if( enable == true ) + { + // Change LoRa modem SyncWord + Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD ); + } + else + { + // Change LoRa modem SyncWord + Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD ); + } +} + + +void SX1276::OnTimeoutIrq( void ) +{ + switch( this->settings.State ) + { + case RF_RX_RUNNING: + if( this->settings.Modem == MODEM_FSK ) + { + this->settings.FskPacketHandler.PreambleDetected = false; + this->settings.FskPacketHandler.SyncWordDetected = false; + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = 0; + + // Clear Irqs + Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI | + RF_IRQFLAGS1_PREAMBLEDETECT | + RF_IRQFLAGS1_SYNCADDRESSMATCH ); + Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN ); + + if( this->settings.Fsk.RxContinuous == true ) + { + // Continuous mode restart Rx chain + Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK ); + SetTimeout(RXTimeoutSyncWordTimer, &SX1276::OnTimeoutIrq, this->settings.Fsk.RxSingleTimeout * 1e3); + } + else + { + this->settings.State = RF_IDLE; + SetTimeout(RXTimeoutSyncWordTimer, NULL); + } + } + if (this->RadioEvents && this->RadioEvents->RxTimeout) + { + this->RadioEvents->RxTimeout(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData); + } + break; + case RF_TX_RUNNING: + // Tx timeout shouldn't happen. + // But it has been observed that when it happens it is a result of a corrupted SPI transfer + // it depends on the platform design. + // + // The workaround is to put the radio in a known state. Thus, we re-initialize it. + // BEGIN WORKAROUND + + // Reset the radio + Reset( ); + + // Calibrate Rx chain + RxChainCalibration( ); + + // Initialize radio default values + SetOpMode( RF_OPMODE_SLEEP ); + + RadioRegistersInit( ); + + SetModem( MODEM_FSK ); + + // Restore previous network type setting. + SetPublicNetwork( this->settings.LoRa.PublicNetwork ); + // END WORKAROUND + + this->settings.State = RF_IDLE; + if (this->RadioEvents && this->RadioEvents->TxTimeout) + { + this->RadioEvents->TxTimeout(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData); + } + break; + default: + break; + } +} + +void SX1276::OnDio0Irq( void ) +{ + volatile uint8_t irqFlags = 0; + + switch( this->settings.State ) + { + case RF_RX_RUNNING: + //TimerStop( &RxTimeoutTimer ); + // RxDone interrupt + switch( this->settings.Modem ) + { + case MODEM_FSK: + if( this->settings.Fsk.CrcOn == true ) + { + irqFlags = Read( REG_IRQFLAGS2 ); + if( ( irqFlags & RF_IRQFLAGS2_CRCOK ) != RF_IRQFLAGS2_CRCOK ) + { + // Clear Irqs + Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI | + RF_IRQFLAGS1_PREAMBLEDETECT | + RF_IRQFLAGS1_SYNCADDRESSMATCH ); + Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN ); + + SetTimeout(RXTimeoutTimer, NULL); + + if( this->settings.Fsk.RxContinuous == false ) + { + SetTimeout(RXTimeoutSyncWordTimer, NULL); + this->settings.State = RF_IDLE; + } + else + { + // Continuous mode restart Rx chain + Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK ); + SetTimeout(RXTimeoutSyncWordTimer, &SX1276::OnTimeoutIrq, this->settings.Fsk.RxSingleTimeout * 1e3); + } + + if (this->RadioEvents && this->RadioEvents->RxError) + { + this->RadioEvents->RxError(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData); + } + this->settings.FskPacketHandler.PreambleDetected = false; + this->settings.FskPacketHandler.SyncWordDetected = false; + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = 0; + break; + } + } + + // Read received packet size + if( ( this->settings.FskPacketHandler.Size == 0 ) && ( this->settings.FskPacketHandler.NbBytes == 0 ) ) + { + if( this->settings.Fsk.FixLen == false ) + { + ReadFifo( ( uint8_t* )&this->settings.FskPacketHandler.Size, 1 ); + } + else + { + this->settings.FskPacketHandler.Size = Read( REG_PAYLOADLENGTH ); + } + ReadFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + } + else + { + ReadFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + } + + SetTimeout(RXTimeoutTimer, NULL); + + if( this->settings.Fsk.RxContinuous == false ) + { + this->settings.State = RF_IDLE; + SetTimeout(RXTimeoutSyncWordTimer, NULL); + } + else + { + // Continuous mode restart Rx chain + Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK ); + SetTimeout(RXTimeoutSyncWordTimer, &SX1276::OnTimeoutIrq, this->settings.Fsk.RxSingleTimeout * 1e3); + } + + if (this->RadioEvents && this->RadioEvents->RxDone) + { + this->RadioEvents->RxDone(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData, rxtxBuffer, this->settings.FskPacketHandler.Size, this->settings.FskPacketHandler.RssiValue, 0 ); + } + this->settings.FskPacketHandler.PreambleDetected = false; + this->settings.FskPacketHandler.SyncWordDetected = false; + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = 0; + break; + case MODEM_LORA: + { + int8_t snr = 0; + + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE ); + + irqFlags = Read( REG_LR_IRQFLAGS ); + if( ( irqFlags & RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK ) == RFLR_IRQFLAGS_PAYLOADCRCERROR ) + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_PAYLOADCRCERROR ); + + if( this->settings.LoRa.RxContinuous == false ) + { + this->settings.State = RF_IDLE; + } + SetTimeout(RXTimeoutTimer, NULL); + + if(this->RadioEvents && this->RadioEvents->RxError) + { + this->RadioEvents->RxError(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData); + } + break; + } + + this->settings.LoRaPacketHandler.SnrValue = Read( REG_LR_PKTSNRVALUE ); + if( this->settings.LoRaPacketHandler.SnrValue & 0x80 ) // The SNR sign bit is 1 + { + // Invert and divide by 4 + snr = ( ( ~this->settings.LoRaPacketHandler.SnrValue + 1 ) & 0xFF ) >> 2; + snr = -snr; + } + else + { + // Divide by 4 + snr = ( this->settings.LoRaPacketHandler.SnrValue & 0xFF ) >> 2; + } + + int16_t rssi = Read( REG_LR_PKTRSSIVALUE ); + if( snr < 0 ) + { + if( this->settings.Channel > RF_MID_BAND_THRESH ) + { + this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_HF + rssi + ( rssi >> 4 ) + + snr; + } + else + { + this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_LF + rssi + ( rssi >> 4 ) + + snr; + } + } + else + { + if( this->settings.Channel > RF_MID_BAND_THRESH ) + { + this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_HF + rssi + ( rssi >> 4 ); + } + else + { + this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_LF + rssi + ( rssi >> 4 ); + } + } + + this->settings.LoRaPacketHandler.Size = Read( REG_LR_RXNBBYTES ); + ReadFifo( rxtxBuffer, this->settings.LoRaPacketHandler.Size ); + + if( this->settings.LoRa.RxContinuous == false ) + { + this->settings.State = RF_IDLE; + } + SetTimeout(RXTimeoutTimer, NULL); + + if(this->RadioEvents && this->RadioEvents->RxDone) + { + this->RadioEvents->RxDone(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData, rxtxBuffer, this->settings.LoRaPacketHandler.Size, this->settings.LoRaPacketHandler.RssiValue, this->settings.LoRaPacketHandler.SnrValue ); + } + } + break; + default: + break; + } + break; + case RF_TX_RUNNING: + SetTimeout(TXTimeoutTimer, NULL); + // TxDone interrupt + switch( this->settings.Modem ) + { + case MODEM_LORA: + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_TXDONE ); + // Intentional fall through + case MODEM_FSK: + default: + this->settings.State = RF_IDLE; + if (this->RadioEvents && this->RadioEvents->TxDone) + { + this->RadioEvents->TxDone(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData); + } + break; + } + break; + default: + break; + } +} + +void SX1276::OnDio1Irq( void ) +{ + switch( this->settings.State ) + { + case RF_RX_RUNNING: + switch( this->settings.Modem ) + { + case MODEM_FSK: + // FifoLevel interrupt + // Read received packet size + if( ( this->settings.FskPacketHandler.Size == 0 ) && ( this->settings.FskPacketHandler.NbBytes == 0 ) ) + { + if( this->settings.Fsk.FixLen == false ) + { + ReadFifo( ( uint8_t* )&this->settings.FskPacketHandler.Size, 1 ); + } + else + { + this->settings.FskPacketHandler.Size = Read( REG_PAYLOADLENGTH ); + } + } + + if( ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ) > this->settings.FskPacketHandler.FifoThresh ) + { + ReadFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.FifoThresh ); + this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.FifoThresh; + } + else + { + ReadFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + } + break; + case MODEM_LORA: + // Sync time out + SetTimeout(RXTimeoutTimer, NULL); + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXTIMEOUT ); + + this->settings.State = RF_IDLE; + if (this->RadioEvents && this->RadioEvents->RxTimeout) + { + this->RadioEvents->RxTimeout(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData); + } + break; + default: + break; + } + break; + case RF_TX_RUNNING: + switch( this->settings.Modem ) + { + case MODEM_FSK: + // FifoEmpty interrupt + if( ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ) > this->settings.FskPacketHandler.ChunkSize ) + { + WriteFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.ChunkSize ); + this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.ChunkSize; + } + else + { + // Write the last chunk of data + WriteFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes; + } + break; + case MODEM_LORA: + break; + default: + break; + } + break; + default: + break; + } +} + +void SX1276::OnDio2Irq( void ) +{ + switch( this->settings.State ) + { + case RF_RX_RUNNING: + switch( this->settings.Modem ) + { + case MODEM_FSK: + // Checks if DIO4 is connected. If it is not PreambleDtected is set to true. + if( this->dioIrq[4] == NULL ) + { + this->settings.FskPacketHandler.PreambleDetected = true; + } + + if( ( this->settings.FskPacketHandler.PreambleDetected == true ) && ( this->settings.FskPacketHandler.SyncWordDetected == false ) ) + { + SetTimeout(RXTimeoutSyncWordTimer, NULL); + + this->settings.FskPacketHandler.SyncWordDetected = true; + + this->settings.FskPacketHandler.RssiValue = -( Read( REG_RSSIVALUE ) >> 1 ); + + this->settings.FskPacketHandler.AfcValue = ( int32_t )( double )( ( ( uint16_t )Read( REG_AFCMSB ) << 8 ) | + ( uint16_t )Read( REG_AFCLSB ) ) * + ( double )FREQ_STEP; + this->settings.FskPacketHandler.RxGain = ( Read( REG_LNA ) >> 5 ) & 0x07; + } + break; + case MODEM_LORA: + if( this->settings.LoRa.FreqHopOn == true ) + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); + + if (this->RadioEvents && this->RadioEvents->FhssChangeChannel) + { + this->RadioEvents->FhssChangeChannel(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData, ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) ); + } + } + break; + default: + break; + } + break; + case RF_TX_RUNNING: + switch( this->settings.Modem ) + { + case MODEM_FSK: + break; + case MODEM_LORA: + if( this->settings.LoRa.FreqHopOn == true ) + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); + + if (this->RadioEvents && this->RadioEvents->FhssChangeChannel) + { + this->RadioEvents->FhssChangeChannel(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData, ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) ); + } + } + break; + default: + break; + } + break; + default: + break; + } +} + +void SX1276::OnDio3Irq( void ) +{ + switch( this->settings.Modem ) + { + case MODEM_FSK: + break; + case MODEM_LORA: + if( ( Read( REG_LR_IRQFLAGS ) & RFLR_IRQFLAGS_CADDETECTED ) == RFLR_IRQFLAGS_CADDETECTED ) + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE ); + if (this->RadioEvents && this->RadioEvents->CadDone) + { + this->RadioEvents->CadDone(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData, true ); + } + } + else + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE ); + if (this->RadioEvents && this->RadioEvents->CadDone) + { + this->RadioEvents->CadDone(this, this->RadioEvents->userThisPtr, this->RadioEvents->userData, false ); + } + } + break; + default: + break; + } +} + +void SX1276::OnDio4Irq( void ) +{ + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + if( this->settings.FskPacketHandler.PreambleDetected == false ) + { + this->settings.FskPacketHandler.PreambleDetected = true; + } + } + break; + case MODEM_LORA: + break; + default: + break; + } +} + +void SX1276::OnDio5Irq( void ) +{ + switch( this->settings.Modem ) + { + case MODEM_FSK: + break; + case MODEM_LORA: + break; + default: + break; + } +}
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/SX1276GenericLib/sx1276/sx1276.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/SX1276GenericLib/sx1276/sx1276.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,642 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2014 Semtech + +Description: Actual implementation of a SX1276 radio, inherits Radio + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ + +/* + * additional development to make it more generic across multiple OS versions + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#ifndef __SX1276_H__ +#define __SX1276_H__ + +#include "radio.h" +#include "sx1276Regs-Fsk.h" +#include "sx1276Regs-LoRa.h" + + + +/*! + * Radio wake-up time from sleep + */ +#define RADIO_WAKEUP_TIME 1 // [ms] + +/*! + * Sync word for Private LoRa networks + */ +#define LORA_MAC_PRIVATE_SYNCWORD 0x12 + +/*! + * Sync word for Public LoRa networks + */ +#define LORA_MAC_PUBLIC_SYNCWORD 0x34 + + +/*! + * SX1276 definitions + */ +#define XTAL_FREQ 32000000 +#define FREQ_STEP 61.03515625 + +#define RX_BUFFER_SIZE 256 + +/*! + * Constant values need to compute the RSSI value + */ +#define RSSI_OFFSET_LF -164.0 +#define RSSI_OFFSET_HF -157.0 + +#define RF_MID_BAND_THRESH 525000000 + + + + +/*! + * Type of the supported board. [SX1276MB1MAS / SX1276MB1LAS] + */ +typedef enum BoardType +{ + SX1276MB1MAS = 0, + SX1276MB1LAS, + RFM95_SX1276, + MURATA_SX1276, + UNKNOWN +}BoardType_t; + + +typedef enum { + LORA_SF6 = 6, // 64 chips/symbol, SF6 requires an TCXO! + LORA_SF7 = 7, // 128 chips/symbol + LORA_SF8 = 8, // 256 chips/symbol + LORA_SF9 = 9, // 512 chips/symbol + LORA_SF10 = 10, // 1024 chips/symbol + LORA_SF11 = 11, // 2048 chips/symbol + LORA_SF12 = 12, // 4096 chips/symbol +} lora_spreading_factor_t; + + +typedef enum { // cyclic error coding to perform forward error detection and correction + LORA_ERROR_CODING_RATE_4_5 = 1, // 1.25x overhead + LORA_ERROR_CODING_RATE_4_6 = 2, // 1.50x overhead + LORA_ERROR_CODING_RATE_4_7 = 3, // 1.75x overhead + LORA_ERROR_CODING_RATE_4_8 = 4, // 2.00x overhead +} lora_coding_rate_t; + + +typedef enum { + RF_FREQUENCY_868_0 = 868000000, // Hz + RF_FREQUENCY_868_1 = 868100000, // Hz + RF_FREQUENCY_868_3 = 868300000, // Hz + RF_FREQUENCY_868_5 = 868500000, // Hz +} rf_frequency_t; + + + +/*! + * Actual implementation of a SX1276 radio, inherits Radio + */ +class SX1276 : public Radio +{ +protected: + + bool isRadioActive; + + BoardType_t boardConnected; //1 = SX1276MB1LAS; 0 = SX1276MB1MAS + + uint8_t *rxtxBuffer; + + /*! + * Hardware IO IRQ callback function definition + */ + typedef void ( SX1276::*DioIrqHandler )( void ); + + /*! + * Hardware DIO IRQ functions + */ + DioIrqHandler *dioIrq; + + + + RadioSettings_t settings; + + /*! + * FSK bandwidth definition + */ + struct BandwidthMap { + uint32_t bandwidth; + uint8_t RegValue; + }; + static const struct BandwidthMap FskBandwidths[]; + static const struct BandwidthMap LoRaBandwidths[]; + +protected: + + /*! + * Performs the Rx chain calibration for LF and HF bands + * \remark Must be called just after the reset so all registers are at their + * default values + */ + void RxChainCalibration( void ); + +public: + SX1276( RadioEvents_t *events); + virtual ~SX1276( ); + + + + + //------------------------------------------------------------------------- + // Redefined Radio functions + //------------------------------------------------------------------------- + /*! + * @brief Return current radio status, returns true if a radios has been found. + * + * @param [IN] events Structure containing the driver callback functions + */ + virtual bool Init( RadioEvents_t *events ); + + /*! + * @brief Initializes the radio registers + */ + virtual void RadioRegistersInit(void); + + /*! + * Return current radio status + * + * @param status Radio status. [RF_IDLE, RX_RUNNING, TX_RUNNING, CAD_RUNNING] + */ + virtual RadioState GetStatus( void ); + + /*! + * @brief Configures the SX1276 with the given modem + * + * @param [IN] modem Modem to be used [0: FSK, 1: LoRa] + */ + virtual void SetModem( RadioModems_t modem ); + + /*! + * @brief Sets the channel frequency + * + * @param [IN] freq Channel RF frequency + */ + virtual void SetChannel( uint32_t freq ); + + /*! + * @brief Sets the channels configuration + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] freq Channel RF frequency + * @param [IN] rssiThresh RSSI threshold + * + * @retval isFree [true: Channel is free, false: Channel is not free] + */ + virtual bool IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ); + + /*! + * @brief Generates a 32 bits random value based on the RSSI readings + * + * \remark This function sets the radio in LoRa modem mode and disables + * all interrupts. + * After calling this function either Radio.SetRxConfig or + * Radio.SetTxConfig functions must be called. + * + * @retval randomValue 32 bits random value + */ + virtual uint32_t Random( void ); + + /*! + * @brief Sets the reception parameters + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] bandwidth Sets the bandwidth + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * @param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * @param [IN] coderate Sets the coding rate ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * @param [IN] bandwidthAfc Sets the AFC Bandwidth ( FSK only ) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * @param [IN] preambleLen Sets the Preamble length ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: Length in symbols ( the hardware adds 4 more symbols ) + * @param [IN] symbTimeout Sets the RxSingle timeout value + * FSK : timeout number of bytes + * LoRa: timeout in symbols + * @param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * @param [IN] payloadLen Sets payload length when fixed lenght is used + * @param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * @param [IN] freqHopOn Enables disables the intra-packet frequency hopping [0: OFF, 1: ON] (LoRa only) + * @param [IN] hopPeriod Number of symbols bewteen each hop (LoRa only) + * @param [IN] iqInverted Inverts IQ signals ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * @param [IN] rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ + virtual void SetRxConfig ( RadioModems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ); + + /*! + * @brief Sets the transmission parameters + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] power Sets the output power [dBm] + * @param [IN] fdev Sets the frequency deviation ( FSK only ) + * FSK : [Hz] + * LoRa: 0 + * @param [IN] bandwidth Sets the bandwidth ( LoRa only ) + * FSK : 0 + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * @param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * @param [IN] coderate Sets the coding rate ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * @param [IN] preambleLen Sets the preamble length + * @param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * @param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * @param [IN] freqHopOn Enables disables the intra-packet frequency hopping [0: OFF, 1: ON] (LoRa only) + * @param [IN] hopPeriod Number of symbols bewteen each hop (LoRa only) + * @param [IN] iqInverted Inverts IQ signals ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * @param [IN] timeout Transmission timeout [ms] + */ + virtual void SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ); + + + /*! + * @brief Checks if the given RF frequency is supported by the hardware + * + * @param [IN] frequency RF frequency to be checked + * @retval isSupported [true: supported, false: unsupported] + */ + virtual bool CheckRfFrequency( uint32_t frequency ) = 0; + + /*! + * @brief Computes the packet time on air for the given payload + * + * \Remark Can only be called once SetRxConfig or SetTxConfig have been called + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] pktLen Packet payload length + * + * @retval airTime Computed airTime for the given packet payload length + */ + virtual uint32_t TimeOnAir ( RadioModems_t modem, int16_t pktLen ); + + /*! + * @brief Sends the buffer of size. Prepares the packet to be sent and sets + * the radio in transmission + * + * @param [IN]: buffer Buffer pointer + * @param [IN]: size Buffer size + * @param [IN]: buffer Header pointer + * @param [IN]: size Header size + */ + virtual void Send(void *buffer, int16_t size, void *header = NULL, int16_t hsize = 0); + + /*! + * @brief Sets the radio in sleep mode + */ + virtual void Sleep( void ); + + /*! + * @brief Sets the radio in standby mode + */ + virtual void Standby( void ); + + /*! + * @brief Sets the radio in CAD mode + */ + virtual void StartCad( void ); + + /*! + * @brief Sets the radio in reception mode for the given time + * @param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ + virtual void Rx( uint32_t timeout ); + + /*! + * @brief Check is radio receives a signal + */ + virtual bool RxSignalPending(); + + + /*! + * @brief Sets the radio in transmission mode for the given time + * @param [IN] timeout Transmission timeout [ms] + * [0: continuous, others timeout] + */ + virtual void Tx( uint32_t timeout ); + + /*! + * @brief Sets the radio in continuous wave transmission mode + * + * @param [IN]: freq Channel RF frequency + * @param [IN]: power Sets the output power [dBm] + * @param [IN]: time Transmission mode timeout [s] + */ + + virtual void SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ); + + /*! + * @brief Returns the maximal transfer unit for a given modem + * + * @retval MTU size in bytes + */ + virtual int16_t MaxMTUSize( RadioModems_t modem ); + + /*! + * @brief Reads the current RSSI value + * + * @retval rssiValue Current RSSI value in [dBm] + */ + virtual int16_t GetRssi ( RadioModems_t modem ); + + /*! + * @brief Reads the current frequency error + * + * @retval frequency error value in [Hz] + */ + virtual int32_t GetFrequencyError( RadioModems_t modem ); + + /*! + * @brief Writes the radio register at the specified address + * + * @param [IN]: addr Register address + * @param [IN]: data New register value + */ + virtual void Write ( uint8_t addr, uint8_t data ) = 0; + + /*! + * @brief Reads the radio register at the specified address + * + * @param [IN]: addr Register address + * @retval data Register value + */ + virtual uint8_t Read ( uint8_t addr ) = 0; + + /*! + * @brief Writes multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [IN] buffer Buffer containing the new register's values + * @param [IN] size Number of registers to be written + */ + virtual void Write( uint8_t addr, void *buffer, uint8_t size ) = 0; + + /*! + * @brief Reads multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [OUT] buffer Buffer where to copy the registers data + * @param [IN] size Number of registers to be read + */ + virtual void Read ( uint8_t addr, void *buffer, uint8_t size ) = 0; + + /*! + * @brief Writes the buffer contents to the SX1276 FIFO + * + * @param [IN] buffer Buffer containing data to be put on the FIFO. + * @param [IN] size Number of bytes to be written to the FIFO + */ + virtual void WriteFifo( void *buffer, uint8_t size ) = 0; + + /*! + * @brief Reads the contents of the SX1276 FIFO + * + * @param [OUT] buffer Buffer where to copy the FIFO read data. + * @param [IN] size Number of bytes to be read from the FIFO + */ + virtual void ReadFifo( void *buffer, uint8_t size ) = 0; + /*! + * @brief Resets the SX1276 + */ + virtual void Reset( void ) = 0; + + /*! + * @brief Sets the maximum payload length. + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] max Maximum payload length in bytes + */ + virtual void SetMaxPayloadLength( RadioModems_t modem, uint8_t max ); + + /*! + * \brief Sets the network to public or private. Updates the sync byte. + * + * \remark Applies to LoRa modem only + * + * \param [IN] enable if true, it enables a public network + */ + virtual void SetPublicNetwork( bool enable ); + + /*! + * @brief Sets the radio output power. + * + * @param [IN] power Sets the RF output power + */ + virtual void SetRfTxPower( int8_t power ) = 0; + + //------------------------------------------------------------------------- + // Board relative functions + //------------------------------------------------------------------------- + /*! + * Radio registers definition + */ + struct RadioRegisters { + ModemType Modem; + uint8_t Addr; + uint8_t Value; + }; + + + static const struct RadioRegisters RadioRegsInit[]; + + typedef enum { + RXTimeoutTimer, + TXTimeoutTimer, + RXTimeoutSyncWordTimer + } TimeoutTimer_t; + + +protected: + /*! + * @brief Initializes the radio I/Os pins interface + */ + virtual void IoInit( void ) = 0; + + /*! + * @brief Initializes the radio SPI + */ + virtual void SpiInit( void ) = 0; + + /*! + * @brief Initializes DIO IRQ handlers + * + * @param [IN] irqHandlers Array containing the IRQ callback functions + */ + virtual void IoIrqInit( DioIrqHandler *irqHandlers ) = 0; + + /*! + * @brief De-initializes the radio I/Os pins interface. + * + * \remark Useful when going in MCU lowpower modes + */ + virtual void IoDeInit( void ) = 0; + + /*! + * @brief Gets the board PA selection configuration + * + * @param [IN] channel Channel frequency in Hz + * @retval PaSelect RegPaConfig PaSelect value + */ + virtual uint8_t GetPaSelect( uint32_t channel ) = 0; + + /*! + * @brief Set the RF Switch I/Os pins in Low Power mode + * + * @param [IN] status enable or disable + */ + virtual void SetAntSwLowPower( bool status ) = 0; + + /*! + * @brief Initializes the RF Switch I/Os pins interface + */ + virtual void AntSwInit( void ) = 0; + + /*! + * @brief De-initializes the RF Switch I/Os pins interface + * + * \remark Needed to decrease the power consumption in MCU lowpower modes + */ + virtual void AntSwDeInit( void ) = 0; + + /*! + * @brief Controls the antenna switch if necessary. + * + * \remark see errata note + * + * @param [IN] opMode Current radio operating mode + */ + virtual void SetAntSw( uint8_t opMode ) = 0; + + typedef void ( SX1276::*timeoutFuncPtr)( void ); + + + /* + * The the Timeout for a given Timer. + */ + virtual void SetTimeout(TimeoutTimer_t timer, timeoutFuncPtr, int timeout_ms = 0) = 0; + + /* + * A simple ms sleep + */ + virtual void Sleep_ms(int ms) = 0; + +protected: + + /*! + * @brief Sets the SX1276 operating mode + * + * @param [IN] opMode New operating mode + */ + virtual void SetOpMode( uint8_t opMode ); + + /* + * SX1276 DIO IRQ callback functions prototype + */ + + /*! + * @brief DIO 0 IRQ callback + */ + virtual void OnDio0Irq( void ); + + /*! + * @brief DIO 1 IRQ callback + */ + virtual void OnDio1Irq( void ); + + /*! + * @brief DIO 2 IRQ callback + */ + virtual void OnDio2Irq( void ); + + /*! + * @brief DIO 3 IRQ callback + */ + virtual void OnDio3Irq( void ); + + /*! + * @brief DIO 4 IRQ callback + */ + virtual void OnDio4Irq( void ); + + /*! + * @brief DIO 5 IRQ callback + */ + virtual void OnDio5Irq( void ); + + /*! + * @brief Tx & Rx timeout timer callback + */ + virtual void OnTimeoutIrq( void ); + + /*! + * Returns the known FSK bandwidth registers value + * + * \param [IN] bandwidth Bandwidth value in Hz + * \retval regValue Bandwidth register value. + */ + static uint8_t GetFskBandwidthRegValue( uint32_t bandwidth ); + + static uint8_t GetLoRaBandwidthRegValue( uint32_t bandwidth ); + + enum { + LORA_BANKWIDTH_7kHz = 0, // 7.8 kHz requires TCXO + LORA_BANKWIDTH_10kHz = 1, // 10.4 kHz requires TCXO + LORA_BANKWIDTH_15kHz = 2, // 15.6 kHz requires TCXO + LORA_BANKWIDTH_20kHz = 3, // 20.8 kHz requires TCXO + LORA_BANKWIDTH_31kHz = 4, // 31.2 kHz requires TCXO + LORA_BANKWIDTH_41kHz = 5, // 41.4 kHz requires TCXO + LORA_BANKWIDTH_62kHz = 6, // 62.5 kHz requires TCXO + LORA_BANKWIDTH_125kHz = 7, + LORA_BANKWIDTH_250kHz = 8, + LORA_BANKWIDTH_500kHz = 9, + LORA_BANKWIDTH_RESERVED = 10, + }; +}; + +#endif // __SX1276_H__
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/Transmitter/Transmitter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/Transmitter/Transmitter.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,249 @@ +#include "mbed.h" +#include "PinMap.h" +#include "main.h" +#include "sx1276-mbed-hal.h" +#include "USBSerial.h" + +USBSerial usb_serial; + +#ifdef FEATURE_LORA + +/* Set this flag to '1' to display debug messages on the console */ +#define DEBUG_MESSAGE 1 + +/* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */ +#define USE_MODEM_LORA 1 +#define USE_MODEM_FSK !USE_MODEM_LORA +#define RF_FREQUENCY RF_FREQUENCY_868_1 // Hz +#define TX_OUTPUT_POWER 14 // 14 dBm + +#if USE_MODEM_LORA == 1 + +#define LORA_BANDWIDTH 125000 // LoRa default, details in SX1276::BandwidthMap +#define LORA_SPREADING_FACTOR LORA_SF7 +#define LORA_CODINGRATE LORA_ERROR_CODING_RATE_4_5 + +#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx +#define LORA_SYMBOL_TIMEOUT 5 // Symbols +#define LORA_FIX_LENGTH_PAYLOAD_ON false +#define LORA_FHSS_ENABLED false +#define LORA_NB_SYMB_HOP 4 +#define LORA_IQ_INVERSION_ON false +#define LORA_CRC_ENABLED true + +#elif USE_MODEM_FSK == 1 + +#define FSK_FDEV 25000 // Hz +#define FSK_DATARATE 19200 // bps +#define FSK_BANDWIDTH 50000 // Hz +#define FSK_AFC_BANDWIDTH 83333 // Hz +#define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx +#define FSK_FIX_LENGTH_PAYLOAD_ON false +#define FSK_CRC_ENABLED true + +#else +#error "Please define a modem in the compiler options." +#endif + + +#define BUFFER_SIZE 2048 + +/* + * Global variables declarations + */ +typedef enum { + LOWPOWER = 0, + IDLE, + + RX, + RX_TIMEOUT, + RX_ERROR, + + TX, + TX_TIMEOUT, + + CAD, + CAD_DONE +} AppStates_t; + +volatile AppStates_t State = LOWPOWER; + +/*! + * Radio events function pointer + */ +static RadioEvents_t RadioEvents; + +/* + * Global variables declarations + */ +SX1276Generic *Radio; + +uint16_t BufferSize = BUFFER_SIZE; +uint8_t Buffer[BUFFER_SIZE]; + +DigitalOut *led3; + +BufferedSerial *serial; +int Transmitter() +{ + //usb_serial.printf("Serial"); +#if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) ) + DigitalOut *led = new DigitalOut(LED2); +#elif defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_DISCO_L072CZ_LRWAN1) + DigitalOut *led = new DigitalOut(LED4); // RX red + led3 = new DigitalOut(LED3); // TX blue +#else + DigitalOut *led = new DigitalOut(LED1); + led3 = led; +#endif + +//////////////////////////////////////////////////////////////// + *led3 = 1; + + serial = new BufferedSerial(USBTX,USBRX); + serial->baud(115200*2); + serial->format(8); + +//////////////////////////////////////////////////////////////// + Radio = new SX1276Generic(NULL, MURATA_SX1276, + LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET, + LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5, + LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO); + + // Initialize Radio driver + RadioEvents.TxDone = OnTxDone; + RadioEvents.RxDone = OnRxDone; + RadioEvents.RxError = OnRxError; + RadioEvents.TxTimeout = OnTxTimeout; + RadioEvents.RxTimeout = OnRxTimeout; + if (Radio->Init( &RadioEvents ) == false) { + + while(Radio->Init( &RadioEvents ) == false) { + //usb_serial.printf("Entrou-not"); + serial->printf("Radio could not be detected!"); + wait( 1 ); + } + } + + + + + Radio->SetChannel(RF_FREQUENCY ); + + + Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, + LORA_SPREADING_FACTOR, LORA_CODINGRATE, + LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, + LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, + LORA_IQ_INVERSION_ON, 2000 ); + + while( 1 ) { +#ifdef TARGET_STM32L4 + WatchDogUpdate(); +#endif + //usb_serial.printf("Entrou2"); + switch( State ) { + case TX: + State = LOWPOWER; + break; + case RX_TIMEOUT: + State = LOWPOWER; + break; + case RX_ERROR: + State = LOWPOWER; + break; + case TX_TIMEOUT: + State = LOWPOWER; + break; + case LOWPOWER: + // going to send" ); + int sendSize = 2; + serial->printf("reached lowpower\n"); + //usb_serial.printf("reached lowpower"); + int i = 0;/* + while(i < BufferSize) { + char temp; + while(!serial->readable()) ; + temp = serial->getc(); + usb_serial.printf("buff\n"); + if(temp == '\n') break; + Buffer[i++] = temp; + sendSize++; + } +*/ + //Buffer[i++] = '\n'; + //Buffer[i++] = 0; + + //sendSize++; + //sendSize++; + Buffer[0] = 'A'; + Radio->Send( Buffer, sendSize); + usb_serial.printf("%s",Buffer); + Radio->Send( Buffer, sendSize); + usb_serial.printf("%s",Buffer); + Radio->Send( Buffer, sendSize); + usb_serial.printf("%s",Buffer); + Radio->Send( Buffer, sendSize); + usb_serial.printf("%s",Buffer); + Radio->Send( Buffer, sendSize); + Buffer[0] = 'H'; + //usb_serial.printf("Sending: %s", Buffer); + //usb_serial.printf("send\n"); + Radio->Send( Buffer, sendSize); + usb_serial.printf("%s",Buffer); + wait(0.5); + *led3 = !*led3 ; + break; + default: + State = LOWPOWER; + break; + } + } +} + +void OnTxDone(void *radio, void *userThisPtr, void *userData) +{ + Radio->Sleep( ); + State = TX; + if (DEBUG_MESSAGE) + serial->printf("> OnTxDone [7]"); +} + +void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) +{ + Radio->Sleep( ); + BufferSize = size; + memcpy( Buffer, payload, BufferSize ); + State = LOWPOWER; + //if (DEBUG_MESSAGE) +// dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr); + //dump("Data:", payload, size); +} + +void OnTxTimeout(void *radio, void *userThisPtr, void *userData) +{ + *led3 = 0; + Radio->Sleep( ); + State = LOWPOWER; + //if(DEBUG_MESSAGE) +// serial->printf("> OnTxTimeout [8] "); +} + +void OnRxTimeout(void *radio, void *userThisPtr, void *userData) +{ + *led3 = 0; + Radio->Sleep( ); + State = LOWPOWER; + if (DEBUG_MESSAGE) + dprintf("> OnRxTimeout [9] "); +} + +void OnRxError(void *radio, void *userThisPtr, void *userData) +{ + Radio->Sleep( ); + State = LOWPOWER; + if (DEBUG_MESSAGE) + dprintf("> OnRxError [100] "); +} + +#endif
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/Transmitter/Transmitter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/Transmitter/Transmitter.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,44 @@ +#ifndef __SX1276PINGPONG_H__ +#define __SX1276PINGPONG_H__ + +int Transmitter(void); + +/* + * Callback functions prototypes + */ +/*! + * @brief Function to be executed on Radio Tx Done event + */ +void OnTxDone(void *radio, void *userThisPtr, void *userData); + +/*! + * @brief Function to be executed on Radio Rx Done event + */ +void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); + +/*! + * @brief Function executed on Radio Tx Timeout event + */ +void OnTxTimeout(void *radio, void *userThisPtr, void *userData); + +/*! + * @brief Function executed on Radio Rx Timeout event + */ +void OnRxTimeout(void *radio, void *userThisPtr, void *userData); + +/*! + * @brief Function executed on Radio Rx Error event + */ +void OnRxError(void *radio, void *userThisPtr, void *userData); + +/*! + * @brief Function executed on Radio Fhss Change Channel event + */ +void OnFhssChangeChannel(void *radio, void *userThisPtr, void *userData, uint8_t channelIndex); + +/*! + * @brief Function executed on CAD Done event + */ +void OnCadDone(void *radio, void *userThisPtr, void *userData); + +#endif // __MAIN_H__
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/USBDevice.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/USBDevice.lib Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/mbed_official/code/USBDevice/#53949e6131f6
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/main.cpp Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + * Licensed under the Apache License, Version 2.0); + */ + #include "main.h" +#include "mbed.h" + + +DigitalOut myled(LED2); +DigitalIn button(PA_14); +BufferedSerial *ser; +//InterruptIn mybutton(PA_14); + //#include "USBSerial.h" + +//USBSerial usb_serial; + +int main() { + //SystemClock_Config(); + //ser = new BufferedSerial(USBTX,USBRX); + //ser->baud(115200*2); + //ser->format(8); + //wait(35); + while(1){ + if(button.read()==1){ + Transmitter(); + } + } + //if (button.read()==0){ + // + //} + +} + + + + +void SystemClock_Config(void) +{ +#ifdef B_L072Z_LRWAN1_LORA + /* + * The L072Z_LRWAN1_LORA clock setup is somewhat differnt from the Nucleo board. + * It has no LSE. + */ + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + + /* Enable HSE Oscillator and Activate PLL with HSE as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSEState = RCC_HSE_OFF; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_6; + RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_3; + + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + // Error_Handler(); + } + + /* Set Voltage scale1 as MCU will run at 32MHz */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */ + while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {}; + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 + clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { + // Error_Handler(); + } +#endif +} + +void dump(const char *title, const void *data, int len, bool dwords) +{ + dprintf("dump(\"%s\", 0x%x, %d bytes)", title, data, len); + + int i, j, cnt; + unsigned char *u; + const int width = 16; + const int seppos = 7; + + cnt = 0; + u = (unsigned char *)data; + while (len > 0) { + ser->printf("%08x: ", (unsigned int)data + cnt); + if (dwords) { + unsigned int *ip = ( unsigned int *)u; + ser->printf(" 0x%08x\r\n", *ip); + u+= 4; + len -= 4; + cnt += 4; + continue; + } + cnt += width; + j = len < width ? len : width; + for (i = 0; i < j; i++) { + ser->printf("%2.2x ", *(u + i)); + if (i == seppos) + ser->putc(' '); + } + ser->putc(' '); + if (j < width) { + i = width - j; + if (i > seppos + 1) + ser->putc(' '); + while (i--) { + printf("%s", " "); + } + } + for (i = 0; i < j; i++) { + int c = *(u + i); + if (c >= ' ' && c <= '~') + ser->putc(c); + else + ser->putc('.'); + if (i == seppos) + ser->putc(' '); + } + len -= width; + u += width; + ser->printf("\r\n"); + } + ser->printf("--\r\n"); +}
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/main.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/main.h Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + * Licensed under the Apache License, Version 2.0); + */ + +#include "mbed.h" +#include "PinMap.h" +#include "BufferedSerial.h" +#include "Transmitter.h" + +void SystemClock_Config(void); + +extern BufferedSerial *ser; +extern void dump(const char *title, const void *data, int len, bool dwords = false); + +#define dprintf(...) { ser->printf(__VA_ARGS__); ser->printf("\r\n"); } \ No newline at end of file
diff -r 000000000000 -r dcbbdc06fcd5 lora_transmitter/mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lora_transmitter/mbed.bld Thu Dec 13 23:19:23 2018 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/mbed_official/code/mbed/builds/e2bfab296f20 \ No newline at end of file