diff --git a/.gitignore b/.gitignore
index 04d47c56d6b887c18d9c38c1dd029ecbb1e9c277..007d64268841d3fb3282a82e2376522174a3d543 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ local.properties
 .idea
 bugfender.properties
 /app/app.iml
+gradle.properties
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index bc39a1084d08f077d7b3212257ff6b73dbe50000..027d93daafacb3fecbcc0d36f3fc6073a5eeb215 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -27,7 +27,7 @@ apply plugin: 'realm-android'
 def gitVersion() {
     // current dir is <your proj>/app, so it's likely that all your git repo files are in the dir
     // above.
-    ext.repo = Grgit.open(project.file('..'))
+    ext.repo = Grgit.open()
 
     // should result in the same value as running
     // git tag -l | wc -l or git tag -l | grep -c ".*" -
@@ -36,14 +36,15 @@ def gitVersion() {
 }
 
 def gitCommitId() {
-    //def process = ['sh', '-c', 'git tag -l | grep -c ".*" -'].execute().text.trim()
-    //return process.toInteger() + 1
-    //return 42
-    // current dir is <your proj>/app, so it's likely that all your git repo files are in the dir
-    // above.
-    ext.repo = Grgit.open(project.file('..'))
+    ext.repo = Grgit.open()
+
+    return ext.repo.log().first().id.substring(0, 7) //+ " " + ext.repo.branch.current.name
+}
+
 
-    return ext.repo.log().first().id.substring(0, 7)
+def gitBranch() {
+    ext.repo = Grgit.open()
+    return ext.repo.branch.current.name
 }
 
 def getBugfenderApiKey() {
@@ -66,7 +67,7 @@ android {
         applicationId "info.nightscout.android"
         minSdkVersion 14
         targetSdkVersion 23
-        versionName project.properties['version'] + "/" + gitCommitId()
+        versionName project.properties['version'] + "/" + gitCommitId() // + " (" + gitBranch()+")"
         versionCode gitVersion()
         buildConfigField "String", "BUGFENDER_API_KEY", getBugfenderApiKey()
     }
@@ -154,8 +155,7 @@ dependencies {
     compile 'com.mikepenz:google-material-typeface:2.2.0.1.original@aar'
     compile 'uk.co.chrisjenx:calligraphy:2.2.0'
     compile 'com.bugfender.sdk:android:0.6.2'
-    compile 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar'
-    compile 'com.github.PhilJay:MPAndroidChart:v3.0.1'
+    compile 'com.jjoe64:graphview:4.2.1'
     compile 'com.android.support:support-v4:23.4.0'
     compile 'com.google.code.gson:gson:2.7'
     compile 'com.squareup.retrofit2:retrofit:2.1.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 17456ec980eb0686f523c15b44c12a3d4973e906..4f075c37ba2f7387d322e3ed95c22c04eb2b6368 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -80,11 +80,7 @@
 
         <receiver android:name=".medtronic.service.MedtronicCnlAlarmReceiver" />
         <receiver android:name=".upload.nightscout.NightscoutUploadReceiver" />
-        <receiver android:name=".xdrip_plus.XDripPlusUploadReceiver" /><!-- ATTENTION: This was auto-generated to add Google Play services to your project for
-     App Indexing.  See https://g.co/AppIndexing/AndroidStudio for more information. -->
-        <meta-data
-            android:name="com.google.android.gms.version"
-            android:value="@integer/google_play_services_version" />
+        <receiver android:name=".xdrip_plus.XDripPlusUploadReceiver" />
 
     </application>
 
diff --git a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
index a16375d180e4bc9f250490bb4425cce173ee0ed2..681f50ee06f600d809b4b987fb57f55366ffcebc 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
@@ -12,6 +12,7 @@ import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Paint;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbManager;
 import android.net.Uri;
@@ -34,28 +35,19 @@ import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.MotionEvent;
 import android.view.View;
 import android.widget.TextView;
 import android.widget.TextView.BufferType;
-
-import com.github.mikephil.charting.charts.ScatterChart;
-import com.github.mikephil.charting.components.AxisBase;
-import com.github.mikephil.charting.components.XAxis;
-import com.github.mikephil.charting.components.YAxis;
-import com.github.mikephil.charting.data.Entry;
-import com.github.mikephil.charting.data.ScatterData;
-import com.github.mikephil.charting.data.ScatterDataSet;
-import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet;
-import com.github.mikephil.charting.formatter.IAxisValueFormatter;
-import com.github.mikephil.charting.formatter.IValueFormatter;
-import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet;
-import com.github.mikephil.charting.listener.ChartTouchListener;
-import com.github.mikephil.charting.listener.OnChartGestureListener;
-import com.github.mikephil.charting.renderer.ScatterChartRenderer;
-import com.github.mikephil.charting.renderer.scatter.IShapeRenderer;
-import com.github.mikephil.charting.utils.Transformer;
-import com.github.mikephil.charting.utils.ViewPortHandler;
+import android.widget.Toast;
+
+import com.jjoe64.graphview.DefaultLabelFormatter;
+import com.jjoe64.graphview.GraphView;
+import com.jjoe64.graphview.Viewport;
+import com.jjoe64.graphview.series.DataPoint;
+import com.jjoe64.graphview.series.DataPointInterface;
+import com.jjoe64.graphview.series.OnDataPointTapListener;
+import com.jjoe64.graphview.series.PointsGraphSeries;
+import com.jjoe64.graphview.series.Series;
 import com.mikepenz.google_material_typeface_library.GoogleMaterial;
 import com.mikepenz.materialdrawer.AccountHeaderBuilder;
 import com.mikepenz.materialdrawer.Drawer;
@@ -65,9 +57,8 @@ import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
 
 import java.text.DateFormat;
 import java.text.DecimalFormat;
-import java.util.ArrayList;
+import java.text.NumberFormat;
 import java.util.Date;
-import java.util.List;
 import java.util.Locale;
 import java.util.Queue;
 import java.util.concurrent.ArrayBlockingQueue;
@@ -83,7 +74,6 @@ import info.nightscout.android.model.medtronicNg.PumpInfo;
 import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
 import info.nightscout.android.settings.SettingsActivity;
 import info.nightscout.android.upload.nightscout.NightscoutUploadIntentService;
-import io.realm.DynamicRealmObject;
 import io.realm.Realm;
 import io.realm.RealmChangeListener;
 import io.realm.RealmResults;
@@ -92,6 +82,7 @@ import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
 
 public class MainActivity extends AppCompatActivity implements OnSharedPreferenceChangeListener, OnEulaAgreedTo {
     private static final String TAG = MainActivity.class.getSimpleName();
+    public static final float MMOLXLFACTOR = 18.016f;
 
     public static int batLevel = 0;
     public static boolean reducePollOnPumpAway = false;
@@ -99,12 +90,18 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
     public static long lowBatteryPollInterval = MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS;
 
     private static long activePumpMac;
+    private int chartZoom = 3;
+    private boolean hasZoomedChart = false;
+
+    private NumberFormat sgvFormatter;
+    private boolean mmolxl;
+    private boolean mmolxlDecimals;
 
     boolean mEnableCgmService = true;
     SharedPreferences prefs = null;
     private PumpInfo mActivePump;
     private TextView mTextViewLog; // This will eventually move to a status page.
-    private ScatterChart mChart;
+    private GraphView mChart;
     private Intent mNightscoutUploadService;
     private Handler mUiRefreshHandler = new Handler();
     private Runnable mUiRefreshRunnable = new RefreshDisplayRunnable();
@@ -112,17 +109,31 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
     private StatusMessageReceiver statusMessageReceiver = new StatusMessageReceiver();
     private MedtronicCnlAlarmReceiver medtronicCnlAlarmReceiver = new MedtronicCnlAlarmReceiver();
 
+    /**
+     * calculate the next poll timestamp based on last svg event
+     *
+     * @param pumpStatusData
+     * @return timestamp
+     */
     public static long getNextPoll(PumpStatusEvent pumpStatusData) {
-        long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset()
-                + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS;
+        long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset(),
+            now = System.currentTimeMillis();
 
-        if (pumpStatusData.getBatteryPercentage() > 25) {
-            // poll every 5 min
-            nextPoll += MainActivity.pollInterval;
+        // align to next poll slot
+        if (nextPoll + 2 * 60 * 60 * 1000 < now) { // last event more than 2h old -> could be a calibration
+            nextPoll = System.currentTimeMillis() + 1000;
         } else {
-            // if pump battery seems to be empty reduce polling to save battery (every 15 min)
-            //TODO add message & document it
-            nextPoll += MainActivity.lowBatteryPollInterval;
+            // align to poll interval
+            nextPoll += (((now - nextPoll) / MainActivity.pollInterval)) * MainActivity.pollInterval
+                    + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS;
+            if (pumpStatusData.getBatteryPercentage() > 25) {
+                // poll every 5 min
+                nextPoll += MainActivity.pollInterval;
+            } else {
+                // if pump battery seems to be empty reduce polling to save battery (every 15 min)
+                //TODO add message & document it
+                nextPoll += MainActivity.lowBatteryPollInterval;
+            }
         }
 
         return nextPoll;
@@ -149,6 +160,18 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         MainActivity.pollInterval = Long.parseLong(prefs.getString("pollInterval", Long.toString(MedtronicCnlIntentService.POLL_PERIOD_MS)));
         MainActivity.lowBatteryPollInterval = Long.parseLong(prefs.getString("lowBatPollInterval", Long.toString(MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS)));
         MainActivity.reducePollOnPumpAway = prefs.getBoolean("doublePollOnPumpAway", false);
+        chartZoom = Integer.parseInt(prefs.getString("chartZoom", "3"));
+        mmolxl = prefs.getBoolean("mmolxl", false);
+        mmolxlDecimals = prefs.getBoolean("mmolDecimals", false);
+
+        if (mmolxl) {
+            if (mmolxlDecimals)
+                sgvFormatter = new DecimalFormat("0.00");
+            else
+                sgvFormatter = new DecimalFormat("0.0");
+        } else {
+            sgvFormatter = new DecimalFormat("0");
+        }
 
         // Disable battery optimization to avoid missing values on 6.0+
         // taken from https://github.com/NightscoutFoundation/xDrip/blob/master/app/src/main/java/com/eveningoutpost/dexdrip/Home.java#L277L298
@@ -260,7 +283,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                             stopCgmService();
                             finish();
                         } else if (drawerItem.equals(itemGetNow)) {
-                            startCgmService();
+                            // It was triggered by user so start reading of data now and not based on last poll.
+                            startCgmService(0);
                         } else if (drawerItem.equals(itemClearLog)) {
                             clearLogText();
                         }
@@ -271,118 +295,57 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                 .build();
 
         mTextViewLog = (TextView) findViewById(R.id.textview_log);
-        mChart = (ScatterChart) findViewById(R.id.chart);
-
-        mChart.setDescription(null);    // Hide the description
 
-        mChart.setTouchEnabled(true);
-        mChart.setPinchZoom(true);
-        mChart.setHighlightPerDragEnabled(false);
-        mChart.setHighlightPerTapEnabled(false);
-        mChart.setOnChartGestureListener(new OnChartGestureListener() {
+        mChart = (GraphView) findViewById(R.id.chart);
 
-            @Override
-            public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
+        // disable scrolling at the moment
+        mChart.getViewport().setScalable(false);
+        mChart.getViewport().setScrollable(false);
+        mChart.getViewport().setXAxisBoundsManual(true);
+        final long now = System.currentTimeMillis(),
+                left = now - chartZoom * 60 * 60 * 1000;
 
-            @Override
-            public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
+        mChart.getViewport().setMaxX(now);
+        mChart.getViewport().setMinX(left);
 
+        mChart.getViewport().setOnXAxisBoundsChangedListener(new Viewport.OnXAxisBoundsChangedListener() {
             @Override
-            public void onChartLongPressed(MotionEvent me) {
-                mChart.fitScreen();
+            public void onXAxisBoundsChanged(double minX, double maxX, Reason reason) {
+                double rightX = mChart.getSeries().get(0).getHighestValueX();
+                hasZoomedChart = (rightX != maxX || rightX - chartZoom * 60 * 60 * 1000 != minX);
             }
-
-            @Override
-            public void onChartDoubleTapped(MotionEvent me) {}
-
-            @Override
-            public void onChartSingleTapped(MotionEvent me) {}
-
-            @Override
-            public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {}
-
-            @Override
-            public void onChartScale(MotionEvent me, float scaleX, float scaleY) {}
-
-            @Override
-            public void onChartTranslate(MotionEvent me, float dX, float dY) {}
         });
 
-        XAxis xAxis = mChart.getXAxis();
-        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
-        xAxis.setTextSize(10f);
-        xAxis.setTextColor(Color.WHITE);
-        xAxis.setDrawAxisLine(true);
-        xAxis.setDrawGridLines(true);
-        xAxis.setDrawLabels(true);
-        xAxis.setValueFormatter(new IAxisValueFormatter() {
-            private DateFormat mFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
-
+        mChart.setOnLongClickListener(new View.OnLongClickListener() {
             @Override
-            public String getFormattedValue(float value, AxisBase axis) {
-                return mFormat.format(new Date((long) value));
+            public boolean onLongClick(View v) {
+                if (!mChart.getSeries().isEmpty() && !mChart.getSeries().get(0).isEmpty()) {
+                    double rightX = mChart.getSeries().get(0).getHighestValueX();
+                    mChart.getViewport().setMaxX(rightX);
+                    mChart.getViewport().setMinX(rightX - chartZoom * 60 * 60 * 1000);
+                }
+                hasZoomedChart = false;
+                return true;
             }
         });
+        mChart.getGridLabelRenderer().setNumHorizontalLabels(6);
+        mChart.getGridLabelRenderer().setHumanRounding(false);
 
-        // left axis
-        mChart.getAxisLeft().setDrawLabels(false);
-
-        // right axis
-        YAxis yAxis = mChart.getAxisRight();
-        yAxis.setTextSize(10f);
-        yAxis.setTextColor(Color.WHITE);
-
-        mChart.getLegend().setEnabled(false);   // Hide the legend
-
-        // TODO: remove if if "coloring bug" in MPAndroidChart is fixed
-        // see: https://github.com/PhilJay/MPAndroidChart/issues/2682
-        mChart.setRenderer(new ScatterChartRenderer(mChart, mChart.getAnimator(), mChart.getViewPortHandler()) {
-
-            float[] mPixelBuffer = new float[2];
-
+        mChart.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() {
+            DateFormat mFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
             @Override
-            protected void drawDataSet(Canvas c, IScatterDataSet dataSet) {
-
-                ViewPortHandler viewPortHandler = mViewPortHandler;
-
-                Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
-
-                float phaseY = mAnimator.getPhaseY();
-
-                IShapeRenderer renderer = dataSet.getShapeRenderer();
-                if (renderer == null) {
-                    Log.i("MISSING", "There's no IShapeRenderer specified for ScatterDataSet");
-                    return;
-                }
-
-                int max = (int)(Math.min(
-                        Math.ceil((float)dataSet.getEntryCount() * mAnimator.getPhaseX()),
-                        (float)dataSet.getEntryCount()));
-
-                for (int i = 0; i < max; i++) {
-
-                    Entry e = dataSet.getEntryForIndex(i);
-
-                    mPixelBuffer[0] = e.getX();
-                    mPixelBuffer[1] = e.getY() * phaseY;
-
-                    trans.pointValuesToPixel(mPixelBuffer);
-
-                    if (!viewPortHandler.isInBoundsRight(mPixelBuffer[0]))
-                        break;
-
-                    if (!viewPortHandler.isInBoundsLeft(mPixelBuffer[0])
-                            || !viewPortHandler.isInBoundsY(mPixelBuffer[1]))
-                        continue;
-
-                    mRenderPaint.setColor(dataSet.getColor(i));
-                    renderer.renderShape(
-                            c, dataSet, mViewPortHandler,
-                            mPixelBuffer[0], mPixelBuffer[1],
-                            mRenderPaint);
+            public String formatLabel(double value, boolean isValueX) {
+                if (isValueX) {
+                    return mFormat.format(new Date((long) value));
+                } else {
+                    if (mmolxl) {
+                        return sgvFormatter.format(value / MMOLXLFACTOR);
+                    } else {
+                        return sgvFormatter.format(value);
+                    }
                 }
-            }
-        });
+            }}
+        );
     }
 
     @Override
@@ -462,7 +425,18 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
     }
 
     private void startCgmService() {
-        startCgmService(System.currentTimeMillis() + 1000);
+        startCgmServiceDelayed(0);
+    }
+
+    private void startCgmServiceDelayed(long delay) {
+        RealmResults<PumpStatusEvent> results = mRealm.where(PumpStatusEvent.class)
+                .findAllSorted("eventDate", Sort.DESCENDING);
+
+        if (results.size() > 0) {
+            startCgmService(getNextPoll(results.first()) + delay);
+        } else {
+            startCgmService(System.currentTimeMillis() + (delay==0?1000:delay));
+        }
     }
 
     private void startCgmService(long initialPoll) {
@@ -543,7 +517,17 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                 mEnableCgmService = true;
                 startCgmService();
             }
-        } else if (key.equals("mmolxl")) {
+        } else if (key.equals("mmolxl") || key.equals("mmolDecimals")) {
+            mmolxl = sharedPreferences.getBoolean("mmolxl", false);
+            mmolxlDecimals = sharedPreferences.getBoolean("mmolDecimals", false);
+            if (mmolxl) {
+                if (mmolxlDecimals)
+                    sgvFormatter = new DecimalFormat("0.00");
+                else
+                    sgvFormatter = new DecimalFormat("0.0");
+            } else {
+                sgvFormatter = new DecimalFormat("0");
+            }
             refreshDisplay();
         } else if (key.equals("pollInterval")) {
             MainActivity.pollInterval = Long.parseLong(sharedPreferences.getString("pollInterval",
@@ -553,6 +537,10 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
                     Long.toString(MedtronicCnlIntentService.LOW_BATTERY_POLL_PERIOD_MS)));
         } else if (key.equals("doublePollOnPumpAway")) {
             MainActivity.reducePollOnPumpAway = sharedPreferences.getBoolean("doublePollOnPumpAway", false);
+        } else if (key.equals("chartZoom")) {
+            chartZoom = Integer.parseInt(sharedPreferences.getString("chartZoom", "3"));
+            hasZoomedChart = false;
+            refreshDisplay();
         }
     }
 
@@ -737,7 +725,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
             TextView textViewBg = (TextView) findViewById(R.id.textview_bg);
             TextView textViewBgTime = (TextView) findViewById(R.id.textview_bg_time);
             TextView textViewUnits = (TextView) findViewById(R.id.textview_units);
-            if (prefs.getBoolean("mmolxl", false)) {
+            if (mmolxl) {
                 textViewUnits.setText(R.string.text_unit_mmolxl);
             } else {
                 textViewUnits.setText(R.string.text_unit_mgxdl);
@@ -763,27 +751,17 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
 
             if (pumpStatusData != null) {
 
-                String sgvString, units;
-                if (prefs.getBoolean("mmolxl", false)) {
-                    DecimalFormat df;
-                    if (prefs.getBoolean("mmolDecimals", false))
-                        df = new DecimalFormat("0.00");
-                    else
-                        df = new DecimalFormat("0.0");
-
+                String sgvString;
+                if (mmolxl) {
                     float fBgValue = (float) pumpStatusData.getSgv();
-                    sgvString = df.format(fBgValue / 18.016f);
-                    units = "mmol/L";
+                    sgvString = sgvFormatter.format(fBgValue / MMOLXLFACTOR);
                     Log.d(TAG, sgvString + " mmol/L");
-
                 } else {
                     sgvString = String.valueOf(pumpStatusData.getSgv());
-                    units = "mg/dL";
                     Log.d(TAG, sgvString + " mg/dL");
                 }
 
                 textViewBg.setText(sgvString);
-                textViewUnits.setText(units);
                 textViewBgTime.setText(DateUtils.getRelativeTimeSpanString(pumpStatusData.getEventDate().getTime()));
                 textViewTrend.setText(Html.fromHtml(renderTrendHtml(pumpStatusData.getCgmTrend())));
                 textViewIOB.setText(String.format(Locale.getDefault(), "%.2f", pumpStatusData.getActiveInsulin()));
@@ -825,77 +803,102 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
 
         private void updateChart(RealmResults<PumpStatusEvent> results) {
             int size = results.size();
-            if (size == 0) return;
+            if (size == 0) {
+                final long now = System.currentTimeMillis(),
+                        left = now - chartZoom * 60 * 60 * 1000;
+
+                mChart.getViewport().setXAxisBoundsManual(true);
+                mChart.getViewport().setMaxX(now);
+                mChart.getViewport().setMinX(left);
+
+                mChart.getViewport().setYAxisBoundsManual(true);
+                if (mmolxl) {
+                    mChart.getViewport().setMinY(80 / MMOLXLFACTOR);
+                    mChart.getViewport().setMaxY(120 / MMOLXLFACTOR);
+                } else {
+                    mChart.getViewport().setMinY(80);
+                    mChart.getViewport().setMaxY(120);
+                }
+                mChart.postInvalidate();
+                return;
+            }
 
-            List<Entry> entries = new ArrayList<Entry>(size);
-            int[] colors = new int[size];  // getColor is called with (i/2)
+            DataPoint[] entries = new DataPoint[size];
+            final long left = System.currentTimeMillis() - chartZoom * 60 * 60 * 1000;
 
+            int pos = 0;
             for (PumpStatusEvent pumpStatus: results) {
                 // turn your data into Entry objects
-                int sgv = pumpStatus.getSgv(),
-                    pos = entries.size();
-
-                entries.add(new Entry(pumpStatus.getEventDate().getTime(), pumpStatus.getSgv()));
-                //TODO: need to be configurable
-                if (sgv < 80)
-                    colors[pos] = Color.RED;
-                else if (sgv <= 180)
-                    colors[pos] = Color.GREEN;
-                else if (sgv <= 260)
-                    colors[pos] = Color.YELLOW;
-                else
-                    colors[pos] = Color.RED;
+                int sgv = pumpStatus.getSgv();
+
+                if (mmolxl) {
+                    entries[pos++] = new DataPoint(pumpStatus.getEventDate(), pumpStatus.getSgv() / MMOLXLFACTOR);
+                } else {
+                    entries[pos++] = new DataPoint(pumpStatus.getEventDate(), pumpStatus.getSgv());
+                }
             }
 
-            if (mChart.getData() == null) {
-                mChart.setMinimumHeight(200);
-                ScatterDataSet dataSet = new ScatterDataSet(entries, null);
+            if (mChart.getSeries().size() == 0) {
+//                long now = System.currentTimeMillis();
+//                entries = new DataPoint[1000];
+//                int j = 0;
+//                for(long i = now - 24*60*60*1000; i < now - 30*60*1000; i+= 5*60*1000) {
+//                    entries[j++] = new DataPoint(i, (float) (Math.random()*200 + 89));
+//                }
+//                entries = Arrays.copyOfRange(entries, 0, j);
 
-                dataSet.setColors(colors); // disabled tue to a bug(??) in MPAndroid Chart
-                //dataSet.setColor(Color.LTGRAY);
-                dataSet.setValueTextColor(Color.WHITE);
-                dataSet.setScatterShape(ScatterChart.ScatterShape.CIRCLE);
-                dataSet.setScatterShapeSize(7.2f);
-                dataSet.setValueFormatter(new IValueFormatter() {
-                    @Override
-                    public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
-                        DecimalFormat df;
+                PointsGraphSeries sgvSerie = new PointsGraphSeries(entries);
+//                sgvSerie.setSize(3.6f);
+//                sgvSerie.setColor(Color.LTGRAY);
+
+
+                sgvSerie.setOnDataPointTapListener(new OnDataPointTapListener() {
+                    DateFormat mFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM);
 
-                        if (prefs.getBoolean("mmolxl", false)) {
-                            if (prefs.getBoolean("mmolDecimals", false))
-                                df = new DecimalFormat("0.00");
-                            else
-                                df = new DecimalFormat("0.0");
+                    @Override
+                    public void onTap(Series series, DataPointInterface dataPoint) {
+                        double sgv = dataPoint.getY();
 
-                            return df.format(value / 18.016f);
+                        StringBuilder sb = new StringBuilder(mFormat.format(new Date((long) dataPoint.getX())) + ": ");
+                        if (mmolxl) {
+                            sb.append(sgvFormatter.format(sgv / MMOLXLFACTOR));
                         } else {
-                            return new DecimalFormat("0").format(value);
+                            sb.append(sgvFormatter.format(sgv));
                         }
+                        Toast.makeText(getBaseContext(), sb.toString(), Toast.LENGTH_SHORT).show();
                     }
                 });
 
-                ArrayList<IScatterDataSet> dataSets = new ArrayList<IScatterDataSet>();
-                dataSets.add(dataSet);
+                sgvSerie.setCustomShape(new PointsGraphSeries.CustomShape() {
+                    @Override
+                    public void draw(Canvas canvas, Paint paint, float x, float y, DataPointInterface dataPoint) {
+                        double sgv = dataPoint.getY();
+                        if (sgv < 80)
+                            paint.setColor(Color.RED);
+                        else if (sgv <= 180)
+                            paint.setColor(Color.GREEN);
+                        else if (sgv <= 260)
+                            paint.setColor(Color.YELLOW);
+                        else
+                            paint.setColor(Color.RED);
+                        canvas.drawCircle(x, y, 3.6f, paint);
+                    }
+                });
 
-                ScatterData lineData = new ScatterData(dataSets);
-                mChart.setData(lineData);
+                mChart.getViewport().setYAxisBoundsManual(false);
+                mChart.addSeries(sgvSerie);
             } else {
-                ((ScatterDataSet)mChart.getScatterData().getDataSets().get(0)).setValues(entries);
-                ((ScatterDataSet)mChart.getScatterData().getDataSets().get(0)).setColors(colors); // disabled tue to a bug(??) in MPAndroid Chart
+                if (entries.length > 0) {
+                    ((PointsGraphSeries) mChart.getSeries().get(0)).resetData(entries);
+                }
             }
 
-            //TODO: make the display timespan configurable
-            //long now = System.currentTimeMillis();
-
-            //Log.d(TAG, "Graph limits: " + (new Date(now - 24 * 60 * 60 * 1000) + " - " + (new Date(now))));
-            //mChart.setVisibleXRangeMaximum(12);
-            //mChart.setVisibleXRangeMinimum(0);
-            //mChart.getXAxis().setAxisMaximum((now + 0*60*1000));
-            //mChart.getXAxis().setAxisMinimum(now - 35 * 60 * 1000);
-
-            //mChart.moveViewToX(now - 35*60*1000); // - 24 * 60 * 60 * 1000);
-            //mChart.invalidate();
-            mChart.postInvalidate();
+            // set vieport to latest SGV
+            long lastSGVTimestamp = (long) mChart.getSeries().get(0).getHighestValueX();
+            if (!hasZoomedChart) {
+                mChart.getViewport().setMaxX(lastSGVTimestamp);
+                mChart.getViewport().setMinX(lastSGVTimestamp - chartZoom * 60 * 60 * 1000);
+            }
         }
     }
 
@@ -934,7 +937,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
 
                 if (hasUsbPermission()) {
                     // Give the USB a little time to warm up first
-                    startCgmService(System.currentTimeMillis() + MedtronicCnlIntentService.USB_WARMUP_TIME_MS);
+                    startCgmServiceDelayed(MedtronicCnlIntentService.USB_WARMUP_TIME_MS);
                 } else {
                     Log.d(TAG, "No permission for USB. Waiting.");
                     waitForUsbPermission();
@@ -964,31 +967,4 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
         }
     }
 
-    private class PumsStatusDataSet extends RealmScatterDataSet<PumpStatusEvent> {
-
-        public PumsStatusDataSet(RealmResults<PumpStatusEvent> result, String yValuesField) {
-            super(result, yValuesField);
-        }
-
-        public PumsStatusDataSet(RealmResults<PumpStatusEvent> result, String xValuesField, String yValuesField) {
-            super(result, xValuesField, yValuesField);
-        }
-
-        public Entry buildEntryFromResultObject(PumpStatusEvent realmObject, float x) {
-            DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject);
-            float xFloat, yFloat;
-
-            if (mXValuesField == null) {
-                xFloat = x;
-            } else {
-                xFloat = dynamicObject.getDate(mXValuesField).getTime();
-            }
-            yFloat = dynamicObject.getInt(mYValuesField);
-
-            return new Entry(mXValuesField == null ? x : xFloat, yFloat);
-        }
-
-    }
-
-
 }
diff --git a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java
index bc4212726eac58819188576a30749516d2ab1ad6..23fdd5dcf4a4fba01066e5e9b1ac38c6792e48e1 100644
--- a/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java
+++ b/app/src/main/java/info/nightscout/android/medtronic/service/MedtronicCnlIntentService.java
@@ -21,15 +21,14 @@ import java.util.Date;
 import java.util.Locale;
 import java.util.concurrent.TimeoutException;
 
-import info.nightscout.android.BuildConfig;
 import info.nightscout.android.R;
 import info.nightscout.android.USB.UsbHidDriver;
 import info.nightscout.android.medtronic.MainActivity;
 import info.nightscout.android.medtronic.MedtronicCnlReader;
 import info.nightscout.android.medtronic.exception.ChecksumException;
 import info.nightscout.android.medtronic.exception.EncryptionException;
-import info.nightscout.android.medtronic.message.MessageUtils;
 import info.nightscout.android.medtronic.exception.UnexpectedMessageException;
+import info.nightscout.android.medtronic.message.MessageUtils;
 import info.nightscout.android.model.medtronicNg.ContourNextLinkInfo;
 import info.nightscout.android.model.medtronicNg.PumpInfo;
 import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
@@ -38,8 +37,6 @@ import info.nightscout.android.xdrip_plus.XDripPlusUploadReceiver;
 import io.realm.Realm;
 import io.realm.RealmResults;
 
-import static info.nightscout.android.medtronic.MainActivity.setActivePumpMac;
-
 public class MedtronicCnlIntentService extends IntentService {
     public final static int USB_VID = 0x1a79;
     public final static int USB_PID = 0x6210;
@@ -155,12 +152,7 @@ public class MedtronicCnlIntentService extends IntentService {
                     .findFirst();
 
             if (info == null) {
-                // TODO - use realm.createObject()?
                 info = realm.createObject(ContourNextLinkInfo.class, cnlReader.getStickSerial());
-                //info = new ContourNextLinkInfo();
-                ///info.setSerialNumber(cnlReader.getStickSerial());
-
-                //info = realm.copyToRealm(info);
             }
 
             cnlReader.getPumpSession().setStickSerial(info.getSerialNumber());
@@ -204,7 +196,7 @@ public class MedtronicCnlIntentService extends IntentService {
 
                     // reduce polling interval to half until pump is available
                     MedtronicCnlAlarmManager.setAlarm(activePump.getLastQueryTS() +
-                            (MainActivity.pollInterval  + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS) / (MainActivity.reducePollOnPumpAway?2L:1L)
+                            (MainActivity.pollInterval / (MainActivity.reducePollOnPumpAway?2L:1L))
                     );
                 } else {
                     setActivePumpMac(pumpMAC);
diff --git a/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java b/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
index 60ad396bfba9043268d5e65486dee173f711d6ee..cfe52c2cf6dd3ea601171455a3b5ca1adf67b851 100644
--- a/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
+++ b/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
@@ -1,7 +1,5 @@
 package info.nightscout.android.model.medtronicNg;
 
-import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet;
-
 import java.util.Date;
 
 import io.realm.RealmObject;
diff --git a/app/src/main/java/info/nightscout/android/settings/SettingsFragment.java b/app/src/main/java/info/nightscout/android/settings/SettingsFragment.java
index d14c7ed19af7df4025bd0731227abfecfb380208..cbabb6a4ec7e9a497f487642f0fd8f1f06ccf3da 100644
--- a/app/src/main/java/info/nightscout/android/settings/SettingsFragment.java
+++ b/app/src/main/java/info/nightscout/android/settings/SettingsFragment.java
@@ -51,8 +51,7 @@ public class SettingsFragment extends PreferenceFragment implements OnSharedPref
      */
     private void setMinBatPollIntervall(ListPreference pollIntervalPref, ListPreference lowBatPollIntervalPref) {
         final String currentValue = lowBatPollIntervalPref.getValue();
-        final int pollIntervalPos = pollIntervalPref.findIndexOfValue(pollIntervalPref.getValue()),
-                lowBatPollIntervalPos = lowBatPollIntervalPref.findIndexOfValue(currentValue),
+        final int pollIntervalPos = (pollIntervalPref.findIndexOfValue(pollIntervalPref.getValue()) >= 0?pollIntervalPref.findIndexOfValue(pollIntervalPref.getValue()):0),
                 length = pollIntervalPref.getEntries().length;
 
         CharSequence[] entries = new String[length - pollIntervalPos],
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 1360a2b54f3cdb032af6023402f818de2b39e7f6..95148622918e6cc996d1ce7e5c3075d7ff3e399a 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -119,11 +119,10 @@
 
     </LinearLayout>
 
-    <com.github.mikephil.charting.charts.ScatterChart
-        android:id="@+id/chart"
+    <com.jjoe64.graphview.GraphView
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:visibility="visible" />
+        android:layout_height="100dip"
+        android:id="@+id/chart" />
 
     <ScrollView
         android:id="@+id/scrollView"
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index d84a02f6bb920f7d4afe27e28ed60ab9cba5f38b..cfb3458e897140a9308cac32f15041128630caad 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -21,4 +21,20 @@
         <item>3600000</item>
         <!--item>0</item-->
     </string-array>
+
+    <string-array name="chart_zoom">
+        <item>1 hour</item>
+        <item>3 hours</item>
+        <item>6 hours</item>
+        <item>12 hours</item>
+        <item>24 hours</item>
+    </string-array>
+
+    <string-array name="chart_zoom_hours">
+        <item>1</item>
+        <item>3</item>
+        <item>6</item>
+        <item>12</item>
+        <item>24</item>
+    </string-array>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 48268a1e642c4b34d2d4e52b74dbdd9963f34731..580e85d04a9bbe67a3b112aa026ec9c260224707 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -57,4 +57,5 @@
     <string name="no_registered_contour_next_link_devices">No registered Contour Next Link devices</string>
     <string name="to_register_a_contour_next_link_you_must_first_plug_it_in_and_get_a_reading_from_the_pump">To register a Contour Next Link you must first plug it in, and get a reading from the pump.</string>
     <string name="serial_number">Serial number</string>
+    <string name="preferences_chart_interval">Chart Zoom</string>
 </resources>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 0183e9581d19c4460d5007c0d754336c9a092668..de93838a97ceafac7a7701ecfbb6ee914ed9c5c3 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -41,6 +41,15 @@
             android:entries="@array/poll_interval"
             android:entryValues="@array/poll_interval_millis"/>
     </PreferenceCategory>
+    <PreferenceCategory android:title="Display">
+    <ListPreference
+        android:key="chartZoom"
+        android:defaultValue="3"
+        android:title="@string/preferences_chart_interval"
+        android:summary="%s"
+        android:entries="@array/chart_zoom"
+        android:entryValues="@array/chart_zoom_hours"/>
+    </PreferenceCategory>
     <PreferenceCategory android:title="Sharing">
         <CheckBoxPreference
             android:disableDependentsState="false"