A UBlox GPS Module Primer for beginners

Support configuration command for uBlox Library added, will release it soon needs clean up.
gps.SetCFG_TP5(15, 50.000000, 50, true); // UBX-CFG-TP5 (0x06 0x31) - Set Time Pulse 0 Parameters.
// Possible Configurations:
// SetCFG_TP5(FreqLocked- 1Hz ~ 24000000Hz, DutyLocked- 0.000000% ~ 100.000000%, antCableDelay- 0~32767ns, print usb ACK- true or false);

Time to get my hands dirty and either rip this GPS led out or hand-solder to the one side of the SMD resistor ;).

Code:
Setting CFG-PRT (0x06 0x00) GPS UART baud rate:1500000
Setting CFG-RATE (0x06 0x08) Navigation/Measurement Rate 200ms 5.00Hz
Setting CFG-NAV5 (0x06 0x24) Dynamic platform model 3: pedestrian
Setting Dis_NAV_PVT
Setting Dis_NAV_ATT
Setting Dis_NAV_POSLLH
Setting Dis_MON_IO (0x0A 0x02) I/O Subsystem Status
 Poll_MON_IO, I/O Subsystem Status
 Poll_MON_VER, Receiver/Software Version
[COLOR="#FF0000"]Setting CFG-TP5 (0x06 0x31) Time Pulse 0 Parameters	(FreqLocked) 15Hz  (DutyLocked) 50.000000% map(2147483648)  (antCableDelay) 50[/COLOR]
UBX_ACK_ACK: Message Acknowledged - CFG-PRT (0x06 0x00) Set GPS UART baud
UBX_ACK_ACK: Message Acknowledged - CFG-RATE 0x06 0x08 Get/Set Navigation/Measurement Rate Settings
UBX_ACK_ACK: Message Acknowledged - Dis_NAV_ATT -Disable periodic auto update
UBX_ACK_ACK: Message Acknowledged - Dis_NAV_PVT -Disable periodic auto update
UBX_ACK_ACK: Message Acknowledged - Dis_NAV_POSLLH -Disable periodic auto update
UBX_ACK_ACK: Message Acknowledged - Dis_MON_IO -Disable periodic auto update
UBX_ACK_ACK: Message Acknowledged - CFG-NAV5 0x06 0x24 Get/Set Navigation Engine Settings
UBX_ACK_NAK: Message Not-Acknowledged - Dis_NAV_ATT, ATT Supported only on protocol v. 19 (only with ADR or UDR products)
[COLOR="#FF0000"]UBX_ACK_ACK: Message Acknowledged - CFG-TP5 0x06 0x31[/COLOR]


 MON_IO- RX Bytes: 0	 TX Bytes: 0	 Overrun Errs: 0
 MON_VER- SW Version: 1.00	 Rev# 59842	 HW Version u-blox: 7	 Protocol: 14.00

 Poll_MON_IO, I/O Subsystem Status
 Poll_MON_VER, Receiver/Software Version

 MON_IO- RX Bytes: 6534	 TX Bytes: 2160	 Overrun Errs: 0
 MON_VER- SW Version: 1.00	 Rev# 59842	 HW Version u-blox: 7	 Protocol: 14.00

 Poll_MON_IO, I/O Subsystem Status
 Poll_MON_VER, Receiver/Software Version

 MON_IO- RX Bytes: 6558	 TX Bytes: 2432	 Overrun Errs: 0
 MON_VER- SW Version: 1.00	 Rev# 59842	 HW Version u-blox: 7	 Protocol: 14.00

 Poll_MON_IO, I/O Subsystem Status
 Poll_MON_VER, Receiver/Software Version

 MON_IO- RX Bytes: 6582	 TX Bytes: 2704	 Overrun Errs: 0
 MON_VER- SW Version: 1.00	 Rev# 59842	 HW Version u-blox: 7	 Protocol: 14.00

 Poll_MON_IO, I/O Subsystem Status
 Poll_MON_VER, Receiver/Software Version

 MON_IO- RX Bytes: 6606	 TX Bytes: 2976	 Overrun Errs: 0
 MON_VER- SW Version: 1.00	 Rev# 59842	 HW Version u-blox: 7	 Protocol: 14.00

 Poll_MON_IO, I/O Subsystem Status
 Poll_MON_VER, Receiver/Software Version

 MON_IO- RX Bytes: 6630	 TX Bytes: 3248	 Overrun Errs: 0
 MON_VER- SW Version: 1.00	 Rev# 59842	 HW Version u-blox: 7	 Protocol: 14.00
 
Support configuration command for uBlox Library added, will release it soon needs clean up.
...

Time to get my hands dirty and either rip this GPS led out or hand-solder to the one side of the SMD resistor ;).

Are you doing this to get the PPS signal? That worked for me to just get a wire on the hot side of the tiny LED.
 
Yeah that was the idea anyways it's all good LED is still blinking;)
I figure if i removed the LED i will not need the resistor so I can solder on top of the entire SMD package.
 
My LED survived the trauma - nice to have a visual indication of the PPS with the blue Tx LED.

Though I've been playing with the SPI_MSTransfer testing since that evolved - that pair isn't even powered as I was also working with PJRC's Teensy_sermon update and two units caused enough trouble. TyCommander still has it beat Hands down with integration of the Uploader All in one solution.

Will have to read prior posts and see about stepping up to higher baud rate from the 400K that is working well.
 
Sounds good let us know how it goes.:rolleyes:

Be careful hooking up the signal to Teensy, I'm not sure if it's my scope yet or the wiring but i am getting large voltage overshoot.
GPS UBX-CFG-TP5 Test1.jpg
DS1Z_QuickPrint1.jpg
 
Just did a comparison of the UBlox 24 MHz signal against Rubidium 30 MHz. I divided the Ruby signal by 100 to get precise 300 KHz to use as the scope reference trigger. Ublox 24 MHz is equivalent to the 80th harmonic of 300 KHz, so there should be exactly 80 cycles for every Ruby 300 KHz cycle.

The good news in scope picture is that 24 MHz is "stationary" on screen (Blue Trace 4) when scope is triggered on the Rubidium 300 KHz reference (Yellow Trace 1). This is indicating that it is holding lock to GPS/UTC timing. However, it could still drop the odd cycle as per the quote in post #21.

The "broadening" seen of the 24 MHz trace is due to UBlox clock jitter - 48 MHz UBlox clock has a 20.8 nS period, and the clock is free running, so appears as an "incremental" phase shift as each display trace is drawn over the previous one - but limited to around 21 nS. If you need a better signal, then you can phase lock a VCO.

I also had a look at the UHF spectrum at 696 MHz, which is the 29th harmonic for 24 MHz. Again good news - a little peak found accurate to better than 1 Hz. The only "bad" news is that the jitter causes many spurs with much greater energy and can make it very difficult to find the 24 MHz harmonics, unless you know exactly where to look.

Scope24MHz300KHz.jpg
 
Wow. That's some testing that you put it through.

Chris O.: Did you update the library with the changes you made for the pps?
 
Mike
Nice links.
Chris O.: Did you update the library with the changes you made for the pps?
To answer your question no not yet, was taking a power nap except on my keyboard (made a mess;)), had too much fun with the scope.
There's a few other things I'm thinking about tweaking before public release, if you need it now I can send you what I have in private message?
 
Hi Chris,
Pretty much did the same today. Needed some rest. Anyway, no rush, whenever you get done was just curious if I missed something. :)

Mike
 
Hi all
For what it's worth I am releasing my quick TP5 (0x06 0x31)Time Pulse Parameters configuration editor based on ILI9341 TFT + Touch interface.
It's not perfect, you can only change settings for Antenna cable delay, Freq period lock and Pulse len ratio lock.
Perhaps someone will find this useful.:D
Code:
// ***********************************************************************************************************
// *(c) Chris O 2018/4 - License: MIT
// * U-Blox UBX-CFG-TP5 (0x06 0x31) Quick configuration editor - ILI9341 TFT + Touch interface
// * v1.0
// *
// * Permission is hereby granted, free of charge, to any person obtaining
// * a copy of this software and associated documentation files (the
// * "Software"), to deal in the Software without restriction, including
// * without limitation the rights to use, copy, modify, merge, publish,
// * distribute, sublicense, and/or sell copies of the Software, and to
// * permit persons to whom the Software is furnished to do so, subject to
// * the following conditions:
// *
// * 1. The above copyright notice and this permission notice shall be
// * included in all copies or substantial portions of the Software.
// *
// * 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.
// ***********************************************************************************************************

