Jump to content
IGNORED

#FujiNet - a WIP SIO Network Adapter for the Atari 8-bit


tschak909

Recommended Posts

Some things:

 

1. Very nice vertical widescreen!

2. Arrays and bits start at 0 ;)

3. Always nice to see CIO had the same concept as /dev on *nix

4. Keep up the good work!

 

Received my NodeMCU two days ago, but waiting on a small 7" screen so I can have my Atari by my side when cross-developing on a PC, and not having to walk across the room everytime I need to test something :)

 

Edited by ivop
typo
  • Like 3
Link to comment
Share on other sites

Some things:
 
1. Very nice vertical widescreen!
2. Arrays and bits start at 0 [emoji6]
3. Always nice to see CIO had the same concept as /dev on *nix
4. Keep up the good work!
 
Received my NodeMCU two days ago, but waiting on a small 7" screen so I can have my Atari by my side when cross-developing on a PC, and not having to walk across the room everytime I need to test something [emoji4]
 
The vertical wide screen is my dedicated coding screen. Typically has emacs running on it.

Sent from my SM-G920F using Tapatalk

  • Like 2
Link to comment
Share on other sites

Ok guys, for those of you who REALLY KNOW SIO and handler loading, I need help:

 

I have checked in a new test:

https://github.com/tschak909/atariwifi/tree/master/tests/cio4-poll

 

Which literally tries to utilize the Atari 850 handler bootstrap method to load in the N: driver I've been developing.

 

So far, I have been able to:

 

* Answer the type 1 poll, with an appropriate DCB for a loader program, that loads into a fixed location $1D00

* The SIO request is honored, loader shows up at $0500, jump to $0506, which sets up ANOTHER DCB to load the handler at $1D00.

* The loader then jumps to $1D01, which, ultimately goes into a loopty-loop, as AUTORUN.SYS gets loaded over and over again with a corresponding long beep.

 

I have tried to daisy chain DOSINI by saving it at the beginning of main(), setting a new DOSINI value (to point to my main()), and then jumping to the value I saved. but it loops.

 

Really wanna know why. Because this has kicked my arse, every step of the way, all day.

 

(and no, the 850 source code isn't much help, it's a highly compressed bowl of pasta in the expediency of conserving ROM space)

 

-Thom

Link to comment
Share on other sites

In main.c

 

	// Manually setting memlo, is there a symbol that can get me actual top of data?
	OS.memlo=(void *)0x23A5;
	asm("jmp ($000C)");
    

 

But from the map file generated

 

_ret 0023B0 RLA
_err 0023B1 RLA
__dosini_save 0023B2 RLA

 

It looks like you're allowing overwrite of the end of the driver. I'd use __BSS_LOAD__ + __BSS_SIZE__ for setting memlo.

Edited by Chilly Willy
fix code weirdness
  • Like 1
Link to comment
Share on other sites

1 hour ago, tschak909 said:

Yeah, I caught that, and adjusted to 23B2, and it goes back into the loop...hm.

-Thom

__dosini_save was at 23b2, so it'd have to be set to at least 23b4. However, __BSS_LOAD__ + __BSS_SIZE__ was even higher than that. You should probably compute _BSS_LOAD__ + _BSS_SIZE__ from the latest compile and set memlo to that value.

  • Like 1
Link to comment
Share on other sites

4 hours ago, mozzwald said:

Finally got all the pieces to test out MIDI Maze with FujiNet and it works with UDP for 2 player games. Code is updated at https://github.com/mozzwald/FujiNet-MIDIMaze and for your viewing pleasure:

 

 

This is great.. Do you have the program to try this thru internet and maybe across the pond.. That would be even more great

Edited by manterola
Link to comment
Share on other sites

3 minutes ago, manterola said:

This is great.. Do you have the program to try this thru internet and maybe across the pond.. That would be even more great

The code is at https://github.com/mozzwald/FujiNet-MIDIMaze but I have not been able to try over the internet. I can test with someone who has the CLKIN line wired to GPIO14 on the Nodemcu. Just need to share IP addresses and open/forward a port on the router.

Link to comment
Share on other sites

Hi Thom, 

I been playing with the tests you have uploaded and sometimes I have problems with some of them. 

