Spark Logic

Hacking the GD32 based ‘Autool X50 OBD2 Monitor and diagnostic Display’

carl0s Wed Apr 11, 2018 5:27 pm

Hi!

I’m Carl

My first project with STM32 will hopefully be to get some code onto this GD32F103 board, and drive the LCD. I first need to figure out what the driver is. It appears to be using 17 pins.. Hopefully the ILI9341.

I will then use this as a screen / controller for my vehicle datalogger that I have already built on an Adafruit Feather M0.

Here’s the thing I want to hack..

Note that the mini-USB on the back here is actually for a vehicle OBD connection, and will be expecting +12v as well as K-Line, L-Line, CAN-Hi/CAN-Lo, etc.. It’s *not* a Mini-USB connection!

(in most web browsers, you can right-click on the images below and choose Open Image in New tab, to view at full resolution).

Image

Image

Image

Image

Image

Replies

carl0s Sun Apr 15, 2018 2:09 pm

[ahull – Sun Apr 15, 2018 1:58 pm] –
I guess we just need to know what the trend is with the LDR, i.e. if it sees less light, we need to increase the LCD brightness and vice versa so if ADC value increases, brightness decreases (assuming the LDR is set up that way). The range of a typical LDR is quite broad, so anything from a few hundred ohms in bright light to perhaps a megohm or more in total darkness.

Using relative values should be doable without necessarily knowing the exact numbers coming from the ADC.

If you are a bit of a masochist you could of course blink out the numbers in Morse code :P
People have blinked out entire firmware dumps this way, but I don’t think we are quite that desperate.
http://chdk.wikia.com/wiki/Blinking_the … _interface

:D

Yeah I’ll come back to this one. I’ve tried dividing by 4 (since analogRead goes up to 1023, and analogWrite goes up to 254 ?) and also dividing by 2, but I don’t see any change. My DMM shows that the voltage goes between about 1v in living room, to between 1.5 or 1.8 v when the LDR is covered. I don’t have enough hands to test with a flashlight on it!

carl0s Sun Apr 15, 2018 3:15 pm

On the (very) remote chance, I thought I would try the STM32Duino ILI9341 examples. I have set the correct pins in the example code.
Needless to say it doesn’t work, however, this TFT is connected up to SPI2 on pins PB12 to PB15), which fits in with Vassilis wrote here: viewtopic.php?t=278

I can’t really see anywhere where (if at all) I need to amend the STM32Duino ILI9341 library for SPI2 instead of SPI1 though. It looks like it just configures SPI on whatever pins are set in the main program. Any thoughts?

oooh. setModule.

ahull Sun Apr 15, 2018 3:17 pm

If we assume an analogRead value of 1023=3v3 and 0 is 0V then our range for the voltage levels you saw would be approximately…

For 1v5 ….. (1.5/3.3)*1023=465
to 1v8 ….. (1.8/3.3)*1023=558

… so a range of 93 units.

So we could do something pretty rough to calculate a suitable analogWrite value for the backlight like like subtract our value from 570 and double it.

Crude, but probably we will see some effect (and since we are using multiplication rather than division, code safe since we can’t divide by zero).

ahull Sun Apr 15, 2018 3:18 pm

I’m no expert on SPI, so perhaps someone else can chime in. (Also I have no suitable boards to test with).

However I do have version of the Pig-O-scope code that I ran on a GD32 board a long time back, which might give some clues, see below.

/*.
(c) Andrew Hull - 2015

STM32-O-Scope - aka "The Pig Scope" or pigScope released under the GNU GENERAL PUBLIC LICENSE Version 2, June 1991

https://github.com/pingumacpenguin/STM32-O-Scope

Adafruit Libraries released under their specific licenses Copyright (c) 2013 Adafruit Industries. All rights reserved.

*/

#include "Adafruit_ILI9341_STM.h"
#include "Adafruit_GFX_AS.h"

// Be sure to use the latest version of the SPI libraries see stm32duino.com - http://stm32duino.com/viewtopic.php?f=13&t=127
#include <SPI.h>

#define PORTRAIT 0
#define LANDSCAPE 1

// Define the orientation of the touch screen. Further
// information can be found in the UTouch library documentation.

#define TOUCH_SCREEN_AVAILABLE
#define TOUCH_ORIENTATION LANDSCAPE

#if defined TOUCH_SCREEN_AVAILABLE
// UTouch Library
// http://www.rinkydinkelectronics.com/library.php?id=56
#include <UTouch.h>

#endif
// Initialize touchscreen
// ----------------------
// Set the pins to the correct ones for your STM32F103 board
// -----------------------------------------------------------

//
// STM32F103C8XX Pin numbers - chosen for ease of use on the "Red Pill" and "Blue Pill" board

// Touch Panel Pins
// T_CLK T_CS T_DIN T_DOUT T_IRQ
// PB12 PB13 PB14 PB15 PA8
// Example wire colours Brown,Red,Orange,Yellow,Violet
// -------- Brown,Red,Orange,White,Grey

#if defined TOUCH_SCREEN_AVAILABLE

UTouch myTouch( PB12, PB13, PB14, PB15, PA8);

#endif

// RTC and NVRam initialisation

#include "RTClock.h"
RTClock rt (RTCSEL_LSE); // initialise
uint32 tt;

// Define the Base address of the RTC registers (battery backed up CMOS Ram), so we can use them for config of touch screen and other calibration.
// See http://stm32duino.com/viewtopic.php?f=15&t=132&hilit=rtc&start=40 for a more details about the RTC NVRam
// 10x 16 bit registers are available on the STM32F103CXXX more on the higher density device.

#define BKP_REG_BASE (uint32_t *)(0x40006C00 +0x04)