// ***********************************************************************************************************
// *                            UBLOX GPS - Important set this to the GPS hardware serial port
// ***********************************************************************************************************
#include "UBLOX.h" // Update #4 U-BLOX lib v1.0.3  https://forum.pjrc.com/threads/36103-uBlox-Library/page2
// Set this to the GPS hardware serial port you wish to use
#define GPShwSERIAL 3 // 1 = Serial1, 2 = Serial2, 3 = Serial3, 4 = Serial4 ....

// ***********************************************************************************************************
// *                            RUN TFT Touch Calibration
// ***********************************************************************************************************
// comment or uncomment me.
#define TFTCalibration  // calibrate the touch screen.
//

uint32_t const BaudDefault = 9600; // default settings
// a uBlox object, which is on Teensy hardware
// GPS serial port
UBLOX gps(GPShwSERIAL);
// the uBlox data structure
gpsData uBloxData;

// ***********************************************************************************************************
// *                            TFT
// ***********************************************************************************************************
#include <SPI.h>
#include <Wire.h>      // this is needed even tho we aren't using it
#include <ILI9341_t3.h>
#include <XPT2046_Touchscreen.h>
//#include <Adafruit_STMPE610.h>

// Rotations 1 or 3 = Landscape mode only ~ 1->TFT conn. pins on right side  : 3->TFT conn. pins on left side
const int rotation = 3; //(1 or 3 only)

// This is calibration data for the raw touch data to the screen coordinates
int TS_MINX = 367;
int TS_MINY = 226;
int TS_MAXX = 3920;
int TS_MAXY = 3809;

// https://www.pjrc.com/store/display_ili9341_touch.html
// Connections For optimized ILI9341_t3 library + XPT2046 Touch library
// ------------------------------------------------------------------------------------------
// ILI9341 Pin | - Teensy 3.x - | - Notes -
// VCC         |           VIN  | Power: 3.6 to 5.5 volts
// GND         |           GND  |
// CS          |            20  | Alternate Pins: 9, 10, 15, 20, 21
// RESET       |         +3.3V  | Optional; #define TFT_RST 255, = unused, connect to 3.3V
// D/C         |            15  | Alternate Pins: 9, 10, 15, 20, 21
// SDI   (MOSI)|(DOUT~MOSI) 11  | Alternate Pin:  7 [SPI.setMOSI(7); - Use befor tft.begin()]
// SCK   (SCK0)|     (SCK0) 13  | Alternate Pin: 14 [SPI.setSCK(14); - Use befor tft.begin()]
// LED         |           VIN  | Use 100 ohm resistor, TFT dependent I'm not using any.
// SDO   (MISO)| (DIN~MISO) 12  | Alternate Pin:  8 [SPI.setMISO(8); - Use befor tft.begin()]
// T_CLK (SCK0)|     (SCK0) 13  | Alternate Pin: 14 [SPI.setSCK(14); - Use befor tft.begin()]
// T_CS        |            16  | Alternate: can use any digital pin  e.g. 6
// T_DIN (MOSI)|(DOUT~MOSI) 11  | Alternate Pin:  7 [SPI.setMOSI(7); - Use befor tft.begin()]
// T_DO  (MISO)| (DIN~MISO) 12  | Alternate Pin:  8 [SPI.setMISO(8); - Use befor tft.begin()]
// T_IRQ       |    NOT IN USE  | Optional: can use any digital pin
// ------------------------------------------------------------------------------------------

#define TOUCH_CS  16 // 8
//Adafruit_STMPE610 ts = Adafruit_STMPE610(TOUCH_CS);
XPT2046_Touchscreen ts(TOUCH_CS);

// For optimized ILI9341_t3 library
#define TFT_DC      15
#define TFT_CS      20
#define TFT_RST    255  // 255 = unused, connect to 3.3V
#define TFT_MOSI    11
#define TFT_SCLK    13
#define TFT_MISO    12
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);

#include "font_Arial.h"

int t_x; // Retrieve point x
int t_y; // Retrieve point y
byte touch_event_detected = 0;
#define MINPRESSURE 5   // 10
#define MAXPRESSURE 3000  // this was 1000

// Slider value editor
uint32_t xFreq = 1; // Hz, Maps the values
uint32_t xAnt = 50; // ns
float xDuty = 50.0000; // %
float xR = 29; // Slider

// The elapsedMillis feature is built into Teensyduino.
// For non-Teensy boards, it is available as a library.
elapsedMillis BLINK;
uint8_t Toggle = 1; // Toggle
uint8_t Select = 22; // 22 ant ,39 freq, 55 duty

// ***********************************************************************************************************
// *
// *                                Setup()
// *
// ***********************************************************************************************************
void setup(void) {
  tft.begin();
  tft.setRotation(rotation); // TFT Rotation 0~3

  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_WHITE);
  tft.setFont(Arial_16);
  byte i = 0;
  while (!Serial && millis() < 5000) { // wait for Arduino Serial Monitor
    if (i >= 240) {
      i = 255;
    }
    tft.fillRect(250, 5, 42, 18, ILI9341_BLACK);
    tft.setCursor(250, 5);
    tft.print((5000.0 - (float)millis()) / 1000.0, 1);
    tft.print(" sec");

    delay(100);
    // BackLight
    if (i <= 254) {
      i += 10;
    }
  }

  if (!ts.begin()) {
    Serial.println("Couldn't start touchscreen controller");
    while (1);
  }
  Serial.println("U-Blox UBX-CFG-TP5 (0x06 0x31), TFT + Touch interface");
  Serial.println("Touchscreen started");

#ifdef TFTCalibration
  int Tx = 0;
  int Ty = 0;
  bool EXIT = true;
  unsigned long y = 10000;
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_WHITE);
  tft.setFont(Arial_9);
  tft.drawRoundRect(250, 140, 70, 40, 3, ILI9341_ORANGE);
  tft.setCursor(273, 155);
  tft.print("EXIT");

  tft.drawRoundRect(250, 200, 70, 40, 3, ILI9341_ORANGE);
  tft.setCursor(273, 208);
  tft.print("RUN");
  tft.setCursor(255, 222);
  tft.print("Calibration");

  tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(2, 2);
  tft.print("Click on screen to draw Pixel");
  tft.setFont(Arial_16);
  while (millis() < y) { // wait for
    tft.fillRect(250, 5, 42, 18, ILI9341_BLACK);
    tft.setCursor(250, 5);
    tft.print((y - (float)millis()) / 1000.0, 1);
    tft.print(" sec");
    delay(10);

    TS_Point p = ts.getPoint();
    if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
      // Retrieve a point
      TS_Point p = ts.getPoint();
      Tx = p.x;
      Ty = p.y;
      if (rotation == 3) { //
        t_y = map(Ty, TS_MINY, TS_MAXY, 0, tft.height());
        t_x = map(Tx, TS_MINX, TS_MAXX, 0, tft.width());
      } else { // rotation == 1
        t_y = map(Ty, TS_MINY, TS_MAXY, tft.height(), 0);
        t_x = map(Tx, TS_MAXX, TS_MINX, 0, tft.width());
      }
      tft.drawPixel(t_x, t_y, ILI9341_BLUE);
      // EXIT
      if (t_x > 250 && t_x < 320 && t_y > 140 && t_y < 180) {
        tft.fillScreen(ILI9341_BLACK);
        y = 0;
        EXIT = true;
        delay(300);
      }
      if (t_x > 250 && t_x < 320 && t_y > 200 && t_y < 240) {
        tft.fillScreen(ILI9341_BLACK);
        y = 0;
        EXIT = false;
        delay(300);
      }
    }
  }
  if (EXIT == false) {
    TS_MINX = 450;
    TS_MINY = 450;
    TS_MAXX = 3700;
    TS_MAXY = 3700;
    TFTCali(); // Run TFT Touch Calibration
  }