I check the code and I am not sure about the way the state machine is coded. As I said I am not sure but  it is a little awkward to start processing the the command frame (like checking the device ID) before validating the whole 5 bytes using the checksum. Then if the checksum is not right, you shouldn't be sending Nak, you just ignore, I guess Nak is when the device ID is right but the command itself is invalid, (or ack if valid). I am not a sio guru, but that is how I understood the sio protocol. 

Maybe some of the errors and corruption of the SIO data might be due to this, like receiving a correct DevID but incorrect data... And not about the esp8266 not keeping up with the timing

Just my $.02

Thanks for the amazing job. 

 

  • Like 1
Link to comment
Share on other sites

2 minutes ago, manterola said:

Hi Thom, 

I been playing with the tests you have uploaded and sometimes I have problems with some of them. 

I check the code and I am not sure about the way the state machine is coded. As I said I am not sure but  it is a little awkward to start processing the the command frame (like checking the device ID) before validating the whole 5 bytes using the checksum. Then if the checksum is not right, you shouldn't be sending Nak, you just ignore, I guess Nak is when the device ID is right but the command itself is invalid, (or ack if valid). I am not a sio guru, but that is how I understood the sio protocol. 

Maybe some of the errors and corruption of the SIO data might be due to this, like receiving a correct DevID but incorrect data... And not about the esp8266 not keeping up with the timing

Just my $.02

Thanks for the amazing job. 

 

This project is wide open for collaboration. If you have a better way to deal with SIO processing, then please, take a whack at it, the only thing I ask is that you share your findings. :)

 

-Thom

Link to comment
Share on other sites

Again, I must remind everyone, that I am writing tons of test programs, this is one of them, to quickly sketch out what will actually be needed. I will have to re-implement all of this when we actually get to production firmware.

 

@jeffpiep is doing excellent work in this area, taking the tests I've written and making nice classes out of them (e.g. making generalized stream classes for TNFS, so they can be used interchangeably with the SPIFFS filesystem objects), and working towards making it more atomic so that multiple instances of the same device can be cleanly handled.

 

My goal with the current incarnation of "Diskulator" is to sketch out what the initial experience should be, and to figure out what SIO and TNFS commands will be needed to implement that experience.

 

This is the largest test program yet, because it's literally melding together "diskulator" and a configuration wizard. and I had to take a few side-lines to learn:

 

  • How to get CC65 to output a boot loadable disk image/program.
  • How to coax a "selection bar" out of some Player/Missile Graphics
  • How to use VS.Code and PlatformIO, as the release version of the software will be written in it.

Some things to work out in diskulator:

  • Scrolling the list of mountable disks from TNFS server, versus amount of network traffic generated for grabbing entries. This is harder than it sounds because of the limited amount of RAM in the ESP8266 (80K, of which, half of it is automatically used to hold Arduino internal state), I can't realistically just cache it all in memory, either in the Atari or in the ESP. Imagine waiting for 2000 ATRs to come across the server
  • other bits that I don't have on my mind atm because I am  hyperfocused.

 

Also, this is a call to everyone, if you have an idea, and can help implement it, please jump in. This project is mushrooming like crazy, and all sorts of functionality needs an implementation that can be used at the very least as a proof of concept.

 

-Thom

Edited by tschak909
Link to comment
Share on other sites

I do have a question for those of you who would be programming in BASIC.

 

But first, some background.

 

The CIO handler will provide an N: device with easy to use ways to do TCP communication, because the idioms used match well enough.

 

UDP communication will most likely have to be handled via SIO calls.

 

Why?

 

Because you're sending individual packets.

 

Why would you use UDP instead of TCP?

 

Because for certain applications, like games, it may make more sense to send fixed packets containing game state in one go. This is especially true if the amount of game state can fit into, say, 512 bytes.

 

Using UDP also allows you to utilize more exotic methods of transmission, such as multicast, where you can send a packet once, and it will be received by all the recipients at once. This works best on a local network, as even today, some 35 years after the initial specification of IP multicast, most routers will not route multicast traffic without some serious cajoling. But I will make the method available, nonetheless.

 

