Adventures with I2C & Minerva Mk2

Anything QL Software or Programming Related.
User avatar
t0nyt
QL Wafer Drive
Posts: 1143
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Adventures with I2C & Minerva Mk2

Post by t0nyt »

I thought I'd create a thread on i2c & Minerva Mk2 to document my adventures on the topic in case anyone else wants to have a play now or in the future. Hope that's ok.

The intention is to document the devices I or anyone else tries, and more specifically "quick and dirty" basic programs to prove functionality and later the creation of extensions to super basic in assembler

It's targeted at i2c on a Minerva Mk2 board (either original or a remake https://github.com/alvaroalea/QL_Minerva_MK2) so the basic test programs use i2c_io_bin (which is assumed to have already been lrespr'd)

A remake of the Minerva Mk2
IMG_5021.jpeg
(I'm using 15 pin D connectors for i2c to maintain hardware compatibility with my BBC Model B's i2c)


A 2 x device harness
IMG_5014.jpeg
IMG_5014.jpeg (43.35 KiB) Viewed 200 times

A harness for attaching a device to the 2 x device harness or to the Minerva Mk2 (with an HTU21D attached)
IMG_5016.jpeg
IMG_5016.jpeg (31.55 KiB) Viewed 200 times


User avatar
t0nyt
QL Wafer Drive
Posts: 1143
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Adventures with I2C & Minerva Mk2

Post by t0nyt »

There's a multitude of i2c LCD displays so I chose a simple 4 lines x 20 characters as my first i2c device to try

Having blatantly copied the code by MartinB on StarDot it proved to be straightforward, so I assume other displays will hopefully be just as simple (maybe not the matrix style that I've not tried yet)


A typical 4x20 LCD (with harness attached)
IMG_5018.jpeg

The reverse shows the PCF8574 GPIO extender board for the i2c (this is a TI version with ID &27, NXP's use &3F)
IMG_5019.jpeg
IMG_5019.jpeg (58.94 KiB) Viewed 191 times

A simple basic test program

Code: Select all

30  PROC_INIT
40  DIM M$(80) : M$="SINCLAIR QL                             JS/Minerva v1.98 Mk2i2c LCD Interface   "
50  FOR C=1 TO LEN(M$)
60   D$=M$(C TO C)
70   C%=CODE(D$)
80   H%=(C% && HEX('F0')) || HEX('09')
90   L%=((C%*16) && HEX('F0')) || HEX('09')
100   D%=H%
110   PROC_EN
120   D%=L%
130   PROC_EN
140 NEXT C
150 STOP
160  DEFine PROCedure PROC_INIT
170   DATA HEX('38'),HEX('38'),HEX('38'),HEX('28'),HEX('28'),HEX('88')
175   DATA HEX('08'),HEX('88'),HEX('08'),HEX('18'),HEX('08'),HEX('68')
180   DATA HEX('08'),HEX('E8'),HEX('88'),HEX('08')
190   RESTORE 170
200   FOR D=0 TO 15
210    READ D%
230    PROC_EN
240   NEXT D
250  END DEFine 
260  DEFine PROCedure PROC_EN
270   D%=D% || HEX('04')
280   I2CTXB(D%) : REMark *I2CTXB 3F D%
290   D%=D% && HEX('FB')
300   I2CTXB(D%) : REMark *I2CTXB 3F D%
310  END DEFine 
500  DEFine PROCedure I2CTXB(D%)
510   LOCal r$
520   r$=I2C_IO(CHR$(164) & CHR$(D%) & CHR$(255),0,HEX('27'),1)
530  END DEFine 
Example output
IMG_5020.jpeg
Last edited by t0nyt on Fri Sep 05, 2025 2:23 pm, edited 1 time in total.


User avatar
t0nyt
QL Wafer Drive
Posts: 1143
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Adventures with I2C & Minerva Mk2

Post by t0nyt »

Next up was an HTU-21D Temperature/Relative Humidity sensor

Device id &40
IMG_5017.jpeg
IMG_5017.jpeg (35.78 KiB) Viewed 187 times

This was the first device I tried where information was being read back and it proved to be a difficult learning curve (see post viewtopic.php?t=5402) and hair puller (not that I have that much now) so a big thanks to those who contributed

The main problem, having worked out the i2c_io syntax, was that Minerva Mk2 doesn't implement clock stretching so i2c_io didn't wait for the measurement to be made before trying to read the result. So it was necessary to split the measurement request and read request into separate i2c_io commands and pause in-between them

The test code

Code: Select all

100 c$=CHR$(164) & CHR$(HEX('FE')) & CHR$(255): REMark Soft Reset
110 r$=I2C_IO(c$,0,HEX('40'),1)
120 PAUSE 20 : REMark pause after reset?
130 r$=GetValue("T"): PRINT "Temperature: " & r$ & "c"
140 r$=GetValue("H"): PRINT "Relative Humidity: " & r$ & "%"
150 DEFine FuNction GetValue(V$)
160 LOCal e,v,c$,r$
170 SELect ON V$
180 ="H","h": e=HEX("E5") : REMark Relative Humidity
190 ="T","t": e=HEX("E3") : REMark Temperature
200 END SELect
210 c$=CHR$(164) & CHR$(e) & CHR$(255)
220 r$=I2C_IO(c$,0,HEX('40'),1)
230 PAUSE 200 : REMark WHAT PAUSE NEEDED???
240 c$=CHR$(2) & CHR$(188) & CHR$(255)
250 r$=I2C_IO(c$,3,HEX('40'),1)
300 v=CODE(r$(2 TO 2))
310 v=v&&253 : REMark strip status bits
320 v=v+(CODE(r$)*256)
330 SELect ON V$
340 ="H","h": v=-6+125*(v/65336)
350 ="T","t": v=-46.85+175.72*(v/65536)
360 END SELect
370 v=INT(v*10)/10
400 RETurn v
500 END DEFine

And the output
IMG_5011.jpeg

Because of the timing issues the super basic extension will have options to:
a) Measure/Wait/Read
b) Just Measure
c) Just Read
d) soft reset
Last edited by t0nyt on Fri Sep 05, 2025 7:42 pm, edited 1 time in total.


