English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 17 March 2020, 16:35   #1
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
Accessing the Amiga CD32 NVRAM directly

I need to access the Amiga CD32 NVRAM directly (nonvolatile.library is not an option), so I searched around for information and I've found basically none. So I looked at a few photos of the Amiga CD32 motherboard somebody kindly posted on the net and found out that the EEPROM is an ATMEL AT24C08N-10SC. I downloaded the official datasheet (attached here for your convenience) and started typing my code...
Getting it to work on UAE was fairly easy. But then it turned out that things work differently on a real machine - and, as a consequence, my code doesn't work. Since I don't have an Amiga CD32, I pestered a friend who patiently ran tens of tests for me. Unfortunately I caught him in the middle of an insanely busy period, so things proceeded very slowly. In the end, after more than one month, I gave up and decided to ask for help here.

The (one?) problem seems to be that reading bits doesn't work. In the best case, I managed to read the ACK (0) returned when a START condition is generated (when even that doesn't work, the code hangs in an endless loop), but then getting 1 with all the following reads.
Additional details:
* the tests have been performed after taking the machine over entirely;
* the tests have been performed after letting AmigasOS/nonvolatile.library initialize the EEPROM;
* performing also an EEPROM reset upon initialization did not make any difference;
* I've tried all the bit-reading code variants I could think of to no avail;
* alternative code that has the SDA direction always set to input (except where output is strictly needed) gave even worse results.

Attached are also my source code files:
* NVRAM-test.s: code with all the bit-reading code variants I tried (see function ReadBit()), plus various writes to $dff180 to follow the code execution;
* NVRAM-clean.s: same code, but with only the variant that theoretically makes more sense (and works in WinUAE).
The code is fully commented and provides futher details.

One important thing to mention is that the datasheet at some point says something impossible.
Main points:
* there are two wires, SCL (the clock, driven by the CPU) and SDA (the data);
* any operation must start with a START condition, which happens when SDA is pulled low (0) while SCL is high (1);
* for random reads, after telling the EEPROM where to start reading from and getting the ACK from it, it is necessary to generate a REPEATED START condition;
* the ACK consists in a 0 received over the SDA wire, and given that SDA is active high, it means that, after receiving the ACK, SDA is low;
* the datasheet shows the REPEATED START happening in the next 1 cycle, which is impossible given that SDA is low!
Here's a picture that shows it (the marked START is the REPEATED START).


(click to enlarge)

According to this picture, in the single REPEATED START cycle SDA has to go from low to high and then from high to low (while SCL is held high, otherwise an additional cycle would be executed). Now, apart from the fact that I can't see how the chip can sense both changes with SCL staying high, pulling SDA high while SCL is high is the specular operation of START and, in fact, it's a STOP, so doing that actually aborts the operation. In this context, that should be fine because the random read is actually the combination of two operations: the beginning of a random write, to provide the address to start reading from, and a sequential read, which reads multiple bytes from the currently latched address. So, in theory, aborting the write and starting a sequential read should work just fine (and in UAE it does). In practice, the tests reported the opposite.
Therefore, I tried with an extra cycle:
1. pull SCL low;
2. pull SDA high (so now SDA is high without generating a STOP condition);
3. pull SCL high;
4. pull SDA low (this generates the START condition for the read).
This gave the exact same result on both WinUAE and the real machine.

For completeness, a couple of words about the memory reset. The procedure indicated in the datasheet is:
"After an interruption in protocol, power loss or system reset, any 2-wire part can be reset by following these steps:
1. Clock up to 9 cycles.
2. Look for SDA high in each cycle while SCL is high.
3. Create a start condition."


Step 3 looks quite weird. If taken literally, it means that when a read or write operation starts, a second START condition has to be generated - pretty odd. Anyway, I've tried both with and without step 3, and the results were exactly the same.

So, what am I missing? Thanks in advance for your help.
Attached Files
File Type: pdf Amiga CD32 EEPROM.pdf (310.1 KB, 94 views)

Last edited by saimo; 09 July 2021 at 09:56.
saimo is offline  
Old 17 March 2020, 17:19   #2
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 46
Posts: 25,034
My first guess is that when reading from the chip, data direction must be kept in input mode all the time. Chip probably detects changing data line state when data direction is changed. Probably also data state and direction change must be done in correct order to prevent glitches.

