Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 14:33 02 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MM2: 2.4" SPI Colour Touchscreen

     Page 3 of 3    
Author Message
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 09:51pm 15 May 2015
Copy link to clipboard 
Print this post

  matherp said  
To fix it change I9341.pstring as below:
[code]SUB I9341.pstring(xx0 AS INTEGER, yy0 AS INTEGER, text$, sz AS INTEGER, orientation AS INTEGER, fontcolour AS INTEGER, backgroundcolour AS INTEGER) 'x, y coordinates of top left of first character, text string, size, orientation
if text$<>"" then
LOCAL INTEGER i=I9341draw(I9341.fpstring,I9341_AddrOfFont,xx0,yy0,sz,orientation,fontcolour,backgroundcolour,I9341_params(),text$)
endif
END SUB[/code]

Works a treat Peter, thanks again.

Another query - how would you recommend to input a string from Graeme's modified code that I posted above in the zip file above, i.e. in 'SUB QwertyTest' down near the bottom.

As I've shown it, it sits in a 'Do Loop' so that you can just keep entering characters but of course if the 'key press' is a bit long you end up with multiples of that character. If you're a bit slow entering characters it'll time-out and drop back to the main program with probably only a part of the string you wanted having been entered. You can also test each character at the end of the routine to catch an 'Enter' (i.e. CR) and then return to the main program but the time-out issue is still there. I guess if you could set the 'T.getxy' function flag back to zero that would be a good way to control it but unfortunately you can only do that within the 'T.getxy' function, not another subroutine or the main program.

I'm probably missing something obvious here so be gentle.

Greg



 
centrex

Guru

Joined: 13/11/2011
Location: Australia
Posts: 320
Posted: 12:16pm 16 May 2015
Copy link to clipboard 
Print this post

Hi Matherp
I have to agree with all the previous posts the drivers for the tft displays are fabulous.
My problem is there are so many variations it is hard to keep track of what is what.
Can you put the latest updated version in the MMBasic library.

I am using a 2.8tft with BigMick BP170 interface.

Thanks
Cliff

Cliff
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10181
Posted: 12:04am 17 May 2015
Copy link to clipboard 
Print this post

  Quote  if the 'key press' is a bit long you end up with multiples of that character


This is easy to fix. Just add one line to the top of QwertyTest as follows:


DO
IF T.getxy(xvalues(0),yvalues(0),1000) AND T.getxy(xvalues(1),yvalues(1),1000) AND T.getxy(xvalues(2),yvalues(2),1000) THEN
DO WHILE PIN(T_IRQ)=0:LOOP 'wait for key release before processing
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 03:53am 17 May 2015
Copy link to clipboard 
Print this post

Nice one again Peter, works brilliantly - love these one-line fixes! Now just one more.

How do I tell the QwertyTest subroutine that T.getxy timed out and therefore it shouldn't do the blanking pstring (2nd pstring from the bottom). I'll have to put the blanking pstring back up in the 'backspace' key (<) test section, but that's OK whereas where it is now the timeout wipes anything previously put on that row before the pad string input is started.

I was thinking maybe a new global flag variable would do it, if it was set in T.getxy after a timeout and tested down there at the bottom of QwertyTest. That reduces the 'standalone-ness' of T.getxy though and doesn't seem very elegant.

Greg
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10181
Posted: 07:39am 17 May 2015
Copy link to clipboard 
Print this post

Not sure if I'm missing something because T.getxy already returns a 0 if there was a timeout or non-zero if there was a keypress so:


IF T.getxy(xvalues(0),yvalues(0),1000) AND T.getxy(xvalues(1),yvalues(1),1000) AND T.getxy(xvalues(2),yvalues(2),1000) THEN
' code handling keypress
ELSE
' code handling timeout
ENDIF

 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 04:30am 18 May 2015
Copy link to clipboard 
Print this post

It was me missing something Peter - I'd put the pstrings after the final ENDIF instead of the one before and now the 'flash' at the end of each timeout doesn't happen. The blanking still happens but that's as it should be.
It works pretty well now - code below:

