Adventures with I2C & Minerva Mk2
Adventures with I2C & Minerva Mk2
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 (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
A harness for attaching a device to the 2 x device harness or to the Minerva Mk2 (with an HTU21D attached)
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 (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
A harness for attaching a device to the 2 x device harness or to the Minerva Mk2 (with an HTU21D attached)
Re: Adventures with I2C & Minerva Mk2
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)
The reverse shows the PCF8574 GPIO extender board for the i2c (this is a TI version with ID &27, NXP's use &3F)
A simple basic test program
Example output
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)
The reverse shows the PCF8574 GPIO extender board for the i2c (this is a TI version with ID &27, NXP's use &3F)
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
Last edited by t0nyt on Fri Sep 05, 2025 2:23 pm, edited 1 time in total.
Re: Adventures with I2C & Minerva Mk2
Next up was an HTU-21D Temperature/Relative Humidity sensor
Device id &40
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
And the output
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
Device id &40
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
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.
Re: Adventures with I2C & Minerva Mk2
Thank you t0nyt.
I have never dabbled with I2C, but it's still interesting to read about your experiences.
I have never dabbled with I2C, but it's still interesting to read about your experiences.
--
All things QL - https://dilwyn.theqlforum.com
All things QL - https://dilwyn.theqlforum.com
Re: Adventures with I2C & Minerva Mk2
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!)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.
Many thanks
Tony
Last edited by t0nyt on Fri Sep 05, 2025 8:18 pm, edited 1 time in total.
Re: Adventures with I2C & Minerva Mk2
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
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
Re: Adventures with I2C & Minerva Mk2
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) 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
A simple test of writing a string (can also be values) then reading back
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) 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!!!"
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!!!"
- NormanDunbar
- Forum Moderator
- Posts: 2508
- Joined: Tue Dec 14, 2010 9:04 am
- Location: Buckie, Scotland
- Contact:
Re: Adventures with I2C & Minerva Mk2
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?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
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.
Author of Arduino Software Internals
Author of Arduino Interrupts
No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
Re: Adventures with I2C & Minerva Mk2
Hi NormNormanDunbar wrote: Sat Sep 06, 2025 7:48 pmThis 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?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
A master/controller doesn't need an address.
Cheers,
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
-
- QL Wafer Drive
- Posts: 1130
- Joined: Sat Oct 25, 2014 9:53 am
Re: Adventures with I2C & Minerva Mk2
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...
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...