#endif

  tft.fillScreen(ILI9341_BLACK);
  ResetScreen();
  // ***********************************************************************************************************
  // *                            UBLOX GPS setup
  // ***********************************************************************************************************
  // serial to display data
  Serial.begin(9600); // Teensy Serial object always communicates at 12 Mbit/sec USB speed.

  /*
    // -- AutoBauding test -- experimental baud rate 1500000
    // Try communication with the GPS receiver at 9600 baud, default settings
    // then set GPS UART Baud to 1500000
    gps.begin(BaudDefault);                   // Enable Teensy serial communication @ 9600 baud, default settings.
    gps.SetGPSbaud(1500000, false);           // Set GPS Port Baud, Possible Baud Rate Configurations 4800~9600~19200~38400~57600~115200~230400~460800-921600
    gps.end();                                // Disables Teensy serial communication, to re-enable serial communication, call gps.begin(Baud, bool);.
    gps.begin(19200);
    gps.SetGPSbaud(1500000, false);
    gps.end();
    gps.begin(38400);
    gps.SetGPSbaud(1500000, false);
    gps.end();
    gps.begin(57600);
    gps.SetGPSbaud(1500000, false);
    gps.end();
    gps.begin(115200);
    gps.SetGPSbaud(1500000, false);
    gps.end();
    gps.begin(230400);
    gps.SetGPSbaud(1500000, false);
    gps.end();
    gps.begin(460800);
    gps.SetGPSbaud(1500000, false);
    gps.end();
    gps.begin(921600);
    gps.SetGPSbaud(1500000, true);
    gps.end();
    // now start communication with the GPS
    // receiver at 1500000 baud,
    gps.begin(1500000);                       // Enable Teensy serial communication @ given baud rate
  */

  // -- AutoBauding test -- baud rate 921600
  // Try communication with the GPS receiver at 9600 baud, default settings
  // then set GPS UART Baud to 921600
  gps.begin(BaudDefault);
  gps.SetGPSbaud(921600, false);
  gps.end();
  gps.begin(19200);
  gps.SetGPSbaud(921600, false);
  gps.end();
  gps.begin(38400);
  gps.SetGPSbaud(921600, false);
  gps.end();
  gps.begin(57600);
  gps.SetGPSbaud(921600, false);
  gps.end();
  gps.begin(115200);
  gps.SetGPSbaud(921600, false);
  gps.end();
  gps.begin(230400);
  gps.SetGPSbaud(921600, false);
  gps.end();
  gps.begin(460800);
  gps.SetGPSbaud(921600, false);
  gps.end();
  gps.begin(921600);
  gps.SetGPSbaud(921600, false);
  gps.end();
  gps.begin(1500000);
  gps.SetGPSbaud(921600, true);
  gps.end();
  // now start communication with the GPS
  // receiver at 921600 baud,
  gps.begin(921600);                        // Enable Teensy serial communication @ given baud rate
  if (gps.read(&uBloxData) ) {}             // reading data clears the hw serial port.

  gps.SetRATE(1000, false);                 // Navigation/Measurement Rate Settings, e.g. 100ms => 10Hz, 200 => 5.00Hz, 1000ms => 1Hz, 10000ms => 0.1Hz
  // Possible Configurations:
  // 60=>16.67Hz, 64=>15.63Hz, 72=>13.89Hz, 80=>12.50Hz, 100=>10.00Hz, 125=>8.00Hz, 200=>5.00Hz, 250=>4.00Hz, 500=>2.00Hz
  // 800=>1.25Hz, 1000=>1.00Hz, 2000=>0.50Hz, 4000=>0.25Hz, 10000=>0.10Hz, 20000=>0.05Hz, 50000=>0.02Hz

  // NOTE: Dis_all_NMEA -strongly suggest changing RX buffer to 255 or more,*otherwise you will miss ACKs*on serial monitor
  gps.Dis_all_NMEA_Child_MSGs(false);       // Disable All NMEA Child Messages Command

  gps.SetNAV5(3, false);                    // Set Dynamic platform model Navigation Engine Settings (0:portable, 2: stationary, 3:pedestrian, Etc)
  // Possible Configurations
  // 0: portable, 2: stationary, 3: pedestrian, 4: automotive, 5: sea, 6: airborne with <1g, 7: airborne with <2g
  // 8: airborne with <4g, 9: wrist worn watch (not supported in protocol v.less than 18)

  // ### Periodic auto update ON,OFF Command ###
  gps.Ena_NAV_PVT(false);                    // Enable periodic auto update NAV_PVT
  //gps.Dis_NAV_PVT(false);                  // Disable periodic auto update NAV_PVT

  //gps.Ena_NAV_ATT(true);                   // Enable periodic auto update NAV_ATT ~ U-blox M8 from protocol version 19
  //gps.Dis_NAV_ATT(false);                  // Disable periodic auto update NAV_ATT ~ ---^

  //gps.Ena_NAV_POSLLH(true);                // Enable periodic auto update NAV_POSLLH
  //gps.Dis_NAV_POSLLH(false);               // Disable periodic auto update NAV_POSLLH

  gps.Ena_Dis_MON_IO(true, false);           // Ena/Dis periodic auto update I/O Subsystem Status, bytes(received, sent), parity errors, framing errors, overrun errors)

  gps.Poll_MON_IO(false);                   // Polls UBX-MON-IO (0x0A 0x02) I/O Subsystem Status
  gps.Poll_MON_VER(false);                  // Polls UBX-MON-VER (0x0A 0x04) Receiver/Software Version

  // A UBlox GPS Module Primer for beginners https://forum.pjrc.com/threads/46058-A-UBlox-GPS-Module-Primer-for-beginners
  gps.SetCFG_TP5(1, 50.0000, 50, true);    // UBX-CFG-TP5 (0x06 0x31) - Set Time Pulse 0 Parameters.
  //          (1Hz,50%,ant50ns,print usb)
  // Possible Configurations:
  // SetCFG_TP5(FreqLocked- 1Hz ~ 24000000Hz, DutyLocked- 0.000000% ~ 100.000000%, antCableDelay- 0~32767ns, print usb ACK- true or false);

  gps.Poll_CFG_TP5(false);                 // Polls CFG-TP5        (0x06 0x31) Poll Time Pulse 0 Parameters
}