Emulation (EEPROM emulation part is from qemu) probably ignores bad states where real chip most likely means undefined behavior. Emulation has logging that may help (recompile is needed to enable them) but most likely these problems are caused by some undocumented Akiko behavior when data direction changes or something similar... I can quickly run it if you attach executable binary.
Toni Wilen is offline  
Old 17 March 2020, 17:35   #3
hooverphonique
ex. demoscener "Bigmama"

 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,286
If you think the explanation is bad, just find one for a different I2C part, the protocol is always the same.

Read the I2C wiki page, it has a specific example for eeproms, and also explains the protocol.

What kind of interface is there from the Amiga side, by the way? Is the eeprom just connected to a couple of Akiko GPIO's, or does it have a dedicated I2C controller?

Edit: a repeated start is the same wire state as START, by way, it just means that bus doesn't go idle between the repeated start and the previous transaction.

Last edited by hooverphonique; 17 March 2020 at 17:40.
hooverphonique is offline  
Old 17 March 2020, 17:37   #4
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
Thanks for the quick reply, Toni!

Quote:
Originally Posted by Toni Wilen View Post
My first guess is that when reading from the chip, data direction must be kept in input mode all the time. Chip probably detects changing data line state when data direction is changed.
At some point I thought so, too, so I modified the whole code to have SDA set to input except when sending data, but that broke things even in WinUAE. So I settled for the version where the direction is always output and I keep track of the SDA state in the NVRAM_LastBit variable, so that it is never changed inadvertedly.

Quote:
Probably also data state and direction change must be done in correct order to prevent glitches.
I agree. Indeed, the various versions of ReadBit() exist precisely because I suspected the same.

Quote:
Emulation (EEPROM emulation part is from qemu) probably ignores bad states where real chip most likely means undefined behavior. Emulation has logging that may help (recompile is needed to enable them) but most likely these problems are caused by some undocumented Akiko behavior when data direction changes or something similar...
Agreed as well.

Quote:
I can quickly run it if you attach executable binary.
Later I'll whip up a test proggie and post it here.
saimo is offline  
Old 17 March 2020, 17:42   #5
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
Quote:
Originally Posted by hooverphonique View Post
If you think the explanation is bad, just find one for a different I2C part, the protocol is always the same.
I looked also at the datasheet of the same chip produced by STM, and that explanation is even worse! It was redundant and badly worded. It explains better only how the operation start works.

Quote:
Read the I2C wiki page, it has a specific example for eeproms, and also explains the protocol.
Thanks for the pointer, but it is not a problem of understanding the protocol here.

Quote:
What kind of interface is there from the Amiga side, by the way? Is the eeprom just connected to a couple of Akiko GPIO's, or does it have a dedicated I2C controller?
Akiko provides two registers, one for data and one for direction (you can see it from the code I posted).
saimo is offline  
Old 17 March 2020, 17:47   #6
hooverphonique
ex. demoscener "Bigmama"

 
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,286
Quote:
Originally Posted by saimo View Post
I looked also at the datasheet of the same chip produced by STM, and that explanation is even worse! It was redundant and badly worded. It explains better only how the operation start works.
I didn't mean the same type of chip by a different manufacturer, but any chip using the I2C protocol (and not necessarily an eeprom either)
hooverphonique is offline  
Old 17 March 2020, 21:30   #7
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
Quote:
Originally Posted by hooverphonique View Post
I didn't mean the same type of chip by a different manufacturer, but any chip using the I2C protocol (and not necessarily an eeprom either)
Ah, OK, sorry.
Well, I had also looked at the datasheet of an ATMEL EEPROM of 64+ kB, and there the diagram did feature the extra cycle
saimo is offline  
Old 17 March 2020, 21:36   #8
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
@Toni

Quote:
Originally Posted by saimo View Post
Later I'll whip up a test proggie and post it here.
I have reimplemented ReadByte() this way:

Code:
************************************************************************************************************************
* INFO              Reads a byte.
*
* IN                a0.w                source address in [0, 1023]
*                   a2.l                CB_CIAA + RO_CIA_PRA
*                   a3.l                CB_AKIKO + RO_NVRAMSIG
*                   a4.l                CB_AKIKO + RO_NVRAMDIR
*
* OUT               d0.b                byte
*
* TRASH             d3/d4
************************************************************************************************************************