FUNCTION filter(values() AS INTEGER) AS INTEGER
LOCAL INTEGER AB,BC,AC
AB=ABS(values(0)-values(1))
BC=ABS(values(1)-values(2))
AC=ABS(values(0)-values(2))
IF AB<=BC AND AB<=AC THEN filter=(values(0)+values(1))\2
IF BC<=AB AND BC<=AC THEN filter=(values(1)+values(2))\2
IF AC<=AB AND AC<=BC THEN filter=(values(0)+values(2))\2
END FUNCTION
'
SUB I9341_test 'Graeme Meagers Qwertypad with QwertyTest & using Peter Mathers x,y touch coords routine
'modified Greg Yaxley
QwertyPad
DO
QwertyTest
LOOP

SUB QwertyPad 'Graeme's routine for a Qwerty pad
LOCAL INTEGER J
LOCAL STRING Q$
Q$="QWERTYUIOPASDFGHJKL^ZXCVBNM< * .1234567890"
I9341.setrot(I9341_rt_left)
I9341.fillscreen(black)
I9341.drect(0, 0, 320, 240, red)
'--------- This section adds a number row
FOR J = 1 TO 10
I9341.frndrect((J*32)-30,68,29,29,3,yellow)
I9341.pstring((J*32)-22,73,MID$(Q$,J+37,1),3,0,black,yellow)
NEXT J
'---------
FOR J = 1 TO 10
I9341.frndrect((J*32)-30,100,29,29,3,cyan)
I9341.pstring((J*32)-22,105,MID$(Q$,J,1),3,0,black,cyan)
NEXT J
FOR J = 1 TO 9
I9341.frndrect((J*32)-16,132,29,29,3,cyan)
I9341.pstring((J*32)-7,137,MID$(Q$,J+10,1),3,0,black,cyan)
NEXT J
FOR J = 1 TO 10
I9341.frndrect((J*32)-30,164,29,29,3,cyan)
I9341.pstring((J*32)-22,169,MID$(Q$,J+19,1),3,0,black,cyan)
NEXT J
FOR J = 1 TO 2
I9341.frndrect((J*32)-15,196,30,30,3,cyan)
I9341.pstring((J*32)-7,201,MID$(Q$,J+29,1),3,0,black,cyan)
NEXT J
I9341.pstring(17,210,"Shift",1,0,black,cyan)
I9341.frndrect(81,196,160,30,3,cyan)
I9341.pstring(125,210,"SPACE",2,0,black,cyan)
FOR J = 8 TO 9
I9341.frndrect((J*32)-13,196,30,30,3,cyan)
NEXT J
I9341.pstring(243,201,".",3,0,black,cyan)
I9341.pstring(275,211,"Enter",1,0,black,cyan)
I9341.pstring(245,230,"spilcdv2.bas",1,0,green,black)
'I9341.frndrect(10,10,300,80,3,white)
I9341.frndrect(10,2,316,44,3,white)
I9341.pstring(15,15,"The First Line is Here",2,0,Black,White)
I9341.pstring(15,35,"The Second Line is Here",2,0,Black,White)
'I9341.pstring(15,55,"The Third Line is Here",2,0,Black,White)
'I9341.pstring(15,75,"The Fourth Line is Here",2,0,Black,White)
END SUB
' -------Test Touch for QwertyPad-------
SUB QwertyTest
LOCAL INTEGER x0,y0,xvalues(3),yvalues(3)
LOCAL INTEGER SHIFT=1
LOCAL STRING L1$=""
SETPIN 24,DOUT
DO
IF T.getxy(xvalues(0),yvalues(0),1000) AND T.getxy(xvalues(1),yvalues(1),1000) AND T.getxy(xvalues(2),yvalues(2),1000) THEN
DO WHILE PIN(T_IRQ)=0:LOOP 'wait for key release before processing
y0=filter(yvalues())
x0=filter(xvalues())
IF 1400 > x0 AND 1160 < x0 THEN 'Value for number row
IF 1850 > y0 AND 1680 < y0 THEN 'Value for Key 1
Beep
L1$=L1$+"1"
ENDIF
IF 1680 > y0 AND 1510 < y0 THEN 'Value for 2
Beep
L1$=L1$+"2"
ENDIF
IF 1510 > y0 AND 1340 < y0 THEN 'Value for 3
Beep
L1$=L1$+"3"
ENDIF
IF 1340 > y0 AND 1170 < y0 THEN 'Value for 4
Beep
L1$=L1$+"4"
ENDIF
IF 1170 > y0 AND 1000 < y0 THEN 'Value for 5
Beep
L1$=L1$+"5"
ENDIF
IF 1000 > y0 AND 830 < y0 THEN 'Value for 6
Beep
L1$=L1$+"6"
ENDIF
IF 830 > y0 AND 660 < y0 THEN 'Value for 7
Beep
L1$=L1$+"7"
ENDIF
IF 660 > y0 AND 490 < y0 THEN 'Value for 8
Beep
L1$=L1$+"8"
ENDIF
IF 490 > y0 AND 320 < y0 THEN 'Value for 9
Beep
L1$=L1$+"9"
ENDIF
IF 320 > y0 AND 150 < y0 THEN 'Value for 0
Beep
L1$=L1$+"0"
ENDIF
ENDIF
IF 1160 > x0 AND 920 < x0 THEN 'Value for 1st alphas row
IF 1850 > y0 AND 1680 < y0 THEN 'Value for Key Q
Beep
IF Shift=1 THEN L1$=L1$+"Q" ELSE L1$=L1$+"q"
ENDIF
IF 1680 > y0 AND 1510 < y0 THEN 'Value for W
Beep
IF Shift=1 THEN L1$=L1$+"W" ELSE L1$=L1$+"w"
ENDIF
IF 1510 > y0 AND 1340 < y0 THEN 'Value for E
Beep
IF Shift=1 THEN L1$=L1$+"E" ELSE L1$=L1$+"e"
ENDIF
IF 1340 > y0 AND 1170 < y0 THEN 'Value for R
Beep
IF Shift=1 THEN L1$=L1$+"R" ELSE L1$=L1$+"r"
ENDIF
IF 1170 > y0 AND 1000 < y0 THEN 'Value for T
Beep
IF Shift=1 THEN L1$=L1$+"T" ELSE L1$=L1$+"t"
ENDIF
IF 1000 > y0 AND 830 < y0 THEN 'Value for Y
Beep
IF Shift=1 THEN L1$=L1$+"Y" ELSE L1$=L1$+"y"
ENDIF
IF 830 > y0 AND 660 < y0 THEN 'Value for U
Beep
IF Shift=1 THEN L1$=L1$+"U" ELSE L1$=L1$+"u"
ENDIF
IF 660 > y0 AND 490 < y0 THEN 'Value for I
Beep
IF Shift=1 THEN L1$=L1$+"I" ELSE L1$=L1$+"i"
ENDIF
IF 490 > y0 AND 320 < y0 THEN 'Value for O
Beep
IF Shift=1 THEN L1$=L1$+"O" ELSE L1$=L1$+"o"
ENDIF
IF 320 > y0 AND 150 < y0 THEN 'Value for P
Beep
IF Shift=1 THEN L1$=L1$+"P" ELSE L1$=L1$+"p"
ENDIF
ENDIF
IF 920 > x0 AND 680 < x0 THEN 'Value for 2nd alphas row
IF 1760 > y0 AND 1590 < y0 THEN 'Value for Key A
Beep
IF Shift=1 THEN L1$=L1$+"A" ELSE L1$=L1$+"a"
ENDIF
IF 1590 > y0 AND 1420 < y0 THEN 'Value for S
Beep
IF Shift=1 THEN L1$=L1$+"S" ELSE L1$=L1$+"s"
ENDIF
IF 1420 > y0 AND 1250 < y0 THEN 'Value for D
Beep
IF Shift=1 THEN L1$=L1$+"D" ELSE L1$=L1$+"d"
ENDIF
IF 1250 > y0 AND 1080 < y0 THEN 'Value for F
Beep
IF Shift=1 THEN L1$=L1$+"F" ELSE L1$=L1$+"f"
ENDIF
IF 1080 > y0 AND 910 < y0 THEN 'Value for G
Beep
IF Shift=1 THEN L1$=L1$+"G" ELSE L1$=L1$+"g"
ENDIF
IF 910 > y0 AND 740 < y0 THEN 'Value for H
Beep
IF Shift=1 THEN L1$=L1$+"H" ELSE L1$=L1$+"h"
ENDIF
IF 740 > y0 AND 570 < y0 THEN 'Value for J
Beep
IF Shift=1 THEN L1$=L1$+"J" ELSE L1$=L1$+"j"
ENDIF
IF 570 > y0 AND 400 < y0 THEN 'Value for K
Beep
IF Shift=1 THEN L1$=L1$+"K" ELSE L1$=L1$+"k"
ENDIF
IF 400 > y0 AND 230 < y0 THEN 'Value for L
Beep
IF Shift=1 THEN L1$=L1$+"L" ELSE L1$=L1$+"l"
ENDIF
ENDIF
IF 680 > x0 AND 440 < x0 THEN 'Value for 3rd row
IF 1850 > y0 AND 1680 < y0 THEN 'Value for Key SHIFT
Beep
Shift= NOT Shift ':QweryPad
ENDIF
IF 1680 > y0 AND 1510 < y0 THEN 'Value for Z
Beep
IF Shift=1 THEN L1$=L1$+"Z" ELSE L1$=L1$+"z"
ENDIF
IF 1510 > y0 AND 1340 < y0 THEN 'Value for X
Beep
IF Shift=1 THEN L1$=L1$+"X" ELSE L1$=L1$+"x"
ENDIF
IF 1340 > y0 AND 1170 < y0 THEN 'Value for C
Beep
IF Shift=1 THEN L1$=L1$+"C" ELSE L1$=L1$+"c"
ENDIF
IF 1170 > y0 AND 1000 < y0 THEN 'Value for V
Beep
IF Shift=1 THEN L1$=L1$+"V" ELSE L1$=L1$+"v"
ENDIF
IF 1000 > y0 AND 830 < y0 THEN 'Value for B
Beep
IF Shift=1 THEN L1$=L1$+"B" ELSE L1$=L1$+"b"
ENDIF
IF 830 > y0 AND 660 < y0 THEN 'Value for N
Beep
IF Shift=1 THEN L1$=L1$+"N" ELSE L1$=L1$+"n"
ENDIF
IF 660 > y0 AND 490 < y0 THEN 'Value for M
Beep
IF Shift=1 THEN L1$=L1$+"M" ELSE L1$=L1$+"m"
ENDIF
IF 490 > y0 AND 320 < y0 THEN 'Value for Backspace
Beep
IF LEN(L1$) > 0 THEN
L1$=LEFT$(L1$,(LEN(L1$)-1))
ENDIF
ENDIF
ENDIF
I9341.pstring(15,15," ",2,0,red,white)
I9341.pstring(15,15,L1$,2,0,red,white)
ENDIF
LOOP
SETPIN 24,OFF
END SUB
'
SUB Beep
PIN(24)=1:PAUSE 20:PIN(24)=0 'flash LED
END SUB
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2931
Posted: 06:32am 18 May 2015
Copy link to clipboard 
Print this post