// ***********************************************************************************************************
// *
// *                                Loop()
// *
// ***********************************************************************************************************
void loop()
{
  if (BLINK > 500) {
    BLINK = 0; // reset since
    Toggle = ! Toggle;
    if (Toggle == 0) {
      tft.setFont(Arial_12);
      tft.setTextColor(ILI9341_YELLOW);
      tft.setCursor(10, Select); //
      tft.print(">");

      tft.setFont(Arial_11); // Arial, Arial
      if (Select == 22) {
        tft.setCursor(85, 100);  // 22
        tft.print("Ant");
      } else if (Select == 39) {
        tft.setCursor(85, 115);  // 22
        tft.print("Freq");
      } else if (Select == 55) {
        tft.setCursor(85, 130);  // 22
        tft.print("Duty");
      }
    } else {
      tft.setFont(Arial_12);
      tft.setTextColor(ILI9341_BLACK);
      tft.setCursor(10, Select); //
      tft.print(">");

      tft.setFont(Arial_11);
      tft.setCursor(85, 100);
      tft.print("Ant");
      tft.setCursor(85, 115);
      tft.print("Freq");
      tft.setCursor(85, 130);
      tft.print("Duty");
    }
  }
  // ***********************************************************************************************************
  // *                            UBLOX GPS read
  // ***********************************************************************************************************
  if (gps.read(&uBloxData) ) {

    //numSV
    tft.setFont(Arial_9);
    tft.setTextColor(ILI9341_CYAN);
    tft.setCursor(265, 6);
    tft.fillRect(297 , 6 , 18, 10, ILI9341_BLACK);
    tft.print("#SV: ");
    tft.print(uBloxData.numSV);

    tft.setCursor(263, 20);
    tft.print("Fix Type:");
    tft.setCursor(263, 35);
    tft.fillRect(263 , 35 , 55, 10, ILI9341_BLACK);
    //fixType;///< [ND], GNSSfix Type: 0: no fix, 1: dead reckoning only, 2: 2D-fix, 3: 3D-fix, 4: GNSS + dead reckoning combined, 5: time only fix
    switch (uBloxData.fixType) { // fixType
      case 0:    // 0: no-fix
        tft.setTextColor(ILI9341_RED);
        tft.print(" NO-fix");
        break;
      case 1:    // 1: dead reckoning only
        tft.print("dead rec");
        break;
      case 2:    // 2: 2D-fix
        tft.setTextColor(ILI9341_BLUE);
        tft.print(" 2D-fix");
        break;
      case 3:    // 3: 3D-fix
        tft.setTextColor(ILI9341_GREEN);
        tft.print(" 3D-fix");
        break;
      case 4:    //  4: GNSS + dead reckoning combined
        tft.print("GNSS+d");
        break;
      case 5:    //  5: time only fix
        tft.print("Time only");
        break;
      default:
        // Not Supported
        tft.print("Not Sup:"), tft.print(uBloxData.fixType);
        break;
    }

    // UBX-CFG-TP5 (0x06 0x31) - Set Time Pulse 0 Parameters.
    //tft.setTextSize(2);
    tft.setFont(Arial_11);
    tft.setTextColor(ILI9341_GREEN);
    tft.fillRect(185 , 23 , 60, 11,  ILI9341_BLACK);
    tft.setCursor(25, 23);
    tft.print("Ant Cable Delay");
    tft.setTextColor(ILI9341_YELLOW);
    tft.setCursor(163, 23);
    tft.print(" ns: ");
    tft.print(uBloxData.antCableDelay);  // antCableDelay

    tft.setTextColor(ILI9341_GREEN);
    tft.fillRect(185 , 40 , 75, 11, ILI9341_BLACK);
    tft.setCursor(25, 40);
    tft.print("Freq Locked");
    tft.setTextColor(ILI9341_YELLOW);
    tft.setCursor(161, 40);
    tft.print(" Hz: ");
    tft.println(uBloxData.freqPeriodL);  // freqPeriodL

    tft.setTextColor(ILI9341_GREEN);
    // CurrentfreqPeriodL = uBloxData.freqPeriodL; //TODO REMOVE?
    tft.fillRect(181 , 58 , 68, 11, ILI9341_BLACK);
    tft.setCursor(25, 58);
    tft.print("Duty Cycle Locked");
    tft.setTextColor(ILI9341_YELLOW);
    tft.setCursor(165, 58);
    tft.print(" %: ");
    tft.print(uBloxData.dutycycleL, 4);  // duty cycle%

    //tft.setTextSize(0);
    tft.setFont(Arial_8);
    tft.setTextColor(ILI9341_CYAN);
    tft.setCursor(0, 200);
    tft.print("I/O Subsystem Status");
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(0, 210);
    tft.fillRect(47 , 210 , 70, 8, ILI9341_BLACK);
    tft.print("RX Bytes: "), tft.print(uBloxData.rxBytes); ///< [B], Number of bytes ever received
    tft.setCursor(0, 220);
    tft.fillRect(45 , 220 , 70, 8, ILI9341_BLACK);
    tft.print("TX Bytes: "), tft.print(uBloxData.txBytes); ///< [B], Number of bytes ever sent
    tft.setCursor(0, 230);
    tft.fillRect(66 , 230 , 70, 8, ILI9341_BLACK);
    tft.print("Overrun Errs: "), tft.print(uBloxData.overrunErrs); ///< [ms], Number of 100ms timeslots with overrun errors

    tft.setTextColor(ILI9341_CYAN);
    tft.setCursor(90, 158);
    tft.fillRect(180 , 158 , 30, 8, 0x31C7);
    tft.print("UBlox SW Version: "), tft.print(uBloxData.swVersion); ///< Software Version
    tft.setCursor(140, 168);
    tft.fillRect(165 , 168 , 50, 8, 0x31C7);
    tft.print("Rev# "), tft.print(uBloxData.revVersion); ///< Rev#
    tft.setCursor(121, 178);
    tft.fillRect(180 , 178 , 16, 8, 0x31C7);
    tft.print("HW Version: "), tft.print(uBloxData.hwVersion); ///< Hardware Version, 7 = u-blox 7
    tft.setCursor(121, 188);
    tft.fillRect(164 , 188 , 32, 8, 0x31C7);
    tft.print("Protocol: "), tft.print(uBloxData.extension1); ///< Protocol version, e.g. 14.00

    tft.drawRoundRect(180, 200, 120, 40, 6, ILI9341_CYAN); // SEND BTN
    tft.setFont(Arial_20);
    tft.setTextColor(ILI9341_GREEN);
    tft.setCursor(208, 210);
    tft.print("SEND");

    ScreenUpdate ();
  }
  // ***********************************************************************************************************
  // *                            TFT
  // ***********************************************************************************************************
  // See if there's any touch data for us
  TouchData();
  if (touch_event_detected == 1) {
    // SEND BUTTON
    if (t_x > 180 && t_x < 300 && t_y > 200 && t_y < 240) {
      tft.drawRoundRect(180, 200, 120, 40, 6, ILI9341_BLUE);
      tft.setFont(Arial_20);
      tft.setTextColor(ILI9341_RED);
      tft.setCursor(208, 210);
      tft.print("SEND");
      gps.SetCFG_TP5(xFreq, xDuty, xAnt, true);  // UBX-CFG-TP5   (0x06 0x31) - Set Time Pulse 0 Parameters.
      gps.Poll_CFG_TP5(true);                  // Polls CFG-TP5 (0x06 0x31) - Poll Time Pulse 0 Parameters
      gps.Poll_MON_VER(false);                 // Polls UBX-MON-VER (0x0A 0x04) Receiver/Software Version
    }
    // Select cur. ant, freq, duty
    byte temp = Select; // clear
    if (t_x > 0 && t_x < 320 && t_y > 20 && t_y < 34) {
      Select = 22; // y = 22
      tft.drawRoundRect(20, 21, 140, 17, 3, ILI9341_ORANGE);

      tft.drawRoundRect(20, 38, 140, 17, 3, ILI9341_BLACK);
      tft.drawRoundRect(20, 56, 140, 17, 3, ILI9341_BLACK);
    }
    if (t_x > 0 && t_x < 320 && t_y > 40 && t_y < 50) {
      Select = 39;
      tft.drawRoundRect(20, 38, 140, 17, 3, ILI9341_ORANGE);

      tft.drawRoundRect(20, 21, 140, 17, 3, ILI9341_BLACK);
      tft.drawRoundRect(20, 56, 140, 17, 3, ILI9341_BLACK);
    }
    if (t_x > 0 && t_x < 320 && t_y > 60 && t_y < 70) {
      Select = 55;
      tft.drawRoundRect(20, 56, 140, 17, 3, ILI9341_ORANGE);

      tft.drawRoundRect(20, 21, 140, 17, 3, ILI9341_BLACK);
      tft.drawRoundRect(20, 38, 140, 17, 3, ILI9341_BLACK);
    }
    tft.setFont(Arial_12);
    tft.setTextColor(ILI9341_BLACK); // clear old
    tft.setCursor(10, temp);
    tft.print(">");
  }
}