ReadByte            move.b              #NM_SCL,(a4)        ;set NVRAMDIR.SDA to input
                    bsr                 delay               ;(to be safe)
                    moveq.l             #7,d3               ;set counter

.read               clr.b               (a3)                ;pull SCL low
                    bsr                 delay
                    move.b              #NM_SCL,(a3)        ;pull SCL high
                    bsr                 delay
                    move.b              (a3),d0             ;read data
                    lsl.b               #2,d0               ;put SDA in ccr.X
                    addx.b              d4,d4               ;shift ccr.X in
                    dbra                d3,.read            ;pass to next bit

                    move.b              d4,d0               ;get result
                    lsl.b               #7,d4
                    lsr.b               #1,d4
                    move.b              d4,NVRAM_LastBit    ;store last bit
                    move.b              #NM_SCL|NM_SDA,(a4) ;set NVRAMDIR.SDA to output
                    bsr                 delay               ;(to be safe)
                    rts
As you can see, the data direction is changed only before and after reading all the bits.
On WinUAE it works in the context of both the bigger program I'm doing all this for and the test proggie.

You can find the latter attached here. It takes over the system, dumps the NVRAM to RAM:NVRAM.raw, restores the system, and quits.
I'm sending it to my tester, too, and when I have a response I'll let you know.

Last edited by saimo; 09 July 2021 at 09:56.
saimo is offline  
Old 17 March 2020, 21:37   #9
kamelito
Zone Friend

kamelito's Avatar
 
Join Date: May 2006
Location: France
Posts: 1,426
Why not disassemble the lowlevel library to understand how CBM did it?
kamelito is offline  
Old 17 March 2020, 22:00   #10
jotd
This cat is no more
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 50
Posts: 5,776
psygore has written some nvram lib in asm, and this time he provided the source code.

I didn't use it in CD32load because I think CD32 NVRAM is too small and there will be conflicts between games (the NVRAM is made to play one game to the end, then play another, deleting previous game data), but I'm pretty sure it's very good given the quality of Psygore prods.
jotd is offline  
Old 17 March 2020, 22:25   #11
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
Quote:
Originally Posted by kamelito View Post
Why not disassemble the lowlevel library to understand how CBM did it?
I have a personal barrier against reading others' code (it's psycologically excruciating to me... I don't know how to explain). Besides, who knows about the quality of that code? What if it contains some weird hack that could only confuse me? I prefer the approach I'm following.
But thanks for the suggestion.
saimo is offline  
Old 17 March 2020, 22:27   #12
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
Quote:
Originally Posted by jotd View Post
psygore has written some nvram lib in asm, and this time he provided the source code.


I didn't use it in CD32load because I think CD32 NVRAM is too small and there will be conflicts between games (the NVRAM is made to play one game to the end, then play another, deleting previous game data), but I'm pretty sure it's very good given the quality of Psygore prods.
I didn't know, but anyway I need/want the code to be really minimal, so that it does only what I strictly need. Plus, I like doing things myself
saimo is offline  
Old 20 March 2020, 15:16   #13
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
OK, I have the results of a few tests. Before reporting them, a quick note.

Before getting bytes reading to work (which is what the new version of the ReadByte() function tries do to), it is necessary to be able to read single bits, as when an operation is started the ACK from the EEPROM needs to be read. The test code I posted in the OP basically tries all these cases:
1. set SDA to input -> pull SCL low -> pull SCL high -> read SDA -> set SDA to output;
2. pull SCL low -> set SDA to input -> pull SCL high -> read SDA -> set SDA to output;
3. pull SCL low -> pull SCL high -> set SDA to input -> read SDA -> set SDA to output.

