SC126 BASIC port input question

231 views
Skip to first unread message

Vince Mulhollon

unread,
Aug 24, 2021, 5:26:46 PM8/24/21
to retro-comp
I'm planning on having some I2C fun using 5V parts and a SC126 and probably interpreted basic because its easy (well aware there's other options)

I have a question about basic use of input ports.

As some background my sc126 works fine; I can use RTC.COM to set and read the onboard RTC and that uses the same port as the I2C pins.  In mbasic I can OUT 13,whatever to turn the onboard LEDs on and off.  So apparently my hardware is fine, from basic I can output port 13 (decimal) to control the LEDs and the dedicated RTC.COM software can easily access the RTC which is on the same port as the I2C as I understand it.

There's an old post from Aug 29 2020 from Anna Christina about using a SC126 and SPO256 along the lines of:
"I'm using Microsoft BASIC from the RomWBW ROM and when issueing "PRINT INP(&H20)", I always get 32 back."

Well I see the same problem, INP(anyportnumber) returns the port number, all the time.  So PRINT INP(12) always returns 12, instead of the RTC/I2C/other port data.

I expected to see binary 10001101 as per I2CDemov2.0.0.asm but whatever.  Basically the MSB is the SDA pins and LSB is the SCL pins.

OK maybe a software problem with mbasic 5.21 on a romwbw eeprom burned a year or two ago.  Thats fine, plenty of BASICs out there.

I was using mbasic.com from the romwbw aka version 5.21,  so I went to 
and downloaded obasic.com and xmodem it across to my sc126.

Now I can run MS Basic version 4.51.  And I get exactly the same confusing behavior.

So I think there's something "basic"  (oh the puns) I'm conceptually missing about inputing from raw ports in BASIC.

Any obvious hint for me?

I see other people have done I2C experiments using assembly on the SC126 so I could do the same; I was just intrigued by the idea of using interpreted basic.

Thanks and have a great day!

Fred Weigel

unread,
Aug 24, 2021, 6:03:18 PM8/24/21
to retro-comp
Just curious:

A>DDT
DDT VERS 2.2
-A100
0100  IN 0C
0102  NOP
0103
-G100,102
*0102
-X

You should get something like:

C0Z0M0E0I0 A=00 B=0000 D=0000 H=0000 S=0100 P=0102 NOP

What is your A register? (assuming 12 is the I2C port).

There really isn't anything strange about MBASIC 5.21 here. 4.51 is old, and even the syntax is a bit different.
but, 5.21 should be just fine. But... it is 8080 code -- NOT Z80 code. In 8080 code, there is only IN port where
port is a constant. MBASIC (both 4.51 and 521) build a IN port instruction with the port passed in the INP()
function, and execute it. But, that should be fine. Doing the I/O in DDT will tell us if it is the port. If the DDT
works, we need to look at the MBASIC code itself.

I don't really have the answer, but I am very curious about this...
FredW

Vince Mulhollon

unread,
Sep 11, 2021, 4:45:50 PM9/11/21
to retro-comp
On Tuesday, August 24, 2021 at 5:03:18 PM UTC-5 fridtjof.ma...@gmail.com wrote:
I don't really have the answer, but I am very curious about this...
FredW

 In summary, there were multiple layers of problems, all solved.  

I knew the RTC works and historically I've built entire I2C libraries using nothing more than a jumper to figure out how to bit bang SDA/SCL, but this time I needed to break out the multimeter to make it all work.

For arbitrary wiring reasons the device I'm trying to interface is to my left if you hold the SC126 LED's toward you, and port P1 aka P11 is on the opposite side of the board so I was using multiple perfectly good ports on the left side of the board.

First mistake was drawing 5 volts for my device off P16 on the left side of the board.  Then I can verify I can read SDA by jumpering it to either +5 or gnd.  Naturally this did not work very well because I had not jumpered P7 so no 5V at P16 to tap.  So when I read SDA it always reads zero regardless if I connect to power or go open circuit because I was connecting it to open circuit or open circuit.  I changed my wiring to pull 5V off P7

Second cascaded mistake was reading the pinout of JP5 from the perspective of LEDs in the lower right side and expansion port on left side and IO to the top/back which seems rational.  However that means I was tapping into SDA on the S3 side.  Rotate how you read JP5 to match the silkscreen and now I'm connected to actual SDA.

Now any time I short SDA to +5 I see the MSB of port 12 go to 1, in mbasic or ddt, working much better now.  Open circuit it reads a zero.  The schematic shows a pull up resistor on SDA not a pull down resistor... is this an inverting input or something?

