Jump to content

Photo

bB AtariVox Support, Part 1... the AtariVox EEPROM


43 replies to this topic

#1 RevEng OFFLINE  

RevEng

    River Patroller

  • 3,397 posts
  • bit player
  • Location:Canada

Posted Sun Feb 6, 2011 4:00 PM

bB AtariVox Support, Part 1... the AtariVox EEPROM

The AtariVox is built around 2 main components:

  • The SpeakJet chip, which is responsible for the Voice Synthesis.
  • The EEPROM chip, which allows game data to be loaded or saved.

In this thread I'll just address using the AtariVox's EEPROM. I'll start a separate thread about the voice capability another time.


The AtariVox EEPROM is separated into 3 different areas:
  • The Static Area. This is quick and simple, but you must reserve a location from Richard Hutchinson.
  • The Scratchpad Area. This area is similar to the Static Area, except you can do what you like here. Another game may also do what it likes here, so you can't expect any data stored in the Scratchpad to survive after the atari is shut-off.
  • The Filesystem Area. You chose your own unique filename for storage in this area, and you may do what you like with the file. Unless another game chooses the same filename, your game's data won't be overwritten by other games.
More details on these areas here...
Attached File  AvoxEEPROMMemoryMap.txt   987bytes   186 downloads


Learn By Example

The easiest way learn how to use the Static Area and Filesystem Area is to look at the commented examples I've attached. They show how to write a single byte to each area, and how to read it back...
Attached File  avoxeeprom-static-area.20110209.zip   4.5KB   181 downloads
Attached File  avoxeeprom-file-area.20110209.zip   6.18KB   168 downloads

...please note that the provided examples are bundled with 2 assembly modules, i2c.inc and bbavox-eeprom-*.asm. The first is the official AtariVox i2c driver, and the second is higher level code for interfacing with bB, written by myself.

Both of these files should be placed in the same directory as the basic program you'll be working with.

Points Worth Noting

While using the AtariVox EEPROM is fairly easy, there are a few things to keep in mind:

  • it's a bad idea to write to the EEPROM continually. (eg. every frame)

    Like most flash devices, the EEPROM can only be written to a limited (but very large) number of times. [contributed by cd-w]

    It's also worth noting this isn't true of Stella, which uses a file to emulate the EEPROM. [contributed by stephena]
  • the EEPROM is quite slow, so the bB routines have been written with that in mind. You need to read or write just a single byte between drawscreen commands. If you fail to do this with reads you'll blow the scanline count, and if you fail to do this with writes the writes will fail and you'll blow the scanline count.

    Even when you're doing that, you won't have a whole lot of cycles left for other things; it's probably a bad idea to read/write EEPROM in your main game loop.
  • For Static Area access, when your game is nearly done you should request an official memory location from Richard H.

    When you just start your game, feel free to instead access the Scratch Area $3000-$3FFF. Do NOT request a memory location until your game is very nearly done.
  • the provided bB Static Area functions force your read/write requests to use the scratch area, even when you tell them to use another location, so a bug won't destroy real saved data.

    When you have been provided a location by Richard, to get your code to use it you'll need to add the line "const AVoxSafetyOff=1" to your code, which disables the safety mechanism.
  • To test this in stella, you need to modify the "game properties->controllers" dialog so a virtual AtariVox is plugged into the right controller port. You'll need to do this each time you change your game, because stella will think it's a new program after the change.

    If you launch stella from command-line, you can also tell it to start with its virtual AtariVox plugged in:
    stella -rc atarivox <romfile> (or with a physical AtariVox plugged into your coputer: stella -rc atarivox -avoxport COMx <romfile>, where x is the commport number) [contributed by cd-w and stephena]
  • The SaveKey by CPUWIZ is functionally equivalent to the AtariVox EEPROM. If your code works with one, it should work with the other.



AtariVox is the creation of Richard Hutchinson, and the drivers were created by Alex Herbert. All thanks and credit should go to these guys!

Please report any bugs or problems with the example code in this thread.

#2 cd-w OFFLINE  

cd-w

    Stargunner

  • 1,249 posts
  • Juno First!
  • Location:Glasgow, UK

Posted Sun Feb 6, 2011 4:10 PM