To me, only the first one makes sense. And yet it's the one that on a real Amiga CD32 returns 1 when reading the ACK, which should be 0. So either bit reading doesn't work, or the EEPROM is actually returning a NACK (I'll deal with the latter case later). Therefore, it dawned on me that there was still a case left: setting SDA to input and pulling SCL low at the same time, with a single longword write to both the registers involved. So, I have modified ReadBit() to do this:

set SDA to input and pull SCL low -> pull SCL high -> read SDA -> set SDA to output
Code:
ReadBit     move.l  #NM_SCL<<8,(a3)     ;set NVRAMDIR.SDA to input and pull SCL low (NM_SCL<<8 = $00008000)
            bsr     delay
            move.b  #NM_SCL,(a3)        ;pull SCL high
            bsr     delay
            move.b  (a3),d4             ;read data
            move.b  #NM_SCL|NM_SDA,(a4) ;set NVRAMDIR.SDA to output
            andi.b  #NM_SDA,d4          ;isolate bit
            move.b  d4,NVRAM_LastBit    ;store bit
            rts
I did the same also for ReadByte():
Code:
ReadByte    moveq.l #7,d3               ;set counter

.read       move.l  #NM_SCL<<8,(a3)     ;set NVRAMDIR.SDA to input and pull SCL low
            bsr     delay
            move.b  #NM_SCL,(a3)        ;pull SCL high
            bsr     delay
            move.b  (a3),d0             ;read data
            lsl.b   #2,d0               ;put SDA in ccr.X
            addx.b  d4,d4               ;shift ccr.X in
            dbra    d3,.read            ;pass to next bit

            move.b  d4,d0               ;get result
            lsl.b   #7,d4
            lsr.b   #1,d4
            move.b  d4,NVRAM_LastBit    ;store last bit
            move.b  #NM_SCL|NM_SDA,(a4) ;set NVRAMDIR.SDA to output
            bsr     delay               ;(to be safe)
            rts
For the tests, I used the single write for bit reading and various combinations of single/separate writes for byte reading and RESTART with or without the extra cycle. The results are that, in all cases, the initial ACK reads 0, and then the dumps of the whole NVRAM are:
extra cycle restart + single-write byte reading -> dump
no + no -> first 17 bytes: 0; other bytes: $ff
no + yes -> all 0s
yes + no -> first 57 bytes: 0; other bytes: $ff
yes + yes -> all 0s

Evidently, nothing really works.

Now I'll check for the umpteenth time the START condition generation and then try the single-write strategy with it, repeating all the tests above.
If nothing helps, I'll change the whole code again to have SDA permanentely set to input, except for when sending bits - and then perform all the tests above.

In the meanwhile, any thoughts?
saimo is offline  
Old 20 March 2020, 17:16   #14
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 46
Posts: 25,034
http://www.winuae.net/files/b/winuae2.7z has CD32 EEPROM debugging enabled. Perhaps it helps to find the differences between ROM code and your code.

Messages that start with I2C are EEPROM emulator debug messages. Direction/data read/write are Akiko I2C port access messages = logs of messages..

NOTE: direction writes that don't change anything are filtered to reduce log flood. ROM code rewrites it every time, even if old and new value is same.
Toni Wilen is offline  
Old 20 March 2020, 22:45   #15
Bruce Abbott
Registered User

Bruce Abbott's Avatar
 
Join Date: Mar 2018
Location: Hastings, New Zealand
Posts: 820
Quote:
Originally Posted by saimo View Post
who knows about the quality of that code? What if it contains some weird hack that could only confuse me?
I doubt it has any weird tricks, and I bet the quality is better than yours. But hey, have fun figuring it out from scratch!

I do have one suggestion though - don't just try random stuff until you get it working. Learn as much as you can about I2C EEPROM protocols and do the job properly. Then those of us who don't mind looking at other people's code won't be disappointed by the quality or confused by weird hacks.
Bruce Abbott is offline  
Old 21 March 2020, 03:36   #16
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
@Toni Wilen

Thank you, I'll give it a try as soon as I can.


@Bruce Abbott

I have the impression you formed the idea that I want to get things done without caring about quality and without making the effort to understand. It's exactly the opposite, instead.

Quote:
Originally Posted by Bruce Abbott View Post
I doubt it has any weird tricks, and I bet the quality is better than yours.
Did you find anything in my code that is so bad to suggest that it's likely that its quality is worse than that of unknown code? Knowing where my code is bad would help me improve it.
Note: I'm not implying neither I implied before that the nonvolatile.library code is necessarily bad or that my code is better. I only said that I prefer a clean-room implementation tailored to my (strict) needs and based on the EEPROM documentation.

Quote:
I do have one suggestion though - don't just try random stuff until you get it working. Learn as much as you can about I2C EEPROM protocols and do the job properly. Then those of us who don't mind looking at other people's code won't be disappointed by the quality or confused by weird hacks.
As the opening post and other bits show, I did the due research: I studied the protocol, the datasheet of the EEPROM, and the datasheet of the same EEPROM from another manufacturer, and even glanced at the datasheet of a different I2C part. According to what I learned, I implemented the code in the cleanest way I was capable of: as the code I posted shows, I did it putting the utmost care in it (but, after all, that's how I write all my code), precisely because I wanted to do the job properly (no weird hacks at all).
I got the code to work on UAE quickly. Unfortunately, the code doesn't work on a real Amiga CD32, unfortunately I don't have a real Amiga CD32 to play with, and even more unfortunately the Akiko chip isn't fully documented, so the only option I had was to write test programs that covered all the possibilities I could think of and disturb a friend to run them to try to figure out what I was doing wrong (and the process was excruciatingly difficult also because he is in another country and in the middle of a very busy period, so I was getting the results with days or even weeks of delay) - that's quite different from trying random stuff.
Finally, since I could not get things to work, I came here, I openly acknowledged my failure, and, knowing that there are people more knowledgeable than me (especially about Akiko, which seems to be the critical component here), I asked what I was doing wrong. Toni provided a suggestion, and, although previously I had made tests according to the same idea, I made some more tests, reported their results, and planned to make even more.

All along, I've been proceeding in the most rigorous way I could. Now, did I misunderstand anything? I don't know, that's why I asked. Did I do anything wrong? I don't know, that's why I asked. Do I miss some information (about Akiko)? I don't know, that's why I asked. For sure, I'm not trying to come up with a solution by randomly assembling a weird hack.
I hope this provides a satisfying clarification.
saimo is offline  
Old 21 March 2020, 18:35   #17
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
@Toni Wilen

I just started looking at the log relative to the boot of the machine. Some things are as expected, others aren't. Before continuing, I'd like to verify whether my reading is correct.

First of all, the initial snippet of the log, with notes added by me:
Code:
log message                                     SCL   SDA   operation   cycle
--------------------------------------------------------------------------------
28-077 [98 062-111]: Direction write: 00->c0    o     o
28-077 [98 062-111]: Data write: c0->c0 (c0)    h     h
28-077 [98 108-111]: I2C START
28-077 [98 108-111]: Data write: c0->80 (80)    h     l     start
28-077 [98 167-111]: Data write: 80->00 (00)    l     l
28-077 [98 221-111]: Data write: 00->40 (40)    l     h    
28-077 [98 041-112]: Data write: 40->c0 (c0)    h     h     send 1      1
28-077 [98 074-112]: Data write: c0->40 (40)    l     h
28-077 [98 104-112]: Data write: 40->00 (00)    l     l
28-077 [98 134-112]: Data write: 00->80 (80)    h     l     send 0      2
28-077 [98 154-112]: Data write: 80->00 (00)    l     l
28-077 [98 188-112]: Data write: 00->40 (40)    l     h
28-077 [98 219-112]: Data write: 40->c0 (c0)    h     h     send 1      3
28-077 [98 012-113]: Data write: c0->40 (40)    l     h
28-077 [98 046-113]: Data write: 40->00 (00)    l     l
28-077 [98 073-113]: Data write: 00->80 (80)    h     l     send 0      4
28-077 [98 102-113]: Data write: 80->00 (00)    l     l
28-077 [98 132-113]: Data write: 00->00 (00)    l     l
28-077 [98 162-113]: Data write: 00->80 (80)    h     l     send 0      5
28-077 [98 187-113]: Data write: 80->00 (00)    l     l    
28-077 [98 217-113]: Data write: 00->00 (00)    l     l
28-077 [98 020-114]: Data write: 00->80 (80)    h     l     send 0      6
28-077 [98 040-114]: Data write: 80->00 (00)    l     l
28-077 [98 074-114]: Data write: 00->00 (00)    l     l
28-077 [98 101-114]: Data write: 00->80 (80)    h     l     send 0      7
28-077 [98 130-114]: Data write: 80->00 (00)    l     l
28-077 [98 160-114]: Data write: 00->00 (00)    l     l
28-077 [98 190-114]: Data write: 00->80 (80)    h     l     send 0      8
28-077 [98 218-114]: Direction write: c0->80    o     i
28-077 [98 218-114]: Data write: 80->00 (40)    l     l    
28-077 [98 041-115]: I2C device address 0xa0
28-077 [98 041-115]: Data write: 40->80 (c0)    h     l                 9
28-077 [98 074-115]: Direction read: 80         o     i     ?
28-077 [98 074-115]: Data read: 00              l     l                 get ACK
28-077 [98 082-115]: Data write: c0->00 (40)    l     l     ?
28-077 [98 093-115]: Data write: 40->00 (40)    l     l     ?
28-077 [98 128-115]: Direction write: 80->c0    i     i
28-077 [98 128-115]: Data write: 40->00 (00)    l     l
28-077 [98 165-115]: Data write: 00->80 (80)    h     l                 10
The first thing worth noting is that the ROM doesn't perform any reset proceduce, but it just sets both SCL and SDA to output and pulls them high (which is what allows to generate a START condition later):
Code:
log message                                     SCL   SDA   operation   cycle
--------------------------------------------------------------------------------
28-077 [98 062-111]: Direction write: 00->c0    o     o
28-077 [98 062-111]: Data write: c0->c0 (c0)    h     h
After that, a START condition is generated by pulling SDA low (the log anticipates that with an "I2C START" message, which I assume is done for readability purposes):
Code:
log message                                     SCL   SDA   operation   cycle
--------------------------------------------------------------------------------
28-077 [98 108-111]: I2C START
28-077 [98 108-111]: Data write: c0->80 (80)    h     l     start
In the next 8 cycles, the ROM addresses the memory, indicating that the addresses that will be specified afterwards are relative to the writes from the very beginning of the EEPROM (device code = 1010, P1 and P0 = 0, Rw = 0):
Code:
log message                                     SCL   SDA   operation   cycle
--------------------------------------------------------------------------------
28-077 [98 167-111]: Data write: 80->00 (00)    l     l
28-077 [98 221-111]: Data write: 00->40 (40)    l     h    
28-077 [98 041-112]: Data write: 40->c0 (c0)    h     h     send 1      1
28-077 [98 074-112]: Data write: c0->40 (40)    l     h
28-077 [98 104-112]: Data write: 40->00 (00)    l     l
28-077 [98 134-112]: Data write: 00->80 (80)    h     l     send 0      2
28-077 [98 154-112]: Data write: 80->00 (00)    l     l
28-077 [98 188-112]: Data write: 00->40 (40)    l     h
28-077 [98 219-112]: Data write: 40->c0 (c0)    h     h     send 1      3
28-077 [98 012-113]: Data write: c0->40 (40)    l     h
28-077 [98 046-113]: Data write: 40->00 (00)    l     l
28-077 [98 073-113]: Data write: 00->80 (80)    h     l     send 0      4
28-077 [98 102-113]: Data write: 80->00 (00)    l     l
28-077 [98 132-113]: Data write: 00->00 (00)    l     l
28-077 [98 162-113]: Data write: 00->80 (80)    h     l     send 0      5
28-077 [98 187-113]: Data write: 80->00 (00)    l     l    
28-077 [98 217-113]: Data write: 00->00 (00)    l     l
28-077 [98 020-114]: Data write: 00->80 (80)    h     l     send 0      6
28-077 [98 040-114]: Data write: 80->00 (00)    l     l
28-077 [98 074-114]: Data write: 00->00 (00)    l     l
28-077 [98 101-114]: Data write: 00->80 (80)    h     l     send 0      7
28-077 [98 130-114]: Data write: 80->00 (00)    l     l
28-077 [98 160-114]: Data write: 00->00 (00)    l     l
28-077 [98 190-114]: Data write: 00->80 (80)    h     l     send 0      8
Then, SDA is set to input and SCL is pulled low to begin the cycle in order to read the ACK. Also, for some reason, only now the log reports the device address sent earlier.
Looking closely, if I'm interpreting the log correctly, this is what happens:
1. the last bit sent before this block is 0 (so SDA is low);
2. SDA gets set to input;
3. SCL gets pulled low to start the 9th cycle;
4. the state of SCL and SDA at this point is 40, which means that SDA must have been pulled high by the EEPROM - is this correct?

Noteworthy: here the direction gets changed before pulling SCL low.
Code:
log message                                     SCL   SDA   operation   cycle
--------------------------------------------------------------------------------
28-077 [98 218-114]: Direction write: c0->80    o     i
28-077 [98 218-114]: Data write: 80->00 (40)    l     h    
28-077 [98 041-115]: I2C device address 0xa0
Finally, the ACK gets read and the sending of the address offset starts. However, here some strange things happen.
Looking closely:
1. SCL is pulled high to start the second part of the 9th cycle (at this point, SDA is still high);
2. the code performs a read from the direction register: what for? trigger a refresh according to the actual voltage of the wires? (this might well be one key element I was missing);
3. the data register gets read, an SDA is now 0 (meaning that the EEPROM has sent the ACK);
4. the code pulls SCL low (starting the 10th cycle, which the sending of the address offset starts at), but both the starting and the current value of SDA are now high: is that correct (in the real chip, the current value is not stable yet; still, why was the starting value 1 instead of 0, given that the last bit sent over the wire was 0? emulation state error? logging error?);
5. the code tries to pull SCL low again (without any effect): why?
6. the direction of SDA is restored to output.

I wonder: what's with all this apparently superfluous fiddling during the 9th cycle?
Also, here, unlike before, the data direction gets changed after starting the cycle: does this mean that for reading the change must be done before pulling SCL low and for writing it must be done after?
Code:
log message                                     SCL   SDA   operation   cycle
--------------------------------------------------------------------------------
28-077 [98 041-115]: Data write: 40->80 (c0)    h     h                 9
28-077 [98 074-115]: Direction read: 80         o     i     ?
28-077 [98 074-115]: Data read: 00              h     l                 get ACK
28-077 [98 082-115]: Data write: c0->00 (40)    l     h     ?
28-077 [98 093-115]: Data write: 40->00 (40)    l     h     ?
28-077 [98 128-115]: Direction write: 80->c0    o     o
What do you think? Am I interpreting the log correctly?
saimo is offline  
Old 21 March 2020, 19:25   #18
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 46
Posts: 25,034
Direction read is most likely simply side-effect of code using bset/bclr or or/and to change the state (even if it is already in correct state). I am quite sure read does not do any side-effects.
Toni Wilen is offline  
Old 21 March 2020, 19:45   #19
saimo
Registered User
saimo's Avatar
 
Join Date: Aug 2010
Location: Italy
Posts: 475
Quote:
Originally Posted by Toni Wilen View Post
Direction read is most likely simply side-effect of code using bset/bclr or or/and to change the state (even if it is already in correct state). I am quite sure read does not do any side-effects.
Ah, OK, so that's a case where the log filter kicked in. Thanks. Well, at least it says that writing to the data direction register after the start of a cycle can be done.
saimo is offline  
Old 25 March 2020, 09:46   #20
Bruce Abbott
Registered User

Bruce Abbott's Avatar
 
Join Date: Mar 2018
Location: Hastings, New Zealand
Posts: 820
Quote:
Originally Posted by saimo View Post
I have the impression you formed the idea that I want to get things done without caring about quality and without making the effort to understand.
No, you suggested that the ROM code was not high quality, which implies you think that you can do better.

Quote:
Did you find anything in my code that is so bad to suggest that it's likely that its quality is worse than that of unknown code?
I don't need to find anything, we know your code's not good because it doesn't work.

Quote:
Note: I'm not implying neither I implied before that the nonvolatile.library code is necessarily bad or that my code is better.
You questioned the ROM code's quality and speculated that it could be a 'weird hack'. That's more than just implication.

Quote:
I only said that I prefer a clean-room implementation tailored to my (strict) needs and based on the EEPROM documentation.
That's fine, try to reinvent the wheel if it pleases you. But 'clean-room implementation' on a 25 year old OS for a dead platform? Go on, take peek! Nobody will care if you do.
Bruce Abbott is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Extend CD32 NVRAM? Akira Hardware mods 41 16 December 2018 14:59
CD32 NVRAM management Akira support.Hardware 9 20 February 2012 13:27
Access CD32-NVRam from Shell Retro1234 support.Other 3 08 August 2010 11:50
CD32 nvram file...? Christian support.WinUAE 11 13 December 2006 22:25
Cd32 Nvram Phantomz request.Apps 5 16 March 2003 21:09

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 05:04.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.
Page generated in 0.10854 seconds with 14 queries