// Defined for power and sleep functions pwr.h and scb.h
#include <libmaple/pwr.h>
#include <libmaple/scb.h>

// #define NVRam register names for the touch calibration values.
#define TOUCH_CALIB_X 0
#define TOUCH_CALIB_Y 1
#define TOUCH_CALIB_Z 2

// Time library - https://github.com/PaulStoffregen/Time
#include "Time.h"
#define TZ "UTC+1"

// End RTC and NVRam initialization

// SeralCommand -> https://github.com/kroimon/Arduino-SerialCommand.git
#include <SerialCommand.h>

/* For reference on STM32F103CXXX

variants/generic_stm32f103c/board/board.h:#define BOARD_NR_SPI 2
variants/generic_stm32f103c/board/board.h:#define BOARD_SPI1_NSS_PIN PA4
variants/generic_stm32f103c/board/board.h:#define BOARD_SPI1_MOSI_PIN PA7
variants/generic_stm32f103c/board/board.h:#define BOARD_SPI1_MISO_PIN PA6
variants/generic_stm32f103c/board/board.h:#define BOARD_SPI1_SCK_PIN PA5

variants/generic_stm32f103c/board/board.h:#define BOARD_SPI2_NSS_PIN PB12
variants/generic_stm32f103c/board/board.h:#define BOARD_SPI2_MOSI_PIN PB15
variants/generic_stm32f103c/board/board.h:#define BOARD_SPI2_MISO_PIN PB14
variants/generic_stm32f103c/board/board.h:#define BOARD_SPI2_SCK_PIN PB13

*/

// Additional display specific signals (i.e. non SPI) for STM32F103C8T6 (Wire colour)
#define TFT_DC PA0 // (Green)
#define TFT_CS PA1 // (Orange)
#define TFT_RST PA2 // (Yellow)

// Hardware SPI1 on the STM32F103C8T6 *ALSO* needs to be connected and pins are as follows.
//
// SPI1_NSS (PA4) (LQFP48 pin 14) (n.c.)
// SPI1_SCK (PA5) (LQFP48 pin 15) (Brown)
// SPI1_MOSO (PA6) (LQFP48 pin 16) (White)
// SPI1_MOSI (PA7) (LQFP48 pin 17) (Grey)
//

#define TFT_LED PA3 // Backlight
#define TEST_WAVE_PIN PB1 // PWM 500 Hz

// Create the lcd object
Adafruit_ILI9341_STM TFT = Adafruit_ILI9341_STM(TFT_CS, TFT_DC, TFT_RST); // Using hardware SPI

// LED - blinks on trigger events - leave this undefined if your board has no controllable LED
// define as PC13 on the "Red/Blue Pill" boards and PD2 on the "Yellow Pill R"
#define BOARD_LED PB0

// Display colours
#define BEAM1_COLOUR ILI9341_GREEN
#define BEAM2_COLOUR ILI9341_RED
#define GRATICULE_COLOUR 0x07FF
#define BEAM_OFF_COLOUR ILI9341_BLACK
#define CURSOR_COLOUR ILI9341_GREEN

// Analog input
#define ANALOG_MAX_VALUE 4096
const int8_t analogInPin = PB1; // Analog input pin: any of LQFP44 pins (PORT_PIN), 10 (PA0), 11 (PA1), 12 (PA2), 13 (PA3), 14 (PA4), 15 (PA5), 16 (PA6), 17 (PA7), 18 (PB0), 19 (PB1)
float samplingTime = 0;

// Variables for the beam position
uint16_t signalX ;
uint16_t signalY ;
uint16_t signalY1;
int16_t xZoomFactor = 1;
// yZoomFactor (percentage)
int16_t yZoomFactor = 200;
int16_t yPosition = -150 ;

// Startup with sweep hold off or on
boolean triggerHeld = 0 ;

unsigned long sweepDelayFactor = 1;
unsigned long timeBase = 100; // Timebase in microseconds

// Screen dimensions
int16_t myWidth ;
int16_t myHeight ;

//Trigger stuff
boolean notTriggered ;

// Sensitivity is the necessary change in AD value which will cause the scope to trigger.
// If VAD=3.3 volts, then 1 unit of sensitivity is around 0.8mV but this assumes no external attenuator. Calibration is needed to match this with the magnitude of the input signal.
int32_t triggerSensitivity = 20;

int16_t retriggerDelay = 10;
int8_t triggerType = 1;

//Array for trigger points
uint16_t triggerPoints[2];

// Serial output of samples - off by default. Toggled from UI/Serial commands.
boolean serialOutput = false;

// Create Serial Command Object.
SerialCommand sCmd;

// Create USB serial port
USBSerial serial_debug;

// Samples - depends on available RAM 6K is about the limit on an STM32F103C8T6
// Bear in mind that the ILI9341 display is only able to display 240x320 pixels, at any time but we can output far more to the serial port, we effectively only show a window on our samples on the TFT.
# define maxSamples 1024*6
uint32_t startSample = 10;
uint32_t endSample = maxSamples ;

// Array for the ADC data
//uint16_t dataPoints[maxSamples];
uint32_t dataPoints32[maxSamples / 2];
uint16_t *dataPoints = (uint16_t *)&dataPoints32;

// End of DMA indication
volatile static bool dma1_ch1_Active;
#define ADC_CR1_FASTINT 0x70000 // Fast interleave mode DUAL MODE bits 19-16