Thanks Greg for sharing your final code; glad you (and Peter) got it going - very useful to see it
 
Zonker

Guru

Joined: 18/08/2012
Location: United States
Posts: 767
Posted: 11:08am 18 May 2015
Copy link to clipboard 
Print this post

YES..! More UI Objects... Awesome work Gent's..!
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 12:32am 19 May 2015
Copy link to clipboard 
Print this post

Mostly thanks to Graeme Meager and Peter Mather actually gents, I didn't do much. The 'backspace' (<) works properly though now and the artefact is fixed.
One thing I should have included in the above code is the change Peter suggested to 'pstring', i.e. change Peter's original 'pstring' subroutine to:

SUB I9341.pstring(xx0 AS INTEGER, yy0 AS INTEGER, text$, sz AS INTEGER, orientation AS INTEGER, fontcolour AS INTEGER, backgroundcolour AS INTEGER) 'x, y coordinates of top left of first character, text string, size, orientation
IF text$<>"" THEN
LOCAL INTEGER i=I9341draw(I9341.fpstring,I9341_AddrOfFont,xx0,yy0,sz,orientation,fontcolour,backgroundcolour,I9341_params(),text$)
ENDIF
END SUB


Greg
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 03:22am 19 May 2015
Copy link to clipboard 
Print this post

  centrex said  ....My problem is there are so many variations it is hard to keep track of what is what.