Third cascaded mistake was I am used to I2C SDA interfaces on other devices idling at Vcc/1 and I see in the schematic that indeed there is a resistor R20 10K pull up to 1.  So why is my SDA acting like there's a pull down to ground?  Remember the RTC does indeed work, so obviously I2C is working...  As powered up, Q7 of U6 is low, which feeds the active low output enable of U11.1, so on power up the output of U11.1 is trying to transmit a zero which I do indeed see when no input connected to SDA.  Apparently my 10K resistor can't force a 74125 outputing zero to high, but a short circuit to VCC certainly can force it to 1 which can be read by the input LOL.  Now if I output a 1 to MSB of port 12, that drops "transmit mode" trying to output a 0, and the pull up resistor pulls up, so reads to unconnected SDA NOW shows a 1 and I can short it to ground simulating a device trying to send a 0 bit and inputs work great in DDT and mbasic.

So I understand the SDA.  To receive on SDA, output a MSB bit of 1 to port 12 to exit "TX mode" and input port 12 and look at the MSB to see if 1 or 0.  To transmit on SDA, output a MSB bit 1 to port 12 to let it float high, or output a MSB bit 0 to port 12 to have U11.1 pull it low.  On power up, unlike most I2C interfaces, it powers up in "transmit a continuous 0 on SDA" mode.  I don't think the device I'm trying to interface cares, so far.

The SCL signal is much simpler.  Control SCL using LSB of port 12.  Because you probably want to leave SDA in receive mode while manipulating the clock, you output a 128 to port 12 to send a SCL low and output a 129 to port 12 to send a SCL high.

So in summary, at least on the hardware side, pay attention to P7 if you're trying to use VCC of P16, try to read the pinout of JP5 as its written on the silkscreen not how you hold the board, and don't assume the I2C is like real hardware I2C, it powers up transmitting a 0 on SDA and stuff like that.  But otherwise, it works just fine as a 5 volt I2C bit bang interface.

And in summary, at least on the software side, if you're trying to write your own homemade bit banged I2C library in mbasic or whatever: Port 12: Output MSB=1 to shut off the SDA 0 transmitter, MSB=0 to transmit SDA=0.  Output LSB bit to set SCL output.  Read and look at MSB to see what is on SDA IF the 0 transmitter had been shut down.

Finally life would be simpler if using port P1 or P11 for I2C, but I'm doing it the hard way pulling 5V from P7, ground from P16, SDA/SCL from JP5, and it works.

I haven't actually written my mbasic I2C library but I think I have a handle on using the I2C pins now.

Thanks and Have a great day!

Kevin Price

unread,
Sep 29, 2021, 12:13:00 PM9/29/21
to retro-comp
I discovered this same behavior in mbasic, and Fred's post helped me figure out what was going on. At least I think. The contents of register A get put on the upper byte of the address bus for the IN opcode used here (DF). This causes issues with reading the internal registers, and some values in A (DB is one) cause the io operation to return the value of the port read.


The z180 manual on page 11 and 12 state that the high order byte MUST be zero to access the internal registers. Patching MBASIC is beyond my current skill level. When I have more time I will try to figure out how to make a CALLable machine language routine to read an internal port.  

You can replicate the behavior in ddt:

-a100
0100  mvi a,df
0102  in df
0104  nop
0105   
-g100,104
*0104
-x
C0Z0M1E0I0 A=DF B=0000 D=0000 H=0000 S=0100 P=0104 NOP  

-a100
0100  mvi a,c0
0102  in 28
0104  nop
0105          
-g100,104
*0104
-x
C0Z0M1E0I0 A=28 B=0000 D=0000 H=0000 S=0100 P=0104 NOP

vs zeroing:
-a100
0100  mvi a,0
0102  in df
0104  nop
0105       
-g100,104
*0104
-x
C0Z0M1E0I0 A=80 B=0000 D=0000 H=0000 S=0100 P=0104 NOP

Mark T

unread,
Sep 29, 2021, 1:00:46 PM9/29/21
to retro-comp

Try :

Ld bc,0x00nn
In a,(c)

This should put the 00 from the b register on the high address lines for the input instruction.

Mark

Kevin Price

unread,
Sep 29, 2021, 3:20:09 PM9/29/21
to retro-comp
So the basic I came up with (disk and extended only):
10 DATA 78,175,71,237,120,119,35,54,0,201
15 DIM S%(10)
16 FOR I%=0 TO 9: READ F:ADD%=VARPTR(S%(0))+I%: POKE ADD%,F:NEXT I%
17 B%=222
18 MYROUT=VARPTR(S%(0))
19 CALL MYROUT(B%)
20 PRINT B%

B% contains the port to read going into the call, and contains the result on return. Fred had some ideas about how to do it in rom basic, and I'll try them later. Love to see improvements people make.

assembled instructions were:
 ld c,(hl)
 xor a
 ld b,a
 in a,(C)
 ld (hl), a
 inc hl
 ld (hl),0
 ret
Reply all
Reply to author
Forward
0 new messages