User avatar
dilwyn
Mr QL
Posts: 3173
Joined: Wed Dec 01, 2010 10:39 pm

Re: Adventures with I2C & Minerva Mk2

Post by dilwyn »

Thank you t0nyt.

I have never dabbled with I2C, but it's still interesting to read about your experiences.


User avatar
t0nyt
QL Wafer Drive
Posts: 1143
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Adventures with I2C & Minerva Mk2

Post by t0nyt »

dilwyn wrote: Fri Sep 05, 2025 5:24 pm Thank you t0nyt.

I have never dabbled with I2C, but it's still interesting to read about your experiences.
I'd heard of i2c but until earlier this year I'd never really looked into it. But am a bit besotted with it now (mainly because I don't have the knowledge to design/build any expansions myself!)

Many thanks
Tony
Last edited by t0nyt on Fri Sep 05, 2025 8:18 pm, edited 1 time in total.


User avatar
t0nyt
QL Wafer Drive
Posts: 1143
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Adventures with I2C & Minerva Mk2

Post by t0nyt »

To save swapping connection harnesses around (or making new ones as it's fiddly work) I've attached one of these breakout boards

It also saves me having to look up my colour codes every time I swap things around too

Will also allow adding more than 2 x i2c devices when playing around (assuming QL can supply enough power!?)

Board with connector to Minerva Mk2 i2c with HTU21D attached
IMG_5023.jpeg


User avatar
t0nyt
QL Wafer Drive
Posts: 1143
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Adventures with I2C & Minerva Mk2

Post by t0nyt »

Next up is an AT24C256

This is a 32KB Non-volatile Memory Module

WARNING: The default ID is &50 which is the SAME device ID as the Minerva Mk2 so MUST be changed
For the purposes of the test programs I enabled jumper A2 which changes the address to &54

The device (with ID still set to &50 which caused all sorts of QL/Minerva problems until changed)
IMG_5025.jpeg
In theory you can have 8 of these devices on the same i2c bus, but because of Minerva's ID you can only have 7

The 32kb is treated as 512 pages x 64 bytes and is addressed with a 15bit address in the commands

So XPPPPPPP PPBBBBBB (where X=Don’t care, P=Page 0 to 511, B=Byte 0 to 63)

Writing can be done as a single byte or up to 64 bytes
Writes are always to a single page and will wrap back to the start of the page if the end is reached (so only the lowest 6 bits of the address are incremented)

Reading can be done as a single byte or multiple bytes either sequentially or randomly (a dummy write is done to move the pointer for random access)

When reading if you don't use a dummy write to put the address pointer where you want it it will use the current position of the internal address pointer. This current address pointer remains over all read/write operations as long as power isn't removed

A simple test of writing and then reading back a single byte

Code: Select all

100 v=123 : REMark byte to write then read
110 a1=0 : REMark msb of address word (bit 8 ignored)
120 a2=0 : REMark lsb of address word
130 REMark Write byte
140 c$=CHR$(164) & CHR$(a1) & CHR$(a2) & CHR$(v) & CHR$(255)
150 r$=I2C_IO(c$,0,HEX('54'),3) : REMark write address + 1 byte
155 PAUSE 15
160 REMark Random access Read Byte (dummy write then read)
170 c$=CHR$(160) & CHR$(a1) & CHR$(a2) & CHR$(255)
180 r$=I2C_IO(c$,0,HEX('54'),2) : REMark position for read
190 c$=CHR$(188) &  CHR$(255)
200 r$=I2C_IO(c$,2,HEX('54'),1) : REMark read byte
210 PRINT CODE(r$) & " : ";
220 IF CODE(r$)<>v THEN PRINT "WRONG VALUE READ!!!"
230 IF CODE(r$)=v THEN PRINT "CORRECT VALUE!!!"
A simple test of writing a string (can also be values) then reading back

Code: Select all

100 v$="This is a test of a Page Write (Max 64 Chars)"
110 a1=0 : REMark msb of address word (bit 8 ignored)
120 a2=0 : REMark lsb of address word
130 REMark Write Page
140 c$=CHR$(164) & CHR$(a1) & CHR$(a2) & v$ & CHR$(255)
150 r$=I2C_IO(c$,0,HEX('54'),LEN(v$)) : REMark write address + string/values
155 PAUSE 15
160 REMark Random access Read Byte (dummy write then read)
170 c$=CHR$(160) & CHR$(a1) & CHR$(a2) & CHR$(255)
180 r$=I2C_IO(c$,0,HEX('54'),2) : REMark position for read
190 c$=CHR$(188) &  CHR$(255)
200 r$=I2C_IO(c$,LEN(v$),HEX('54'),LEN(v$)) : REMark read string/values
210 r$=r$(1 TO LEN(r$)-1): PRINT r$ & " : "
220 IF r$<>v$ THEN PRINT "WRONG VALUES READ!!!"
230 IF r$=v$ THEN PRINT "CORRECT VALUE!!!"


User avatar
NormanDunbar
Forum Moderator
Posts: 2508
Joined: Tue Dec 14, 2010 9:04 am
Location: Buckie, Scotland
Contact:

Re: Adventures with I2C & Minerva Mk2

Post by NormanDunbar »

t0nyt wrote: Sat Sep 06, 2025 4:48 pm WARNING: The default ID is &50 which is the SAME device ID as the Minerva Mk2 so MUST be changed
This sort of implies that the Minerva MK2 can be communicated with, over I2C as a slave/peripheral device rather than as a controller. Anything in the docs to confirm this thought?

A master/controller doesn't need an address.

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
t0nyt
QL Wafer Drive
Posts: 1143
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Adventures with I2C & Minerva Mk2

Post by t0nyt »

NormanDunbar wrote: Sat Sep 06, 2025 7:48 pm
t0nyt wrote: Sat Sep 06, 2025 4:48 pm WARNING: The default ID is &50 which is the SAME device ID as the Minerva Mk2 so MUST be changed
This sort of implies that the Minerva MK2 can be communicated with, over I2C as a slave/peripheral device rather than as a controller. Anything in the docs to confirm this thought?

A master/controller doesn't need an address.

Cheers,
Norm.
Hi Norm

As far as I know it’s just used to address the small amount of memory on the mk2 board that holds the boot options as per miniconfig


martyn_hill
QL Wafer Drive
Posts: 1130
Joined: Sat Oct 25, 2014 9:53 am

Re: Adventures with I2C & Minerva Mk2

Post by martyn_hill »

Hi t0nyt

I recall reading that the Minerva MKII can only act as Master and that ID clash will therefore be with the RTC/NV-RAM device that is fitted alongside the EEPROM and PAL.

Not sure whether the RTC IC can be configured for another ID, but would imagine so...


Post Reply