....I am using a 2.8tft with BigMick BP170 interface.
Cliff

Hi Cliff,
Not sure if you've got your 2.8" screen going yet but the following might help. I'm assuming it's the same ILI9341 SPI one that Mick mentioned in this thread (9/4/15 6:51 am). I don't have a 2.8" but Mick said the pinout is the same as the 2.4" version and it's the same 240x320 resolution.

There are two connections to each of the MX170's fixed SPIin, SPIout and SPIclk pins (14, 3 and 25 resp.) because of the two controllers (LCD and Touch) on the screen. The other five control lines are shown below on pins 2, 4, 5, 6, and 7, of the 170 but can be assigned to what you want in Peter's code. The connections I'm using are from 'twofingers' post in this thread (16/2/15 11:04pm) as below.

This 2015-05-19_115415_QwertyPadTest.zip is the code I'm using. You should be able to see the Qwerty pad if you just run the program but you'll need to calibrate your 2.8" raw touch screen positions (x,y,max,min) using the appropriate program from Peter's first post of this thread first. Next you'll need to change Graeme's ranges for the different row and key positions in the QwertyTest subroutine to match your scaled touch parameters obtained using the calibration program. Once at this point you should be able to see the correct keys you touch print on the first line - they're stored in L1$ and the 'backspace' also works properly.