[*]To test this in stella, you need to modify the "game properties->controllers" dialog so a virtual AtariVox is plugged into the right controller port. You'll need to do this each time you change your game, because stella will think it's a new program after the change.


This option can be configured from the command line. If I remember correctly, this is done by:

stella -rc atarivox <romfile>

The -avoxport <port> option may also be required if the default port is incorrect. You can create a short-cut to Stella (under Windows) to pass these command line parameters, so you won't have to type them every time.

Also, note that the eeprom does have a limited number of write cycles. This number is large, but you will use them up very quickly if you attempt to write on every frame. It is best just to use the eeprom for occasional writes, such as high score tables and game saves. The number of read cycles is unlimited.

Chris

#3 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Sun Feb 6, 2011 4:13 PM

I believe this option can be configured from the command line. If I remember correctly, this is done by:

stella -rc atarivox <romfile>

The -avoxport <port> option may also be required if the default port is incorrect. You can modify the Stella shortcut (under Windows) to pass these command line parameters to Stella, so you won't have to set this every time.

Also, the eeprom does have a limited number of write cycles. This number is large, but you will use them up very quickly if you attempt to write on every frame. It is best just to use the eeprom for occasional writes, such as high score tables and game saves. The number of read cycles is unlimited.

Chris

Both excellent points! I'll add the eeprom one into the first post, so nobody wears out their EEPROM unnecessarily!

#4 GroovyBee OFFLINE  

GroovyBee

    Games Developer

  • 7,938 posts
  • Busy bee!
  • Location:North, England

Posted Sun Feb 6, 2011 4:46 PM

I developed a PC based SaveKey app a couple of years ago :-

http://www.atariage....savekey-driver/

#5 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,493 posts
  • begin 644 contest

Posted Sun Feb 6, 2011 4:55 PM

There is apparently a huge "file" area, which I think has never been used. I believe this is because some were afraid that files would overwrite one another. Some suggested amazingly stringent requirements. This doomed the file area from ever being used, and 5 years later, it still hasn't been used.

There were reasonable suggestions, though. The most reasonable involved a file type byte as the first byte of the file, then a filename may follow. I suggested that any files with the first byte of $BB belong to bB. There are then 254 other file types to use, and a byte that shows an empty file (probably $00 or $FF, or whatever the state is when the area has never been used.) So I think it's fine to go ahead with this proposal. Anyone may use any scheme they want to use if they ever want to use the file area, just as long as they don't mess with files that have $BB as the first char (unless there is no space.)

So here's how it would work: there should be three functions, read, write and erase. Read and write will take a filename up to 8 chars with $00 to terminate the string (it can be less), a length, and a source/destination in RAM to read/write from. Read will search all blocks for $BB then for the filename and copy the data if it exists. Write will look for the file, overwrite if it exists, if not, create a new file in the first free slot. If there are no slots (I don't expect this to ever happen, as I think there are 256 of them) I'm not sure what to do yet (maybe overwrite the last file.)

Erase would take a filename (wildcards accepted). bB can only erase files starting with $BB.

Before this is etched in stone, let's verify where the file area is and also verify that nobody has ever used it. The first one to use it will establish the de facto rules, so it's about time someone did.

#6 GroovyBee OFFLINE  

GroovyBee

    Games Developer

  • 7,938 posts
  • Busy bee!
  • Location:North, England

Posted Sun Feb 6, 2011 5:00 PM

Games can also use a fixed page. See the following list for games that are using fixed pages already :-

http://www.richard.h.../new_page_6.htm

If you need a fixed page for your own game just contact Richard H. and he'll allocate you one.

#7 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Sun Feb 6, 2011 5:07 PM

Before this is etched in stone, let's verify where the file area is and also verify that nobody has ever used it. The first one to use it will establish the de facto rules, so it's about time someone did.

Verifying where it is, is easy enough. From Alex's doc...

Memory Partitions

0000-3fff Static Allocation Area
4000-7fff File Area

[snip]

Proposed Format for File Area

Note: No software currently uses the File Area so the following is only a proposed format and is not set in stone.

64-byte pages are paired to form 128-byte Blocks.
Each block starts with an 8 character ASCII filename (7-bit character codes) and the remaining 120 bytes are free for data.
Bit 7 of the first character is used to determine if the block is allocated or available. 0 indicates the block is in use, a 1 means it is free.

