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..bf1a8b2ede019c027433d26b51362306cd0ac1e7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -154,8 +154,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/java/info/nightscout/android/medtronic/MainActivity.java b/app/src/main/java/info/nightscout/android/medtronic/MainActivity.java
index a16375d180e4bc9f250490bb4425cce173ee0ed2..421368b960d470437517a980649ca8c48ad2cf65 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.util.Arrays;
 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;
@@ -99,12 +89,14 @@ 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;
 
     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();
@@ -271,118 +263,46 @@ 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() {
-
-            @Override
-            public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
+        mChart = (GraphView) findViewById(R.id.chart);
 
-            @Override
-            public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {}
+        //mChart.setDescription(null);    // Hide the description
 
+        mChart.getViewport().setScalable(true);
+        mChart.getViewport().setScrollable(true);
+        mChart.getViewport().setXAxisBoundsManual(true);
+        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) {
+                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 {
+                    // show currency for y values
+                    return super.formatLabel(value, false); //nf.format(value);
                 }
-            }
-        });
+            }}
+        );
     }
 
     @Override
@@ -553,6 +473,14 @@ 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("doublePollOnPumpAway")) {
+            chartZoom = Integer.parseInt(sharedPreferences.getString("chartZoom", "3"));
+            hasZoomedChart = false;
+
+            long now = (long) mChart.getSeries().get(0).getHighestValueX(),
+                    left = now - chartZoom * 60 * 60 * 1000;
+            mChart.getViewport().setMinX(left);
+            mChart.getViewport().setMaxX(now);
         }
     }
 
@@ -825,77 +753,95 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
 
         private void updateChart(RealmResults<PumpStatusEvent> results) {
             int size = results.size();
-            if (size == 0) return;
+            if (size == 0) {
+                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;
+
+            final DecimalFormat df;
+            final boolean mmolxl = prefs.getBoolean("mmolxl", false);
+
+            if (mmolxl) {
+                if (prefs.getBoolean("mmolDecimals", false))
+                    df = new DecimalFormat("0.00");
+                else
+                    df = new DecimalFormat("0.0");
+            } else {
+                df = new DecimalFormat("0");
+            }
 
+            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() / 18.016f);
+                } 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);
+
+                PointsGraphSeries sgvSerie = new PointsGraphSeries(entries);
+//                sgvSerie.setSize(3.6f);
+//                sgvSerie.setColor(Color.LTGRAY);
+                sgvSerie.setOnDataPointTapListener(new OnDataPointTapListener() {
+                    DateFormat mFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM);
 
-                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;
+                    public void onTap(Series series, DataPointInterface dataPoint) {
+                        double sgv = dataPoint.getY();
 
-                        if (prefs.getBoolean("mmolxl", false)) {
-                            if (prefs.getBoolean("mmolDecimals", false))
-                                df = new DecimalFormat("0.00");
-                            else
-                                df = new DecimalFormat("0.0");
-
-                            return df.format(value / 18.016f);
+                        StringBuilder sb = new StringBuilder(mFormat.format(new Date((long) dataPoint.getX())) + ": ");
+                        if (mmolxl) {
+                            sb.append(df.format(sgv / 18.016f));
                         } else {
-                            return new DecimalFormat("0").format(value);
+                            sb.append(df.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.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);
+            }
         }
     }
 
@@ -964,31 +910,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/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/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"