Test program for FF1705.

Dependencies:   libxDot-dev-mbed5-deprecated ISL29011

Files at this revision

API Documentation at this revision

Comitter:
jernej_vrscaj
Date:
Tue Nov 07 11:18:57 2017 +0000
Child:
1:12a289bd6b82
Commit message:
Testing program for production purposes (v1.0).

Changed in this revision

.hg_archival.txt Show annotated file Show diff for this revision Revisions of this file
.hgignore Show annotated file Show diff for this revision Revisions of this file
Example/example_config.h Show annotated file Show diff for this revision Revisions of this file
Example/inc/RadioEvent.h Show annotated file Show diff for this revision Revisions of this file
Example/inc/dot_util.h Show annotated file Show diff for this revision Revisions of this file
Example/lib/ISL29011.lib Show annotated file Show diff for this revision Revisions of this file
Example/src/dot_util.cpp Show annotated file Show diff for this revision Revisions of this file
Example/src/peer_to_peer_example.cpp Show annotated file Show diff for this revision Revisions of this file
Libraries/C12832/.hg_archival.txt Show annotated file Show diff for this revision Revisions of this file
Libraries/C12832/C12832.cpp Show annotated file Show diff for this revision Revisions of this file
Libraries/C12832/C12832.h Show annotated file Show diff for this revision Revisions of this file
Libraries/C12832/GraphicsDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
Libraries/C12832/GraphicsDisplay.h Show annotated file Show diff for this revision Revisions of this file
Libraries/C12832/Small_7.h Show annotated file Show diff for this revision Revisions of this file
Libraries/C12832/TextDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
Libraries/C12832/TextDisplay.h Show annotated file Show diff for this revision Revisions of this file
libxDot-dev-mbed5.lib Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
setup.sh Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hg_archival.txt	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,6 @@
+repo: a151a6350d7f74a54936ddd722ab406db8f7a9a4
+node: 7ec180e84cb6c654babe1e4cc85a47471530ed87
+branch: default
+latesttag: null
+latesttagdistance: 32
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,5 @@
+mbed-os
+.build
+/mdot/
+/mdot-library/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Example/example_config.h	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,29 @@
+#ifndef __EXAMPLE__CONFIG_H__
+#define __EXAMPLE__CONFIG_H__
+
+#define OTA_EXAMPLE              1  // see ota_example.cpp
+#define AUTO_OTA_EXAMPLE         2  // see auto_ota_example.cpp
+#define MANUAL_EXAMPLE           3  // see manual_example.cpp
+#define PEER_TO_PEER_EXAMPLE     4  // see peer_to_peer_example.cpp
+#define CLASS_C_EXAMPLE          5  // see class_c_example.cpp
+
+// the active example is the one that will be compiled
+#if !defined(ACTIVE_EXAMPLE)
+#define ACTIVE_EXAMPLE   PEER_TO_PEER_EXAMPLE
+#endif
+
+// the active channel plan is the one that will be compiled
+// options are :
+//      CP_US915
+//      CP_AU915
+//      CP_EU868
+//      CP_KR920
+//      CP_AS923
+//      CP_AS923_JAPAN
+//      CP_IN865
+#if !defined(CHANNEL_PLAN)
+#define CHANNEL_PLAN CP_US915
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Example/inc/RadioEvent.h	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,143 @@
+#ifndef __RADIO_EVENT_H__
+#define __RADIO_EVENT_H__
+
+#include "dot_util.h"
+#include "mDotEvent.h"
+#include "C12832.h"
+
+//#define TEST_board
+#define REFERENCE_board
+
+#ifdef TEST_board
+extern C12832 lcd;
+extern uint8_t trx; 
+extern uint8_t sent_rx; 
+
+#elif defined(REFERENCE_board)
+extern uint8_t received;
+extern uint16_t *ptr_rx;
+
+#endif
+
+class RadioEvent : public mDotEvent
+{
+ 
+public:
+    RadioEvent() {}
+ 
+    virtual ~RadioEvent() {}
+ 
+    /*!
+     * MAC layer event callback prototype.
+     *
+     * \param [IN] flags Bit field indicating the MAC events occurred
+     * \param [IN] info  Details about MAC events occurred
+     */
+    virtual void MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) {
+ 
+        if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
+            std::string msg = "OK";
+            switch (info->Status) {
+                case LORAMAC_EVENT_INFO_STATUS_ERROR:
+                    msg = "ERROR";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
+                    msg = "TX_TIMEOUT";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
+                    msg = "RX_TIMEOUT";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
+                    msg = "RX_ERROR";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
+                    msg = "JOIN_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
+                    msg = "DOWNLINK_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
+                    msg = "ADDRESS_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
+                    msg = "MIC_FAIL";
+                    break;
+                default:
+                    break;
+            }
+            logTrace("Event: %s", msg.c_str());
+ 
+            logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
+                     flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
+            logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
+                     info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
+                     info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
+        }
+ 
+        if (flags->Bits.Rx) {
+            
+            printf("Rx %d bytes \r\n", info->RxBufferSize);                     // Rx 2 bytes
+            
+            if (info->RxBufferSize > 0) {
+
+#ifdef TEST_board
+                
+                sent_rx = 1;
+                
+                uint16_t *ptr_tx = (uint16_t*)(info->RxBuffer);                 // warning! get shifted transmited data; MSByte relevant
+                printf("*ptr_tx: %#x\r\n", *ptr_tx);
+                *ptr_tx = *ptr_tx >> 8;                                         // shift MSByte to LSByte
+                printf("*ptr_tx shift left by 8-bit: %#x\r\n", *ptr_tx);
+                
+                printf("%#x\r\n",trx);
+                
+                // print RX data as string and hexadecimal 
+                std::string rx((const char*)info->RxBuffer, info->RxBufferSize);
+                    
+                printf("Rx data: (String):%s (HexString):%s \r\n", rx.c_str(), mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
+
+                lcd.locate(0,10);
+                lcd.printf("Prejeto: %u (+1)", *ptr_tx);
+                
+                
+                if(*ptr_tx == trx+1)                                            // compare received and transmitted+1 value
+                {
+                   lcd.locate(0,20);
+                   lcd.printf("PASS!");   
+                   printf("PASS\r\n");
+
+                }
+                else
+                {
+                   lcd.locate(0,20);
+                   lcd.printf("FAIL!"); 
+                   printf("FAIL\r\n");
+                }
+                            
+                
+                
+#elif defined(REFERENCE_board)
+                
+                // get Received value       
+                ptr_rx = (uint16_t*)(info->RxBuffer);                           // warning! get shifted transmited data; MSByte relevant
+                *ptr_rx = *ptr_rx >> 8;                                         // shift MSByte to LSByte
+                printf("*ptr_rx shift left by 8-bit: %#x \r\n", *ptr_rx);
+            
+                // print RX data as string and hexadecimal    
+                std::string rx((const char*)info->RxBuffer, info->RxBufferSize);
+                printf("Rx data: (String):%s (HexString):%s \r\n", rx.c_str(), mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
+                          
+                received = 1;                                                   // indicate that the RadioEvent has happened
+                
+                printf("received: %u \r\n", received);
+ 
+#endif
+                
+            }
+        }
+    }
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Example/inc/dot_util.h	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,43 @@
+#ifndef __DOT_UTIL_H__
+#define __DOT_UTIL_H__
+
+#include "mbed.h"
+#include "mDot.h"
+#include "ChannelPlans.h"
+#include "MTSLog.h"
+#include "MTSText.h"
+#include "ISL29011.h"
+#include "example_config.h"
+
+extern mDot* dot;
+
+void display_config();
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power);
+
+void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold);
+
+void join_network();
+
+void sleep_wake_rtc_only(bool deepsleep);
+
+void sleep_wake_interrupt_only(bool deepsleep);
+
+void sleep_wake_rtc_or_interrupt(bool deepsleep);
+
+void sleep_save_io();
+
+void sleep_configure_io();
+
+void sleep_restore_io();
+
+void send_data(std::vector<uint8_t> data);
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Example/lib/ISL29011.lib	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/Multi-Hackers/code/ISL29011/#c1d5f4999b9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Example/src/dot_util.cpp	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,715 @@
+#include "dot_util.h"
+#if defined(TARGET_XDOT_L151CC)
+#include "xdot_low_power.h"
+#endif
+
+#if defined(TARGET_MTS_MDOT_F411RE)
+uint32_t portA[6];
+uint32_t portB[6];
+uint32_t portC[6];
+uint32_t portD[6];
+uint32_t portH[6];
+#endif
+
+
+void display_config() {
+    // display configuration and library version information
+    logInfo("=====================");
+    logInfo("general configuration");
+    logInfo("=====================");
+    logInfo("version ------------------ %s", dot->getId().c_str());
+    logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
+    logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str());
+    logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+        logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
+    }
+    logInfo("public network ----------- %s", dot->getPublicNetwork() ? "on" : "off");
+    logInfo("=========================");
+    logInfo("credentials configuration");
+    logInfo("=========================");
+    logInfo("device class ------------- %s", dot->getClass().c_str());
+    logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
+    if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
+	logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
+	logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
+	logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
+    } else {
+	logInfo("network name ------------- %s", dot->getNetworkName().c_str());
+	logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
+	logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
+	logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
+    }
+    logInfo("========================");
+    logInfo("communication parameters");
+    logInfo("========================");
+    if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
+	logInfo("TX frequency ------------- %lu", dot->getTxFrequency());
+    } else {
+	logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
+    }
+    logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
+    logInfo("TX power ----------------- %lu dBm", dot->getTxPower());
+    logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain());
+    logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off");
+    if (dot->getLbtTimeUs()) {
+	logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs());
+	logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold());
+    }
+}
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::string current_network_name = dot->getNetworkName();
+    std::string current_network_passphrase = dot->getNetworkPassphrase();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+    
+    if (current_network_name != network_name) {
+        logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str());
+        if (dot->setNetworkName(network_name) != mDot::MDOT_OK) {
+            logError("failed to set network name to \"%s\"", network_name.c_str());
+        }
+    }
+    
+    if (current_network_passphrase != network_passphrase) {
+        logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str());
+        if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) {
+            logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str());
+        }
+    }
+    
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+	if (current_frequency_sub_band != frequency_sub_band) {
+	    logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+	    if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+		logError("failed to set frequency sub band to %u", frequency_sub_band);
+	    }
+	}
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::vector<uint8_t> current_network_id = dot->getNetworkId();
+    std::vector<uint8_t> current_network_key = dot->getNetworkKey();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+
+    std::vector<uint8_t> network_id_vector(network_id, network_id + 8);
+    std::vector<uint8_t> network_key_vector(network_key, network_key + 16);
+    
+    if (current_network_id != network_id_vector) {
+        logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str());
+        if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) {
+            logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str());
+        }
+    }
+    
+    if (current_network_key != network_key_vector) {
+        logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str());
+        if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str());
+        }
+    }
+    
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+	if (current_frequency_sub_band != frequency_sub_band) {
+	    logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+	    if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+		logError("failed to set frequency sub band to %u", frequency_sub_band);
+	    }
+	}
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
+    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+
+    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
+    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
+    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
+
+    if (current_network_address != network_address_vector) {
+        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
+        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
+            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
+        }
+    }
+    
+    if (current_network_session_key != network_session_key_vector) {
+        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
+        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_data_session_key != data_session_key_vector) {
+        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
+        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_frequency_sub_band != frequency_sub_band) {
+        logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+        if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+            logError("failed to set frequency sub band to %u", frequency_sub_band);
+        }
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power) {
+    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
+    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
+    uint32_t current_tx_frequency = dot->getTxFrequency();
+    uint8_t current_tx_datarate = dot->getTxDataRate();
+    uint8_t current_tx_power = dot->getTxPower();
+
+    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
+    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
+    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
+
+    if (current_network_address != network_address_vector) {
+        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
+        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
+            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
+        }
+    }
+    
+    if (current_network_session_key != network_session_key_vector) {
+        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
+        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_data_session_key != data_session_key_vector) {
+        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
+        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_tx_frequency != tx_frequency) {
+	logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency);
+	if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) {
+	    logError("failed to set TX frequency to %lu", tx_frequency);
+	}
+    }
+
+    if (current_tx_datarate != tx_datarate) {
+	logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
+	if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
+	    logError("failed to set TX datarate to %u", tx_datarate);
+	}
+    }
+
+    if (current_tx_power != tx_power) {
+	logInfo("changing TX power from %u to %u", current_tx_power, tx_power);
+	if (dot->setTxPower(tx_power) != mDot::MDOT_OK) {
+	    logError("failed to set TX power to %u", tx_power);
+	}
+    }
+}
+
+void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) {
+    uint8_t current_link_check_count = dot->getLinkCheckCount();
+    uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();
+
+    if (current_link_check_count != link_check_count) {
+	logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count);
+	if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
+	    logError("failed to set link check count to %u", link_check_count);
+	}
+    }
+
+    if (current_link_check_threshold != link_check_threshold) {
+	logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold);
+	if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
+	    logError("failed to set link check threshold to %u", link_check_threshold);
+	}
+    }
+}
+
+void join_network() {
+    int32_t j_attempts = 0;
+    int32_t ret = mDot::MDOT_ERROR;
+    
+    // attempt to join the network
+    while (ret != mDot::MDOT_OK) {
+        logInfo("attempt %d to join network", ++j_attempts);
+        ret = dot->joinNetwork();
+        if (ret != mDot::MDOT_OK) {
+            logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+            // in some frequency bands we need to wait until another channel is available before transmitting again
+            uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
+            if (delay_s < 2) {
+                logInfo("waiting %lu s until next free channel", delay_s);
+                wait(delay_s);
+            } else {
+                logInfo("sleeping %lu s until next free channel", delay_s);
+                dot->sleep(delay_s, mDot::RTC_ALARM, false);
+            }
+        }
+    }
+}
+
+void sleep_wake_rtc_only(bool deepsleep) {
+    // in some frequency bands we need to wait until another channel is available before transmitting again
+    // wait at least 10s between transmissions
+    uint32_t delay_s = dot->getNextTxMs() / 1000;
+    if (delay_s < 10) {
+        delay_s = 10;
+    }
+    
+    logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s);
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm
+    dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_wake_interrupt_only(bool deepsleep) {
+#if defined (TARGET_XDOT_L151CC)
+    if (deepsleep) {
+        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
+        //      other pins can be confgured instead: GPIO0-3 or UART_RX
+        dot->setWakePin(WAKE);    
+    }
+
+    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#else
+
+    if (deepsleep) {
+        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
+        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
+        dot->setWakePin(XBEE_DIO7);    
+    }
+
+    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#endif
+
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep)
+    // since we're not waking on the RTC alarm, the interval is ignored
+    dot->sleep(0, mDot::INTERRUPT, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_wake_rtc_or_interrupt(bool deepsleep) {
+    // in some frequency bands we need to wait until another channel is available before transmitting again
+    // wait at least 10s between transmissions
+    uint32_t delay_s = dot->getNextTxMs() / 1000;
+    if (delay_s < 10) {
+        delay_s = 10;
+    }
+
+#if defined (TARGET_XDOT_L151CC)
+    if (deepsleep) {
+        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
+        //      other pins can be confgured instead: GPIO0-3 or UART_RX
+        dot->setWakePin(WAKE);    
+    }
+
+    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#else
+    if (deepsleep) {
+        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
+        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
+        dot->setWakePin(XBEE_DIO7);    
+    }
+
+    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#endif
+
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep and wake using the RTC alarm after delay_s seconds or rising edge of configured wake pin (only the WAKE pin in deepsleep)
+    // whichever comes first will wake the xDot
+    dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_save_io() {
+#if defined(TARGET_XDOT_L151CC)
+	xdot_save_gpio_state();
+#else
+	portA[0] = GPIOA->MODER;
+	portA[1] = GPIOA->OTYPER;
+	portA[2] = GPIOA->OSPEEDR;
+	portA[3] = GPIOA->PUPDR;
+	portA[4] = GPIOA->AFR[0];
+	portA[5] = GPIOA->AFR[1];
+
+	portB[0] = GPIOB->MODER;
+	portB[1] = GPIOB->OTYPER;
+	portB[2] = GPIOB->OSPEEDR;
+	portB[3] = GPIOB->PUPDR;
+	portB[4] = GPIOB->AFR[0];
+	portB[5] = GPIOB->AFR[1];
+
+	portC[0] = GPIOC->MODER;
+	portC[1] = GPIOC->OTYPER;
+	portC[2] = GPIOC->OSPEEDR;
+	portC[3] = GPIOC->PUPDR;
+	portC[4] = GPIOC->AFR[0];
+	portC[5] = GPIOC->AFR[1];
+
+	portD[0] = GPIOD->MODER;
+	portD[1] = GPIOD->OTYPER;
+	portD[2] = GPIOD->OSPEEDR;
+	portD[3] = GPIOD->PUPDR;
+	portD[4] = GPIOD->AFR[0];
+	portD[5] = GPIOD->AFR[1];
+
+	portH[0] = GPIOH->MODER;
+	portH[1] = GPIOH->OTYPER;
+	portH[2] = GPIOH->OSPEEDR;
+	portH[3] = GPIOH->PUPDR;
+	portH[4] = GPIOH->AFR[0];
+	portH[5] = GPIOH->AFR[1];
+#endif
+}
+
+void sleep_configure_io() {
+#if defined(TARGET_XDOT_L151CC)
+    // GPIO Ports Clock Enable
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    __GPIOC_CLK_ENABLE();
+    __GPIOH_CLK_ENABLE();
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    // I2C_SDA & I2C_SCL to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+    if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_4;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_2;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_10;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+#else
+    /* GPIO Ports Clock Enable */
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    __GPIOC_CLK_ENABLE();
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 
+                | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);    
+
+    // PB_0, PB_1, PB_3 & PB_4 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
+
+    // PC_9 & PC_13 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
+
+    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+    // XBEE_DIN - PA3
+    // XBEE_DIO2 - PA5
+    // XBEE_DIO3 - PA4
+    // XBEE_DIO4 - PA7
+    // XBEE_DIO5 - PC1
+    // XBEE_DIO6 - PA1
+    // XBEE_DIO7 - PA0
+    // XBEE_SLEEPRQ - PA11
+                
+    if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_3;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+    if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+    if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_4;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+         if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_7;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_1;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_1;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_11;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+#endif
+}
+
+void sleep_restore_io() {
+#if defined(TARGET_XDOT_L151CC)
+    xdot_restore_gpio_state();
+#else
+    GPIOA->MODER = portA[0];
+    GPIOA->OTYPER = portA[1];
+    GPIOA->OSPEEDR = portA[2];
+    GPIOA->PUPDR = portA[3];
+    GPIOA->AFR[0] = portA[4];
+    GPIOA->AFR[1] = portA[5];
+
+    GPIOB->MODER = portB[0];
+    GPIOB->OTYPER = portB[1];
+    GPIOB->OSPEEDR = portB[2];
+    GPIOB->PUPDR = portB[3];
+    GPIOB->AFR[0] = portB[4];
+    GPIOB->AFR[1] = portB[5];
+
+    GPIOC->MODER = portC[0];
+    GPIOC->OTYPER = portC[1];
+    GPIOC->OSPEEDR = portC[2];
+    GPIOC->PUPDR = portC[3];
+    GPIOC->AFR[0] = portC[4];
+    GPIOC->AFR[1] = portC[5];
+
+    GPIOD->MODER = portD[0];
+    GPIOD->OTYPER = portD[1];
+    GPIOD->OSPEEDR = portD[2];
+    GPIOD->PUPDR = portD[3];
+    GPIOD->AFR[0] = portD[4];
+    GPIOD->AFR[1] = portD[5];
+
+    GPIOH->MODER = portH[0];
+    GPIOH->OTYPER = portH[1];
+    GPIOH->OSPEEDR = portH[2];
+    GPIOH->PUPDR = portH[3];
+    GPIOH->AFR[0] = portH[4];
+    GPIOH->AFR[1] = portH[5];
+#endif
+}
+
+void send_data(std::vector<uint8_t> data) {
+    int32_t ret;
+
+    ret = dot->send(data);
+    if (ret != mDot::MDOT_OK) {
+        logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str());
+    } else {
+        logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway");
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Example/src/peer_to_peer_example.cpp	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,287 @@
+#include "dot_util.h"
+#include "RadioEvent.h"
+#include "mDotEvent.h"
+#include "C12832.h"
+
+#if ACTIVE_EXAMPLE == PEER_TO_PEER_EXAMPLE
+
+//#define TEST_board
+#define REFERENCE_board
+
+
+/////////////////////////////////////////////////////////////////////////////
+// -------------------- DOT LIBRARY REQUIRED ------------------------------//
+// * Because these example programs can be used for both mDot and xDot     //
+//     devices, the LoRa stack is not included. The libmDot library should //
+//     be imported if building for mDot devices. The libxDot library       //
+//     should be imported if building for xDot devices.                    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libmDot-mbed5/        //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-dev-mbed5/    //
+// * https://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/        //
+/////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////
+// * these options must match between the two devices in   //
+//   order for communication to be successful
+/////////////////////////////////////////////////////////////
+
+/*============================= INIT =========================================*/
+
+static uint8_t network_address[] = { 0x01, 0x02, 0x03, 0x04 };
+static uint8_t network_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+static uint8_t data_session_key[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+
+mDot* dot = NULL;
+lora::ChannelPlan* plan = NULL;
+
+Serial pc(USBTX, USBRX);
+
+#ifdef TEST_board
+C12832 lcd(PB_15, PB_13, PB_14, PA_12, PB_12);                                  // init LCD
+
+DigitalIn joystick_up(PB_2);                                                    // init button to start the send routine
+DigitalOut led(PB_8, 1);                                                        // init LED to indicate sending messages
+
+DigitalIn BTN_1(PA_5);                                                          // init LoRa button
+DigitalOut LED_1(PA_4, 0);                                                      // init LoRa LED
+
+
+uint8_t trx = 0x2F;                                                             // initial sending value (0x2F dec 47)
+uint8_t sent = 0; 
+uint8_t sent_rx = 0; 
+
+#elif defined(REFERENCE_board)
+DigitalOut led(PA_4, 0);                                                        // init LED to indicate sending messages
+
+uint8_t received = 0;                                                           // check for RadioEvent
+
+uint16_t *ptr_rx;                                                               // init pointer to RxBuffer
+
+#endif
+
+/*============================ END INIT ======================================*/
+
+
+/*============================== MAIN ========================================*/
+
+int main()
+{
+    // Custom event handler for automatically displaying RX data
+    RadioEvent events;
+    uint32_t tx_frequency;
+    uint8_t tx_datarate;
+    uint8_t tx_power;
+    uint8_t frequency_band;
+
+    // sending data
+
+    pc.baud(115200);
+
+    mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+
+#if CHANNEL_PLAN == CP_US915
+    plan = new lora::ChannelPlan_US915();
+#elif CHANNEL_PLAN == CP_AU915
+    plan = new lora::ChannelPlan_AU915();
+#elif CHANNEL_PLAN == CP_EU868
+    plan = new lora::ChannelPlan_EU868();
+#elif CHANNEL_PLAN == CP_KR920
+    plan = new lora::ChannelPlan_KR920();
+#elif CHANNEL_PLAN == CP_AS923
+    plan = new lora::ChannelPlan_AS923();
+#elif CHANNEL_PLAN == CP_AS923_JAPAN
+    plan = new lora::ChannelPlan_AS923_Japan();
+#elif CHANNEL_PLAN == CP_IN865
+    plan = new lora::ChannelPlan_IN865();
+#endif
+    assert(plan);
+
+    dot = mDot::getInstance(plan);
+    assert(dot);
+
+    logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
+
+    // start from a well-known state
+    logInfo("defaulting Dot configuration");
+    dot->resetConfig();
+
+    // make sure library logging is turned on
+    dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+    // attach the custom events handler
+    dot->setEvents(&events);
+
+    // update configuration if necessary
+    if (dot->getJoinMode() != mDot::PEER_TO_PEER) {
+        logInfo("changing network join mode to PEER_TO_PEER");
+        if (dot->setJoinMode(mDot::PEER_TO_PEER) != mDot::MDOT_OK) {
+            logError("failed to set network join mode to PEER_TO_PEER");
+        }
+    }
+    frequency_band = dot->getFrequencyBand();
+    switch (frequency_band) {
+        case lora::ChannelPlan::EU868_OLD:
+        case lora::ChannelPlan::EU868:
+            // 250kHz channels achieve higher throughput
+            // DR_6 : SF7 @ 250kHz
+            // DR_0 - DR_5 (125kHz channels) available but much slower
+            tx_frequency = 869850000;
+            tx_datarate = lora::DR_6;
+            // the 869850000 frequency is 100% duty cycle if the total power is under 7 dBm - tx power 4 + antenna gain 3 = 7
+            tx_power = 4;
+            break;
+
+        case lora::ChannelPlan::US915_OLD:
+        case lora::ChannelPlan::US915:
+        case lora::ChannelPlan::AU915_OLD:
+        case lora::ChannelPlan::AU915:
+            // 500kHz channels achieve highest throughput
+            // DR_8 : SF12 @ 500kHz
+            // DR_9 : SF11 @ 500kHz
+            // DR_10 : SF10 @ 500kHz
+            // DR_11 : SF9 @ 500kHz
+            // DR_12 : SF8 @ 500kHz
+            // DR_13 : SF7 @ 500kHz
+            // DR_0 - DR_3 (125kHz channels) available but much slower
+            tx_frequency = 915500000;
+            tx_datarate = lora::DR_13;
+            // 915 bands have no duty cycle restrictions, set tx power to max
+            tx_power = 20;
+            break;
+
+        case lora::ChannelPlan::AS923:
+        case lora::ChannelPlan::AS923_JAPAN:
+            // 250kHz channels achieve higher throughput
+            // DR_6 : SF7 @ 250kHz
+            // DR_0 - DR_5 (125kHz channels) available but much slower
+            tx_frequency = 924800000;
+            tx_datarate = lora::DR_6;
+            tx_power = 16;
+            break;
+
+        case lora::ChannelPlan::KR920:
+            // DR_5 : SF7 @ 125kHz
+            tx_frequency = 922700000;
+            tx_datarate = lora::DR_5;
+            tx_power = 14;
+            break;
+
+        default:
+            while (true) {
+                logFatal("no known channel plan in use - extra configuration is needed!");
+                wait(5);
+            }
+            break;
+    }
+    // in PEER_TO_PEER mode there is no join request/response transaction
+    // as long as both Dots are configured correctly, they should be able to communicate
+    update_peer_to_peer_config(network_address, network_session_key, data_session_key, tx_frequency, tx_datarate, tx_power);
+
+    // save changes to configuration
+    logInfo("saving configuration");
+    if (!dot->saveConfig()) {
+        logError("failed to save configuration");
+    }
+
+    // display configuration
+    display_config();
+
+#ifdef TEST_board
+
+    while (true) {
+
+        lcd.locate(0,0);
+        lcd.printf("Zacni test s pritiskom na   JOYSTICK tipko...");
+
+                    // join network if not joined
+        if (!dot->getNetworkJoinStatus()) {
+            join_network();
+        }
+            
+        while(!BTN_1) LED_1 = 1;                                                // press btn to light up led
+        LED_1 = 0;                                                              // clear LED
+
+        
+        if(joystick_up) {                                                       // wait for user input
+        
+            sent = 1;
+
+            lcd.cls();
+            led = 0;
+
+            std::vector<uint8_t> tx_data;
+
+            trx++;                                                              // +1 to value to be send
+            tx_data.push_back((trx >> 8) & 0xFF);                               // shift data eg. 0x0031 -> 0x3100
+            tx_data.push_back(trx & 0xFF);
+            logInfo("send_data: 0x%x", trx);
+            
+            lcd.locate(0,0);
+            lcd.printf("Poslano: %u", trx);
+            
+            send_data(tx_data);                                                 // send data
+
+            wait(1);
+            
+            if(!(sent && sent_rx)) 
+            {
+                
+                lcd.locate(0,10);
+                lcd.printf("FAIL!"); 
+                lcd.locate(0,20);
+                lcd.printf("Preveri REFERENCNO platico."); 
+            }          
+            
+            wait(4);     
+            
+            sent = 0;
+            sent_rx = 0;                    
+
+            lcd.cls();
+            led = 1;
+
+        }
+    }
+    
+#elif defined(REFERENCE_board)
+
+    while (true) {
+        
+        std::vector<uint8_t> tx_data;
+
+            // join network if not joined
+            if (!dot->getNetworkJoinStatus()) {
+                join_network();
+            }
+        
+        if(received)                                                            // RadioEvent happened
+        {
+            
+        led = 1;
+        
+        received = 0;                                                           // clear event flag
+        ++*ptr_rx;                                                              // +1 to received value
+        tx_data.push_back((*ptr_rx >> 8) & 0xFF);                               // shift data eg. 0x0031 -> 0x3100
+        tx_data.push_back(*ptr_rx & 0xFF);
+        logInfo("Sent *ptr_rx: %#x", *ptr_rx);
+        send_data(tx_data);                                                     // then send back
+        
+        wait(1);
+        
+        led = 0;        
+        
+        NVIC_SystemReset();                                                     // reset Reference board
+        
+        }
+    }
+
+#endif
+
+    return 0;
+}
+
+#endif
+
+/*============================ END MAIN =======================================*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libraries/C12832/.hg_archival.txt	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,6 @@
+repo: 4bbc531be6e23ee4d06af3b31bc09c5dfb23837a
+node: 7de323fa46fe1eacc470c8e7ebaafef8923fdcf3
+branch: default
+latesttag: null
+latesttagdistance: 16
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libraries/C12832/C12832.cpp	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,565 @@
+/* mbed library for the mbed Lab Board  128*32 pixel LCD
+ * use C12832 controller
+ * Copyright (c) 2012 Peter Drescher - DC2PD
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// 13.10.12    initial design
+// 25.10.12    add autorefresh of screen
+// 25.10.12    add standart font
+// 20.12.12    add bitmap graphics
+
+// optional defines :
+// #define debug_lcd  1
+
+#include "C12832.h"
+#include "mbed.h"
+#include "stdio.h"
+#include "Small_7.h"
+
+#define BPP    1       // Bits per pixel
+
+
+C12832::C12832(PinName mosi, PinName sck, PinName reset, PinName a0, PinName ncs, const char* name)
+    : _spi(mosi,NC,sck),_reset(reset),_A0(a0),_CS(ncs),GraphicsDisplay(name)
+{
+    orientation = 1;
+    draw_mode = NORMAL;
+    char_x = 0;
+    lcd_reset();
+}
+
+
+int C12832::width()
+{
+    if (orientation == 0 || orientation == 2) return 32;
+    else return 128;
+}
+
+int C12832::height()
+{
+    if (orientation == 0 || orientation == 2) return 128;
+    else return 32;
+}
+
+
+void C12832::invert(unsigned int o)
+{
+    if(o == 0) wr_cmd(0xA6);
+    else wr_cmd(0xA7);
+}
+
+
+void C12832::set_contrast(unsigned int o)
+{
+    contrast = o;
+    wr_cmd(0x81);      //  set volume
+    wr_cmd(o & 0x3F);
+}
+
+unsigned int C12832::get_contrast(void)
+{
+    return(contrast);
+}
+
+
+// write command to lcd controller
+
+void C12832::wr_cmd(unsigned char cmd)
+{
+    _A0 = 0;
+    _CS = 0;
+    _spi.write(cmd);
+    _CS = 1;
+}
+
+// write data to lcd controller
+
+void C12832::wr_dat(unsigned char dat)
+{
+    _A0 = 1;
+    _CS = 0;
+    _spi.write(dat);
+    _CS = 1;
+}
+
+// reset and init the lcd controller
+
+void C12832::lcd_reset()
+{
+
+    _spi.format(8,3);                 // 8 bit spi mode 3
+    _spi.frequency(20000000);          // 19,2 Mhz SPI clock
+    _A0 = 0;
+    _CS = 1;
+    _reset = 0;                        // display reset
+    wait_us(50);
+    _reset = 1;                       // end reset
+    wait_ms(5);
+
+    /* Start Initial Sequence ----------------------------------------------------*/
+
+    wr_cmd(0xAE);   //  display off
+    wr_cmd(0xA2);   //  bias voltage
+
+    wr_cmd(0xA0);
+    wr_cmd(0xC8);   //  colum normal
+
+    wr_cmd(0x22);   //  voltage resistor ratio
+    wr_cmd(0x2F);   //  power on
+    //wr_cmd(0xA4);   //  LCD display ram
+    wr_cmd(0x40);   // start line = 0
+    wr_cmd(0xAF);     // display ON
+
+    wr_cmd(0x81);   //  set contrast
+    wr_cmd(0x17);   //  set contrast
+
+    wr_cmd(0xA6);     // display normal
+
+
+    // clear and update LCD
+    memset(buffer,0x00,512);  // clear display buffer
+    copy_to_lcd();
+    auto_up = 1;              // switch on auto update
+    // dont do this by default. Make the user call
+    //claim(stdout);           // redirekt printf to lcd
+    locate(0,0);
+    set_font((unsigned char*)Small_7);  // standart font
+}
+
+// set one pixel in buffer
+
+void C12832::pixel(int x, int y, int color)
+{
+    // first check parameter
+    if(x > 128 || y > 32 || x < 0 || y < 0) return;
+
+    if(draw_mode == NORMAL) {
+        if(color == 0)
+            buffer[x + ((y/8) * 128)] &= ~(1 << (y%8));  // erase pixel
+        else
+            buffer[x + ((y/8) * 128)] |= (1 << (y%8));   // set pixel
+    } else { // XOR mode
+        if(color == 1)
+            buffer[x + ((y/8) * 128)] ^= (1 << (y%8));   // xor pixel
+    }
+}
+
+// update lcd
+
+void C12832::copy_to_lcd(void)
+{
+    
+    int i=0;
+    
+    //page 0
+    wr_cmd(0x00);      // set column low nibble 0
+    wr_cmd(0x10);      // set column hi  nibble 0
+    wr_cmd(0xB0);      // set page address  0
+    _A0 = 1;
+    for(i=0; i<128; i++) {
+        wr_dat(buffer[i]);
+    }
+
+    // page 1
+    wr_cmd(0x00);      // set column low nibble 0
+    wr_cmd(0x10);      // set column hi  nibble 0
+    wr_cmd(0xB1);      // set page address  1
+    _A0 = 1;
+    for(i=128; i<256; i++) {
+        wr_dat(buffer[i]);
+    }
+
+    //page 2
+    wr_cmd(0x00);      // set column low nibble 0
+    wr_cmd(0x10);      // set column hi  nibble 0
+    wr_cmd(0xB2);      // set page address  2
+    _A0 = 1;
+    for(i=256; i<384; i++) {
+        wr_dat(buffer[i]);
+    }
+
+    //page 3
+    wr_cmd(0x00);      // set column low nibble 0
+    wr_cmd(0x10);      // set column hi  nibble 0
+    wr_cmd(0xB3);      // set page address  3
+    _A0 = 1;
+
+    _CS = 0;
+    
+    for(i=384; i<512; i++) {
+        wr_dat(buffer[i]);
+    }
+
+}
+
+void C12832::cls(void)
+{
+    memset(buffer,0x00,512);  // clear display buffer
+    copy_to_lcd();
+}
+
+
+void C12832::line(int x0, int y0, int x1, int y1, int color)
+{
+    int   dx = 0, dy = 0;
+    int   dx_sym = 0, dy_sym = 0;
+    int   dx_x2 = 0, dy_x2 = 0;
+    int   di = 0;
+
+    dx = x1-x0;
+    dy = y1-y0;
+
+    //  if (dx == 0) {        /* vertical line */
+    //      if (y1 > y0) vline(x0,y0,y1,color);
+    //      else vline(x0,y1,y0,color);
+    //      return;
+    //  }
+
+    if (dx > 0) {
+        dx_sym = 1;
+    } else {
+        dx_sym = -1;
+    }
+    //  if (dy == 0) {        /* horizontal line */
+    //      if (x1 > x0) hline(x0,x1,y0,color);
+    //      else  hline(x1,x0,y0,color);
+    //      return;
+    //  }
+
+    if (dy > 0) {
+        dy_sym = 1;
+    } else {
+        dy_sym = -1;
+    }
+
+    dx = dx_sym*dx;
+    dy = dy_sym*dy;
+
+    dx_x2 = dx*2;
+    dy_x2 = dy*2;
+
+    if (dx >= dy) {
+        di = dy_x2 - dx;
+        while (x0 != x1) {
+
+            pixel(x0, y0, color);
+            x0 += dx_sym;
+            if (di<0) {
+                di += dy_x2;
+            } else {
+                di += dy_x2 - dx_x2;
+                y0 += dy_sym;
+            }
+        }
+        pixel(x0, y0, color);
+    } else {
+        di = dx_x2 - dy;
+        while (y0 != y1) {
+            pixel(x0, y0, color);
+            y0 += dy_sym;
+            if (di < 0) {
+                di += dx_x2;
+            } else {
+                di += dx_x2 - dy_x2;
+                x0 += dx_sym;
+            }
+        }
+        pixel(x0, y0, color);
+    }
+    if(auto_up) copy_to_lcd();
+}
+
+void C12832::rect(int x0, int y0, int x1, int y1, int color)
+{
+
+    if (x1 > x0) line(x0,y0,x1,y0,color);
+    else  line(x1,y0,x0,y0,color);
+
+    if (y1 > y0) line(x0,y0,x0,y1,color);
+    else line(x0,y1,x0,y0,color);
+
+    if (x1 > x0) line(x0,y1,x1,y1,color);
+    else  line(x1,y1,x0,y1,color);
+
+    if (y1 > y0) line(x1,y0,x1,y1,color);
+    else line(x1,y1,x1,y0,color);
+
+    if(auto_up) copy_to_lcd();
+}
+
+void C12832::fillrect(int x0, int y0, int x1, int y1, int color)
+{
+    int l,c,i;
+    if(x0 > x1) {
+        i = x0;
+        x0 = x1;
+        x1 = i;
+    }
+
+    if(y0 > y1) {
+        i = y0;
+        y0 = y1;
+        y1 = i;
+    }
+
+    for(l = x0; l<= x1; l ++) {
+        for(c = y0; c<= y1; c++) {
+            pixel(l,c,color);
+        }
+    }
+    if(auto_up) copy_to_lcd();
+}
+
+
+
+void C12832::circle(int x0, int y0, int r, int color)
+{
+
+    int draw_x0, draw_y0;
+    int draw_x1, draw_y1;
+    int draw_x2, draw_y2;
+    int draw_x3, draw_y3;
+    int draw_x4, draw_y4;
+    int draw_x5, draw_y5;
+    int draw_x6, draw_y6;
+    int draw_x7, draw_y7;
+    int xx, yy;
+    int di;
+    //WindowMax();
+    if (r == 0) {       /* no radius */
+        return;
+    }
+
+    draw_x0 = draw_x1 = x0;
+    draw_y0 = draw_y1 = y0 + r;
+    if (draw_y0 < height()) {
+        pixel(draw_x0, draw_y0, color);     /* 90 degree */
+    }
+
+    draw_x2 = draw_x3 = x0;
+    draw_y2 = draw_y3 = y0 - r;
+    if (draw_y2 >= 0) {
+        pixel(draw_x2, draw_y2, color);    /* 270 degree */
+    }
+
+    draw_x4 = draw_x6 = x0 + r;
+    draw_y4 = draw_y6 = y0;
+    if (draw_x4 < width()) {
+        pixel(draw_x4, draw_y4, color);     /* 0 degree */
+    }
+
+    draw_x5 = draw_x7 = x0 - r;
+    draw_y5 = draw_y7 = y0;
+    if (draw_x5>=0) {
+        pixel(draw_x5, draw_y5, color);     /* 180 degree */
+    }
+
+    if (r == 1) {
+        return;
+    }
+
+    di = 3 - 2*r;
+    xx = 0;
+    yy = r;
+    while (xx < yy) {
+
+        if (di < 0) {
+            di += 4*xx + 6;
+        } else {
+            di += 4*(xx - yy) + 10;
+            yy--;
+            draw_y0--;
+            draw_y1--;
+            draw_y2++;
+            draw_y3++;
+            draw_x4--;
+            draw_x5++;
+            draw_x6--;
+            draw_x7++;
+        }
+        xx++;
+        draw_x0++;
+        draw_x1--;
+        draw_x2++;
+        draw_x3--;
+        draw_y4++;
+        draw_y5++;
+        draw_y6--;
+        draw_y7--;
+
+        if ( (draw_x0 <= width()) && (draw_y0>=0) ) {
+            pixel(draw_x0, draw_y0, color);
+        }
+
+        if ( (draw_x1 >= 0) && (draw_y1 >= 0) ) {
+            pixel(draw_x1, draw_y1, color);
+        }
+
+        if ( (draw_x2 <= width()) && (draw_y2 <= height()) ) {
+            pixel(draw_x2, draw_y2, color);
+        }
+
+        if ( (draw_x3 >=0 ) && (draw_y3 <= height()) ) {
+            pixel(draw_x3, draw_y3, color);
+        }
+
+        if ( (draw_x4 <= width()) && (draw_y4 >= 0) ) {
+            pixel(draw_x4, draw_y4, color);
+        }
+
+        if ( (draw_x5 >= 0) && (draw_y5 >= 0) ) {
+            pixel(draw_x5, draw_y5, color);
+        }
+        if ( (draw_x6 <=width()) && (draw_y6 <= height()) ) {
+            pixel(draw_x6, draw_y6, color);
+        }
+        if ( (draw_x7 >= 0) && (draw_y7 <= height()) ) {
+            pixel(draw_x7, draw_y7, color);
+        }
+    }
+    if(auto_up) copy_to_lcd();
+}
+
+void C12832::fillcircle(int x, int y, int r, int color)
+{
+    int i,up;
+    up = auto_up;
+    auto_up = 0;   // off
+    for (i = 0; i <= r; i++)
+        circle(x,y,i,color);
+    auto_up = up;
+    if(auto_up) copy_to_lcd();
+}
+
+void C12832::setmode(int mode)
+{
+    draw_mode = mode;
+}
+
+void C12832::locate(int x, int y)
+{
+    char_x = x;
+    char_y = y;
+}
+
+
+
+int C12832::columns()
+{
+    return width() / font[1];
+}
+
+
+
+int C12832::rows()
+{
+    return height() / font[2];
+}
+
+
+
+int C12832::_putc(int value)
+{
+    if (value == '\n') {    // new line
+        char_x = 0;
+        char_y = char_y + font[2];
+        if (char_y >= height() - font[2]) {
+            char_y = 0;
+        }
+    } else {
+        character(char_x, char_y, value);
+        if(auto_up) copy_to_lcd();
+    }
+    return value;
+}
+
+void C12832::character(int x, int y, int c)
+{
+    unsigned int hor,vert,offset,bpl,j,i,b;
+    unsigned char* zeichen;
+    unsigned char z,w;
+
+    if ((c < 31) || (c > 127)) return;   // test char range
+
+    // read font parameter from start of array
+    offset = font[0];                    // bytes / char
+    hor = font[1];                       // get hor size of font
+    vert = font[2];                      // get vert size of font
+    bpl = font[3];                       // bytes per line
+
+    if (char_x + hor > width()) {
+        char_x = 0;
+        char_y = char_y + vert;
+        if (char_y >= height() - font[2]) {
+            char_y = 0;
+        }
+    }
+
+    zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
+    w = zeichen[0];                          // width of actual char
+    // construct the char into the buffer
+    for (j=0; j<vert; j++) {  //  vert line
+        for (i=0; i<hor; i++) {   //  horz line
+            z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
+            b = 1 << (j & 0x07);
+            if (( z & b ) == 0x00) {
+                pixel(x+i,y+j,0);
+            } else {
+                pixel(x+i,y+j,1);
+            }
+
+        }
+    }
+
+    char_x += w;
+}
+
+
+void C12832::set_font(unsigned char* f)
+{
+    font = f;
+}
+
+void C12832::set_auto_up(unsigned int up)
+{
+    if(up ) auto_up = 1;
+    else auto_up = 0;
+}
+
+unsigned int C12832::get_auto_up(void)
+{
+    return (auto_up);
+}
+
+void C12832::print_bm(Bitmap bm, int x, int y)
+{
+    int h,v,b;
+    char d;
+
+    for(v=0; v < bm.ySize; v++) {   // lines
+        for(h=0; h < bm.xSize; h++) { // pixel
+            if(h + x > 127) break;
+            if(v + y > 31) break;
+            d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)];
+            b = 0x80 >> (h & 0x07);
+            if((d & b) == 0) {
+                pixel(x+h,y+v,0);
+            } else {
+                pixel(x+h,y+v,1);
+            }
+        }
+    }
+
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libraries/C12832/C12832.h	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,307 @@
+/* mbed library for the mbed Lab Board  128*32 pixel LCD
+ * use C12832 controller
+ * Copyright (c) 2012 Peter Drescher - DC2PD
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef C12832_H
+#define C12832_H
+
+#include "mbed.h"
+#include "GraphicsDisplay.h"
+
+
+/** optional Defines :
+  * #define debug_lcd  1  enable infos to PC_USB
+  */
+
+// some defines for the DMA use
+#define DMA_CHANNEL_ENABLE      1
+#define DMA_TRANSFER_TYPE_M2P   (1UL << 11)
+#define DMA_CHANNEL_TCIE        (1UL << 31)
+#define DMA_CHANNEL_SRC_INC     (1UL << 26)
+#define DMA_MASK_IE             (1UL << 14)
+#define DMA_MASK_ITC            (1UL << 15)
+#define DMA_SSP1_TX             (1UL << 2)
+#define DMA_SSP0_TX             (0)
+#define DMA_DEST_SSP1_TX        (2UL << 6)
+#define DMA_DEST_SSP0_TX        (0UL << 6)
+
+/** Draw mode
+  * NORMAl
+  * XOR set pixel by xor the screen
+  */
+enum {NORMAL,XOR};
+
+/** Bitmap
+ */
+struct Bitmap{
+    int xSize;
+    int ySize;
+    int Byte_in_Line;
+    char* data;
+    };
+
+class C12832 : public GraphicsDisplay
+{
+public:
+    /** Create a C12832 object connected to SPI1
+      *
+      */
+
+    C12832(PinName mosi, PinName sck, PinName reset, PinName a0, PinName ncs, const char* name = "LCD");
+
+
+    /** Get the width of the screen in pixel
+      *
+      * @param
+      * @returns width of screen in pixel
+      *
+      */
+    virtual int width();
+
+    /** Get the height of the screen in pixel
+     *
+     * @returns height of screen in pixel
+     *
+     */
+    virtual int height();
+
+    /** Draw a pixel at x,y black or white
+     *
+     * @param x horizontal position
+     * @param y vertical position
+     * @param colour ,1 set pixel ,0 erase pixel
+     */
+    virtual void pixel(int x, int y,int colour);
+
+    /** draw a circle
+      *
+      * @param x0,y0 center
+      * @param r radius
+      * @param colour ,1 set pixel ,0 erase pixel
+      *
+      */
+    void circle(int x, int y, int r, int colour);
+
+    /** draw a filled circle
+     *
+     * @param x0,y0 center
+     * @param r radius
+     * @param color ,1 set pixel ,0 erase pixel
+     *
+     * use circle with different radius,
+     * can miss some pixel
+     */
+    void fillcircle(int x, int y, int r, int colour);
+
+    /** draw a 1 pixel line
+      *
+      * @param x0,y0 start point
+      * @param x1,y1 stop point
+      * @param color ,1 set pixel ,0 erase pixel
+      *
+      */
+    void line(int x0, int y0, int x1, int y1, int colour);
+
+    /** draw a rect
+    *
+    * @param x0,y0 top left corner
+    * @param x1,y1 down right corner
+    * @param color 1 set pixel ,0 erase pixel
+    *                                                   *
+    */
+    void rect(int x0, int y0, int x1, int y1, int colour);
+
+    /** draw a filled rect
+      *
+      * @param x0,y0 top left corner
+      * @param x1,y1 down right corner
+      * @param color 1 set pixel ,0 erase pixel
+      *
+      */
+    void fillrect(int x0, int y0, int x1, int y1, int colour);
+
+    /** copy display buffer to lcd
+      *
+      */
+
+    void copy_to_lcd(void);
+
+    /** set the orienation of the screen
+      *
+      */
+
+
+    void set_contrast(unsigned int o);
+
+    /** read the contrast level
+      *
+      */
+    unsigned int get_contrast(void);
+
+
+    /** invert the screen
+      *
+      * @param o = 0 normal, 1 invert
+      */
+    void invert(unsigned int o);
+
+    /** clear the screen
+       *
+       */
+    virtual void cls(void);
+
+    /** set the drawing mode
+      *
+      * @param mode NORMAl or XOR
+      */
+
+    void setmode(int mode);
+
+    virtual int columns(void);
+
+    /** calculate the max number of columns
+     *
+     * @returns max column
+     * depends on actual font size
+     *
+     */
+    virtual int rows(void);
+
+    /** put a char on the screen
+     *
+     * @param value char to print
+     * @returns printed char
+     *
+     */
+    virtual int _putc(int value);
+
+    /** draw a character on given position out of the active font to the LCD
+     *
+     * @param x x-position of char (top left)
+     * @param y y-position
+     * @param c char to print
+     *
+     */
+    virtual void character(int x, int y, int c);
+
+    /** setup cursor position
+     *
+     * @param x x-position (top left)
+     * @param y y-position
+     */
+    virtual void locate(int x, int y);
+    
+    /** setup auto update of screen 
+      *
+      * @param up 1 = on , 0 = off
+      * if switched off the program has to call copy_to_lcd() 
+      * to update screen from framebuffer
+      */
+    void set_auto_up(unsigned int up);
+
+    /** get status of the auto update function
+      *
+      *  @returns if auto update is on
+      */
+    unsigned int get_auto_up(void);
+
+    /** Vars     */
+    SPI _spi;
+    DigitalOut _reset;
+    DigitalOut _A0;
+    DigitalOut _CS;
+    unsigned char* font;
+    unsigned int draw_mode;
+
+
+    /** select the font to use
+      *
+      * @param f pointer to font array
+      *
+      *   font array can created with GLCD Font Creator from http://www.mikroe.com
+      *   you have to add 4 parameter at the beginning of the font array to use:
+      *   - the number of byte / char
+      *   - the vertial size in pixel
+      *   - the horizontal size in pixel
+      *   - the number of byte per vertical line
+      *   you also have to change the array to char[]
+      *
+      */
+    void set_font(unsigned char* f);
+    
+    /** print bitmap to buffer
+      *
+      * @param bm Bitmap in flash
+      * @param x  x start
+      * @param y  y start 
+      *
+      */
+
+    void print_bm(Bitmap bm, int x, int y);
+
+protected:
+
+    /** draw a horizontal line
+      *
+      * @param x0 horizontal start
+      * @param x1 horizontal stop
+      * @param y vertical position
+      * @param ,1 set pixel ,0 erase pixel
+      *
+      */
+    void hline(int x0, int x1, int y, int colour);
+
+    /** draw a vertical line
+     *
+     * @param x horizontal position
+     * @param y0 vertical start
+     * @param y1 vertical stop
+     * @param ,1 set pixel ,0 erase pixel
+     */
+    void vline(int y0, int y1, int x, int colour);
+
+    /** Init the C12832 LCD controller
+     *
+     */
+    void lcd_reset();
+
+    /** Write data to the LCD controller
+     *
+     * @param dat data written to LCD controller
+     *
+     */
+    void wr_dat(unsigned char value);
+
+    /** Write a command the LCD controller
+      *
+      * @param cmd: command to be written
+      *
+      */
+    void wr_cmd(unsigned char value);
+
+    void wr_cnt(unsigned char cmd);
+
+    unsigned int orientation;
+    unsigned int char_x;
+    unsigned int char_y;
+    unsigned char buffer[512];
+    unsigned int contrast;
+    unsigned int auto_up;
+
+};
+
+
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libraries/C12832/GraphicsDisplay.cpp	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,177 @@
+/* mbed GraphicsDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+ 
+#include "GraphicsDisplay.h"
+
+const unsigned char FONT8x8[97][8] = {
+0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, // columns, rows, num_bytes_per_char
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // space 0x20
+0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00, // !
+0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, // "
+0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // #
+0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00, // $
+0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00, // %
+0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00, // &
+0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00, // '
+0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00, // (
+0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00, // )
+0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // *
+0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, // +
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30, // ,
+0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, // -
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00, // .
+0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00, // / (forward slash)
+0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00, // 0 0x30
+0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00, // 1
+0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00, // 2
+0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00, // 3
+0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00, // 4
+0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00, // 5
+0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00, // 6
+0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00, // 7
+0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00, // 8
+0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00, // 9
+0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00, // :
+0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30, // ;
+0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00, // <
+0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00, // =
+0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00, // >
+0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00, // ?
+0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00, // @ 0x40
+0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00, // A
+0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00, // B
+0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00, // C
+0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00, // D
+0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00, // E
+0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00, // F
+0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00, // G
+0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00, // H
+0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // I
+0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // J
+0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00, // K
+0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00, // L
+0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00, // M
+0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00, // N
+0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00, // O
+0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00, // P 0x50
+0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00, // Q
+0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00, // R
+0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00, // S
+0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00, // T
+0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00, // U
+0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00, // V
+0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00, // W
+0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00, // X
+0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00, // Y
+0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00, // Z
+0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, // [
+0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00, // \ (back slash)
+0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, // ]
+0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00, // ^
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, // _
+0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00, // ` 0x60
+0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00, // a
+0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00, // b
+0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00, // c
+0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00, // d
+0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00, // e
+0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00, // f
+0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C, // g
+0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00, // h
+0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00, // i
+0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C, // j
+0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00, // k
+0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // l
+0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00, // m
+0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00, // n
+0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00, // o
+0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78, // p
+0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F, // q
+0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00, // r
+0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00, // s
+0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00, // t
+0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00, // u
+0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00, // v
+0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00, // w
+0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00, // x
+0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C, // y
+0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00, // z
+0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00, // {
+0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00, // |
+0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00, // }
+0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00, // ~
+0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00}; // DEL
+    
+GraphicsDisplay::GraphicsDisplay(const char *name):TextDisplay(name) {
+    foreground(0xFFFF);
+    background(0x0000);
+}
+    
+void GraphicsDisplay::character(int column, int row, int value) { 
+    blitbit(column * 8, row * 8, 8, 8, (char*)&(FONT8x8[value - 0x1F][0]));
+}
+
+void GraphicsDisplay::window(int x, int y, int w, int h) {
+    // current pixel location
+    _x = x;
+    _y = y;
+    // window settings
+    _x1 = x;
+    _x2 = x + w - 1;
+    _y1 = y;
+    _y2 = y + h - 1;
+}
+    
+void GraphicsDisplay::putp(int colour) {
+    // put pixel at current pixel location
+    pixel(_x, _y, colour);
+    // update pixel location based on window settings
+    _x++;
+    if(_x > _x2) {
+        _x = _x1;
+        _y++;
+        if(_y > _y2) {
+            _y = _y1;
+        }
+    }
+}
+
+void GraphicsDisplay::fill(int x, int y, int w, int h, int colour) { 
+    window(x, y, w, h);
+    for(int i=0; i<w*h; i++) {
+        putp(colour);
+    }
+}
+    
+void GraphicsDisplay::cls() {
+    fill(0, 0, width(), height(), _background);
+}
+    
+void GraphicsDisplay::blit(int x, int y, int w, int h, const int *colour) { 
+    window(x, y, w, h);
+    for(int i=0; i<w*h; i++) {
+        putp(colour[i]);
+    }
+}
+    
+void GraphicsDisplay::blitbit(int x, int y, int w, int h, const char* colour) {
+    window(x, y, w, h);
+    for(int i = 0; i < w*h; i++) {
+        char byte = colour[i >> 3];
+        int offset = i & 0x7;
+        int c = ((byte << offset) & 0x80) ? _foreground : _background;
+        putp(c);
+    }
+}
+    
+int GraphicsDisplay::columns() { 
+    return width() / 8; 
+}
+
+int GraphicsDisplay::rows() { 
+    return height() / 8; 
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libraries/C12832/GraphicsDisplay.h	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,56 @@
+/* mbed GraphicsDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * A library for providing a common base class for Graphics displays
+ * To port a new display, derive from this class and implement
+ * the constructor (setup the display), pixel (put a pixel
+ * at a location), width and height functions. Everything else
+ * (locate, printf, putc, cls, window, putp, fill, blit, blitbit) 
+ * will come for free. You can also provide a specialised implementation
+ * of window and putp to speed up the results
+ */
+
+#ifndef MBED_GRAPHICSDISPLAY_H
+#define MBED_GRAPHICSDISPLAY_H
+
+#include "TextDisplay.h"
+
+class GraphicsDisplay : public TextDisplay {
+
+public:         
+          
+    GraphicsDisplay(const char* name);
+     
+    virtual void pixel(int x, int y, int colour) = 0;
+    virtual int width() = 0;
+    virtual int height() = 0;
+        
+    virtual void window(int x, int y, int w, int h);
+    virtual void putp(int colour);
+    
+    virtual void cls();
+    virtual void fill(int x, int y, int w, int h, int colour);
+    virtual void blit(int x, int y, int w, int h, const int *colour);    
+    virtual void blitbit(int x, int y, int w, int h, const char* colour);
+    
+    virtual void character(int column, int row, int value);
+    virtual int columns();
+    virtual int rows();
+    
+protected:
+
+    // pixel location
+    short _x;
+    short _y;
+    
+    // window location
+    short _x1;
+    short _x2;
+    short _y1;
+    short _y2;
+
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libraries/C12832/Small_7.h	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,105 @@
+#ifndef small_7
+#define small_7
+
+const unsigned char Small_7[] = {
+        19,9,9,2,                                    // Length,horz,vert,byte/vert    
+        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char  
+        0x02, 0x00, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char !
+        0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char "
+        0x06, 0x00, 0x00, 0x50, 0x00, 0xF8, 0x00, 0x50, 0x00, 0xF8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char #
+        0x06, 0x00, 0x00, 0x8C, 0x00, 0x92, 0x00, 0xFE, 0x01, 0xA2, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char $
+        0x07, 0x1E, 0x00, 0x92, 0x00, 0x5E, 0x00, 0x20, 0x00, 0xF8, 0x00, 0x94, 0x00, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char %
+        0x07, 0x00, 0x00, 0x64, 0x00, 0x9A, 0x00, 0xAA, 0x00, 0xCC, 0x00, 0x60, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char &
+        0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char '
+        0x03, 0x00, 0x00, 0x7C, 0x00, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char (
+        0x03, 0x00, 0x00, 0x83, 0x01, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char )
+        0x04, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char *
+        0x05, 0x10, 0x00, 0x10, 0x00, 0x7C, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char +
+        0x02, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ,
+        0x04, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char -
+        0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char .
+        0x04, 0x00, 0x01, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char /
+        0x05, 0x00, 0x00, 0x7C, 0x00, 0x82, 0x00, 0x82, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 0
+        0x05, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 1
+        0x05, 0x00, 0x00, 0x84, 0x00, 0xC2, 0x00, 0xA2, 0x00, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 2
+        0x05, 0x00, 0x00, 0x82, 0x00, 0x92, 0x00, 0x92, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 3
+        0x05, 0x00, 0x00, 0x38, 0x00, 0x2C, 0x00, 0x22, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 4
+        0x05, 0x00, 0x00, 0x9E, 0x00, 0x92, 0x00, 0x92, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 5
+        0x05, 0x00, 0x00, 0x7C, 0x00, 0x92, 0x00, 0x92, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 6
+        0x05, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x00, 0x32, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 7
+        0x05, 0x00, 0x00, 0x6C, 0x00, 0x92, 0x00, 0x92, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 8
+        0x05, 0x00, 0x00, 0x9C, 0x00, 0x92, 0x00, 0x92, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char 9
+        0x02, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char :
+        0x02, 0x00, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ;
+        0x05, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char <
+        0x05, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char =
+        0x05, 0x00, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char >
+        0x05, 0x00, 0x00, 0x02, 0x00, 0xB2, 0x00, 0x12, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ?
+        0x09, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x01, 0x72, 0x01, 0x4A, 0x01, 0x4A, 0x01, 0x7A, 0x01, 0x42, 0x00, 0x3C, 0x00,  // Code for char @
+        0x06, 0x00, 0x00, 0xF8, 0x00, 0x24, 0x00, 0x22, 0x00, 0x24, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char A
+        0x06, 0x00, 0x00, 0xFE, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char B
+        0x06, 0x00, 0x00, 0x7C, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char C
+        0x06, 0x00, 0x00, 0xFE, 0x00, 0x82, 0x00, 0x82, 0x00, 0xC6, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char D
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char E
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char F
+        0x06, 0x00, 0x00, 0x7C, 0x00, 0xC6, 0x00, 0x82, 0x00, 0x92, 0x00, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char G
+        0x06, 0x00, 0x00, 0xFE, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char H
+        0x02, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char I
+        0x04, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char J
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x10, 0x00, 0x2C, 0x00, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char K
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char L
+        0x08, 0x00, 0x00, 0xFE, 0x00, 0x06, 0x00, 0x18, 0x00, 0xE0, 0x00, 0x18, 0x00, 0x06, 0x00, 0xFE, 0x00, 0x00, 0x00,  // Code for char M
+        0x06, 0x00, 0x00, 0xFE, 0x00, 0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char N
+        0x06, 0x00, 0x00, 0x7C, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char O
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x12, 0x00, 0x12, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char P
+        0x07, 0x00, 0x00, 0x7C, 0x00, 0x82, 0x00, 0x82, 0x00, 0xC2, 0x00, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,  // Code for char Q
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x12, 0x00, 0x12, 0x00, 0xEC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char R
+        0x05, 0x00, 0x00, 0xCC, 0x00, 0x92, 0x00, 0x92, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char S
+        0x06, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFE, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char T
+        0x06, 0x00, 0x00, 0x7E, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char U
+        0x07, 0x00, 0x00, 0x06, 0x00, 0x3C, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char V
+        0x06, 0x00, 0x00, 0x1E, 0x00, 0xE0, 0x00, 0x3E, 0x00, 0xE0, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char W
+        0x06, 0x00, 0x00, 0x82, 0x00, 0x64, 0x00, 0x38, 0x00, 0x6C, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char X
+        0x06, 0x00, 0x00, 0x02, 0x00, 0x0C, 0x00, 0xF0, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char Y
+        0x06, 0x00, 0x00, 0x82, 0x00, 0xE2, 0x00, 0x92, 0x00, 0x8E, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char Z
+        0x03, 0x00, 0x00, 0xFF, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char [
+        0x04, 0x01, 0x00, 0x0E, 0x00, 0x70, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char BackSlash
+        0x02, 0x01, 0x01, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ]
+        0x04, 0x00, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ^
+        0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char _
+        0x03, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char `
+        0x05, 0x00, 0x00, 0xE8, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char a
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char b
+        0x05, 0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char c
+        0x05, 0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0x88, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char d
+        0x05, 0x00, 0x00, 0x70, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char e
+        0x04, 0x08, 0x00, 0xFE, 0x00, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char f
+        0x05, 0x00, 0x00, 0x30, 0x00, 0x48, 0x01, 0x48, 0x01, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char g
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char h
+        0x02, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char i
+        0x02, 0x00, 0x01, 0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char j
+        0x05, 0x00, 0x00, 0xFE, 0x00, 0x20, 0x00, 0x50, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char k
+        0x02, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char l
+        0x06, 0x00, 0x00, 0xF8, 0x00, 0x08, 0x00, 0xF8, 0x00, 0x08, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char m
+        0x05, 0x00, 0x00, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char n
+        0x05, 0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char o
+        0x05, 0x00, 0x00, 0xF8, 0x01, 0x48, 0x00, 0x48, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char p
+        0x05, 0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char q
+        0x04, 0x00, 0x00, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char r
+        0x04, 0x00, 0x00, 0x98, 0x00, 0xA8, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char s
+        0x04, 0x00, 0x00, 0x08, 0x00, 0xFC, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char t
+        0x05, 0x00, 0x00, 0x78, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char u
+        0x04, 0x00, 0x00, 0x38, 0x00, 0xC0, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char v
+        0x06, 0x00, 0x00, 0x78, 0x00, 0xC0, 0x00, 0x38, 0x00, 0xC0, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char w
+        0x05, 0x00, 0x00, 0x88, 0x00, 0x70, 0x00, 0x70, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char x
+        0x05, 0x00, 0x00, 0x38, 0x00, 0x40, 0x01, 0x40, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char y
+        0x05, 0x00, 0x00, 0xC8, 0x00, 0xE8, 0x00, 0xB8, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char z
+        0x04, 0x10, 0x00, 0x38, 0x00, 0xEF, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char {
+        0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char |
+        0x04, 0x01, 0x01, 0xC7, 0x01, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char }
+        0x05, 0x0C, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Code for char ~
+        0x03, 0xFE, 0x01, 0x02, 0x01, 0xFE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // Code for char 
+        };
+        
+#endif        
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libraries/C12832/TextDisplay.cpp	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,78 @@
+/* mbed TextDisplay Display Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+ 
+#include "TextDisplay.h"
+
+TextDisplay::TextDisplay(const char *name) : Stream(name){
+    _row = 0;
+    _column = 0;
+    if (name == NULL) {
+        _path = NULL;
+    } else {
+        _path = new char[strlen(name) + 2];
+        sprintf(_path, "/%s", name);
+    }
+}
+    
+int TextDisplay::_putc(int value) {
+    if(value == '\n') {
+        _column = 0;
+        _row++;
+        if(_row >= rows()) {
+            _row = 0;
+        }
+    } else {
+        character(_column, _row, value);
+        _column++;
+        if(_column >= columns()) {
+            _column = 0;
+            _row++;
+            if(_row >= rows()) {
+                _row = 0;
+            }
+        }
+    }
+    return value;
+}
+
+// crude cls implementation, should generally be overwritten in derived class
+void TextDisplay::cls() {
+    locate(0, 0);
+    for(int i=0; i<columns()*rows(); i++) {
+        putc(' ');
+    }
+}
+
+void TextDisplay::locate(int column, int row) {
+    _column = column;
+    _row = row;
+}
+
+int TextDisplay::_getc() {
+    return -1;
+}
+        
+void TextDisplay::foreground(uint16_t colour) {
+    _foreground = colour;
+}
+
+void TextDisplay::background(uint16_t colour) {
+    _background = colour;
+}
+
+bool TextDisplay::claim (FILE *stream) {
+    if ( _path == NULL) {
+        fprintf(stderr, "claim requires a name to be given in the instantioator of the TextDisplay instance!\r\n");
+        return false;
+    }
+    if (freopen(_path, "w", stream) == NULL) {
+        // Failed, should not happen
+        return false;
+    }
+    // make sure we use line buffering
+    setvbuf(stdout, NULL, _IOLBF, columns());
+    return true;
+} 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libraries/C12832/TextDisplay.h	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,81 @@
+/* mbed TextDisplay Library Base Class
+ * Copyright (c) 2007-2009 sford
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ * A common base class for Text displays
+ * To port a new display, derive from this class and implement
+ * the constructor (setup the display), character (put a character
+ * at a location), rows and columns (number of rows/cols) functions.
+ * Everything else (locate, printf, putc, cls) will come for free
+ *
+ * The model is the display will wrap at the right and bottom, so you can
+ * keep writing and will always get valid characters. The location is 
+ * maintained internally to the class to make this easy
+ */
+
+#ifndef MBED_TEXTDISPLAY_H
+#define MBED_TEXTDISPLAY_H
+
+#include "mbed.h"
+
+class TextDisplay : public Stream {
+public:
+
+  // functions needing implementation in derived implementation class
+  /** Create a TextDisplay interface
+     *
+     * @param name The name used in the path to access the strean through the filesystem
+     */
+    TextDisplay(const char *name = NULL);
+
+    /** output a character at the given position
+     *
+     * @param column column where charater must be written
+     * @param  row where character must be written
+     * @param c the character to be written to the TextDisplay
+     */
+    virtual void character(int column, int row, int c) = 0;
+
+    /** return number if rows on TextDisplay
+     * @result number of rows
+     */
+    virtual int rows() = 0;
+
+    /** return number if columns on TextDisplay
+    * @result number of rows
+    */
+    virtual int columns() = 0;
+    
+    // functions that come for free, but can be overwritten
+
+    /** redirect output from a stream (stoud, sterr) to  display
+    * @param stream stream that shall be redirected to the TextDisplay
+    */
+    virtual bool claim (FILE *stream);
+
+    /** clear screen
+    */
+    virtual void cls();
+    virtual void locate(int column, int row);
+    virtual void foreground(uint16_t colour);
+    virtual void background(uint16_t colour);
+    // putc (from Stream)
+    // printf (from Stream)
+    
+protected:
+
+    virtual int _putc(int value);
+    virtual int _getc();
+
+    // character location
+    uint16_t _column;
+    uint16_t _row;
+
+    // colours
+    uint16_t _foreground;
+    uint16_t _background;
+    char *_path;
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libxDot-dev-mbed5.lib	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/teams/MultiTech/code/libxDot-dev-mbed5/#8c938c4e4b6a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,2 @@
+https://github.com/ARMmbed/mbed-os/#6e0d01cd13e8aca7bf4d697c3699ec9225386881
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.sh	Tue Nov 07 11:18:57 2017 +0000
@@ -0,0 +1,4 @@
+if [ ! -d ISL29011 ]; then
+    hg clone https://developer.mbed.org/teams/Multi-Hackers/code/ISL29011/
+fi
+