Even implementing something as simple as this gets quite fiddly on the 2600. The time taken to search for a file/free block is variable and may take several TV frames to complete and care must be taken to ensure that VSYNC still happens at the right time. Also, any software that uses the File Area should provide the user with some way to delete files as well as create them. This will possibly involve text routines, a character set, etc., all adding further bulk to the program.


...but the static allocation area does seem more straightforward to use.

Edited by RevEng, Sun Feb 6, 2011 5:08 PM.


#8 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,493 posts
  • begin 644 contest

Posted Sun Feb 6, 2011 5:55 PM

You need to apply for space in the static area, which few have ever done and I don't think bB users to have any need to do that. I think it's about time someone used the file area. Alex's proposal is reasonable but I think mine is a bit better since you have a file type as well as a name, so if any non-bB users ever use it, they can easily avoid bB files.

I think bB users could just be reasonable about file use (such as only using a few files per game, and not an arbitrary number of files.) If they really want static allocation, they can apply for that and some mechanism could be put in place to allow use of it.

If it ever is a problem (which I doubt), a simple file management utility could be written to browse the files by name and erase them if desired.

Anyway, one potential use for the file area is a savegame. There are 119 bytes per file possible so a savegame could recover basically all of the RAM you need. You don't need the temp variables and savegames should not try to save or recover the upper bytes of RAM (reserved for the stack) so that's more than enough space.

#9 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,493 posts
  • begin 644 contest

Posted Sun Feb 6, 2011 7:15 PM

Here's some thoughts about how files could work. You define somewhere the filenames (must be in the same bank as the functions) like this:
data file1
  "Ginger1",0
end
The zero is only needed for files shorter than 8 chars.

There are lots of ways that file access could be done. One way is to let the programmer handle it. There could be a function that takes a file number and returns 0 if the file matches a name, 1 if the slot is used but the file doesn't match, and 2 if empty.
  a=getfilename(<file1, >file1, 23)
This would check slot 23 to see if the file is called "Ginger1."

The reason I suggest this is because it would probably take more than a frame to scan all 256 slots looking for a match, so the user could put these in a loop with a drawscreen in there to avoid screen rolling. Then, read, write and erase could simply use the slot number.

Read and write could then just take a slot number, number of bytes to read/write and RAM location to start reading/writing from/to. E.g.:
  temp1=read(23, 4, e)
  temp1=write(23, 4, e)
The first would read 4 bytes of data into e, f, g, and h from slot 23. The second would write the same data.

read could return 0 on success, 1 if the slot was empty or 2 if the slot was not a bB file. Write could return 0 on success, 1 if the slot was not empty, or 2 if not a bB file.

To help avoid bad programming overwriting files you want to keep, a file could not be written unless first erased (which is required with the EEPROM anyway), and the erase function would require a slot number and a file match:
  temp1=erase(<file1, >file1, 23)
This would return 0 if successful, 1 if the file didn't match, or 2 if it wasn't a bB file.

Shouldn't be very hard to write the functions. As for savegames (i.e. saving all RAM), that will probably require special functions.

#10 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,493 posts
  • begin 644 contest

Posted Sun Feb 6, 2011 7:39 PM

I just read the OP completely - is it really so slow you can only read one byte a frame? It could be a driver issue then, and perhaps the driver could be rewritten. The slowest devices I know of are 100 kHz, which should allow several bytes per frame.

Also, I see no mention of erasing. All serial EEPROMs I know of are sectored, meaning you can't overwrite any data unless you erase an entire sector first (which seem to be 64 bytes on this device.) So you can't just keep writing to the same place.