void ScreenUpdate () {
  if (Select == 22) { // Ant
    xR = modifiedMap(xAnt, 0, 32767, 29, 285); // 0~32767, default 50ns
    // Draws the positioners
    tft.fillRoundRect(29, 80, xR - 28 , 15, 1, ILI9341_BLUE);
    tft.fillRoundRect(xR + 2 , 80, 285 - xR , 15, 1, ILI9341_BLACK);
    tft.fillRoundRect(xR - 1, 80, 4, 15, 3, ILI9341_RED);
    // Draws the positioner outside box
    tft.drawRoundRect(28, 79, 285 - 25, 17, 1, ILI9341_GREEN);
    tft.drawRoundRect(27, 78, 285 - 25, 19, 3, ILI9341_CYAN);
  } // Ant
  tft.setCursor(125, 100);
  if (xAnt == uBloxData.antCableDelay) {
    tft.setTextColor(ILI9341_YELLOW);
  }  else {
    tft.setTextColor(ILI9341_RED);
  }
  // print the new value in the slider bar
  tft.setFont(Arial_12);
  tft.fillRect(125, 100, 100, 12, ILI9341_BLACK); // Clear
  tft.print(xAnt);

  if (Select == 39) { // Freq
    xR = modifiedMap(xFreq, 1, 24000000, 29, 285); // 1Hz ~ 24000000Hz
    // Draws the positioners
    tft.fillRoundRect(29, 80, xR - 28 , 15, 1, ILI9341_BLUE);
    tft.fillRoundRect(xR + 2 , 80, 285 - xR , 15, 1, ILI9341_BLACK);
    tft.fillRoundRect(xR - 1, 80, 4, 15, 3, ILI9341_RED);
    // Draws the positioner outside box
    tft.drawRoundRect(28, 79, 285 - 25, 17, 1, ILI9341_GREEN);
    tft.drawRoundRect(27, 78, 285 - 25, 19, 3, ILI9341_CYAN);
  } // Freq
  tft.setCursor(125, 115);
  if (xFreq == uBloxData.freqPeriodL) {
    tft.setTextColor(ILI9341_YELLOW);
  }  else {
    tft.setTextColor(ILI9341_RED);
  }
  // print the new value in the slider bar
  tft.setFont(Arial_12);
  tft.fillRect(125, 115, 100, 12, ILI9341_BLACK); // Clear
  tft.print(xFreq);

  if (Select == 55) { // Duty
    xR = map(xDuty, 0 , 100, 29, 285);
    // Draws the positioners
    tft.fillRoundRect(29, 80, xR - 28 , 15, 1, ILI9341_BLUE);
    tft.fillRoundRect(xR + 2 , 80, 285 - xR , 15, 1, ILI9341_BLACK);
    tft.fillRoundRect(xR - 1, 80, 4, 15, 3, ILI9341_RED);
    // Draws the positioner outside box
    tft.drawRoundRect(28, 79, 285 - 25, 17, 1, ILI9341_GREEN);
    tft.drawRoundRect(27, 78, 285 - 25, 19, 3, ILI9341_CYAN);
  } // Duty

  tft.setCursor(125, 130);
  if (xDuty == uBloxData.dutycycleL) {
    tft.setTextColor(ILI9341_YELLOW);
  }  else {
    tft.setTextColor(ILI9341_RED);
  }
  // print the new value in the slider bar
  tft.setFont(Arial_12);
  tft.fillRect(125, 130, 100, 12, ILI9341_BLACK); // Clear
  tft.print(xDuty, 4);
}

void ResetScreen () {
  tft.fillScreen(ILI9341_BLACK);
  tft.fillRoundRect(5, 1, 256, 73, 3, 0x1000); // 0x52AA

  tft.setCursor(6, 6);
  tft.setTextColor(ILI9341_BLUE);
  tft.setFont(Arial_8);
  tft.print("UBX-CFG-TP5 Current Time Pulse Configuration");

  // Select = 22; // y = 22
  tft.drawRoundRect(20, 21, 140, 17, 3, ILI9341_ORANGE);

  tft.drawRoundRect(20, 38, 140, 17, 3, ILI9341_BLACK);
  tft.drawRoundRect(20, 56, 140, 17, 3, ILI9341_BLACK);

  //http://www.barth-dev.de/online/rgb565-color-picker/
  //COLOR GRAY 0x52AA
  //DK GRY 0x31C7
  //DK BLUE 0x006F
  tft.fillRoundRect(0, 75, 320, 123, 5, 0x31C7); // frame around slider and black rear axle msg. box
  tft.drawRoundRect(0, 75, 320, 124, 5, ILI9341_GREEN); //
  tft.fillRoundRect(20, 76, 274, 52, 5, ILI9341_BLACK); // frame around slider and - + bottons
  tft.fillRoundRect(20, 125, 64, 72, 5, ILI9341_BLACK); // blue side
  tft.fillRoundRect(230, 125, 64, 72, 5, ILI9341_BLACK); // red side
  tft.fillRoundRect(81, 98, 152, 60, 5, ILI9341_GREEN); // red side
  tft.fillRoundRect(82, 99, 150, 58, 5, ILI9341_BLACK); // red side
  tft.fillRoundRect(83, 100, 35, 56, 5, 0x31C7); // red side

  tft.drawRoundRect(0, 0, 320, 75, 5, ILI9341_YELLOW); //

  tft.drawRoundRect(28, 97, 51, 29, 5, ILI9341_BLUE); // - botton
  tft.setCursor( 50, 105);
  tft.setTextColor(ILI9341_BLUE);
  tft.setFont(Arial_16);
  tft.print("-");
  tft.drawRoundRect(284 - 48, 97, 53, 29, 5, ILI9341_RED); // + botton
  tft.setCursor(284 - 28, 105);
  tft.setTextColor(ILI9341_RED);
  tft.setFont(Arial_16);
  tft.print("+");

  tft.drawRoundRect(28, 130, 51, 29, 5, ILI9341_BLUE); // - botton
  tft.setCursor( 30, 137);
  tft.setTextColor(ILI9341_BLUE);
  tft.setFont(Arial_16);
  tft.print("-500");
  tft.drawRoundRect(284 - 48, 130, 53, 29, 5, ILI9341_RED); // + botton
  tft.setCursor(284 - 48, 137);
  tft.setTextColor(ILI9341_RED);
  tft.setFont(Arial_16);
  tft.print("+500");

  tft.drawRoundRect(28, 165, 51, 29, 5, ILI9341_BLUE); // - botton
  tft.setCursor( 30, 173);
  tft.setTextColor(ILI9341_BLUE);
  tft.setFont(Arial_13);
  tft.print("-5000");
  tft.drawRoundRect(284 - 48, 165, 53, 29, 5, ILI9341_RED); // + botton
  tft.setCursor(284 - 48, 173);
  tft.setTextColor(ILI9341_RED);
  tft.setFont(Arial_13);
  tft.print("+5000");

  Draw_Slider(); // Draw Slider
}