void setup()
{

// BOARD_LED blinks on triggering assuming you have an LED on your board. If not simply dont't define it at the start of the sketch.
#if defined BOARD_LED
pinMode(BOARD_LED, OUTPUT);
digitalWrite(BOARD_LED, HIGH);
delay(1000);
digitalWrite(BOARD_LED, LOW);
delay(1000);
#endif

serial_debug.begin();
delay(1000);
serial_debug.println("# STM-32-Oscope started.");
delay(1000);
adc_calibrate(ADC1);
adc_calibrate(ADC2);
setADCs(); //Setup ADC peripherals for interleaved continuous mode.

//
// Serial command setup
// Setup callbacks for SerialCommand commands
sCmd.addCommand("timestamp", setCurrentTime); // Set the current time based on a unix timestamp
sCmd.addCommand("date", serialCurrentTime); // Show the current time from the RTC
sCmd.addCommand("sleep", sleepMode); // Experimental - puts system to sleep

#if defined TOUCH_SCREEN_AVAILABLE
sCmd.addCommand("touchcalibrate", touchCalibrate); // Calibrate Touch Panel
#endif

sCmd.addCommand("s", toggleSerial); // Turns serial sample output on/off
sCmd.addCommand("h", toggleHold); // Turns triggering on/off
sCmd.addCommand("t", decreaseTimebase); // decrease Timebase by 10x
sCmd.addCommand("T", increaseTimebase); // increase Timebase by 10x
sCmd.addCommand("z", decreaseZoomFactor); // decrease Zoom
sCmd.addCommand("Z", increaseZoomFactor); // increase Zoom
sCmd.addCommand("r", scrollRight); // start onscreen trace further right
sCmd.addCommand("l", scrollLeft); // start onscreen trae further left
sCmd.addCommand("e", incEdgeType); // increment the trigger edge type 0 1 2 0 1 2 etc
sCmd.addCommand("y", decreaseYposition); // move trace Down
sCmd.addCommand("Y", increaseYposition); // move trace Down
sCmd.addCommand("P", toggleTestPulseOn); // Toggle the test pulse pin from high impedence input to square wave output.
sCmd.addCommand("p", toggleTestPulseOff); // Toggle the Test pin from square wave test to high impedence input.

sCmd.setDefaultHandler(unrecognized); // Handler for command that isn't matched (says "Unknown")
sCmd.clearBuffer();

// Backlight, use with caution, depending on your display, you may exceed the max current per pin if you use this method.
// A safer option would be to add a suitable transistor capable of sinking or sourcing 100mA (the ILI9341 backlight on my display is quoted as drawing 80mA at full brightness)
// Alternatively, connect the backlight to 3v3 for an always on, bright display.
//pinMode(TFT_LED, OUTPUT);
//analogWrite(TFT_LED, 127);

// Setup Touch Screen
// http://www.rinkydinkelectronics.com/library.php?id=56
#if defined TOUCH_SCREEN_AVAILABLE
myTouch.InitTouch();
myTouch.setPrecision(PREC_EXTREME);
#endif

// The test pulse is a square wave of approx 3.3V (i.e. the STM32 supply voltage) at approx 1 kHz
// "The Arduino has a fixed PWM frequency of 490Hz" - and it appears that this is also true of the STM32F103 using the current STM32F03 libraries as per
// STM32, Maple and Maple mini port to IDE 1.5.x - http://forum.arduino.cc/index.php?topic=265904.2520
// therefore if we want a precise test frequency we can't just use the default uncooked 50% duty cycle PWM output.
timer_set_period(Timer3, 1000);
toggleTestPulseOn();

// Set up our sensor pin(s)
pinMode(analogInPin, INPUT_ANALOG);
serial_debug.println("# Setting up display.");
TFT.begin();
// initialize the display
clearTFT();
TFT.setRotation(PORTRAIT);
myHeight = TFT.width() ;
myWidth = TFT.height();
TFT.setTextColor(CURSOR_COLOUR, BEAM_OFF_COLOUR) ;
#if defined TOUCH_SCREEN_AVAILABLE
touchCalibrate();
#endif

TFT.setRotation(LANDSCAPE);
clearTFT();
showCredits(); // Honourable mentions ;¬)
showGraticule();
delay(5000) ;
clearTFT();
notTriggered = true;
showGraticule();
showLabels();
}

void loop()
{

#if defined TOUCH_SCREEN_AVAILABLE
readTouch();
#endif

sCmd.readSerial(); // Process serial commands
if ( !triggerHeld )
{
// Wait for trigger
trigger();
showGraticule();
if ( !notTriggered )
{
blinkLED();
//Blank out previous plot
TFTSamples(BEAM_OFF_COLOUR);
showLabels();

// Show the showGraticule
showGraticule();
//notTriggered = true;

// Take our samples
takeSamples();

// Display the Labels ( uS/Div, Volts/Div etc).
showLabels();

//Display the samples
TFTSamples(BEAM1_COLOUR);

}
// Display the RTC time.
showTime();
}
// Wait before allowing a re-trigger
delay(retriggerDelay);
// DEBUG: increment the sweepDelayFactor slowly to show the effect.
// sweepDelayFactor ++;
}

void showGraticule()
{
TFT.drawRect(0, 0, myHeight, myWidth, GRATICULE_COLOUR);
// Dot grid - ten distinct divisions (9 dots) in both X and Y axis.
for (uint16_t TicksX = 1; TicksX < 10; TicksX++)
{
for (uint16_t TicksY = 1; TicksY < 10; TicksY++)
{
TFT.drawPixel( TicksX * (myHeight / 10), TicksY * (myWidth / 10), GRATICULE_COLOUR);
}
}
// Horizontal and Vertical centre lines 5 ticks per grid square with a longer tick in line with our dots
for (uint16_t TicksX = 0; TicksX < myWidth; TicksX += (myHeight / 50))
{
if (TicksX % (myWidth / 10) > 0 )
{
TFT.drawFastHLine( (myHeight / 2) - 2 , TicksX, 5, GRATICULE_COLOUR);
}
else
{
TFT.drawFastHLine( (myHeight / 2) - 6 , TicksX, 11, GRATICULE_COLOUR);
}

}
for (uint16_t TicksY = 0; TicksY < myHeight; TicksY += (myHeight / 50) )
{
if (TicksY % (myHeight / 10) > 0 )
{
TFT.drawFastVLine( TicksY, (myWidth / 2) - 2 , 5, GRATICULE_COLOUR);
}
else
{
TFT.drawFastVLine( TicksY, (myWidth / 2) - 5 , 11, GRATICULE_COLOUR);
}
}
}

