txrx test code

Dependencies:   BufferedSerial SX1276GenericLib mbed

Files at this revision

API Documentation at this revision

Comitter:
rtavk3
Date:
Thu Sep 07 18:56:20 2017 +0000
Commit message:
TXRX Project data

Changed in this revision

BufferedSerial.lib Show annotated file Show diff for this revision Revisions of this file
PinMap.h Show annotated file Show diff for this revision Revisions of this file
SX1276GenericLib.lib Show annotated file Show diff for this revision Revisions of this file
SX1276GenericPingPong/GenericPingPong.cpp Show annotated file Show diff for this revision Revisions of this file
SX1276GenericPingPong/GenericPingPong.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 2871c35d504d BufferedSerial.lib
--- /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
diff -r 000000000000 -r 2871c35d504d PinMap.h
--- /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
diff -r 000000000000 -r 2871c35d504d SX1276GenericLib.lib
--- /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
diff -r 000000000000 -r 2871c35d504d SX1276GenericPingPong/GenericPingPong.cpp
--- /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
diff -r 000000000000 -r 2871c35d504d SX1276GenericPingPong/GenericPingPong.h
--- /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__
diff -r 000000000000 -r 2871c35d504d main.cpp
--- /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");
+}
diff -r 000000000000 -r 2871c35d504d main.h
--- /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
diff -r 000000000000 -r 2871c35d504d mbed.bld
--- /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