Greg


SPI interface: ILI9341S controller

MX170 uM2 2.4" Touch LCD
28 Pin Display PCB Pin
----------------------------------
Vcc (3.3v)–––––– 1 VCC (3.3V)
GND––––––––––––– 2 GND
2–––T_IRQ––––––– 14 T_IRQ
3–––SPIout–––––– 6 SDI(MOSI)
3–––SPIout-T–––– 12 T-DIN
4–––I9341_CD–––– 5 D/C
5–––I9341_RESET– 4 RESET
6–––I9341_CS–––– 3 CS
7–––T_CS–––––––– 11 T_CS
14––SPIin––––––– 9 SDO(MISO)
14––SPIin-T––––– 13 T-DO
25––SPI CLK––––– 7 SCK
25––SPI CLK-T––– 10 T-CLK
8 LED (direct to 3.3v)
---------------------------------------------
T = Touch-screen signal


 
centrex

Guru

Joined: 13/11/2011
Location: Australia
Posts: 320
Posted: 10:32pm 19 May 2015
Copy link to clipboard 
Print this post

Hi paceman
I have the display working fine, its just there seems to a lot of changes to the code that are hard to keep up with (all due respect to matherp).
Maybe with Ver 4.7 Beta now out it wont be a problem as one would just wait for updates, it appears to use Peters code which works very well.
Thanks for your input.

regards
Cliff
Cliff
 
disco4now

Guru

Joined: 18/12/2014
Location: Australia
Posts: 1000
Posted: 02:36am 20 May 2015
Copy link to clipboard 
Print this post

Hi paceman,

I have been using the touch screen interrupt driven in one on my programs.
The main changes are when you set the SETPIN T_IRQ use:

SETPIN T_IRQ,INTL,QwertyTest,pullup 'Use interrupt driver touch