void setADCs()
{
// const adc_dev *dev = PIN_MAP[analogInPin].adc_device;
int pinMapADCin = PIN_MAP[analogInPin].adc_channel;
adc_set_sample_rate(ADC1, ADC_SMPR_13_5);
adc_set_sample_rate(ADC2, ADC_SMPR_13_5);

// adc_reg_map *regs = dev->regs;
adc_set_reg_seqlen(ADC1, 1);
ADC1->regs->SQR3 = pinMapADCin;
ADC1->regs->CR2 |= ADC_CR2_CONT; // | ADC_CR2_DMA; // Set continuous mode and DMA
ADC1->regs->CR1 |= ADC_CR1_FASTINT; // Interleaved mode
ADC1->regs->CR2 |= ADC_CR2_SWSTART;

ADC2->regs->CR2 |= ADC_CR2_CONT; // ADC 2 continuos
ADC2->regs->SQR3 = pinMapADCin;
}

// Crude triggering on positive or negative or either change from previous to current sample.
void trigger()
{
notTriggered = true;
switch (triggerType) {
case 1:
triggerNegative() ;
break;
case 2:
triggerPositive() ;
break;
default:
triggerBoth() ;
break;
}
}

void triggerBoth()
{
triggerPoints[0] = analogRead(analogInPin);
delayMicroseconds(20);
if (((analogRead(analogInPin) - triggerPoints[0] ) < triggerSensitivity) or ((triggerPoints[0] - analogRead(analogInPin) ) < triggerSensitivity)) {
notTriggered = false ;
}
}

void triggerPositive() {

triggerPoints[1] = analogRead(analogInPin);
if ((triggerPoints[1] - triggerPoints[0] ) > triggerSensitivity) {
notTriggered = false;
}
triggerPoints[0] = analogRead(analogInPin);
}

void triggerNegative() {

triggerPoints[1] = analogRead(analogInPin);
if ((triggerPoints[0] - triggerPoints[1] ) > triggerSensitivity) {
notTriggered = false;
}
triggerPoints[0] = analogRead(analogInPin);
}

void incEdgeType() {
triggerType += 1;
if (triggerType > 2)
{
triggerType = 0;
}
/*
serial_debug.println(triggerPoints[0]);
serial_debug.println(triggerPoints[1]);
serial_debug.println(triggerType);
*/
}

void clearTFT()
{
TFT.fillScreen(BEAM_OFF_COLOUR); // Blank the display
}

void blinkLED()
{
#if defined BOARD_LED
digitalWrite(BOARD_LED, LOW);
delay(10);
digitalWrite(BOARD_LED, HIGH);
#endif

}

// Grab the samples from the ADC
// Theoretically the ADC can not go any faster than this.
//
// According to specs, when using 72Mhz on the MCU main clock,the fastest ADC capture time is 1.17 uS. As we use 2 ADCs we get double the captures, so .58 uS, which is the times we get with ADC_SMPR_1_5.
// I think we have reached the speed limit of the chip, now all we can do is improve accuracy.
// See; http://stm32duino.com/viewtopic.php?f=19&t=107&p=1202#p1194

void takeSamples ()
{
// This loop uses dual interleaved mode to get the best performance out of the ADCs
//

dma_init(DMA1);
dma_attach_interrupt(DMA1, DMA_CH1, DMA1_CH1_Event);

adc_dma_enable(ADC1);
dma_setup_transfer(DMA1, DMA_CH1, &ADC1->regs->DR, DMA_SIZE_32BITS,
dataPoints32, DMA_SIZE_32BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));// Receive buffer DMA
dma_set_num_transfers(DMA1, DMA_CH1, maxSamples / 2);
dma1_ch1_Active = 1;
// regs->CR2 |= ADC_CR2_SWSTART; //moved to setADC
dma_enable(DMA1, DMA_CH1); // Enable the channel and start the transfer.
//adc_calibrate(ADC1);
//adc_calibrate(ADC2);
samplingTime = micros();
while (dma1_ch1_Active);
samplingTime = (micros() - samplingTime);

dma_disable(DMA1, DMA_CH1); //End of trasfer, disable DMA and Continuous mode.
// regs->CR2 &= ~ADC_CR2_CONT;

}

void TFTSamples (uint16_t beamColour)
{
signalX = 1;
while (signalX < myWidth - 2)
{
// Scale our samples to fit our screen. Most scopes increase this in steps of 5,10,25,50,100 250,500,1000 etc
// Pick the nearest suitable samples for each of our myWidth screen resolution points
signalY = ((myHeight * dataPoints[signalX * ((endSample - startSample) / (myWidth * timeBase / 100)) + 1]) / ANALOG_MAX_VALUE) * (yZoomFactor / 100) + yPosition;
signalY1 = ((myHeight * dataPoints[(signalX + 1) * ((endSample - startSample) / (myWidth * timeBase / 100)) + 1]) / ANALOG_MAX_VALUE) * (yZoomFactor / 100) + yPosition ;
TFT.drawLine ( signalY * 99 / 100 + 1, signalX, signalY1 * 99 / 100 + 1 , signalX + 1, beamColour) ;
signalX += 1;
}
}

