Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BufferedSerial SX1276GenericLib mbed
Revision 0:2871c35d504d, committed 2017-09-07
- Comitter:
- rtavk3
- Date:
- Thu Sep 07 18:56:20 2017 +0000
- Commit message:
- TXRX Project data
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferedSerial.lib Thu Sep 07 18:56:20 2017 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/sam_grove/code/BufferedSerial/#a0d37088b405
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PinMap.h Thu Sep 07 18:56:20 2017 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1276GenericLib.lib Thu Sep 07 18:56:20 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/Helmut64/code/SX1276GenericLib/#b0203b4a36ec
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SX1276GenericPingPong/GenericPingPong.cpp Thu Sep 07 18:56:20 2017 +0000
@@ -0,0 +1,351 @@
+/*
+ * This file contains a copy of the master content sx1276PingPong
+ * with adaption for the SX1276Generic environment
+ * (c) 2017 Helmut Tschemernjak
+ * 30826 Garbsen (Hannover) Germany
+ */
+
+#include "mbed.h"
+#include "PinMap.h"
+#include "GenericPingPong.h"
+#include "sx1276-mbed-hal.h"
+#include "main.h"
+
+#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_SF11
+#define LORA_CODINGRATE LORA_ERROR_CODING_RATE_4_5
+
+#define LORA_PREAMBLE_LENGTH 6 // Same for Tx and Rx
+#define LORA_SYMBOL_TIMEOUT 10 // 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 6 // Same for Tx and Rx
+#define FSK_FIX_LENGTH_PAYLOAD_ON true
+#define FSK_CRC_ENABLED true
+
+#else
+ #error "Please define a modem in the compiler options."
+#endif
+
+
+#define RX_TIMEOUT_VALUE 3500 // in ms
+
+//#define BUFFER_SIZE 32 // Define the payload size here
+#define BUFFER_SIZE 2 // Define the payload size here
+
+/*
+ * Global variables declarations
+ */
+typedef enum {
+ SLEEP = 0,
+ RX_INIT,
+ RX_INIT_WAIT,
+ RX_ENUM,
+ RX_ENUM_WAIT,
+ TX_PING,
+ RX_TIMEOUT,
+ RX_ERROR,
+ TX_INIT,
+ TX_INIT_WAIT,
+ TX_ENUM,
+ TX_ENUM_WAIT,
+ CAD,
+ CAD_DONE
+} AppStates_t;
+
+volatile AppStates_t State = TX_INIT;
+
+/*!
+ * Radio events function pointer
+ */
+static RadioEvents_t RadioEvents;
+
+/*
+ * Global variables declarations
+ */
+SX1276Generic *Radio;
+
+
+const uint8_t PingMsg[] = { 0xFF, 0xFF, 0xFF, 0xFF};// "PING";
+const uint8_t PongMsg[] = { 0xFF, 0xFF, 0xFF, 0xFF};// "PONG";
+uint16_t BufferSize = BUFFER_SIZE;
+uint8_t *Buffer;
+
+DigitalOut *led3;
+
+
+int SX1276PingPong()
+{
+#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
+
+ Buffer = new uint8_t[BUFFER_SIZE];
+ *led3 = 1;
+
+#ifdef B_L072Z_LRWAN1_LORA
+ 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);
+#else // RFM95
+ Radio = new SX1276Generic(NULL, RFM95_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);
+
+#endif
+
+ uint8_t i;
+
+ dprintf("SX1276 Ping Pong Demo Application" );
+ dprintf("Freqency: %.1f", (double)RF_FREQUENCY/1000000.0);
+ dprintf("TXPower: %d dBm", TX_OUTPUT_POWER);
+#if USE_MODEM_LORA == 1
+ dprintf("Bandwidth: %d Hz", LORA_BANDWIDTH);
+ dprintf("Spreading factor: SF%d", LORA_SPREADING_FACTOR);
+#elif USE_MODEM_FSK == 1
+ dprintf("Bandwidth: %d kHz", FSK_BANDWIDTH);
+ dprintf("Baudrate: %d", FSK_DATARATE);
+#endif
+ // Initialize Radio driver
+ RadioEvents.TxDone = OnTxDone;
+ RadioEvents.RxDone = OnRxDone;
+ RadioEvents.RxError = OnRxError;
+ RadioEvents.TxTimeout = OnTxTimeout;
+ RadioEvents.RxTimeout = OnRxTimeout;
+ if (Radio->Init( &RadioEvents ) == false) {
+ while(1) {
+ dprintf("Radio could not be detected!");
+ wait( 1 );
+ }
+ }
+
+
+ switch(Radio->DetectBoardType()) {
+ case SX1276MB1LAS:
+ if (DEBUG_MESSAGE)
+ dprintf(" > Board Type: SX1276MB1LAS <");
+ break;
+ case SX1276MB1MAS:
+ if (DEBUG_MESSAGE)
+ dprintf(" > Board Type: SX1276MB1LAS <");
+ case MURATA_SX1276:
+ if (DEBUG_MESSAGE)
+ dprintf(" > Board Type: MURATA_SX1276_STM32L0 <");
+ break;
+ case RFM95_SX1276:
+ if (DEBUG_MESSAGE)
+ dprintf(" > HopeRF RFM95xx <");
+ break;
+ default:
+ dprintf(" > Board Type: unknown <");
+ }
+
+ Radio->SetChannel(RF_FREQUENCY );
+
+#if USE_MODEM_LORA == 1
+
+ if (LORA_FHSS_ENABLED)
+ dprintf(" > LORA FHSS Mode <");
+ if (!LORA_FHSS_ENABLED)
+ dprintf(" > LORA Mode <");
+
+ 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 );
+
+ Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
+ LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
+ LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
+ LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
+ LORA_IQ_INVERSION_ON, true );
+
+#elif USE_MODEM_FSK == 1
+
+ dprintf(" > FSK Mode <");
+ Radio->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
+ FSK_DATARATE, 0,
+ FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
+ FSK_CRC_ENABLED, 0, 0, 0, 2000 );
+
+ Radio->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
+ 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
+ 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
+ 0, 0, false, true );
+
+#else
+
+#error "Please define a modem in the compiler options."
+
+#endif
+
+
+ if (DEBUG_MESSAGE)
+ dprintf("Starting INIT_LOOP");
+
+
+
+ while( 1 ) {
+#ifdef TARGET_STM32L4
+ WatchDogUpdate();
+#endif
+
+ switch( State ) {
+ case SLEEP:
+
+ dprintf("Sleep()");
+ wait_ms(10000);
+ State = RX_INIT;
+ break;
+ case RX_INIT:
+ dprintf("RX_INIT()");
+ Radio->Rx( 8000 );
+ while(State == RX_INIT) {}
+ break;
+ case RX_ENUM:
+ dprintf("RX_ENUM()!!!!!!!!!!!!!!!!!!!!!!!!");
+ Radio->Rx( 23000 );
+ while(State == RX_ENUM) {}
+ break;
+ case RX_TIMEOUT:
+ dprintf("RX_TIMEOUT()");
+ State = SLEEP;
+ break;
+
+ case TX_PING:
+ dprintf("RX_Ping()!!!!!!!!!!!!!!!!!!!!!!!!");
+ State = SLEEP;
+ break;
+ case TX_INIT:
+ int txcount = 0;
+ for(txcount=0;txcount<1000;txcount++) {
+ dprintf("TX_INIT()");
+ // Send the next PING frame
+ //memcpy(Buffer, PingMsg, 2);
+
+ wait_ms( 1000 );
+ dprintf("dump(0x%x, %d bytes)", PingMsg, 2);
+ Radio->Send( (void*) PingMsg, BufferSize );
+ dprintf("TX_INIT_SENT()");
+ State = TX_INIT_WAIT;
+ while(State == TX_INIT_WAIT) {};
+
+ }
+ State=TX_ENUM;
+ break;
+ case TX_INIT_WAIT:
+ wait_ms(100);
+ break;
+ case TX_ENUM:
+ dprintf("TX_ENUM()!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ wait_ms(500);
+ // Send the next PING frame
+ memcpy(Buffer, PingMsg, sizeof(PingMsg));
+ for( i = 4; i < BufferSize; i++ ) {
+ Buffer[i] = i - 4;
+ }
+ wait_ms( 10 );
+ Radio->Send( Buffer, BufferSize );
+ dprintf("TX_ENUM_SENT()");
+ State = TX_INIT_WAIT;
+ while(State == TX_INIT_WAIT) {}
+ break;
+ default:
+ State = SLEEP;
+ break;
+ }
+ }
+}
+
+void OnTxDone(void *radio, void *a, void *b)
+{
+ Radio->Sleep( );
+ if(State == TX_INIT_WAIT) State = TX_INIT;
+ dprintf("> OnTxDone");
+}
+
+void OnRxDone(void *radio, void *a, void *b, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
+{
+ dprintf("dump(0x%x, %d bytes)", payload, 2);
+ dprintf("> OnRxDone");
+ Radio->Sleep( );
+ BufferSize = size;
+ //memcpy( Buffer, payload, BufferSize );
+ dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d, size=%d", rssi, snr, size);
+ if(size != 2) {
+ State=SLEEP;
+ dprintf("> Payload error");
+ return;}
+ decodePayload(payload, size);
+}
+
+void decodePayload(const void *data, int len)
+{
+ dprintf("dump(0x%x, %d bytes)", data, len);
+
+ unsigned char *u;
+
+ u = (unsigned char *)data;
+ if(*u == 1) State = RX_ENUM;
+ if(*u == 2) State == TX_PING;
+ else {
+ dprintf("> Invalid RX Command");
+ State = SLEEP;
+ }
+}
+
+void OnTxTimeout(void *radio, void *a, void *b)
+{
+ Radio->Sleep( );
+ State = SLEEP;
+ dprintf("> OnTxTimeout");
+}
+
+void OnRxTimeout(void *radio, void *a, void *b)
+{
+ dprintf("> OnRxTimeout");
+ Radio->Sleep( );
+ Buffer[BufferSize-1] = 0;
+ dprintf("> OnRxTimeout");
+ State = SLEEP;
+}
+
+void OnRxError(void *radio, void *a, void *b)
+{
+ dprintf("> OnRxError");
+ Radio->Sleep( );
+ dprintf("> OnRxError");
+}
+
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1276GenericPingPong/GenericPingPong.h Thu Sep 07 18:56:20 2017 +0000 @@ -0,0 +1,70 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ( C )2014 Semtech + +Description: Contains the callbacks for the IRQs and any application related details + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ + +/* + * This file contains a copy of the master content sx1276PingPong + * with adaption for the SX1276Generic environment + * (c) 2017 Helmut Tschemernjak + * 30826 Garbsen (Hannover) Germany + */ + +#ifndef __SX1276PINGPONG_H__ +#define __SX1276PINGPONG_H__ + +#ifdef FEATURE_LORA +int SX1276PingPong(void); +#else +#define SX1276PingPong(x) void() +#endif +/* + * 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); + +void decodePayload(const void *data, int len); +#endif // __MAIN_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Thu Sep 07 18:56:20 2017 +0000
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2017 Helmut Tschemernjak
+ * 30826 Garbsen (Hannover) Germany
+ * Licensed under the Apache License, Version 2.0);
+ */
+ #include "main.h"
+
+DigitalOut myled(LED1);
+BufferedSerial *ser;
+
+int main() {
+ SystemClock_Config();
+ ser = new BufferedSerial(USBTX, USBRX);
+ ser->baud(115200*2);
+ ser->format(8);
+ ser->printf("Hello World\n\r");
+ myled = 1;
+
+ SX1276PingPong();
+}
+
+
+
+
+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");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h Thu Sep 07 18:56:20 2017 +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 "GenericPingPong.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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Sep 07 18:56:20 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2bfab296f20 \ No newline at end of file