I think that these devices can only change individual bits from zero to one (or maybe one to zero, I forget.) If you want to change anything from 1 to 0 (or maybe it's 0 to 1), you have to do an entire sector at once. Therefore writing to the same location will essentially do a logical OR (or it could be AND :) ) on the location and not necessarily write the value.

Edited by batari, Sun Feb 6, 2011 7:45 PM.


#11 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Sun Feb 6, 2011 8:23 PM

Both on real hardware and in stella, we can't seek and then fetch any more than 3 bytes of eeprom data before we blow overscan. Without the seek, we can only fetch 7 bytes without blowing overscan.

In his docs, Alex mentions being able to grab 32 bytes during the visible area of the frame. Given the ratio of time, that would be equivalent to 5 bytes in overscan, which is in the same ballpark.

My wrapper does a byte at a time for simplicity and to allow for overhead. We can do the seek, do the read/write, and still have a small bit of time left to play a tune, change colors, animate something, etc.

Regarding the proposal, it may be better if the user coughs up a persistent byte or two to keep the status across frames, and the open function does the full scan, returning a status code for "in progress", as well as "not found" or "found". If the code is "in progress", the user does a drawscreen and then loops back.

The read/write could have a similar "in progress" code.

Edited by RevEng, Sun Feb 6, 2011 10:29 PM.


#12 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Sun Feb 6, 2011 9:13 PM

Just caught this part...

Also, I see no mention of erasing. All serial EEPROMs I know of are sectored, meaning you can't overwrite any data unless you erase an entire sector first (which seem to be 64 bytes on this device.) So you can't just keep writing to the same place.

I think that these devices can only change individual bits from zero to one (or maybe one to zero, I forget.) If you want to change anything from 1 to 0 (or maybe it's 0 to 1), you have to do an entire sector at once. Therefore writing to the same location will essentially do a logical OR (or it could be AND :) ) on the location and not necessarily write the value.


Alex's docs don't make mention of needing to erase, and it's working flawlessly on real hardware. I read in a stored value, incremented it and stored it again, over and over, and it counted up fine.

I've attached the datasheet for the 24LC256, and it has a "byte write" command in addition to "page write". Maybe byte writing is what's being used. For that matter, I don't see an erase command anywhere in the datasheet.

Attached File  24XX256.pdf   447.31KB   144 downloads

Edited by RevEng, Sun Feb 6, 2011 10:30 PM.


#13 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,493 posts
  • begin 644 contest

Posted Mon Feb 7, 2011 1:44 AM

OK, then, this one isn't sectored. There's probably no need for the erase function, then, but there should still be a way to prevent programming errors from overwriting files. More about that later.

Since you have real hardware handy, what is the state of uninitialized data on the EEPROM? I'd imagine it's $00 or $FF, but either way, that will indicate a "file unused" type.

The "in progress" state should work fine for multiple byte reads and writes, though I wonder if it's really necessary now. Perhaps users should just read and write manually. All they need, really, is a file number and they can read/write to that file as they please. Read/writes could then just ask for a file number, offset and byte of RAM to read/write to/from. It shouldn't be very hard for users to figure out how to read or write multiple bytes in a loop.

For a file seek, an "in progress" state probably won't work. First, you would need several free bytes of RAM. Not sure how many, but it could be quite a few. This could be problematic as RAM is scarce already. Another issue is the file seek time - really, all 256 slots should be checked. Best case, this will take around five seconds, but worst case, close to a minute. Still, too slow.

Instead, file seek could include an encapsulated kernel. It will show a few frames of an icon (that the user can define) in the center of the screen, kind of like the Harmony spinner. The rest of the frame can be used for file seek so it should take no more than a few seconds.

Now to help prevent erasing files that aren't yours - during development, you could use a special write function that calls the file seek function before any write to make sure the file being written is yours. If it is not, show some error indication on the screen somehow. Once the bugs are out, the user can choose to use the regular write function. It's not a foolproof method but since this thing is so slow, a foolproof method is not very feasible (which is something I don't think anyone ever thought of until now, not even the creators!)

Edited by batari, Mon Feb 7, 2011 1:44 AM.


#14 stephena OFFLINE  

stephena

    River Patroller

  • 2,528 posts
  • Stella maintainer
  • Location:Newfoundland, Canada

Posted Mon Feb 7, 2011 8:56 AM


[*]To test this in stella, you need to modify the "game properties->controllers" dialog so a virtual AtariVox is plugged into the right controller port. You'll need to do this each time you change your game, because stella will think it's a new program after the change.


This option can be configured from the command line. If I remember correctly, this is done by:

stella -rc atarivox <romfile>

The -avoxport <port> option may also be required if the default port is incorrect. You can create a short-cut to Stella (under Windows) to pass these command line parameters, so you won't have to type them every time.

Yes, I was about to remind everyone of this. If you're continuously doing an edit-compile-run cycle, it's much easier to use commandline arguments:
stella -rc atarivox -avoxport COMx <romfile>, where x is the commport number
Of course you're free to change it every time in the UI, but that would be insane ;)

Also, note that the eeprom does have a limited number of write cycles. This number is large, but you will use them up very quickly if you attempt to write on every frame. It is best just to use the eeprom for occasional writes, such as high score tables and game saves. The number of read cycles is unlimited.

Also a reminder that while this is definitely true for the real hardware, it isn't for Stella. Stella emulates access to the EEPROM, creating a 32KB file on your computer and modifying it accordingly. So I wouldn't worry too much about overwrites in testing. But it should definitely be fixed before testing and release on the real hardware.

#15 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Mon Feb 7, 2011 9:12 AM

Thanks stephena! I've folded both points into the first post.

#16 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Mon Feb 7, 2011 9:59 AM

Instead, file seek could include an encapsulated kernel. It will show a few frames of an icon (that the user can define) in the center of the screen, kind of like the Harmony spinner. The rest of the frame can be used for file seek so it should take no more than a few seconds.

I haven't given up on the idea that this can happen during overscan. I've been looking at the problem sideways...

What utility does a filename give us? IMO, it serves two purposes:

  • a unique self-service key, so the appropriate eeprom page can be found
  • a description so the avox owner can decide what to delete

If we use different mechanisms for those two functions we can do the search a lot more efficiently...

The 2600 coder can generate their own key with a program that uses a simple hash function and their game name, a passphrase, or whatever, for input.

Instead of searching filenames, a small table of hash keys could be sequentially searched instead. This also means we only need to seek at the beginning of the lookup.

For a 32-bit hash key size, this would yield a worst case lookup of ~17 seconds in overscan. And if we assume 16-bit hash keys are sufficient to avoid collisions, then we can cut down the worst case search to 1/3, or under 6 seconds. That could be halved if the user throws vblank time at the search as well.

The first 8 chars of the retrieved page would contain the description. These should be named after the game, since the user doesn't care or know what "map01" is, but they would care that its data belonging to "robotron".

I'm also thinking that we run with 64 byte files. 56 bytes should be more than enough for most purposes, but if it's not a game can allocate multiple files. 64 byte files would give 256 files to work with, less a bit for the overhead of the hash table.

Edited by RevEng, Mon Feb 7, 2011 5:25 PM.


#17 Richard H. OFFLINE  

Richard H.

    Dragonstomper

  • 933 posts
  • VecMulti Vectrex cart
  • Location:UK

Posted Mon Feb 7, 2011 11:50 AM

If it'll help, I can reserve all the pages after the scratch pad area for bB only games. That's pages $100 to $1FF

#18 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Mon Feb 7, 2011 2:24 PM

Thanks, Richard! I think if we come up with an agreeable solution here, it should be open for everybody to implement.

If we get there, the best approach would probably be for you to flag that half of the eeprom in your map as being "file storage" with a link to documentation.

#19 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,493 posts
  • begin 644 contest

Posted Mon Feb 7, 2011 6:28 PM

Instead, file seek could include an encapsulated kernel. It will show a few frames of an icon (that the user can define) in the center of the screen, kind of like the Harmony spinner. The rest of the frame can be used for file seek so it should take no more than a few seconds.

I haven't given up on the idea that this can happen during overscan. I've been looking at the problem sideways...

What utility does a filename give us? IMO, it serves two purposes:

  • a unique self-service key, so the appropriate eeprom page can be found
  • a description so the avox owner can decide what to delete

If we use different mechanisms for those two functions we can do the search a lot more efficiently...

The 2600 coder can generate their own key with a program that uses a simple hash function and their game name, a passphrase, or whatever, for input.

Instead of searching filenames, a small table of hash keys could be sequentially searched instead. This also means we only need to seek at the beginning of the lookup.

For a 32-bit hash key size, this would yield a worst case lookup of ~17 seconds in overscan. And if we assume 16-bit hash keys are sufficient to avoid collisions, then we can cut down the worst case search to 1/3, or under 6 seconds. That could be halved if the user throws vblank time at the search as well.

The first 8 chars of the retrieved page would contain the description. These should be named after the game, since the user doesn't care or know what "map01" is, but they would care that its data belonging to "robotron".

I'm also thinking that we run with 64 byte files. 56 bytes should be more than enough for most purposes, but if it's not a game can allocate multiple files. 64 byte files would give 256 files to work with, less a bit for the overhead of the hash table.

A 16-bit hash table is going to have a high probability of collision (60% with 256 numbers!). A 32-bit hash will have a sufficiently low probability (0.00076%). However, finding 4 bytes instead of 8 (or 9) is IMO not enough savings to be worth it. When I used hash tables, the point of them was not really to save a bit of space and still search linearly through a bunch of keys but to allow a non-linear search for speed.

Since Richard seems agreeable to whatever we decide, so I agree on part of this - we should use a directory. If we allow 8-byte filenames, this means the first 32 64-byte slots would be dedicated to this. Also 64-byte files are nice in theory but it's a little inconvenient to require a programmer to store a number from 0-512. 0-256 is much nicer.

I still wonder if the driver can't be improved. Even 100kHz devices should be able to retrieve 8 bytes pretty quickly since subsequent bytes may be read without reissuing the address. It takes 27 clocks to set up the address and 9 clocks for each byte read - this means 8 bytes could be read in 99 clocks, which is a hair under 1 ms. This is around 15 scanlines. I'm sure the driver can't quite go full speed but how I wonder how fast it can go? Either way, if 8 bytes can be searched per frame, this means 4 seconds maximum search time, which is probably reasonable.

#20 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Mon Feb 7, 2011 6:56 PM

A 16-bit hash table is going to have a high probability of collision (60% with 256 numbers!). A 32-bit hash will have a sufficiently low probability (0.00076%). However, finding 4 bytes instead of 8 (or 9) is IMO not enough savings to be worth it. When I used hash tables, the point of them was not really to save a bit of space and still search linearly through a bunch of keys but to allow a non-linear search for speed.

Yeah, nobody is going to sit through a sort, so we're not going to be binary searching them any time soon.

I hadn't figured out the probability of collisions on 16-bit hashes - probability is definitely a blind spot in my background. Agreed that 16-bit won't cut it.

I'll look at the driver and see if I can do something. if 8 bytes can happen in overscan, then the directory approach is the clear way to go.

While I'm using the same eeprom as the AtariVox, mine is a DIY breadboard setup. If I do somehow manage a speed increase, someone with a real AtariVox will need to verify the results.


Also 64-byte files are nice in theory but it's a little inconvenient to require a programmer to store a number from 0-512. 0-256 is much nicer.


We only have the upper half of the eeprom to use. That's 16k, so we could reference all of the 64-byte files with one byte.

#21 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,493 posts
  • begin 644 contest

Posted Tue Feb 8, 2011 1:45 AM

A 16-bit hash table is going to have a high probability of collision (60% with 256 numbers!). A 32-bit hash will have a sufficiently low probability (0.00076%). However, finding 4 bytes instead of 8 (or 9) is IMO not enough savings to be worth it. When I used hash tables, the point of them was not really to save a bit of space and still search linearly through a bunch of keys but to allow a non-linear search for speed.

Yeah, nobody is going to sit through a sort, so we're not going to be binary searching them any time soon.

I hadn't figured out the probability of collisions on 16-bit hashes - probability is definitely a blind spot in my background. Agreed that 16-bit won't cut it.

I'll look at the driver and see if I can do something. if 8 bytes can happen in overscan, then the directory approach is the clear way to go.

While I'm using the same eeprom as the AtariVox, mine is a DIY breadboard setup. If I do somehow manage a speed increase, someone with a real AtariVox will need to verify the results.

100 kHz is about 12 6507 cycles for every EEPROM clock, which makes it difficult to overclock - it takes two 4-cycle writes just to service the clock, and that's 8 cycles right there.

Depending on what bits are used for SDA and SCL, reading data could be relatively fast, though. Hopefully, they put SDA on bit 0. If not, shifting and masking will be needed to get data in and out (and it will be irksome to code.)

Also 64-byte files are nice in theory but it's a little inconvenient to require a programmer to store a number from 0-512. 0-256 is much nicer.

We only have the upper half of the eeprom to use. That's 16k, so we could reference all of the 64-byte files with one byte.

Somehow I thought the EEPROM was 64k. So 64 byte files it is.

#22 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Tue Feb 8, 2011 7:16 AM

Depending on what bits are used for SDA and SCL, reading data could be relatively fast, though. Hopefully, they put SDA on bit 0. If not, shifting and masking will be needed to get data in and out (and it will be irksome to code.)

The SpeakJet is at bits 0 and 1, and the eeprom is at 2 and 3. The extra time for shifting and masking appears to be the main limiting factor.

I took Thomas' optimized i2c driver, copied his byte read, wrapped it in a loop (to avoid 8 jsr/rts pairs) and inlined the only subroutine he had in his code.

It did a bit better, but I still blew overscan in the standard kernel by a couple of lines.

These are the choices as I see them:

  • Reduce the filename size.

    This means we'll deal with a non-power of 2, making the math ugly, and increasing the rom footprint. That's a non-starter.
  • Use 32-bit hashes.

    Its not dead, but I won't beat this horse again.
  • Use the visible part of the screen as you previously suggested.

    This looks like it will take around 50 frames for a full 8 char*256 entry directory search.
  • break up the scan into 2 parts. I think this is still doable with minimal ram - the actual value returned could hold the intermediate index, and the status code could be one of the temps.

    The first half would do a seek+3 byte read. The return code could be "get next entry" if the 3 bytes don't match, "do second part check" to indicate the coder should do a second half-check in the next frame, or "file not found".

    I don't think there would be a lot of 3 letter false-matches in the first check, so we're probably looking at ~5 seconds for a full directory scan.

I'm loathe to blank the screen, but its looking more attractive. Less than a second isn't too bad, and I could then use another temp variable to also flag the first empty file found, in case the file isn't found and the programmer needs to create a new one.

I think its the winner, at least for now... the eeprom layout for it doesn't rule out a later split-overscan implementation.

Edited by RevEng, Tue Feb 8, 2011 8:17 AM.


#23 RevEng OFFLINE  

RevEng

    River Patroller

  • Topic Starter
  • 3,397 posts
  • bit player
  • Location:Canada

Posted Tue Feb 8, 2011 2:20 PM

Ok, my first whack at the AVoxOpenFile routine is done. It looks like I can fit 4 directory entry searches in the visible area, with a small bit of time leftover. With the extra time maybe I'll do an optional spinner or something.

So we have a worst-case completion time of 64 frames. If the file isn't found, the location of the first directory entry that has a leading FF byte is returned in temp6.

Next up will be the routines to handle file creation, and reading and writing individual bytes to the files.

[edit]

It's also worth noting that this file-area method we're working on isn't a replacement for the static-area method I posted in the first post. It will be an additional option.

Edited by RevEng, Tue Feb 8, 2011 2:30 PM.


#24 cd-w OFFLINE  

cd-w

    Stargunner

  • 1,249 posts
  • Juno First!
  • Location:Glasgow, UK

Posted Tue Feb 8, 2011 4:46 PM

I took Thomas' optimized i2c driver, copied his byte read, wrapped it in a loop (to avoid 8 jsr/rts pairs) and inlined the only subroutine he had in his code.
It did a bit better, but I still blew overscan in the standard kernel by a couple of lines.


Have you tested it on real AtariVox hardware and not just in Stella? e1will reported some problems with the optimized i2c driver when he attempted to use it in Duck Attack (possibly timing related).

Chris

#25 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,493 posts
  • begin 644 contest

Posted Tue Feb 8, 2011 5:50 PM


I took Thomas' optimized i2c driver, copied his byte read, wrapped it in a loop (to avoid 8 jsr/rts pairs) and inlined the only subroutine he had in his code.
It did a bit better, but I still blew overscan in the standard kernel by a couple of lines.


Have you tested it on real AtariVox hardware and not just in Stella? e1will reported some problems with the optimized i2c driver when he attempted to use it in Duck Attack (possibly timing related).

Chris

I couldn't find the post(s) where he reported the problems - do you have a link?




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users