/*
// Run a bunch of NOOPs to trim the inter ADC conversion gap
void sweepDelay(unsigned long sweepDelayFactor) {
volatile unsigned long i = 0;
for (i = 0; i < sweepDelayFactor; i++) {
__asm__ __volatile__ ("nop");
}
}
*/

void showLabels()
{
TFT.setRotation(LANDSCAPE);
TFT.setTextSize(2);
TFT.setCursor(10, 190);
// TFT.print("Y=");
//TFT.print((samplingTime * xZoomFactor) / maxSamples);
TFT.print(float (float(samplingTime) / float(maxSamples)));

TFT.setTextSize(1);
TFT.print(" uS/Sample ");
TFT.setTextSize(2);
TFT.setCursor(10, 210);
TFT.print("3.0");
TFT.setTextSize(1);
TFT.print(" V/Div ");
TFT.setTextSize(2);
TFT.print(samplingTime);
TFT.setTextSize(1);
TFT.print(" us for ");
TFT.print(maxSamples);
TFT.print(" samples ");
//showTime();
TFT.setRotation(PORTRAIT);
}

void showTime ()
{
// Show RTC Time.
TFT.setTextSize(1);
TFT.setRotation(LANDSCAPE);
if (rt.getTime() != tt)
{
tt = rt.getTime();
TFT.setCursor(5, 10);
if (hour(tt) < 10) {
TFT.print("0");
}
TFT.print(hour(tt));
TFT.print(":");
if (minute(tt) < 10) {
TFT.print("0");
}
TFT.print(minute(tt));
TFT.print(":");
if (second(tt) < 10) {
TFT.print("0");
}
TFT.print(second(tt));
TFT.print(" ");
TFT.print(day(tt));
TFT.print("-");
TFT.print(month(tt));
TFT.print("-");
TFT.print(year(tt));
TFT.print(" "TZ" ");
// TFT.print(tt);

}
TFT.setRotation(PORTRAIT);
}

void serialSamples ()
{
// Send *all* of the samples to the serial port.
serial_debug.println("#Time(uS), ADC Number, value, diff");
for (int16_t j = 1; j < maxSamples ; j++ )
{
// Time from trigger in milliseconds
serial_debug.print((samplingTime / (maxSamples))*j);
serial_debug.print(" ");
// raw ADC data
serial_debug.print(j % 2 + 1);
serial_debug.print(" ");
serial_debug.print(dataPoints[j] );
serial_debug.print(" ");
serial_debug.print(dataPoints[j] - dataPoints[j - 1]);
serial_debug.print(" ");
serial_debug.print(dataPoints[j] - ((dataPoints[j] - dataPoints[j - 1]) / 2));
serial_debug.print("\n");

// delay(100);

}
serial_debug.print("\n");
}

void toggleHold()
{
triggerHeld ^= 1 ;
//serial_debug.print("# ");
//serial_debug.print(triggerHeld);
if (triggerHeld)
{
serial_debug.println("# Toggle Hold on");
}
else
{
serial_debug.println("# Toggle Hold off");
}
}

void toggleSerial() {
serialOutput = !serialOutput ;
serial_debug.println("# Toggle Serial");
serialSamples();
}

void unrecognized(const char *command) {
serial_debug.print("# Unknown Command.[");
serial_debug.print(command);
serial_debug.println("]");
}

void decreaseTimebase() {
clearTrace();
/*
sweepDelayFactor = sweepDelayFactor / 2 ;
if (sweepDelayFactor < 1 ) {

serial_debug.print("Timebase=");
sweepDelayFactor = 1;
}
*/
if (timeBase > 100)
{
timeBase -= 100;
}
showTrace();
serial_debug.print("# Timebase=");
serial_debug.println(timeBase);

}

void increaseTimebase() {
clearTrace();
serial_debug.print("# Timebase=");
if (timeBase < 10000)
{
timeBase += 100;
}
//sweepDelayFactor = 2 * sweepDelayFactor ;
showTrace();
serial_debug.print("# Timebase=");
serial_debug.println(timeBase);
}

void increaseZoomFactor() {
clearTrace();
if ( xZoomFactor < 21) {
xZoomFactor += 1;
}
showTrace();
serial_debug.print("# Zoom=");
serial_debug.println(xZoomFactor);

}

void decreaseZoomFactor() {
clearTrace();
if (xZoomFactor > 1) {
xZoomFactor -= 1;
}
showTrace();
Serial.print("# Zoom=");
Serial.println(xZoomFactor);
//clearTFT();
}

void clearTrace() {
TFTSamples(BEAM_OFF_COLOUR);
showGraticule();
}

void showTrace() {
showLabels();
TFTSamples(BEAM1_COLOUR);
}

void scrollRight() {
clearTrace();
if (startSample < (endSample - 120)) {
startSample += 100;
}
showTrace();
Serial.print("# startSample=");
Serial.println(startSample);

}

void scrollLeft() {
clearTrace();
if (startSample > (120)) {
startSample -= 100;
showTrace();
}
Serial.print("# startSample=");
Serial.println(startSample);

}

void increaseYposition() {

if (yPosition < myHeight ) {
clearTrace();
yPosition ++;
showTrace();
}
Serial.print("# yPosition=");
Serial.println(yPosition);
}

void decreaseYposition() {

if (yPosition > -myHeight ) {
clearTrace();
yPosition --;
showTrace();
}
Serial.print("# yPosition=");
Serial.println(yPosition);
}

void atAt() {
serial_debug.println("# Hello");
}

void toggleTestPulseOn () {
pinMode(TEST_WAVE_PIN, OUTPUT);
analogWrite(TEST_WAVE_PIN, 75);
serial_debug.println("# Test Pulse On.");
}

void toggleTestPulseOff () {
pinMode(TEST_WAVE_PIN, INPUT);
serial_debug.println("# Test Pulse Off.");
}