void TouchData()
{
  touch_event_detected = 0; // reset flag

  // See if there's any touch data for us
  if (ts.touched())
    //if (ts.bufferEmpty()) // WAS: if (!ts.bufferEmpty())
  {

    // Retrieve a point
    TS_Point p = ts.getPoint();
    int Tx = 0;
    int Ty = 0;

    // we have some minimum pressure we consider 'valid'
    // pressure of 0 means no pressing!
    if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
      // Wait for end of the touch event before continuing
      while (ts.touched()) { //
        TS_Point p = ts.getPoint();
        Tx = p.x;
        Ty = p.y;

        if (rotation == 3) { //
          t_y = map(Ty, TS_MINY, TS_MAXY, 0, tft.height());
          t_x = map(Tx, TS_MINX, TS_MAXX, 0, tft.width());
        } else { // rotation == 1
          t_y = map(Ty, TS_MINY, TS_MAXY, tft.height(), 0);
          t_x = map(Tx, TS_MAXX, TS_MINX, 0, tft.width());
        }

        // drawPixel
        //  if ((t_x) && ((t_y) < tft.height())) {
        //    tft.drawPixel(t_x, t_y, currentcolor);
        //  }

        if (gps.read(&uBloxData)) {
        }

        // Area of the slider
        if ( (t_y >= 80) && (t_y <= 95)) {
          xR = t_x; // Stores the X value where the screen has been pressed in to variable xR
          if (xR <= 29) { // Confines the area of the slider to be above 38 pixels
            xR = 29;
          }
          if (xR >= 285) { /// Confines the area of the slider to be under 310 pixels
            xR = 285;
          }

          if (Select == 22) { // Ant
            xAnt = modifiedMap(xR, 29, 285, 0, 32767); // 0~32767
            // Draws the positioners
            tft.fillRoundRect(29, 80, xR - 28 , 15, 1, ILI9341_BLUE);
            tft.fillRoundRect(xR + 2 , 80, 285 - xR , 15, 1, ILI9341_BLACK);
            tft.fillRoundRect(xR - 1, 80, 4, 15, 3, ILI9341_RED);
            // Draws the positioner outside box
            tft.drawRoundRect(28, 79, 285 - 25, 17, 1, ILI9341_GREEN);
            tft.drawRoundRect(27, 78, 285 - 25, 19, 3, ILI9341_CYAN);

            tft.setCursor(125, 100);
            if (xAnt == uBloxData.antCableDelay) {
              tft.setTextColor(ILI9341_YELLOW);
            }  else {
              tft.setTextColor(ILI9341_RED);
            }
            // print the new value in the slider bar
            tft.setFont(Arial_12);
            tft.fillRect(125, 100, 100, 12, ILI9341_BLACK); // Clear
            tft.print(xAnt);
          } // Ant

          if (Select == 39) { // Freq
            xFreq = modifiedMap(xR, 29, 285, 1, 24000000);
            // Draws the positioners
            tft.fillRoundRect(29, 80, xR - 28 , 15, 1, ILI9341_BLUE);
            tft.fillRoundRect(xR + 2 , 80, 285 - xR , 15, 1, ILI9341_BLACK);
            tft.fillRoundRect(xR - 1, 80, 4, 15, 3, ILI9341_RED);
            // Draws the positioner outside box
            tft.drawRoundRect(28, 79, 285 - 25, 17, 1, ILI9341_GREEN);
            tft.drawRoundRect(27, 78, 285 - 25, 19, 3, ILI9341_CYAN);

            tft.setCursor(125, 115);
            if (xFreq == uBloxData.freqPeriodL) {
              tft.setTextColor(ILI9341_YELLOW);
            }  else {
              tft.setTextColor(ILI9341_RED);
            }
            // print the new value in the slider bar
            tft.setFont(Arial_12);
            tft.fillRect(125, 115, 100, 12, ILI9341_BLACK); // Clear
            tft.print(xFreq);
          } // Freq

          if (Select == 55) { // Duty
            //xDuty = modifiedMap(xR, 29, 285, (0 - 0.125), (100 - 0.125)); // 100% 4294967295
            xDuty = map(xR, 29, 285, 0 , 100); // 100% 4294967295
            // Draws the positioners
            tft.fillRoundRect(29, 80, xR - 28 , 15, 1, ILI9341_BLUE);
            tft.fillRoundRect(xR + 2 , 80, 285 - xR , 15, 1, ILI9341_BLACK);
            tft.fillRoundRect(xR - 1, 80, 4, 15, 3, ILI9341_RED);
            // Draws the positioner outside box
            tft.drawRoundRect(28, 79, 285 - 25, 17, 1, ILI9341_GREEN);
            tft.drawRoundRect(27, 78, 285 - 25, 19, 3, ILI9341_CYAN);

            tft.setCursor(125, 130);
            if (xDuty == uBloxData.dutycycleL) {
              tft.setTextColor(ILI9341_YELLOW);
            }  else {
              tft.setTextColor(ILI9341_RED);
            }
            // print the new value in the slider bar
            tft.setFont(Arial_12);
            tft.fillRect(125, 130, 100, 12, ILI9341_BLACK); // Clear
            tft.print(xDuty, 4);
          }
        }
      } // while
      touch_event_detected = 1; // reset flag
    }
    Draw_Slider(); // Draw Slider
    if (rotation == 1) {
      // p.x, p.y reversed //
      t_y = map(Ty, TS_MINY, TS_MAXY, tft.height(), 0);
      t_x = map(Tx, TS_MAXX, TS_MINX, 0, tft.width());
      // debug print
      //Serial.print("rot 1 t_x:");
      //Serial.print(t_x);
      //Serial.print("  t_y:");
      //Serial.println(t_y);
    }
    if ((rotation == 3) && (touch_event_detected == 1)) { // p.x, p.y reversed
      t_y = map(Ty, TS_MINY, TS_MAXY, 0, tft.height());
      t_x = map(Tx, TS_MINX, TS_MAXX, 0, tft.width());
      // debug print
      //Serial.print("rot 3 t_x:");
      //Serial.print(t_x);
      //Serial.print("  t_y:");
      //Serial.println(t_y);
    }
    touch_event_detected = 1; // set flag
  }
}

void Draw_Slider() { // Tooth Slider
  if (Select == 22) { // antCableDelay, 0~32767, default 50ns
    // If we press the [-] Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 97) && (t_y <= 126)) {
      xAnt = xAnt - 1;
    }
    // If we press the [+] Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 97) && (t_y <= 126)) {
      xAnt = xAnt + 1;
    }

    // If we press the [-]500 Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 140) && (t_y <= 165)) {
      if (xAnt < 502) {
        xAnt = 1;
      } else {
        xAnt = xAnt - 500;
      }
    }
    // If we press the [+]500 Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 140) && (t_y <= 165)) {
      xAnt = xAnt + 500;
    }

    // If we press the [-]5000 Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 170) && (t_y <= 190)) {
      if (xAnt < 5002) {
        xAnt = 1;
      } else {
        xAnt = xAnt - 5000;
      }
    }
    // If we press the [+]5000 Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 170) && (t_y <= 190)) {
      xAnt = xAnt + 5000;
    }
    if (xAnt == 0) {
      xAnt = 0;
      xR = modifiedMap(xAnt, 0, 32767, 29, 285); // Confines for the draw slider
    }  else if (xAnt >= 32767) {
      xAnt = 32767;
      xR = modifiedMap(xAnt, 0, 32767, 29, 285); // Confines for the draw slider
    }
    // curr Ant
    tft.setCursor(125, 100);
    if (xAnt == uBloxData.antCableDelay) {
      tft.setTextColor(ILI9341_YELLOW);
    }  else {
      tft.setTextColor(ILI9341_RED);
    }
    // print the new value in the slider bar
    tft.setFont(Arial_12);
    tft.fillRect(125, 100, 100, 12, ILI9341_BLACK); // Clear
    tft.print(xAnt);
    xR = modifiedMap(xAnt, 0, 32767, 29, 285);
  }

  if (Select == 39) { // freqPeriodLock, 24000000Hz ~ 1Hz
    // If we press the [-] Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 97) && (t_y <= 126)) {
      xFreq = xFreq - 1;
    }
    // If we press the [+] Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 97) && (t_y <= 126)) {
      xFreq = xFreq + 1;
    }

    // If we press the [-]500 Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 140) && (t_y <= 165)) {
      if (xFreq < 502) {
        xFreq = 1;
      } else {
        xFreq = xFreq - 500;
      }
    }
    // If we press the [+]500 Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 140) && (t_y <= 165)) {
      xFreq = xFreq + 500;
    }

    // If we press the [-]5000 Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 170) && (t_y <= 190)) {
      if (xFreq < 5002) {
        xFreq = 1;
      } else {
        xFreq = xFreq - 5000;
      }
    }
    // If we press the [+]5000 Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 170) && (t_y <= 190)) {
      xFreq = xFreq + 5000;
    }
    if (xFreq == 0) {
      xFreq = 1;
      xR = modifiedMap(xFreq, 1, 24000000, 29, 285); // Confines for the draw slider
    }  else if (xFreq >= 24000000) {
      xFreq = 24000000;
      xR = modifiedMap(xFreq, 1, 24000000, 29, 285); // Confines for the draw slider
    }
    // curr Freq
    tft.setCursor(125, 115);
    if (xFreq == uBloxData.freqPeriodL) {
      tft.setTextColor(ILI9341_YELLOW);
    }  else {
      tft.setTextColor(ILI9341_RED);
    }
    // print the new value in the slider bar
    tft.setFont(Arial_12);
    tft.fillRect(125, 115, 100, 12, ILI9341_BLACK); // Clear
    tft.print(xFreq);
    xR = modifiedMap(xFreq, 1, 24000000, 29, 285);
  }

  if (Select == 55) { // Duty, 100% 4294967295
    // If we press the [-] Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 97) && (t_y <= 126)) {
      if (xDuty < 0.0001) {
        xDuty = 0;
      } else {
        xDuty = xDuty - 0.0001;
      }
    }
    // If we press the [+] Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 97) && (t_y <= 126)) {
      xDuty = xDuty + 0.0001;
    }

    // If we press the [-]500 Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 140) && (t_y <= 165)) {
      if (xDuty < 0.5) {
        xDuty = 0;
      } else {
        xDuty = xDuty - 0.0500;
      }
    }
    // If we press the [+]500 Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 140) && (t_y <= 165)) {
      xDuty = xDuty + 0.0500;
    }

    // If we press the [-]5000 Button
    if ((t_x >= 28) && (t_x <= 78) && (t_y >= 170) && (t_y <= 190)) {
      if (xDuty < 0.5001) {
        xDuty = 0;
      } else {
        xDuty = xDuty - 0.5000;
      }
    }
    // If we press the [+]5000 Button
    if ((t_x >= 284 - 48) && (t_x <= 286) && (t_y >= 170) && (t_y <= 190)) {
      xDuty = xDuty + 0.5000;
    }

    if (xDuty <= 0) {
      xDuty = 0;
      xR = modifiedMap(xDuty, 0 , 100, 29, 285); // Confines for the draw slider //(xDuty, (0 - 0.125), (100 - 0.125), 29, 285);
    }  else if (xDuty >= 100) {
      xDuty = 100;
      xR = modifiedMap(xDuty, 0 , 100, 29, 285); // Confines for the draw slider
    }
    // curr Duty
    tft.setCursor(125, 130);
    if (xDuty == uBloxData.dutycycleL) {
      tft.setTextColor(ILI9341_YELLOW);
    }  else {
      tft.setTextColor(ILI9341_RED);
    }
    // print the new value in the slider bar
    tft.setFont(Arial_12);
    tft.fillRect(125, 130, 100, 12, ILI9341_BLACK); // Clear
    tft.print(xDuty, 4);
    xR = map(xDuty, 0 , 100, 29, 285);
  }
  // Draws the positioners
  tft.fillRoundRect(29, 80, xR - 28 , 15, 1, ILI9341_BLUE);
  tft.fillRoundRect(xR + 2 , 80, 285 - xR , 15, 1, ILI9341_BLACK);
  tft.fillRoundRect(xR - 1, 80, 4, 15, 3, ILI9341_RED);
  // Draws the positioner outside box
  tft.drawRoundRect(28, 79, 285 - 25, 17, 1, ILI9341_GREEN);
  tft.drawRoundRect(27, 78, 285 - 25, 19, 3, ILI9341_CYAN);
}