It does mean, that you lose some aspects of TCP, such as ensuring that packets come in the right order (you have to handle sequencing yourself, even if it just means incrementing a response counter, putting that in the packet, and rejecting packets that have the wrong response #, it's simple enough.), but those usually are inconsequential.

 

What would that look like, e.g. in BASIC?

 

It looks like an SIO call. Basically, to do an SIO call, you POKE a bunch of parameters into a location in memory that is set aside by the OS to hold SIO parameters, the Device Control Block (DCB), and then you use a small USR routine that simply calls SIOV, which does what you ask in the DCB and returns back to BASIC.

 

It looks something like this:

 

100 DIM BUF$(256)
110 DCB=768:REM LOCATION $0300
120 DDEVIC=112:REM $70 = NETWORK
121 DUNIT=1:REM UNIT (DDEVIC+UNIT-1)
130 DCOMND=ASC("U"):REM U = UDP WRITE
140 DSTATS=128:REM $80 = WRITE
150 ADDR=ADR(BUF$)
160 ADDRH=INT(ADDR/256)
170 ADDRL=ADDR-(ADDRH*256)
180 DBUFL=ADDRL:REM BUFFER LO
190 DBUFH=ADDRH:REM BUFFER HI
200 DTIMLO=15:REM 15 SEC TIMEOUT
210 DRESVD=0:REM RESERVED
220 DBYTL=0:REM # OF BYTES LO
230 DBYTH=1:REM # OF BYTES HI (256)
240 AUX1=0:REM AUX1=0
250 AUX2=0:REM AUX2=0
300 REM POKE VALUES INTO DCB
310 POKE DCB,DDEVIC:POKE DCB+1,DUNIT:POK
E DCB+2,DCOMND:POKE DCB+3,DSTATS:POKE DC
B+4,DBUFL:POKE DCB+5,DBUFH
320 POKE DCB+6,DTIMLO:POKE DCB+7,DRESVD:
POKE DCB+8,DBYTL:POKE DCB+9,DBYTH:POKE D
CB+10,DAUX1:POKE DCB+11,DAUX2
330 REM DO THE ACTUAL CIO CALL
340 X=USR(ADR("h Yd`")):REM JSR SIOV
350 RETURN

Line 340 looks like this:

image.thumb.png.3fd9a0873b512520e9d26e14fc3cb841.png

 

And the read would be similar, only the command and DSTATS are different (command would be 'V' and the dstats would be 64, aka $40)

 

So my question is:

 

Should this just be distributed as an example subroutine for sending commands directly to #FujiNet? or should we try to come up with a better way to do UDP comms?

 

-Thom

Link to comment
Share on other sites

Compared to TCP communications UDP looks much more complicated to an inexperienced programmer, especially given how hostile the old basics are in regards to readability and structured programming. Instead, if you could use the OPEN statement but in the address parameter you could express the address as say "N:192.168.1.2:U6502" for UDP and "N:192.168.1.2:T6502" for TCP. I would also say keep the other method as an example as well. It might have a speed advantage given that you're directly poking memory.

Link to comment
Share on other sites

My initial thoughts were to keep TCP in the CIO handler, and leave UDP completely out of it, because every call in the CIO handler takes up resident RAM, whether you use it, or not. UDP's usage doesn't fit well into existing CIO methodologies, at all (and the nail in that coffin is that BASIC doesn't afford multi-byte CIO transfers at all.)

 

-Thom

Link to comment
Share on other sites

Well that takes care of that idea. No wonder there's so many alternative basics for the A8's out there. It sounds like you've already identified the best way to do UDP given the limitations of BASIC. I just foresee TCP being over used at first only because there will be a perceived simplicity of use. This will of course change as the limitations become apparent latter.

 

As an aside it sounds like a better BASIC is needed when this launches to be more compatible with the 'net.

Link to comment
Share on other sites

Hi,

 

   I like the idea of specifying the IP address (and port) for an N: device in the CIO OPEN statement, but you might want to think about having something similar to a Percom block for a network device if you are doing UDP via SIO. That way you can set/get the ip address and port, and anything else you need. Otherwise you have to put the info in each buffer/frame that gets written, and there also isn't really a place in the DCB buffer for this info.

 

   

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...