uint16 timer_set_period(HardwareTimer timer, uint32 microseconds) {
if (!microseconds) {
timer.setPrescaleFactor(1);
timer.setOverflow(1);
return timer.getOverflow();
}

uint32 cycles = microseconds * (72000000 / 1000000); // 72 cycles per microsecond

uint16 ps = (uint16)((cycles >> 16) + 1);
timer.setPrescaleFactor(ps);
timer.setOverflow((cycles / ps) - 1 );
return timer.getOverflow();
}

/**
* @brief Enable DMA requests
* @param dev ADC device on which to enable DMA requests
*/

void adc_dma_enable(const adc_dev * dev) {
bb_peri_set_bit(&dev->regs->CR2, ADC_CR2_DMA_BIT, 1);
}

/**
* @brief Disable DMA requests
* @param dev ADC device on which to disable DMA requests
*/

void adc_dma_disable(const adc_dev * dev) {
bb_peri_set_bit(&dev->regs->CR2, ADC_CR2_DMA_BIT, 0);
}

static void DMA1_CH1_Event() {
dma1_ch1_Active = 0;
}

void setCurrentTime() {
char *arg;
arg = sCmd.next();
String thisArg = arg;
serial_debug.print("# Time command [");
serial_debug.print(thisArg.toInt() );
serial_debug.println("]");
setTime(thisArg.toInt());
time_t tt = now();
rt.setTime(tt);
serialCurrentTime();
}

void serialCurrentTime() {
serial_debug.print("# Current time - ");
if (hour(tt) < 10) {
serial_debug.print("0");
}
serial_debug.print(hour(tt));
serial_debug.print(":");
if (minute(tt) < 10) {
serial_debug.print("0");
}
serial_debug.print(minute(tt));
serial_debug.print(":");
if (second(tt) < 10) {
serial_debug.print("0");
}
serial_debug.print(second(tt));
serial_debug.print(" ");
serial_debug.print(day(tt));
serial_debug.print("/");
serial_debug.print(month(tt));
serial_debug.print("/");
serial_debug.print(year(tt));
serial_debug.println("("TZ")");

}

#if defined TOUCH_SCREEN_AVAILABLE
void touchCalibrate() {
// showGraticule();
for (uint8_t screenLayout = 0 ; screenLayout < 4 ; screenLayout += 1)
{
TFT.setRotation(screenLayout);
TFT.setCursor(0, 10);
TFT.print(" Press and hold centre circle ");
TFT.setCursor(0, 20);
TFT.print(" to calibrate touch panel.");
}
TFT.setRotation(PORTRAIT);
TFT.drawCircle(myHeight / 2, myWidth / 2, 20, GRATICULE_COLOUR);
TFT.fillCircle(myHeight / 2, myWidth / 2, 10, BEAM1_COLOUR);
//delay(5000);
readTouchCalibrationCoordinates();
clearTFT();
}

void readTouchCalibrationCoordinates()
{
int calibrationTries = 6000;
int failCount = 0;
int thisCount = 0;
uint32_t tx = 0;
uint32_t ty = 0;
boolean OK = false;

while (OK == false)
{
while ((myTouch.dataAvailable() == false) && thisCount < calibrationTries) {
thisCount += 1;
delay(1);
}
if ((myTouch.dataAvailable() == false)) {
return;
}
// myGLCD.print("* HOLD! *", CENTER, text_y_center);
thisCount = 0;
while ((myTouch.dataAvailable() == true) && (thisCount < calibrationTries) && (failCount < 10000))
{
myTouch.calibrateRead();
if (!((myTouch.TP_X == 65535) || (myTouch.TP_Y == 65535)))
{
tx += myTouch.TP_X;
ty += myTouch.TP_Y;
thisCount++;
}
else
failCount++;
}
if (thisCount >= calibrationTries)
{
for (thisCount = 10 ; thisCount < 100 ; thisCount += 10)
{
TFT.drawCircle(myHeight / 2, myWidth / 2, thisCount, GRATICULE_COLOUR);
}
delay(500);
OK = true;
}
else
{
tx = 0;
ty = 0;
thisCount = 0;
}
if (failCount >= 10000)
// Didn't calibrate so just leave calibration as is.
return;
}
serial_debug.print("# Calib x: ");
serial_debug.println(tx/thisCount,HEX);
serial_debug.print("# Calib y: ");
serial_debug.println(ty/thisCount,HEX);
// Change calibration data from here..
// cx = tx / iter;
// cy = ty / iter;
}

void readTouch() {

if (myTouch.dataAvailable())
{
myTouch.read();
// Note: This is corrected to account for different orientation of screen origin (x=0,y=0) in Adafruit lib from UTouch lib
uint32_t touchY = myWidth - myTouch.getX();
uint32_t touchX = myTouch.getY();
//

serial_debug.print("# Touched ");
serial_debug.print(touchX);
serial_debug.print(",");
serial_debug.println(touchY);

TFT.drawPixel(touchX, touchY, BEAM2_COLOUR);
}
}

#endif

void showCredits() {
TFT.setTextSize(2); // Small 26 char / line
//TFT.setTextColor(CURSOR_COLOUR, BEAM_OFF_COLOUR) ;
TFT.setCursor(0, 50);
TFT.print(" STM-O-Scope by Andy Hull") ;
TFT.setCursor(0, 70);
TFT.print(" Inspired by");
TFT.setCursor(0, 90);
TFT.print(" Ray Burnette.");
TFT.setCursor(0, 130);
TFT.print(" Victor PV");
TFT.setCursor(0, 150);
TFT.print(" Roger Clark");
TFT.setCursor(0, 170);
TFT.print(" and all at stm32duino.com");
TFT.setCursor(0, 190);
TFT.print(" CH1 Probe STM32F Pin [");
TFT.print(analogInPin);
TFT.print("]");
TFT.setCursor(0, 220);
TFT.setTextSize(1);
TFT.print(" GNU GENERAL PUBLIC LICENSE Version 2 ");
TFT.setTextSize(2);
TFT.setRotation(PORTRAIT);
}