// ***********************************************************************************************************
// *
// *                            Modified Map
// * ARDUINO "map" function have problems with large numbers, rolling my own "Modified Map"
// ***********************************************************************************************************
double modifiedMap(double x, double in_min, double in_max, double out_min, double out_max)
{
  double temp = (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  temp = (double) (4 * temp + .5);
  return (double) temp / 4;
}

// ***********************************************************************************************************
// *
// *                                TFT Touch Calibration ()
// * based on http://cyaninfinite.com/tutorials/2-8-tft-lcd-touchscreen-shield/
// ***********************************************************************************************************
#ifdef TFTCalibration
void TFTCali ()
{
  byte count = 0;
  bool tft_y = false;

  tft.fillScreen(ILI9341_BLACK);
  Serial.println("TFT Calibration");
  //Splash
  tft.setCursor(30, (tft.height() / 2) - 20);
  //tft.setTextSize(2);
  tft.setFont(Arial_18);
  tft.println("TFT Calibration v1.1");
  tft.setCursor(30, tft.height() / 2 + 10);
  tft.setFont(Arial_9);
  tft.setTextColor(ILI9341_WHITE);
  tft.print("Screen size:");
  tft.print(tft.width());
  tft.print("x");
  tft.println(tft.height());
  tft.setCursor(30, (tft.height() / 2) + 30);
  tft.println("Test wil begin in 2s...");
  delay(2000);
  tft.fillScreen(ILI9341_BLACK);
  //TFT Calibration
  tft.setCursor(30, (tft.height() / 2) - 20);
  tft.setFont(Arial_14);
  tft.println("TFT Calibration");
  tft.setCursor(30, (tft.height() / 2));
  tft.setFont(Arial_9);
  tft.setTextColor(ILI9341_WHITE);
  tft.print("Click on screen to begin...");
  tft_y = true;

  tft.setTextColor(ILI9341_WHITE);
  tft.setFont(Arial_9);
  // Retrieve a point
  //TS_Point p = ts.getPoint();
  int Tx = 0;
  int Ty = 0;

  while (count < 5) {
    // Retrieve a point
    TS_Point p = ts.getPoint();
    Tx = 0;
    Ty = 0;

    if (tft_y == true) {
      delay(200);
      if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
        TS_Point p = ts.getPoint();
        Tx = p.x;
        Ty = p.y;
        //Serial.print("X = "); Serial.print(Tx);
        //Serial.print("  Y = "); Serial.print(Ty);
        //Serial.print("  Pressure = "); Serial.print(p.z);
        //Serial.print("  Count = "); Serial.println(count);
        switch (count) {
          case 0:
            tft.fillRect(30, (tft.height() / 2), 180, (tft.height() / 2) + 10, ILI9341_BLACK);
            tft.setCursor(30, (tft.height() / 2));
            tft.print("Press the dots on the corners of the screen.");
            //drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
            tft.setCursor(tft.width() / 2, 10);
            tft.print(count);
            tft.fillCircle(0, 0, 16, ILI9341_YELLOW);
            getMinMax(Tx, Ty);
            count++;
            break;
          case 1:
            tft.fillCircle(tft.width(), 0, 16, ILI9341_YELLOW);
            tft.fillRect(tft.width() / 2, 10, 10, 10, ILI9341_BLACK);
            tft.setCursor(tft.width() / 2, 10);
            tft.print(count);
            getMinMax(Tx, Ty);
            count++;
            break;
          case 2:
            tft.fillCircle(tft.width(), tft.height(), 16, ILI9341_YELLOW);
            tft.fillRect(tft.width() / 2, 10, 10, 10, ILI9341_BLACK);
            tft.setCursor(tft.width() / 2, 10);
            tft.print(count);
            getMinMax(Tx, Ty);
            count++;
            break;
          case 3:
            tft.fillCircle(0, tft.height(), 16, ILI9341_YELLOW);
            tft.fillRect(tft.width() / 2, 10, 10, 10, ILI9341_BLACK);
            tft.setCursor(tft.width() / 2, 10);
            tft.print(count);
            getMinMax(Tx, Ty);
            count++;
            break;
          case 4:
            tft.fillRect(tft.width() / 2, 10, 10, 10, ILI9341_BLACK);
            tft.setCursor(tft.width() / 2, 10);
            tft.print(count);
            //Serial.print("\nMin X = "); Serial.print(TS_MINX);
            //Serial.println("Min Y = "); Serial.print(TS_MINY);
            tft.fillRect(30, (tft.height() / 2), 300, (tft.height() / 2) + 10, ILI9341_BLACK);
            tft.setCursor(30, tft.height() / 2);
            tft.print("Calibration completed!");
            tft.setCursor(30, (tft.height() / 2) + 20);
            tft.print("TS_MINX:");
            tft.print(TS_MINX);
            tft.setCursor(130, (tft.height() / 2) + 20);
            tft.print("TS_MINY:");
            tft.print(TS_MINY);
            tft.setCursor(30, (tft.height() / 2) + 40);
            tft.print("TS_MAXX:");
            tft.print(TS_MAXX);
            tft.setCursor(130, (tft.height() / 2) + 40);
            tft.print("TS_MAXY:");
            tft.print(TS_MAXY);
            tft.setCursor(30, (tft.height() / 2) + 75);
            tft.setTextColor(ILI9341_OLIVE);
            tft.print("Press Try Again or Exit...");
            tft.setCursor(30, (tft.height() / 2) + 60);
            tft.print("Click on screen to draw Pixel");
            tft.setTextColor(ILI9341_WHITE);

            tft.drawRoundRect(270, 200, 50, 40, 3, ILI9341_ORANGE);
            tft.setCursor(285, 208);
            tft.print("Try");
            tft.setCursor(278, 222);
            tft.print("Again");

            tft.drawRoundRect(270, 140, 50, 40, 3, ILI9341_ORANGE);
            tft.setCursor(283, 155);
            tft.print("EXIT");
            tft_y = false;
            break;
        }
        delay(200);
      }
    } else {
      //tft.setRotation(0);

      if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
        TS_Point p = ts.getPoint();
        Tx = p.x;
        Ty = p.y;

        tft.fillRect(52, 50, 30, 10, ILI9341_BLACK);
        tft.setCursor(30, 50);
        tft.print("X = "); tft.print(Tx);
        tft.fillRect(52, 65, 30, 10, ILI9341_BLACK);
        tft.setCursor(30, 65);
        tft.print("Y = "); tft.print(Ty);
        tft.fillRect(97, 82, 30, 10, ILI9341_BLACK);
        tft.setCursor(30, 82);
        tft.print("Pressure = "); tft.println(p.z);
        if (rotation == 3) { //
          t_y = map(Ty, TS_MINY, TS_MAXY, 0, tft.height());
          t_x = map(Tx, TS_MINX, TS_MAXX, 0, tft.width());
        } else { // rotation == 1
          t_y = map(Ty, TS_MINY, TS_MAXY, tft.height(), 0);
          t_x = map(Tx, TS_MAXX, TS_MINX, 0, tft.width());
        }
        tft.drawPixel(t_x, t_y, ILI9341_BLUE);

        tft.fillRect(132, 50, 25, 10, ILI9341_BLACK);
        tft.setCursor(100, 50);
        tft.print("t_x = "); tft.print(t_x);
        tft.fillRect(132, 65, 25, 10, ILI9341_BLACK);
        tft.setCursor(100, 65);
        tft.print("t_y = "); tft.print(t_y);

        tft.setCursor(30, tft.height() / 2);
        tft.print("Calibration completed!");
        tft.setCursor(30, (tft.height() / 2) + 20);
        tft.print("TS_MINX:");
        tft.print(TS_MINX);
        tft.setCursor(130, (tft.height() / 2) + 20);
        tft.print("TS_MINY:");
        tft.print(TS_MINY);
        tft.setCursor(30, (tft.height() / 2) + 40);
        tft.print("TS_MAXX:");
        tft.print(TS_MAXX);
        tft.setCursor(130, (tft.height() / 2) + 40);
        tft.print("TS_MAXY:");
        tft.print(TS_MAXY);


        // EXIT
        if (t_x > 270 && t_x < 320 && t_y > 140 && t_y < 180) {
          tft.fillScreen(ILI9341_BLACK);
          count = 5; // exit while()
          delay(300);
        }
        // Try Again
        if (t_x > 270 && t_x < 320 && t_y > 200 && t_y < 240) { // tft 320 x 240
          tft.fillScreen(ILI9341_BLACK);
          tft_y = true;
          count = 0; // reset
          tft.setCursor(30, (tft.height() / 2));
          //tft.setFont(Arial_9);
          tft.setTextColor(ILI9341_WHITE);
          tft.print("Click on screen to begin...");
          TS_MINX = 450;
          TS_MINY = 450;
          TS_MAXX = 3600;
          TS_MAXY = 3600;
          delay(300);
        }
      }
    }
  }
}
void getMinMax(int Tx, int Ty) {
  if (Tx < TS_MINX) {
    TS_MINX = Tx;
  }
  if (Ty < TS_MINY) {
    TS_MINY = Ty;
  }
  if (Tx > TS_MAXX) {
    TS_MAXX = Tx;
  }
  if (Ty > TS_MAXY) {
    TS_MAXY = Ty;
  }
}
#endif
TP5 configuration editor.jpg
EDIT: Forgot to mention, needs - UBlox Library v1.0.3
 
