Very well done. I can't wait to get home from work. The settings sound fine - 4 drives is plenty (one per user) and 20 ticks per second is fine. I've been testing packet routing software and can't wait to see if this runs on MP/M.
Dr_Acula said...
Very well done. I can't wait to get home from work. The settings sound fine - 4 drives is plenty (one per user) and 20 ticks per second is fine. I've been testing packet routing software and can't wait to see if this runs on MP/M.
Well, I actually don't see the improvement after reducing the hard disks or the ticks per second, so I'll go back to the original values.
Is the 8MB size some absolute limit? I thought I read somewhere that CP/M supports up to 256MB or even 512MB!?
It might make sense to use less and bigger HDs then.
The console #1 on keyboard is acting funny. Only control characters are displayed, some even fire some events (debugger?), but normal keys are not shown. I have to check the port handler for console #1 and see what could cause this. I have no terminal on SIO #1, so I don't know if console #2 works.
CP/M 3 and MP/M can handle much bigger disks. Up to 512MB if I remember correctly.
Are you using the same SIMH style hard drive interface as used in ZiCog?
If so, and if I remember correctly, all one has to do is set up some different Disk Parameter Blocks (DPB) in the Spin code DPB tables to describe the geometry and layout of the bigger disks.
Those new disk descriptions get pulled in by the BIOS though the hard disk interface when a drive is selected and used by CP/M rather than having fixed disk parameter tables in the BISO like the CP/M 2 floppies.
We have tried setting up different disk sizes in those tables in the past, smaller sizes for a floppy sized disk and for a RAM disk. They worked as expected so I see no reason why going larger should not work.
Mind you, figuring out how to set up those tables is a trick. They have many interdependent fields. It's all described in the MP/M manual some where. Also somewhere I saw some assembler macros that generated the required DPB entries given some basic disk parameters. Perhaps that was in the manual also.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
heater said...
Are you using the same SIMH style hard drive interface as used in ZiCog?
Yes, I used the same code that was in your CBIOSX.MAC, i.e. reading 17 bytes of DPB data from the core. Changing the size should be just a matter of finding the right BSH, BLM, EXM and DSM values. Fortunately we can handle different sized disks, so I could try to have a second DPB for drive B: and try to make it e.g. twice as big etc.
1) Juergen, can you edit your second post in the FAQs you can now say that banked memory is working.
2) I'm testing the second serial port - is there another user there? I'm getting a few bytes back but not an A prompt.
I need to study the code a bit more. For networking code I'd like USER1 to be about to output a byte to a port (any unused port) and for that byte to appear in USER0 as if it had been typed by USER0. I don't know if that is possible, but if it is then it would be possible for communication between users - eg the packet processing program can be processing a packet then getting just the data bytes and 'typing' them into the other user.
3) The autoexec.sub maybe needs changing so it automatically runs MP/M. Then the local keyboard works without having to have it attached to a PC (in order to type MP/M).
4) I need to create a new version of XMODEM that uses the correct i/o ports, so we can do file transfers.
That's great, should work then. Hacking away on the DPB for a drive other than A: is exactly what I was up to when creating the floppy and RAM disk sized disks.
Dr_A: What a great sight that dual screen shot is[noparse]:)[/noparse]
Well done guys. You are now doing on a Prop what MSDOS could never do on a PC!!!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
I'm working on xmodem. The N8VEM uses ports $68 for data and $6D for status. I have a version of xmodem configured for this. I think the MPM uses port $11 for data and $10 for status.
In the xmodem code there are only two settings - this is the N8VEM version and it is 6D and 68
.IF EXTMOD
MODCTLP:.EQU 06DH ; PUT YOUR MODEM STATUS PORT HERE
MODSNDB:.EQU 20H ; YOUR BIT TO TEST FOR SEND
MODSNDR:.EQU 20H ; YOUR VALUE WHEN READY
MODRCVB:.EQU 01H ; YOUR BIT TO TEST FOR RECEIVE
MODRCVR:.EQU 01H ; YOUR VALUE WHEN READY
MODDCDB:.EQU 02H ; CARRIER DETECT BIT *** DSR change status bit
MODDCDA:.EQU 00H ; VALUE WHEN ACTIVE *** 0 = no change since
MODDATP:.EQU 068H ; YOUR MODEM DATA IN PORT
MODDATO:.EQU 068H ; YOUR MODEM DATA OUT PORT
MODCTL2:.EQU 0C1H ; SECOND CONTROL/STATUS PORT.
.ENDIF ; END OF EXTERNAL MODEM .EQUATES
all the others stay the same.
Well maybe not.
I tried changing to $10 and $11 and it does not send out the regular bytes when it is expecting a download.
A quick test with mbasic and OUT &h10,65 sends out a character.
however, A=INP(&H11) returns 02 and the values that xmodem expects with this version are 32 and 33 (decimal)
See the settings above, it tests a bit, in reality the test is whether the LSB is 0 or 1. I can post lots of code here - for those that might want to experiment, .asm source and TASM to do the recompilation and you also need a working SIMH so you can read in the copy of the xmodem program onto the disk image then save it back onto the sd card. I've been down this road before with the N8VEM - essentially the program to get working is XMODEM and once a copy is on that sd card then everything else is easy.
So I think the data byte is working - it all comes down to the status byte and how it is handled, which bit is handled and how it works both sending and receiving.
Juergen, in spin the relevant line is
condata_port = $11 ' SIO port 0 data port
and I need to pull the exact code out that handles that, and see what it does.
But... after midnight and I need to go to work tomorrow, so no more coding for another 20 hours.
@Dr_A: the second serial port should work just as the console #0. It uses the same baud rate as the primary port. I hope I got the pins right? SI2 = 25 and SO2 = 24.
Port wrapping: I think I can add a port to do that by stuffing the data sent into the rx_buff0 at rx_head0. Then the console #0 will read it as if it came from the serial input. Done: see version 0.9.16.
If you change AUTOEXEC, you won't be able to go back to CP/M, because the cpm command also executes the AUTOEXEC.SUB again. Perhaps you can Ctrl+C it away...
The status bits for all status ports are bit 0 = rx data available, bit 1 = tx data possible. Bit 1 is always set now and if the tx buffer is really full, the tx out waits until the buffer has room for another character again.
Constat should be $10 and condata $11, so you should read a 2 from inp(&H10) and the next character from inp(&H11). The port numbers are listed as constants in io.spin. You should perhaps use the MP/M functions to read characters, because otherwise you may (or rather will) miss some characters that are polled away by the OS.
@heater: Glad you like it. It's fun but it's also really a bit too slow for my taste.
Just thinking out loud: When I reduce the number of hard disks to only 2, I can massively shrink the size of the common memory under MP/M so that the bank limit can be set at $c000. In the first bank this leaves just enough space to run Wordstar under MP/M and gives abt. 24KB to MBASIC. I really think we should limit the number of drives and instead make two of them big enough to keep anything we want. I will play with the tables to see if I can fit a 32MB hard disk without growing the allocation table. For 16K blocks - the maximum possible - there would be 2047 (- 6 reserved) blocks on a 32MB HD, and the allocation tables would have the same size as they have now with 2047-6 * 4KB blocks. Going to bigger drives would in any case require more blocks = more allocation table space and I don't yet know how much I can fit above $c000.
Banking at $C000 and more memory for programs and bigger drives would be fine.
Speed is more than enough for me. Picaxe and other similar chips run about 1000 instructions per second and this is comparable. I prefer the flexibility of high level programming, in particular big arrays and string manipulation, rather than speed. 8 hours to go before I get back to programming...
Dr_Acula said...
Banking at $C000 and more memory for programs and bigger drives would be fine.
Speed is more than enough for me. Picaxe and other similar chips run about 1000 instructions per second and this is comparable. I prefer the flexibility of high level programming, in particular big arrays and string manipulation, rather than speed. 8 hours to go before I get back to programming...
I now have code in io.spin that initializes the DPBs depending on the size of the *.DSK file, so you can even rename files without the need to change anything in the setup.
I will go with 3 drives and the max. supported size per drive is 32MB. If you use 64MB it would still basically work, but the allocation tables in the XIOS area would be too small. Not sure what implications this has.
Stat is already reporting nonsense for a 32MB drive. The total number of sectors is printed as 49024 while it really is ~261952 (262144 - 6 tracks of 32 sectors). This is probably an overflow in the math that stat is doing to print the values.
The MP/M stat is printing the correct values.
Regarding speed I found a tweak that improves execution speed a little: There is now a cog long "oldx", which is the most recent memory address. This is XORed with the new address and the result is zero, no address latches are written. Then after writing the LSB latch oldx is ANDed with !$ff, i.e. LSB removed. If oldx is zero afterwards, then the middle and high parts didn't change and the setup is done. Finally, after setting the middle latch, oldx is anded with !$ffff to see if the high latch changed. In average this seems to save a couple of instructions, because many times it is sufficient to just change the LSB.
The only thing required was to reset the oldx value to -1 after a port write, because that could potentially change the address latches on its own, e.g. in disk i/o.
The first page is updated again. Everything switched to max. 3 hard disks with max. 32MB each.
Aaargh, I'm stuck. Does anyone have Juergen's code from the 19th April?
Let me explain because this is complicated. I am experimenting with xmodem. Xmodem is the first program needed to get onto a disk and if you have that you can transfer anything. But you can't xmodem xmodem itself onto a disk.
Juergen's new file system is 32Mb. The SIMH gives an error reading this file because the block sizes are incorrect. So I can't run the SIMH to read xmodem into the sd card image.
I only have one thing to test on xmodem, and I could have tested it with the 19th April version of code that read 8mb files. If that had worked I could have sent the new version of xmodem to Juergen and he could have put it on the MPM disk. But I have overwritten the 19th April version with today's version. Silly me!
So what I need is a way of reading 32mb files. Or a way of converting them to 8mb files which are the 'standard' SIMH file image, then converting back to 32mb.
Addit: I might have a solution - it is stil reading drive B and C as 8mb files. I should be able to PIP it over from an 8mb simh image...
Dr_Acula said...
Aaargh, I'm stuck. Does anyone have Juergen's code from the 19th April?
Let me explain because this is complicated. I am experimenting with xmodem. Xmodem is the first program needed to get onto a disk and if you have that you can transfer anything. But you can't xmodem xmodem itself onto a disk.
Juergen's new file system is 32Mb. The SIMH gives an error reading this file because the block sizes are incorrect. So I can't run the SIMH to read xmodem into the sd card image.
I only have one thing to test on xmodem, and I could have tested it with the 19th April version of code that read 8mb files. If that had worked I could have sent the new version of xmodem to Juergen and he could have put it on the MPM disk. But I have overwritten the 19th April version with today's version. Silly me!
So what I need is a way of reading 32mb files. Or a way of converting them to 8mb files which are the 'standard' SIMH file image, then converting back to 32mb.
But you can use one of your 8MB images as drive B: or drive C: with the most recent code. The original images you once posted are on my website.
Or you can use an 8MB A: drive and rename my A.DSK to B.DSK or C.DSK and copy files over there.
Ok, working on it now. xmodem code is extremely complex and I still can't find the bit that does what I think it should do (send the startup NAK 10 times when receiving a file). I have some alternatives. Find that bit of code and test why it is not sending those NAK at startup.
Or change the test bit.
MODSNDR:.EQU 20H ; YOUR VALUE WHEN READY
which is 00100000
combine this with bit 0 and you have 00100000 and 00100001 which are 32 and 33 respectively.
You are reading 2 I think, and I'm not sure that is correct for the N8VEM uart settings. Where is that code?
I need to either find the NAK startup code (which I can't find) or find the bit setting in your code to test if it is ok to send a byte (which I can't find). This is confusing to explain I know. It took months to get xmodem working on the N8VEM.
I tried bypassing three lines in xmodem but that hasn't worked. Back to starting again...
.IF EXTMOD
MODCTLP:.EQU 06DH ; PUT YOUR MODEM STATUS PORT HERE
MODSNDB:.EQU 20H ; YOUR BIT TO TEST FOR SEND
MODSNDR:.EQU 20H ; YOUR VALUE WHEN READY
MODRCVB:.EQU 01H ; YOUR BIT TO TEST FOR RECEIVE
MODRCVR:.EQU 01H ; YOUR VALUE WHEN READY
MODDCDB:.EQU 02H ; CARRIER DETECT BIT *** DSR change status bit
MODDCDA:.EQU 00H ; VALUE WHEN ACTIVE *** 0 = no change since
MODDATP:.EQU 068H ; YOUR MODEM DATA IN PORT
MODDATO:.EQU 068H ; YOUR MODEM DATA OUT PORT
MODCTL2:.EQU 0C1H ; SECOND CONTROL/STATUS PORT.
.ENDIF
MODSNDB is 00100000% and so is MODSNDR
MODDATP AND MODDATO are the same port.
So to read a byte, first read port MODCTLP. If bit 0 is 0 then repeat. If bit 0 is 1 then a valid byte is available. Read it from MODDATP.
To output a byte, first read port MODCTLP. If bit 5 is 0 then repeat. If bit 5 is 1 then it is ok to send a byte. Output it to port MODDATO.
In the dracblade code I always set bit 5 to 1 so it told xmodem it was always ready to send.
Dr_Acula said...
In the dracblade code I always set bit 5 to 1 so it told xmodem it was always ready to send.
Well, this isn't how SIMH uses the port. SIMH has just bits 1 and 0 for tx and rx. Try with these figures for console #0. As I told you, you will have trouble getting in before the concurrent MP/M kernel code polls the port, though. You could perhaps run everything with interrupts disabled (DI) or with disabling the timer interrupt by writing 20 (14h) to port 0feh.
.IF EXTMOD
MODCTLP:.EQU 010H ; PUT YOUR MODEM STATUS PORT HERE
MODSNDB:.EQU 02H ; YOUR BIT TO TEST FOR SEND
MODSNDR:.EQU 02H ; YOUR VALUE WHEN READY
MODRCVB:.EQU 01H ; YOUR BIT TO TEST FOR RECEIVE
MODRCVR:.EQU 01H ; YOUR VALUE WHEN READY
MODDCDB:.EQU 00H ; CARRIER DETECT BIT *** DSR change status bit (we don't have it)
MODDCDA:.EQU 00H ; VALUE WHEN ACTIVE *** 0 = no change since (anything & 0 = 0)
MODDATP:.EQU 011H ; YOUR MODEM DATA IN PORT
MODDATO:.EQU 011H ; YOUR MODEM DATA OUT PORT
MODCTL2:.EQU 010H ; SECOND CONTROL/STATUS PORT.
.ENDIF ; END OF EXTERNAL MODEM .EQUATES
Ah, I see the problem. Two things polling a port at the same time. Now I remember how I solved this - I added two new ports in the dracblade code. Only xmodem ever polled those ports:
PRI on_input
'Handle Z80 IO port reads
case io_port
' srport: 'Altair front panel switches register
' in_srport
simhport: 'SIMH control port
in_simhport
constat: 'Console status port $0F
in_constat
condata: 'Console data port
in_condata
n8vem_uart_test: ' test port $6D
in_test_n8vem ' is a byte ready returns %00100000 for no byte, %00100001 for a byte
n8vem_uart_in: ' ask for input from port $68
in_uart_n8vem ' get the byte
port2_test: ' test second port $7D
in_test_port2 ' is a byte ready returns %00100000 for no byte, %00100001 for a byte
port2_io: ' get the byte from port $78
in_port2 ' get the byte
hdskport:
in_hdskport 'SIMH style hard disk port
keystat: ' test just the keyboard (constat above is a combo of both ports and keyboard)
in_keystat
keydata: ' get the keyboard character
in_keydata
PRI in_test_n8vem
' for xmodem tests if any input from serial port 0
' input present = bit 0. Output ready to go = bit 5 (always high).
if UART.rxavail(0)
io_data :=%00100001 'yes
else
io_data :=%00100000 'no
PRI in_uart_n8vem ' for xmodem transfers
if UART.rxavail(0)
io_data := UART.rx(0) ' get the byte
else
io_data := "?"
so ports like condata are the SIMH ports. And there is additional code for the N8VEM ports.
On a single CP/M emulation, if it is running an emulation and the program it is running is assembly, and that program is not calling any CP/M bios calls, then it never reads these ports. xmodem does that because it talks to ports directly.
But if MP/M is polling those ports too, then it can escape out of the tight assembly control loop that is in xmodem.
So - on CP/M a byte arrives from the serial port to type on the screen and CP/M handles that. When you run xmodem then every byte that arrives goes into xmodem. CP/M is disabled until xmodem ends.
What is MP/M doing? Is it polling the port in between emulating each instruction?
Yes, we could do this by disabling interrupts and switching everything off for MPM. Xmodem could do that at the beginning (and switches them back on at the end)
Then it flushes the buffers (this is already in the code).
Then it polls (say) port 6D. This does the same as the spin code above - it asks ' is there a byte in the serial object?' But it does not read that byte.
Then if there is a byte, grab the byte with a read to port 68, which bypasses MP/M reading the byte.
Here's a quick hack support for ports $68 and $6d. They seem to work when I tested them from mbasic.
I had to throw out the (unused) console #3 port handling. Since no one polls console #3, that shouldn't hurt.
I also fixed a bug in console #2 (SIO #1) input function. It was reading from the wrong input buffer location.
The simh_reset command is not supposed to reset the CPU, but the SIMH internal state AFAIK. I have to try on altairz80 what happens when I issue this out.
Very close. Getting the NAK back as expected. It is *much* faster than the existing dracblade code looking at the timing delays between the NAKs. About 10 times faster, so already that is a huge improvement. I might have to tweak some timing delays as it is coming in even faster than the original N8VEM.
I'm using this in CP/M rather than within MPM - is that ok?
It prints 32 continuously. When I type a character, it should print 33 to say a character is now in the buffer
(running from CP/M, not MP/M). Off to test it in MPM now.
Dr_Acula said...
Small problem with the status port.
In mbasic
10 A=INP(&H6D)
20 PRINT A
30 GOTO 10
It prints 32 continuously. When I type a character, it should print 33 to say a character is now in the buffer
(running from CP/M, not MP/M). Off to test it in MPM now.
Hmm.. strange. Here's the piece of code doing the status port read:
'**********************************************************************************************
'
' Read N8VEM status for the FullDuplexSerial rx_buffer0
'
n8vem_st
mov data, #%00100000 ' no data available
rdlong sio_head, rx_head1
rdlong sio_tail, rx_tail1
cmp sio_head, sio_tail WZ ' set zero flag if no data available
if_nz or data, #%00000001 ' set data available bit
jmp lmm_func_ret
DOH! Now I see it. I tested sio port #1, not #0 ... stupid me.
You can download the attachment or fix it yourself in io.spin: change rx_head1 to rx_head0 and rx_tail1 to rx_tail0.
I just needed to tweak some timings in the vb.net program
LineOfText = "ERA " + CPMFilename + vbCr
Call StringToPacket(LineOfText)
Sleep(1500) ' 1000 for 4800 baud
' mod June 2009 to run new xmodemf which deletes and undone again as doesnt work
' MPM increased from 500 to 2000 and finalised at about 1500
LineOfText = "XMODEMF R " + CPMFilename + vbCr
Call StringToPacket(LineOfText) '
'LineOfText = vbCrLf
'Call StringToPacket(LineOfText) ' send a return/LF
Sleep(500) ' wait for text to come back before disabling timer
' 100 is a bit short, 300 works, 200 seems a bit better
' xmodem is taking 2 seconds to acknowledge so have at least this much time
' to get the text back. Need the longest delay out of N8VEM, CP/M and MPM
Because xmodem does not delete old files of the same name, the first thing I do with a download is to ERA a file of the same name. If the file does not exist, or even if the file does exist, it takes a little while to actually erase the file. So the timing tweak is not with xmodem, but rather with the delay of 1.5 seconds after the ERA to make sure MPM is back at the 0A> prompt.
This is brilliant. Now we can transfer files back and forth.
Next step - I need to try at faster baud rates as I've been using 19200 as all my programs default to that. BRB
Just a word of warning. I've seen Bdos errors with MP/M (read/write sector error) and I know the reason. The sector read/write code has to do a sequence of 6 out commands, which should not be interrupted. Now since MP/M polls ports round robin, it still might happen occasionally that the read/write sector command is disturbed by another port in or out. I tried to circumvent that by not issuing an interrupt as long as the io.spin code is expecting or replying a sequence of bytes, but even with that measure the errors happen from time to time.
I have to integrate a retry count into MPMXIOS.MAC to catch these errors and try the same command again - twice I think. I also would better break compatibility with SIMH and add a checksum to the sequence to verify it has not been intercepted by interrupt code. That should suffice to catch the cases that slip through the interrupt prevention. I need to make a new A.DSK for that, so it would be wise to include your working Xmodem code!?
Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
· Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Well, I actually don't see the improvement after reducing the hard disks or the ticks per second, so I'll go back to the original values.
Is the 8MB size some absolute limit? I thought I read somewhere that CP/M supports up to 256MB or even 512MB!?
It might make sense to use less and bigger HDs then.
The console #1 on keyboard is acting funny. Only control characters are displayed, some even fire some events (debugger?), but normal keys are not shown. I have to check the port handler for console #1 and see what could cause this. I have no terminal on SIO #1, so I don't know if console #2 works.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Post Edited (pullmoll) : 4/20/2010 9:06:46 AM GMT
Are you using the same SIMH style hard drive interface as used in ZiCog?
If so, and if I remember correctly, all one has to do is set up some different Disk Parameter Blocks (DPB) in the Spin code DPB tables to describe the geometry and layout of the bigger disks.
Those new disk descriptions get pulled in by the BIOS though the hard disk interface when a drive is selected and used by CP/M rather than having fixed disk parameter tables in the BISO like the CP/M 2 floppies.
We have tried setting up different disk sizes in those tables in the past, smaller sizes for a floppy sized disk and for a RAM disk. They worked as expected so I see no reason why going larger should not work.
Mind you, figuring out how to set up those tables is a trick. They have many interdependent fields. It's all described in the MP/M manual some where. Also somewhere I saw some assembler macros that generated the required DPB entries given some basic disk parameters. Perhaps that was in the manual also.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Yes, I used the same code that was in your CBIOSX.MAC, i.e. reading 17 bytes of DPB data from the core. Changing the size should be just a matter of finding the right BSH, BLM, EXM and DSM values. Fortunately we can handle different sized disks, so I could try to have a second DPB for drive B: and try to make it e.g. twice as big etc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Juergen is the best. We have two users attached here - see the attached photo.
It needs the latest version of both the A.DSK and the source code from the first page of this thread.
On the left is Teraterm talking to the first serial port. This is User 0. On the right is the local keyboard and local VGA display. This is User 1.
If you type MPMSTAT on either you can get some statistics.
If you type DIR on User 0 there are all the files on the disk. User 1 has no files at bootup. You can transfer files from User 0 with this syntax
0A>pip mbasic.com[noparse][[/noparse]G1]=mbasic.com
And then run mbasic on user1.
Ok, where to now?
1) Juergen, can you edit your second post in the FAQs you can now say that banked memory is working.
2) I'm testing the second serial port - is there another user there? I'm getting a few bytes back but not an A prompt.
I need to study the code a bit more. For networking code I'd like USER1 to be about to output a byte to a port (any unused port) and for that byte to appear in USER0 as if it had been typed by USER0. I don't know if that is possible, but if it is then it would be possible for communication between users - eg the packet processing program can be processing a packet then getting just the data bytes and 'typing' them into the other user.
3) The autoexec.sub maybe needs changing so it automatically runs MP/M. Then the local keyboard works without having to have it attached to a PC (in order to type MP/M).
4) I need to create a new version of XMODEM that uses the correct i/o ports, so we can do file transfers.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Post Edited (Dr_Acula) : 4/20/2010 2:10:01 PM GMT
That's great, should work then. Hacking away on the DPB for a drive other than A: is exactly what I was up to when creating the floppy and RAM disk sized disks.
Dr_A: What a great sight that dual screen shot is[noparse]:)[/noparse]
Well done guys. You are now doing on a Prop what MSDOS could never do on a PC!!!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
In the xmodem code there are only two settings - this is the N8VEM version and it is 6D and 68
all the others stay the same.
Well maybe not.
I tried changing to $10 and $11 and it does not send out the regular bytes when it is expecting a download.
A quick test with mbasic and OUT &h10,65 sends out a character.
however, A=INP(&H11) returns 02 and the values that xmodem expects with this version are 32 and 33 (decimal)
See the settings above, it tests a bit, in reality the test is whether the LSB is 0 or 1. I can post lots of code here - for those that might want to experiment, .asm source and TASM to do the recompilation and you also need a working SIMH so you can read in the copy of the xmodem program onto the disk image then save it back onto the sd card. I've been down this road before with the N8VEM - essentially the program to get working is XMODEM and once a copy is on that sd card then everything else is easy.
So I think the data byte is working - it all comes down to the status byte and how it is handled, which bit is handled and how it works both sending and receiving.
Juergen, in spin the relevant line is
condata_port = $11 ' SIO port 0 data port
and I need to pull the exact code out that handles that, and see what it does.
But... after midnight and I need to go to work tomorrow, so no more coding for another 20 hours.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Port wrapping: I think I can add a port to do that by stuffing the data sent into the rx_buff0 at rx_head0. Then the console #0 will read it as if it came from the serial input. Done: see version 0.9.16.
If you change AUTOEXEC, you won't be able to go back to CP/M, because the cpm command also executes the AUTOEXEC.SUB again. Perhaps you can Ctrl+C it away...
The status bits for all status ports are bit 0 = rx data available, bit 1 = tx data possible. Bit 1 is always set now and if the tx buffer is really full, the tx out waits until the buffer has room for another character again.
Constat should be $10 and condata $11, so you should read a 2 from inp(&H10) and the next character from inp(&H11). The port numbers are listed as constants in io.spin. You should perhaps use the MP/M functions to read characters, because otherwise you may (or rather will) miss some characters that are polled away by the OS.
@heater: Glad you like it. It's fun but it's also really a bit too slow for my taste.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Post Edited (pullmoll) : 4/20/2010 4:17:10 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Post Edited (pullmoll) : 4/20/2010 7:57:19 PM GMT
Having a couple of 32MB disks should be quite enough given the speed of this system.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Speed is more than enough for me. Picaxe and other similar chips run about 1000 instructions per second and this is comparable. I prefer the flexibility of high level programming, in particular big arrays and string manipulation, rather than speed. 8 hours to go before I get back to programming...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
I now have code in io.spin that initializes the DPBs depending on the size of the *.DSK file, so you can even rename files without the need to change anything in the setup.
I will go with 3 drives and the max. supported size per drive is 32MB. If you use 64MB it would still basically work, but the allocation tables in the XIOS area would be too small. Not sure what implications this has.
Stat is already reporting nonsense for a 32MB drive. The total number of sectors is printed as 49024 while it really is ~261952 (262144 - 6 tracks of 32 sectors). This is probably an overflow in the math that stat is doing to print the values.
The MP/M stat is printing the correct values.
Regarding speed I found a tweak that improves execution speed a little: There is now a cog long "oldx", which is the most recent memory address. This is XORed with the new address and the result is zero, no address latches are written. Then after writing the LSB latch oldx is ANDed with !$ff, i.e. LSB removed. If oldx is zero afterwards, then the middle and high parts didn't change and the setup is done. Finally, after setting the middle latch, oldx is anded with !$ffff to see if the high latch changed. In average this seems to save a couple of instructions, because many times it is sufficient to just change the LSB.
The only thing required was to reset the oldx value to -1 after a port write, because that could potentially change the address latches on its own, e.g. in disk i/o.
The first page is updated again. Everything switched to max. 3 hard disks with max. 32MB each.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Post Edited (pullmoll) : 4/21/2010 12:11:17 AM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Let me explain because this is complicated. I am experimenting with xmodem. Xmodem is the first program needed to get onto a disk and if you have that you can transfer anything. But you can't xmodem xmodem itself onto a disk.
Juergen's new file system is 32Mb. The SIMH gives an error reading this file because the block sizes are incorrect. So I can't run the SIMH to read xmodem into the sd card image.
I only have one thing to test on xmodem, and I could have tested it with the 19th April version of code that read 8mb files. If that had worked I could have sent the new version of xmodem to Juergen and he could have put it on the MPM disk. But I have overwritten the 19th April version with today's version. Silly me!
So what I need is a way of reading 32mb files. Or a way of converting them to 8mb files which are the 'standard' SIMH file image, then converting back to 32mb.
Addit: I might have a solution - it is stil reading drive B and C as 8mb files. I should be able to PIP it over from an 8mb simh image...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Post Edited (Dr_Acula) : 4/21/2010 8:06:30 AM GMT
But you can use one of your 8MB images as drive B: or drive C: with the most recent code. The original images you once posted are on my website.
Or you can use an 8MB A: drive and rename my A.DSK to B.DSK or C.DSK and copy files over there.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Or change the test bit.
MODSNDR:.EQU 20H ; YOUR VALUE WHEN READY
which is 00100000
combine this with bit 0 and you have 00100000 and 00100001 which are 32 and 33 respectively.
You are reading 2 I think, and I'm not sure that is correct for the N8VEM uart settings. Where is that code?
I need to either find the NAK startup code (which I can't find) or find the bit setting in your code to test if it is ok to send a byte (which I can't find). This is confusing to explain I know. It took months to get xmodem working on the N8VEM.
I tried bypassing three lines in xmodem but that hasn't worked. Back to starting again...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
The relevant bit is this
MODSNDB is 00100000% and so is MODSNDR
MODDATP AND MODDATO are the same port.
So to read a byte, first read port MODCTLP. If bit 0 is 0 then repeat. If bit 0 is 1 then a valid byte is available. Read it from MODDATP.
To output a byte, first read port MODCTLP. If bit 5 is 0 then repeat. If bit 5 is 1 then it is ok to send a byte. Output it to port MODDATO.
In the dracblade code I always set bit 5 to 1 so it told xmodem it was always ready to send.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Well, this isn't how SIMH uses the port. SIMH has just bits 1 and 0 for tx and rx. Try with these figures for console #0. As I told you, you will have trouble getting in before the concurrent MP/M kernel code polls the port, though. You could perhaps run everything with interrupts disabled (DI) or with disabling the timer interrupt by writing 20 (14h) to port 0feh.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Post Edited (pullmoll) : 4/21/2010 10:23:46 AM GMT
so ports like condata are the SIMH ports. And there is additional code for the N8VEM ports.
On a single CP/M emulation, if it is running an emulation and the program it is running is assembly, and that program is not calling any CP/M bios calls, then it never reads these ports. xmodem does that because it talks to ports directly.
But if MP/M is polling those ports too, then it can escape out of the tight assembly control loop that is in xmodem.
So - on CP/M a byte arrives from the serial port to type on the screen and CP/M handles that. When you run xmodem then every byte that arrives goes into xmodem. CP/M is disabled until xmodem ends.
What is MP/M doing? Is it polling the port in between emulating each instruction?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Post Edited (Dr_Acula) : 4/21/2010 10:34:11 AM GMT
Then it flushes the buffers (this is already in the code).
Then it polls (say) port 6D. This does the same as the spin code above - it asks ' is there a byte in the serial object?' But it does not read that byte.
Then if there is a byte, grab the byte with a read to port 68, which bypasses MP/M reading the byte.
Is there room in pasm for such a thing?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
You mean emulating the n8vem ports $68 and $6d? I think that should be possible as LMM code. I'll give it a try.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Emulate ports 68 and 6D
or
use port 10 and 11. But totally disable anything else using those ports while xmodem is running.
I'm just worrying how much spare memory you have left.
addit
Not sure if I am doing this right, but if I use mbasic and go
OUT &h11,65
then it prints
AOk
as expected
but if I use
OUT &HFE,14
is that supposed to reset the emulation?
As an aside
OUT &H21,65
types A on the other users screen as if they typed it. Now that is going to be extremely useful!!!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Post Edited (Dr_Acula) : 4/21/2010 11:05:01 AM GMT
I had to throw out the (unused) console #3 port handling. Since no one polls console #3, that shouldn't hurt.
I also fixed a bug in console #2 (SIO #1) input function. It was reading from the wrong input buffer location.
The simh_reset command is not supposed to reset the CPU, but the SIMH internal state AFAIK. I have to try on altairz80 what happens when I issue this out.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Post Edited (pullmoll) : 4/21/2010 11:02:50 AM GMT
Very close. Getting the NAK back as expected. It is *much* faster than the existing dracblade code looking at the timing delays between the NAKs. About 10 times faster, so already that is a huge improvement. I might have to tweak some timing delays as it is coming in even faster than the original N8VEM.
I'm using this in CP/M rather than within MPM - is that ok?
Ok, next I need to put the port sniffer on...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Post Edited (Dr_Acula) : 4/21/2010 11:15:18 AM GMT
In mbasic
It prints 32 continuously. When I type a character, it should print 33 to say a character is now in the buffer
(running from CP/M, not MP/M). Off to test it in MPM now.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
DOH! Now I see it. I tested sio port #1, not #0 ... stupid me.
You can download the attachment or fix it yourself in io.spin: change rx_head1 to rx_head0 and rx_tail1 to rx_tail0.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
I just needed to tweak some timings in the vb.net program
Because xmodem does not delete old files of the same name, the first thing I do with a download is to ERA a file of the same name. If the file does not exist, or even if the file does exist, it takes a little while to actually erase the file. So the timing tweak is not with xmodem, but rather with the delay of 1.5 seconds after the ERA to make sure MPM is back at the 0A> prompt.
This is brilliant. Now we can transfer files back and forth.
Next step - I need to try at faster baud rates as I've been using 19200 as all my programs default to that. BRB
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.smarthome.viviti.com/propeller
Just a word of warning. I've seen Bdos errors with MP/M (read/write sector error) and I know the reason. The sector read/write code has to do a sequence of 6 out commands, which should not be interrupted. Now since MP/M polls ports round robin, it still might happen occasionally that the read/write sector command is disturbed by another port in or out. I tried to circumvent that by not issuing an interrupt as long as the io.spin code is expecting or replying a sequence of bytes, but even with that measure the errors happen from time to time.
I have to integrate a retry count into MPMXIOS.MAC to catch these errors and try the same command again - twice I think. I also would better break compatibility with SIMH and add a checksum to the sequence to verify it has not been intercepted by interrupt code. That should suffice to catch the cases that slip through the interrupt prevention. I need to make a new A.DSK for that, so it would be wise to include your working Xmodem code!?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Pullmoll's Propeller Projects
Post Edited (pullmoll) : 4/21/2010 11:59:29 AM GMT