static inline int readBKP(int registerNumber)
{
if (registerNumber > 9)
{
registerNumber += 5; // skip over BKP_RTCCR,BKP_CR,BKP_CSR and 2 x Reserved registers
}
return *(BKP_REG_BASE + registerNumber) & 0xffff;
}

static inline void writeBKP(int registerNumber, int value)
{
if (registerNumber > 9)
{
registerNumber += 5; // skip over BKP_RTCCR,BKP_CR,BKP_CSR and 2 x Reserved registers
}

*(BKP_REG_BASE + registerNumber) = value & 0xffff;
}

void sleepMode()
{
serial_debug.println("# Nighty night!");
// Set PDDS and LPDS bits for standby mode, and set Clear WUF flag (required per datasheet):
PWR_BASE->CR |= PWR_CR_CWUF;
PWR_BASE->CR |= PWR_CR_PDDS;

// set sleepdeep in the system control register
SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP;

// Now go into stop mode, wake up on interrupt
// disableClocks();
asm("wfi");
}

fredbox Sun Apr 15, 2018 3:21 pm

If we assume an analogRead value of 1023=3v3 and 0 is 0V then our range for the voltage levels you saw would be approximately…
You are not using an Arduino, so 0-1023 does not apply. It is 0-4095.
See http://docs.leaflabs.com/static.leaflab … gread.html

carl0s Sun Apr 15, 2018 3:22 pm

[fredbox – Sun Apr 15, 2018 3:21 pm] –
If we assume an analogRead value of 1023=3v3 and 0 is 0V then our range for the voltage levels you saw would be approximately…
You are not using an Arduino, so 0-1023 does not apply. It is 0-4095.
See http://docs.leaflabs.com/static.leaflab … gread.html

Ah. Good spot. Thanks!

carl0s Sun Apr 15, 2018 3:24 pm

[ahull – Sun Apr 15, 2018 3:18 pm] –
I’m no expert on SPI, so perhaps someone else can chime in.

I’m really rubbish at C++, but it looks like it creates a new SPI instance called mSPI using the pin values set elsewhere, but, crucially, I just don’t see where MOSI and SCLK are being pulled through. Just CS, DS, and RST.
void Adafruit_ILI9341_STM::begin(SPIClass & spi, uint32_t freq)
{
mSPI = spi;
_freq = freq;
_safe_freq = (freq>SAFE_FREQ) ? SAFE_FREQ : _freq;
pinMode(_dc, OUTPUT);
pinMode(_cs, OUTPUT);
csport = portSetRegister(_cs);
cspinmask = digitalPinToBitMask(_cs);
cs_set(); // deactivate chip
dcport = portSetRegister(_dc);
dcpinmask = digitalPinToBitMask(_dc);

mSPI.beginTransaction(SPISettings(_safe_freq, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT));

// toggle RST low to reset
if (_rst > 0) {
pinMode(_rst, OUTPUT);
digitalWrite(_rst, HIGH);
delay(5);
digitalWrite(_rst, LOW);
delay(20);
digitalWrite(_rst, HIGH);
delay(150);
}

ahull Sun Apr 15, 2018 3:49 pm

[fredbox – Sun Apr 15, 2018 3:21 pm] –
If we assume an analogRead value of 1023=3v3 and 0 is 0V then our range for the voltage levels you saw would be approximately…
You are not using an Arduino, so 0-1023 does not apply. It is 0-4095.
See http://docs.leaflabs.com/static.leaflab … gread.html

OK Try this..
If we assume 4096=3v3 then Our range for the voltage levels you saw would be approximately…

From 1v5 ….. (1.5/3.3)*4096=1861
to 3v3 ….. (1.8/3.3)*4096=2234

… so a range of 373 units. So we could do something pretty rough like like subtract our value from 2300 and halve it.

Also worth a read ..

http://docs.leaflabs.com/static.leaflab … analogread
http://docs.leaflabs.com/static.leaflab … write.html
http://docs.leaflabs.com/static.leaflab … 65b9cbd98c

carl0s Sun Apr 15, 2018 4:29 pm

[ahull – Sun Apr 15, 2018 3:49 pm] –
[fredbox – Sun Apr 15, 2018 3:21 pm] –
If we assume an analogRead value of 1023=3v3 and 0 is 0V then our range for the voltage levels you saw would be approximately…
You are not using an Arduino, so 0-1023 does not apply. It is 0-4095.
See http://docs.leaflabs.com/static.leaflab … gread.html

OK Try this..
If we assume 4096=3v3 then Our range for the voltage levels you saw would be approximately…

From 1v5 ….. (1.5/3.3)*4096=1861
to 3v3 ….. (1.8/3.3)*4096=2234

… so a range of 373 units. So we could do something pretty rough like like subtract our value from 2300 and halve it.

Also worth a read ..

http://docs.leaflabs.com/static.leaflab … analogread
http://docs.leaflabs.com/static.leaflab … write.html
http://docs.leaflabs.com/static.leaflab … 65b9cbd98c

I must admit I have gone down an LCD / SPI rabbit hole for a bit.

I realised it was daft trying to get the ILI thing to work, also the STM32Duino ILI stuff doesn’t seem to extend the erm objects which pass mosi and sclk. I think. Adafruit have two definitions, one where you pass mosi and sclk, and one where you don’t and I guess it just assumes SPI1.

Anyway, I am now just trying the Adafruit ST7735 library, and, well… something is happening at least! Although, I think it is supposed to flash some colours, and then write ‘hello world’. Clearly a lot of work to go still.. :)