This will call your QwertyTest whenever a key is pressed.
The DO LOOPS that continually call it are then not need.
Your program sets up the interrupt and writes the keyboard layout, then does nothing at all until a key is pressed.

The advantage is its free to do other stuff if you want, and the key is displayed immediately when pressed but only once unless the press is released and pushed again.

As the program is not stuck in the QwertyTest continually, but called new each time, a couple of the local variables need to be made global

I have modified it to run interrupt driven.

2015-05-20_123245_QwertyPadTestInterrupt.zip

Hope it useful
Regards
Gerry

Latest F4 Latest H7 FotS
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 03:19am 20 May 2015
Copy link to clipboard 
Print this post

Thanks Gerry, that sounds very neat. I've just re-programmed my current MX170 setup to V4.7 beta3 to give that a try so I'll need to re-hash things a bit to give yours a try. I'll report back when I've set things up and tried it.

Greg
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 03:31am 20 May 2015
Copy link to clipboard 
Print this post

  centrex said   Hi paceman
I have the display working fine, its just there seems to a lot of changes to the code that are hard to keep up with (all due respect to matherp). Maybe with Ver 4.7 Beta now out it wont be a problem as one would just wait for updates, it appears to use Peters code which works very well.
Thanks for your input.
Cliff

Hi Cliff,

Yes, it's a bit academic now that Geoff's released the V7 betas so I'll just go with them now too. It was getting a bit confusing but I'd been following it pretty closely for a while using a 170 and a 470 so I (mostly) knew where I was at. Peter no doubt would have been working closely with Geoff on it so putting time into documenting all the earlier versions would have been a bit of a waste when he knew V1.7 was imminent.

Greg
 
Bizzie
Senior Member

Joined: 06/07/2014
Location: Australia
Posts: 192
Posted: 10:53am 03 Oct 2015
Copy link to clipboard 
Print this post

I'll ask my question here as it relates to the 2.4" SPI TFT display.
How much current does a typical display draw?

Or putting it another way can I power a display and piggy backed 28 pin mite (on BigMicks Backpack 170 board) off the 5v (500mA) supply available from a CGCOLORMAX 2?

Rob

Rob White
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1566
Posted: 11:16am 03 Oct 2015
Copy link to clipboard 
Print this post

  Bizzie said   I'll ask my question here as it relates to the 2.4" SPI TFT display.
How much current does a typical display draw?

Or putting it another way can I power a display and piggy backed 28 pin mite (on BigMicks Backpack 170 board) off the 5v (500mA) supply available from a CGCOLORMAX 2?

Rob

Yes!

Edit:
With back light (100%) about 150mA.Edited by twofingers 2015-10-04
causality ≠ correlation ≠ coincidence
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 07:47pm 03 Oct 2015
Copy link to clipboard 
Print this post

My 2.4" pulled a lot less than that, about 45mA at 3.3v without a limiting resistor. See the posts on this thread on 13 March 2015 at 10:58pm.

Greg
 
bigmik

Guru

Joined: 20/06/2011
Location: Australia
Posts: 2947
Posted: 08:25pm 03 Oct 2015
Copy link to clipboard 
Print this post

Hi Rob,

In my testing for the BackPack170, the backlight drew between 65 to 80mA and the entire board came it at 140-150mA including the backlight drive.

That was at a standard 40MHz

Well within the capability of a 500mA drive power source.

Regards,

Mick
Mick's uMite Stuff can be found >>> HERE (Kindly hosted by Dontronics) <<<
 
Bizzie
Senior Member

Joined: 06/07/2014
Location: Australia
Posts: 192
Posted: 09:51pm 03 Oct 2015
Copy link to clipboard 
Print this post

Thanks all,

Will continue my development.

Regards

Rob

Rob White
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 946
Posted: 02:25am 18 Apr 2016
Copy link to clipboard 
Print this post

Hi to all:

Is there a version of QwertyPadTestInterrupt which works on Mick's BackPack170 and MMBasic V5.1?

It seems that some things has changed...

THANKS!

Frank
 
     Page 3 of 3    
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025