Thanks Mike.
LOL my to do list is like small circular buffer, between my two kids and demanding wife things get quickly over written;).
 
no comment on wives :) but kids I understand - don't have a young one but do have a puppy that always wants to play.
 
Ok Chris. I am trying to get this to work with a T3.2 with a 2.4inch screen I picked up on amazon. It didn't work out of the box so I loaded up some of the il and touch sketches. The pressure test worked so at least I know that piece works but no graphics will display. I saw a note in the il file about the 3.1 having to run at 120Mhz so I overclocked the T3.2 but nothing got displayed. Here is the info from the diagnostics:
Code:
Display Power Mode: 0x2
MADCTL Mode: 0x2
Pixel Format: 0x0
Image Format: 0x2
Self Diagnostic: 0x2

Any help would be appreciated - never used displays before so I am in new territory.

Did check wiring and had a couple wrong - may wind up just rewiring
 
Don't overclock for testing, in fact you better off slowing it down.
I had issues with long wires and i was also overclocking the F_bus.

Run this:
Code:
void setup() {
  // put your setup code here, to run once:
  CPUspecs();
}

void loop() {
  // put your main code here, to run repeatedly:

}

// ***********************************************************************************************************
// *
// *                            CPU specs
// * Thanks defragster ): 
// ***********************************************************************************************************
void CPUspecs() {
  Serial.println();
#if defined(__MK20DX128__)
  Serial.println( "CPU is T_LC");
#elif defined(__MK20DX256__)
  Serial.println( "CPU is T_3.1/3.2");
#elif defined(__MKL26Z64__)
  Serial.println( "CPU is T_3.0");
#elif defined(__MK64FX512__)
  Serial.println( "CPU is T_3.5");
#elif defined(__MK66FX1M0__)
  Serial.println( "CPU is T_3.6");
#endif
  Serial.print( "F_CPU =");   Serial.println( F_CPU );
  Serial.print( "ARDUINO =");   Serial.println( ARDUINO );
  Serial.print( "F_PLL =");   Serial.println( F_PLL );
  Serial.print( "F_BUS =");   Serial.println( F_BUS );
  Serial.print( "F_MEM =");   Serial.println( F_MEM );
  Serial.print( "NVIC_NUM_INTERRUPTS =");   Serial.println( NVIC_NUM_INTERRUPTS );
  Serial.print( "DMA_NUM_CHANNELS =");   Serial.println( DMA_NUM_CHANNELS );
  Serial.print( "CORE_NUM_TOTAL_PINS =");   Serial.println( CORE_NUM_TOTAL_PINS );
  Serial.print( "CORE_NUM_DIGITAL =");   Serial.println( CORE_NUM_DIGITAL );
  Serial.print( "CORE_NUM_INTERRUPT =");   Serial.println( CORE_NUM_INTERRUPT );
  Serial.print( "CORE_NUM_ANALOG =");   Serial.println( CORE_NUM_ANALOG );
  Serial.print( "CORE_NUM_PWM =");   Serial.println( CORE_NUM_PWM );
  Serial.println("");
}

Make sure the F_BUS = 60000000, this will give you a SPI speed of 30000000 Mhz
 
That code looks familiar :) Anyway
Code:
CPU is T_3.1/3.2
F_CPU =72000000
ARDUINO =10805
F_PLL =72000000
F_BUS =36000000
F_MEM =24000000
NVIC_NUM_INTERRUPTS =95
DMA_NUM_CHANNELS =16
CORE_NUM_TOTAL_PINS =34
CORE_NUM_DIGITAL =34
CORE_NUM_INTERRUPT =34
CORE_NUM_ANALOG =21
CORE_NUM_PWM =12

So where do I change the F_BUS - remember see how to change it before but forgot?

EDIT _ redid a wire and the only thing left that is not 0 is Pixel Format: 0x2
 
So where do I change the F_BUS
In kinetis.h @ about line 765 and down.
But for testing youre good for now, F_BUS @ 36000000 = SPI @ 18000000 hz

EDIT:
I got this on my display
Code:
ILI9341 Test!
Display Power Mode: 0x2
MADCTL Mode: 0x2
Pixel Format: 0x2
Image Format: 0x3
Self Diagnostic: 0x2
 
Last edited:
Thanks Chris - The screen is now displaying - not sure about the touch yet. Will let you know. Man, a 2.4in display is small. Have to get a bigger one :)
 
I can send you one tomorrow if you need one quick i got about a hundred of these 2.8" :D28displys.jpg
 
Last edited:
Back
Top