Although, according to this discussion, I should be able to use the IL9341 library..

That ST7735 library is for a much lower resolution display than the ST7789

ahull Sun Apr 15, 2018 5:28 pm

Looking good. I suspect there is either a slight speed/timing timing issue, or one of your pins is floating or incorrect, double check your pin modes and pin definitions.

Also, try the IL9341 library.. it may well be a better match than the ST7735 library

I vaguely recall one of my no-name cheap displays stating it was a ST77 something or other in the listings, but working with the ILI9341 driver.

The fact that you are getting a response means we are heading in the correct direction.

Its getting late here, so I’ll check back in the morning. Good luck. :D

Rick Kimball Sun Apr 15, 2018 6:05 pm

[carl0s – Sun Apr 15, 2018 1:51 pm] –
I was about to try some code to vary the screen brightness based on the LDR, but, without a serial console, I don’t know what numbers are coming back from analogRead(LDR_PIN), so I don’t know what maths to do for the analogWrite to the TFT_LED.

Am I approaching this properly? Should I come back to it once I have a serial console?

You could use your stlink programmer as a debugger and look at the values in arm-none-eabi-gdb … Al from Hackaday did a nice video describing how to do basic debugging.

https://www.youtube.com/watch?v=D-MbC9N5U7o

carl0s Sun Apr 15, 2018 8:53 pm

[Rick Kimball – Sun Apr 15, 2018 6:05 pm] –
[carl0s – Sun Apr 15, 2018 1:51 pm] –
I was about to try some code to vary the screen brightness based on the LDR, but, without a serial console, I don’t know what numbers are coming back from analogRead(LDR_PIN), so I don’t know what maths to do for the analogWrite to the TFT_LED.

Am I approaching this properly? Should I come back to it once I have a serial console?

You could use your stlink programmer as a debugger and look at the values in arm-none-eabi-gdb … Al from Hackaday did a nice video describing how to do basic debugging.

https://www.youtube.com/watch?v=D-MbC9N5U7o

Ooh, I was wondering about that.

I have also oredered a Black Magic Probe.. sounded like a cool thing to have, certainly for in circuit eeprom reading etc, but maybe more..

carl0s Sun Apr 15, 2018 8:56 pm

[ahull – Sun Apr 15, 2018 5:28 pm] –
Looking good. I suspect there is either a slight speed/timing timing issue, or one of your pins is floating or incorrect, double check your pin modes and pin definitions.

Also, try the IL9341 library.. it may well be a better match than the ST7735 library

I vaguely recall one of my no-name cheap displays stating it was a ST77 something or other in the listings, but working with the ILI9341 driver.

The fact that you are getting a response means we are heading in the correct direction.

Its getting late here, so I’ll check back in the morning. Good luck. :D

Thanks Andy! I think I need to call it a day for today as well.

I think I understand how you’re supposed to use the ILI9341_STM library with SPI2. I told you I was rubbish at C/C++, but.. I think I finally understand that you have to do:

SPIClass mySPI2(2);
Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC);

tft.begin(mySPI2);

stevestrong Sun Apr 15, 2018 9:49 pm

I think you also need to define a third parameter, the reset line:
Adafruit_ILI9341_STM tft(TFT_CS, TFT_DC, TFT_RST);

RogerClark Sun Apr 15, 2018 10:01 pm

Can’t you just use the SPI.setModule(2)

Then your libraries use SPI 2 even when they think they are using SPI 1

carl0s Sun Apr 15, 2018 11:39 pm

[stevestrong – Sun Apr 15, 2018 9:49 pm] –
I think you also need to define a third parameter, the reset line:
Adafruit_ILI9341_STM tft(TFT_CS, TFT_DC, TFT_RST);

carl0s Sun Apr 15, 2018 11:40 pm

[RogerClark – Sun Apr 15, 2018 10:01 pm] –
Can’t you just use the SPI.setModule(2)

Then your libraries use SPI 2 even when they think they are using SPI 1

Tried that too! I’ll get back on it tomorrow with the scope to see if the spi is coming out the MCU.

RogerClark Mon Apr 16, 2018 12:10 am

OK

One thing I don’t think it takes into consideration if that SPI2 max speed is half that of SPI1, but I have used setModule() for some libs and it did work

ahull Mon Apr 16, 2018 6:28 am

[carl0s – Sun Apr 15, 2018 11:40 pm] –
[RogerClark – Sun Apr 15, 2018 10:01 pm] –
Can’t you just use the SPI.setModule(2)

Then your libraries use SPI 2 even when they think they are using SPI 1

Tried that too! I’ll get back on it tomorrow with the scope to see if the spi is coming out the MCU.

I suspect, since you have that “static” pattern, that you are sending *some* commands to the display. They may be mangled, or they may not apply to that particular controller, so we do need to check the waveforms on the pins.

ahull Mon Apr 16, 2018 6:40 am

[Rick Kimball – Sun Apr 15, 2018 6:05 pm] –
[carl0s – Sun Apr 15, 2018 1:51 pm] –
I was about to try some code to vary the screen brightness based on the LDR, but, without a serial console, I don’t know what numbers are coming back from analogRead(LDR_PIN), so I don’t know what maths to do for the analogWrite to the TFT_LED.

Am I approaching this properly? Should I come back to it once I have a serial console?

You could use your stlink programmer as a debugger and look at the values in arm-none-eabi-gdb … Al from Hackaday did a nice video describing how to do basic debugging.

https://www.youtube.com/watch?v=D-MbC9N5U7o

Thanks Rick, I hadn’t spotted that video. Good find.

Sign in to reply