Welcome, Guest. Please login or register.


Author Topic: Enterprise C compiler for PC (Read 34207 times)

Offline lgb

  • EP addict
  • *
  • Posts: 3563
  • Country: hu
  • æðsta yfirmaður
    • http://lgb.hu/
Re: Enterprise C compiler for PC
« Reply #30 on: 2015.August.24. 11:50:06 »
Quote
The user-level documentation I found on EXDOS mentioned that a disk channel was automatically closed after a read or write operation, so it seemed like EXDOS would not be able to support streamed i/o.  I was reading user-level documentation which was concerned with loadng and saving entire files rather than random access so it could be I was unlucky to look at the wrong place.

I'm not sure what you mean here, where did you find this information and in what kind of context?

Quote
Would something like this be able to be efficiently implemented using just EXDOS?

Code: [Select]
while ((c = fgetc(in)) != EOF)
   fputc(process(c), out);

For this kind of common code to be efficient, the implementation has to cache several disk sectors in memory so that individual reads and writes go to memory rather than disk.  Most z80 disk implementations have been as simple as possible and perform very badly under C without assistance which is why z88dk is trying to supply disk i.o in a layered manner so that these simple systems can sit on top of a caching mechanism.

Well, that  code is not so nice anyway, since you need to issue "system calls" (or whatever we want to name them) all the time character by character, even on a modern OS on decent hardware it will be much slower than doing more bytes on the I/O by your code already. Just to mention that I had to write a log analyzer/"converter" software in C on UNIX and it was much slower using the scheme above. Anyway, that's true that still some may want to try to optimize these somewhat at least on the compiler/OS level.

Regarding your question about the implementation of this in EXDOS. Really, EXDOS is "only" an EXOS_ROM extension for EXOS. Thus, for "generic" file I/O you still use EXOS function calls (like open channel, read channel, check channel status), whatever the file is located on a disk or eg on tape. It's another question that internally, EXDOS will get the request by EXOS if it should be handled. But you even don't need to know there is something like "EXDOS" in the system for basic file I/O, those are just files, and open channels like any other similar entities (or even devices, just think about DISPLAY: or SOUND: ...). However, if you need something "special" over the "generic file I/O", like change directory, create directory whatever, that's not handled by EXOS, and then you need to "talk" with EXDOS then, since it's implementation specific and not generic (eg no "directory" notion of SOUND: device, or on the tape ...). But please note, that's more like my feelings about the structure of EXOS/EXDOS than "official specification" :)

In my opinion the code above can be done with opening two (file) channels with EXOS one for reading and one for writing. The "read character from channel" EXOS call (function 5) can be used to read a character, and "write character to channel" EXOS call (function 7) to write, to replace fgetc() and fputc(). What I am not sure about: the EOF check. According to the specification of the EXOS calls (see the URL later), "read character from channel" call will wait till a character is available for reading. Well, that's a reasonable thing with eg keyboard channel open, but with file, I don't know what happens if you hit the end of the file. Anyway, there is an EXOS call to check the channel status too: function 9, which can also return with the "end-of-file" state for you (if function 5 won't return with 0 read characters in case of EOF, that must be checked, or some other guy should tell the truth here who is more familiar with the EXOS internals than me). EXDOS internally has buffers, so what I can guess that it won't access the disk all the time if you read byte by byte only. However of course there is a price that you issue an EXOS call byte by byte still, but as I mentioned it's even problem on a decent OS running on modern hardware ...

Again, in this simple example it's not important at all that the file open (and then read, written, whatever) refers for a file in the "realm" of the EXDOS, or not, it's handled by EXOS, and it will talk with EXDOS if needed (however if you really want you can use EXDOS directly anyway even for generic file I/O only ...).

About EXOS calls:

http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/kernel/Ch11.html

To be honest, I feel a problem (I mean to use EXOS) with this though. If you read the page at the URL above, you will find that file names can be used to open channels can be maximum of 28 bytes long. It does not feel a problem too much, as with FAT (no VFAT whatever) the 8+3 file name length seems to be OK. But consider the situation that you want to open a file "deeply" in a directory structure like A:\LONGDIR.1\LONGDIR.2\.....\FINAL.TXT so the file name (with full path I mean, what you pass to the EXOS open channel function) can be longer than 28 characters then, which is a no-no then. If I remember correctly I've already asked this on this forum, and the response was something similar that: "it's not so common to use absolute long paths on the EP anyway, just change directory first and access files there without the path information then".

EXOS "channel" operations btw is more like (in my opinion) open() read() etc calls common in C language with "int" typed file descriptors (fd) with the major difference that with EXOS, you must specify a channel number you want even at open(), while open() would "choose" an fd for you (the lowest unused one). It's somewhat also similar that in case of UNIX you can use C code like open("/dev/...", ...) to open a device instead of a "real file" (or maybe CON, PRN in case of DOS-style stuffs?) just that on EXOS would be something like KEYBOARD: and DISPLAY: names.

Quote
We don't replace the underlying system, only add to it.  So eg, a cpm system can still do file i/o by calling the bdos directly but the c standard i/o is also available to use.

By the way CP/M, EP also has a CP/M compatibility system, named "IS-DOS". It's an interesting stuff (though I've never used too much), in theory it supports even MSX-DOS stuffs (??), and beyond the CP/M (not v3 ...) the disk filling system in the background is still EXDOS, so unlike "original" CP/M systems (using their own file systems, often not even compatible with each other) IS-DOS - with the help of EXDOS - uses FAT12. So IS-DOS is not an "official" CP/M version from Digital Research with only a CBIOS created for the EP keeping BDOS (as far as I know!) but a system developed for the EP with the goal to be compatible with CP/M though (again, as far as I know).

Quote
Ok, is there any documentation on what is returned from a port read of $b6?  The only doc I've found so far is this:

http://gafz.enterpriseforever.com/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/keyboard/Ch3.html#3.7
which is using the EXOS keyboard driver to read the joystick.  The bits are obviously moved because when you read the internal joystick those bits do not correspond to the keys read from $b5.

Reading the external joysticks also uses the $B5 port (like the keyboard) to select what you want to scan, but after the selection is made, you must read port $B6 (unlike the keyboard, where you can read the state on $B5), and bit 0 will carry the state of the selected line. The "selection" itself (numbers are the values written to $B5), and if I recall correctly: 0 = fire, 1 = up, 2 = down, 3 = left, 4 = right, for external joy-1, and for kbd sel 5-9 the same series of assignments for external joy-2. Or something similar. I've never tried to use external joystick(s) in my programs though ... The interesting point here that other machines usually have the joystick as some kind of inputs and you can read a byte, with bits assigned to the fire and direction. On the EP however, as you can see, you must "scan" the joystick somewhat similar as with the keyboard. Maybe you can use a common routine to scan kbd and joystick (and save some CPU cycles?) that you write 0 to $B5, read $B5 to get the state of keys in kbd matrix row #0, and also read $B6 and check bit 0 of the result for joy-1 fire. Then write 1 to $B5, read $B5 to get the state of keys in kbd matrix row #1, but also read $B6 then and check bit 0 of the result for joy-1 direction "up". And so on. Thus you can save to "walk" on 0...9 writes to $B5 twice then (one run is for the kbd, one is for joysticks). As far as I know, for real not only bit 0 can be used (from value read on port $B6) but maybe bits 1, 2 too, thus you can in theory connect "tons of" joysticks to the EP128 with many lines, extra buttons, etc. I am really not sure on this though. I guess, mostly used (though I have no external joysticks at all) "official" (??) solutions uses only bit 0, hopefully on the way I've described above (or maybe not, hmm).

By the way:

https://enterpriseforever.com/hardver/dave/msg27102/#msg27102

Unfortunately, it's in Hungarian, so I am not sure how useful it is for you (and what result you'll get with google translator or something like that). But here it is:

https://translate.google.com/translate?sl=hu&tl=en&js=y&prev=_t&hl=hu&ie=UTF-8&u=https%3A%2F%2Fenterpriseforever.com%2Fhardver%2Fdave%2Fmsg27102%2F%23msg27102&edit-text=

Joysticks - again - are something I am not so experienced with ...

Another interesting thing, that mouse also works like this (well, the "official" EP mouse is said to be "terrible" - I don't know it personally - so I talk about the "common" solution instead, often named as "boxsoft mouse". It also uses control port lines to read mouse data (originally an MSX-mouse like protocol serialized to one bit transfer with a "shift" signal produced on a line on the serial port .... or something like that). It has some problem though that there is a conflict between external joystick and a mouse then. There is an on-going project (also can be found on the forum) to create a hardware solution for more modern (PS/2?) mouses with some modification to avoid the mentioned conflict.


Quote
Yes it is - that's why I'm sort of staggering around to figure out the best way to do this   I'm sure the best way will evolve over time.

Quote
I don't mind.. the more info the better.   Once I have something preliminary ready I'm sure it will be easier to point out how to improve things.

Indeed.

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #31 on: 2015.August.24. 18:34:48 »
I'm not sure what you mean here, where did you find this information and in what kind of context?

I was glancing through http://ep.homeserver.hu/Dokumentacio/Konyvek/EXDOS/EXDOSeng.htm but I can see now it is mentioned that the disk channel is only opened and closed if you're loading / saving without first opening a channel.  There's no mention of seeking or random access of files.  It's just a simple reference for basic so there isn't a lot of meaty information there.  I found a reference to ISDOS on the same site (in Hungarian) which seems to have a lot more information and makes it look like ISDOS has a lot in common with cpm.  But of course ISDOS is an extension / replacement of EXDOS.

Code: [Select]
while ((c = fgetc(in)) != EOF)
   fputc(process(c), out);

Quote
Well, that  code is not so nice anyway, since you need to issue "system calls" (or whatever we want to name them) all the time character by character, even on a modern OS on decent hardware it will be much slower than doing more bytes on the I/O by your code already. Just to mention that I had to write a log analyzer/"converter" software in C on UNIX and it was much slower using the scheme above. Anyway, that's true that still some may want to try to optimize these somewhat at least on the compiler/OS level.

There are a lot of programs out there doing things this way because sometimes the top performance is not the main concern.  On modern OSes buffering is done at the FILE* level so that the c library is maintaining a 256/512/..4k block of memory for each open FILE so that i/o goes to this user-level buffer and only spills to the OS when the buffer is exhausted.  That way the very slow OS calls are avoided and are traded for a small (on big machines!) memory penalty.  That memory penalty is too high in a 64k memory space so z88dk has changed things somewhat by giving the responsibility to the driver to manage buffers for all storage access.  This way it's not one buffer per open FILE, it's a small number of buffers shared by all storage devices.  But the device driver has to be able to manage such a cache and if it can't z88dk is supposed to supply that code and disk devices will sit on top of that.  So the question is does EXDOS on its own manage such a buffer so that disk thrashing is avoided (read one byte from one file, write one byte to another -- does that mean entire sectors are read and written to access that one byte?)

Note that fuzix, an 8-bit project to bring a unix-like OS to the z80/6809/6502 is doing things like a modern machine as described above and is currently impractical on a 64k machine partly because of this.

In the sample program above the performance issue is very clear but a little more hidden is the exact same issue when using scanf for files:

Code: [Select]
fscanf(in, " %*[A-Z] %d %f", &i, &num);

This just an illustrative example and isn't really a meaningful program fragment.

The first specifier "%*[A-Z]" is supposed to throw away any group of chars from the stream in the set [A-Z].  Then it's supposed to skip whitespace, read an integer, skip whitespace and read a float.

To do any of those specifiers, the c library itself must read one char at a time from the file and decide whether to accept it or not.  That's not any different from the fgetc() case.

People who are concerned with performance normally do this in a line-oriented manner:

Code: [Select]
getline(&line, &len, in);
sscanf(line, " %*[A-Z] %d %f", &i, &num);

But getline() must *still* read chars one at a time because it needs to identify the end of the line on the stream.  So the improvement is only marginal.  (This is a much better way to do things for a different reason:  error handling and having the file pointer at a known position).

Anyway the unique thing that z88dk does is it pushes a state machine to the driver so that the driver is able to determine what is accepted by stdio as it reads chars from the device/cache.

Quote
In my opinion the code above can be done with opening two (file) channels with EXOS one for reading and one for writing. The "read character from channel" EXOS call (function 5) can be used to read a character, and "write character to channel" EXOS call (function 7) to write, to replace fgetc() and fputc(). What I am not sure about: the EOF check.

If EXOS can do it, it's no problem to do it that way.  EOF is one thing but also C allows files to be opened for updating.  That means there are two file pointers in a single file:  one where the reads are coming from and one used to append to the end of a file.  I'm not aware of any z80 disk system that is able to handle this well since it requires the system to maintain two buffers for a single file in order to avoid thrashing.  But if it's a problem, open for update can be disallowed too.

Quote
seems to be OK. But consider the situation that you want to open a file "deeply" in a directory structure like A:\LONGDIR.1\LONGDIR.2\.....\FINAL.TXT so the file name (with full path I mean, what you pass to the EXOS open channel function) can be longer than 28 characters then, which is a no-no then. If I remember correctly I've already asked this on this forum, and the response was something similar that: "it's not so common to use absolute long paths on the EP anyway, just change directory first and access files there without the path information then".

Another way to solve is to traverse the path in a loop and only change one directory at a time.  So it should be ok.

Quote
Reading the external joysticks also uses the $B5 port (like the keyboard) to select what you want to scan, but after the selection is made, you must read port $B6 (unlike the keyboard, where you can read the state on $B5), and bit 0 will carry the state of the selected line. The "selection" itself (numbers are the values written to $B5), and if I recall correctly: 0 = fire, 1 = up, 2 = down, 3 = left, 4 = right, for external joy-1, and for kbd sel 5-9 the same series of assignments for external joy-2. Or something similar.

Thanks I also found a reference through the links you gave and it gives all the info needed:
http://enterprise.iko.hu/technical/Converting_Spectrum_programs.pdf

Joystick scanning is separated from key scanning so that it can be faster.  Admittedly in this case the EP needs to scan all rows anyway but the logic to make sure only one key is pressed and applying shifts can be skipped.

Quote
Another interesting thing, that mouse also works like this (well, the "official" EP mouse is said to be "terrible" - I don't know it personally -

Ok, it's probably a joystick mouse or a mouse that needs to be polled constantly in a loop.  Yeah they aren't too useful.

Quote
so I talk about the "common" solution instead, often named as "boxsoft mouse". It also uses control port lines to read mouse data (originally an MSX-mouse like protocol serialized to one bit transfer with a "shift" signal produced on a line on the serial port .... or something like that). It has some problem though that there is a conflict between external joystick and a mouse then. There is an on-going project (also can be found on the forum) to create a hardware solution for more modern (PS/2?) mouses with some modification to avoid the mentioned conflict.

Ok if I can find something I can add it too.


Another question about the keyboard:  is there a list of standard ascii codes for keypresses returned by the EP firmware somewhere?  I'm not sure what to do about returning ascii codes for ALT keys and some special keys.  I realize the function keys are macros on the EP but in the c lib it's lower level so there is no macro expansion and key codes would have to be returned.

Offline gflorez

  • EP addict
  • *
  • Posts: 3615
  • Country: es
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #32 on: 2015.August.24. 19:35:31 »
Hello. About the mouse I think is better to wait the first batch of Entermices to reach their new owners, but the mouse reading routine can be like this:


      ld   a, (INPUT_DEVICE) ; EXOS Variable 189
      cp   1
      jp   z, loc_C28F
      cp   2
      jp   z, loc_C294
;modification here
      cp   5
      jp   z, loc_C285    ; Serial Mouse Systems is merged with the internal Joystick
      cp   6
      jp   z, loc_C285      ; Serial Mouse Systems WILL be merged with the internal Joystick
;end
      or   a
      jp   z, loc_C285
;Modification here
      ;Here begin the   Neos mouse reading
      ld   hl, X_REL   ; first   byte
      ld   a, 2      ; RTS low
      out   (0B7h),   a
      ld   b, 8      ; long delay
      call   WAIT
      call   READ_4BIT   ; read four higher bits
      rld         ; push them in (HL)
      xor   a      ; RTS high
      out   (0B7h),   a
      ld   b, 5      ; short   delay
      call   WAIT
      call   READ_4BIT   ; read four lower bits
      rld         ; push them in (HL)
      ld   hl, Y_REL   ; second byte
      ld   a, 2      ; RTS low
      out   (0B7h),   a
      ld   b, 5      ; short   delay
      call   WAIT
      call   READ_4BIT   ; read four higher bits
      rld         ; push them in (HL)
      xor   a      ; RTS high
      out   (0B7h),   a
      ld   b, 5      ; short   delay
      call   WAIT
      call   READ_4BIT   ; read four lower bits
      rld         ; push them in (HL)
                      ;<======Here will be added the future Wheel and three spare buttons reading. FIRST TENTATIVE
      ld   hl, SW_Z_STATUS
      ld   a, 2      ; RTS low
      out   (0B7h),   a
      ld   b, 5      ; short delay
      call   WAIT
      call   READ_4BIT   ; read four higher bits
      and 15
      cp 1         ; IF THIS NIBBLE=0001 THEN THE MOUSE IS IN EXTENDED PROTOCOL
      jr z, CONTINUE_READ
      xor   a      ; RTS high
      out   (0B7h),   a           ;IGNORE THAT NIBBLE
                             ld (hl), 0. ; we don't need old values
      jr STOP_READ
      
CONTINUE_READ:
      xor   a      ; RTS high
      out   (0B7h),   a
      ld   b, 5      ; short   delay
      call   WAIT
      call   READ_4BIT   ; read four higher bits, the three lower bits are the buttons. They come ready to store
      push af      ; push them in stack. they are in the lower nibble.
      ld a, (hl);
                             push af   ;save the Z counter for later.
      ld   a, 2      ; RTS low
      out   (0B7h),   a
      ld   b, 5      ; short   delay
      call   WAIT
      call   READ_4BIT   ; read four bits
      rld         ;we need z displacement in 8 bit
      xor   a      ; RTS high
      out   (0B7h),   a
      ld   b, 5      ; short   delay
      call   WAIT
      call   READ_4BIT   ; read four lower bits. Z displacement
      rld         ; push them in (HL)   ;NOW WE HAVE Z displacement in (hl)
      pop af         ; restored Z counter to "a", but we have garbage on high nibble   
                             and 00Fh
                             bit 3, a
                             jr z, SIGN_DONE
                             or 0F0h
 SIGN_DONE:                                               ; now we have the sign extended to 8 bits on "a"
                             add a, (hl)
                            cp 128                              ;positive or negative?
                             jr c, POSITIVE
                             cp 248                             ;lower than -8?
                              jr nc, FINISHED             ;
                              ld a, 248                          ; -8 is the bottom
                              jr FINISHED
POSITIVE:
                              cp 8                                 ;higer than 7?
                              jr c, FINISHED
                              ld a, 7                             ; 7 is the top
FINISHED:                                                  ; the excess  of 7 or -8 has been wipped
                              ld c, a                            ;save Z addition on c
                              pop af                            ; retrieve the buttons status. They are now on first nibble of a
                              rld                                  ;buttons stored
                              ld a, c                           ;we only need the first nibble of Z counter addition
                              rld                                 ; the spare buttons status and the Z counter are now in SW_Z_STATUS
STOP_READ:
      xor   a                       ;recall buttons on row 0
      out   (0B5h),   a
      in   a, (0B6h)   ; read Mouse buttons
      and 7      ;mask
      xor 7      ;flip them all as on Enterprise a pressed key is 1 and released 0
      rl (hl)    ;Get ready the bit 7 of "hl" register pair. Inside is SW_Z_STATUS, variable number 190
      srl a   ; This is the very FIRST "srl a". The button status is now in the carry flag
            ; secondary button of Boxsoft is read on J column. Primary button of Entermice is read on K column
      push af
      ld   a, (INPUT_DEVICE)
      cp 3   ;Boxsoft interface mode buttons   
      jr nz, L_BUTTON     
      pop af  ; We need the value of "a" and "f" registers. Carry flag still stores the value of secondary button
      rr (hl) ;secondary button goes to bit 7 of SW_Z_STATUS, variable number 190
      srl a   ; Primary button of Boxsoft is on J column. This is the second "srl a"
      JR MAIN_BUTTON
L_BUTTON:   ;Entermice interface mode buttons
      pop af  ;retrieve the value of register "a". "f" is disposable, soon we will load the button on carry flag
      push af ; I still will need later the register "a" value
      srl a  ; two "srl a" because the secondary button of Entermice is read on L column
      srl a  ; the proper button status is now in the carry flag
      rr (hl) ;secondary button goes to bit 7 of SW_Z_STATUS, variable number 190
      pop af  ;retrieve the value of register "a" just after the FIRST "srl a"
MAIN_BUTTON:
      and 1
      ld   (FIRE_STATUS), a ; EXOS   Variable 188. K column if Boxsoft or L column if Entermice
      call   sub_C3A6   ; this is the "corrections and drawing" routine where the "velocity" 1.1 modification was made
      ld   a, (X_REL)
      ld   c, a
      ld   a, (Y_REL)
      or   c
      ret
   ;end   



;-------------------------------------
WAIT:               
      nop
      nop
      nop
      dec   b
      jr   nz, WAIT
      ret
      ;end
;-----------------------------------------


READ_4BIT:            
      ld   b, 4
      ld   d, 0
      ld a, (INPUT_DEVICE)
      cp 3
      jr z, L_COLUMN
      
K_COLUMN:            
      ld   a, b
      ;inc   c ;    this is not necessary
      out   (0B5h),   a
      in   a, (0B6h)
      ld c, a
      rra         ;data read from K column
      rra
      rl   d
      djnz   K_COLUMN
      jr CONTINUE

L_COLUMN:            
      ld   a, b
      ;inc   c ;    this is not necessary
      out   (0B5h),   a
      in   a, (0B6h)
      ld c, a
      rra         ;data read from L column
      rl   d
      djnz   L_COLUMN

CONTINUE:
      ld   a, d
      ret
;end



----------------------------

Ovserve, the old mouse type is INPUT_DEVICE=3. The new standard is INPUT_DEVICE=4.

I'm already working in this routine and some aspects need to be tested on a real Enterprise.

« Last Edit: 2015.September.06. 08:57:29 by gflorez »

Offline gflorez

  • EP addict
  • *
  • Posts: 3615
  • Country: es
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #33 on: 2015.August.24. 19:49:43 »
X_REL               x axis displacement since last reading, 8 bits signed
Y_REL.              Y axis displavement since last reading, 8 bits signed
FIRE_STATUS.  main mouse button
SW_Z_STATUS  high nibble: bit 7 = secondary mouse button, bits 4, 5 and 6 spare buttons
                           Low nibble Z displacement counter, 4 bits signed
                                 
« Last Edit: 2015.August.27. 00:59:16 by gflorez »

Offline gflorez

  • EP addict
  • *
  • Posts: 3615
  • Country: es
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #34 on: 2015.August.24. 20:30:54 »
The mouse is read every 50 Hz  by interrupts.

The reading of the mouse is triggered by putting RTS low for  a long pause. Then the mouse sends the first nibble.
RTS is put high for a short pause and the mouse sends the second nibble.
RTS is put low for a short pause and the mouse sends the third nibble.

And so on. Two nibbles make a byte. Two bytes are read if we have a legacy mouse, but upto four if in extended mode.
« Last Edit: 2015.August.24. 20:40:02 by gflorez »

Offline gflorez

  • EP addict
  • *
  • Posts: 3615
  • Country: es
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #35 on: 2015.August.24. 20:38:00 »
The control ports of the Enterprise are only for reading keypresses, for inputs, so it is needed an output signal in order to comunicate with the mouse.

The solution is to use the RTS pin signal from the underused serial port.

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #36 on: 2015.August.25. 18:06:19 »
Thanks gflorez I can see how it works.

The boxsoft mouse replaces one of the external joysticks and the entermouse communicates on a different bit.

I'm not sure what this does:

Code: [Select]
      call   sub_C3A6   ; this is the "corrections and drawing" routine where the "velocity" 1.1 modification was made

Are you compensating for low precision legacy mice?


Code: [Select]
      ld   a, 2      ; RTS low
      out   (0B7h),   a
      ld   b, 8      ; long delay
      call   WAIT
      call   READ_4BIT   ; read four higher bits

I assume this first long delay resets the mouse logic so if the subroutine does not read all nibbles for whatever reason, this will make the mouse start again at the first nibble?

Are these delays specified precisely in seconds or z80 clock cycles?  I saw mention in other threads of faster z80 substitutions so if it's measured in seconds I think it's best to compute a cycle delay depending on the cpu clock rate.  There is a config option in the compiler that sets the target's clock rate for situations like this.

If you're unaware of them, there are z80 subroutines around that can busy-wait a precise number of z80 clock cycles.  This is one of them by Jan Bobrowski:

http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/libsrc/_DEVELOPMENT/z80/z80/asm_z80_delay_tstate.asm?revision=1.4&content-type=text%2Fplain

You use it like this:

Code: [Select]
ld hl,500  ; at least 141
call asm_z80_delay_tstate
; here exactly 500 cycles have passed assuming no 'clock stretching'

Offline pear

  • EP lover
  • *
  • Posts: 825
  • Country: pl
  • Z80 only
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #37 on: 2015.August.25. 18:23:28 »
Maybe timings will help you understand more.
The mouse is polled after each interruption of video (IRQ 50Hz) (answer later in the same thread).

Offline gflorez

  • EP addict
  • *
  • Posts: 3615
  • Country: es
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #38 on: 2015.August.25. 20:49:16 »
What I've shown you above  are modifications done to an old driver from the 80's. It was part of a third party product named Boxsoft mouse interface bundled as a paint program. The creator assured here in this page that he only sold about 100 units.

It consisted on an adapter that implemented a standard d9 joystick port on the Enterprise, a Neos mouse, the Paintbox program and the driver itstelf.

It worked like a conventional modern mouse, but lacked velocity(acceleration). In the last modification made by the author he introduced a fix that doubled the amount of movement when greater than 1 or -1 pixels.

That  "corrections and drawing" call is not important for you as you will draw the pointer with your own routines, I think.

But now the interface has evolved to avoid some incompatibilities with programs that expect a joystick on that port.

Now  the mouse status is read on some undocumented possible switchs on the same controller port.

Also, it has been discovered that the Neos mouse is in reality a modified Msx mouse. So a Msx to ps2 mouse converter has been added to the interface. The name of the interface evolution is Entermice.

Meanwhile Prodatron, the creator of the superb multiplatform operative system named SymbOs, has made a port for the Enterprise. One of the target platforms is Msx and he has expanded its mouse protocol to manage ps2 mice(by Msx to ps2 adapter) with up to 5 buttons and wheel. He can apply easily that mouse protocol expansion also to the Enterprise port if there is already a hardware supporting it.

I have to say that ps2 mice have certain velocity in its circuits, so the feel now is almost exactly as a modern mouse.


All that improvements are included in that little routine....


Abut the timming of the delays.... They don't need to be accurate. Only the first delay is important. Then the mouse or the converter watch for all the readings done in a fixed total time.
« Last Edit: 2015.August.27. 00:56:24 by gflorez »

Offline lgb

  • EP addict
  • *
  • Posts: 3563
  • Country: hu
  • æðsta yfirmaður
    • http://lgb.hu/
Re: Enterprise C compiler for PC
« Reply #39 on: 2015.August.26. 00:19:39 »
I was glancing through http://ep.homeserver.hu/Dokumentacio/Konyvek/EXDOS/EXDOSeng.htm but I can see now it is mentioned that the disk channel is only opened and closed if you're loading / saving without first opening a channel.  There's no mention of seeking or random access of files.  It's just a simple reference for basic so there isn't a lot of meaty information there.  I found a reference to ISDOS on the same site (in Hungarian) which seems to have a lot more information and makes it look like ISDOS has a lot in common with cpm.  But of course ISDOS is an extension / replacement of EXDOS.

IS-DOS is written by IS (Intelligent Software) to be compatible with CP/M, so it's a CP/M in some way, but not the from the original BDOS from DR. If I remember correctly, it's compatible with CP/M version 2.2 (at least if I remember correctly, I wrote a small CP/M program to get CP/M version and then print it, and it was 0x22). It does not replace EXDOS/EXOS, but it's another layer "built top on them". So some even name iS-DOS as "the CP/M for EP" too. This means several things, for example something I've already mentioned: it uses EXDOS, thus its native file system (FAT12) with all the directory etc stuff which was not possible with a "real" CP/M 2 (if I remember correctly) only maybe in later CP/M versions (?). Once I found the disassembled BDOS source is available (well, as far as I remember, know even "officially" available?), it was quite trivial try from me, to write a stupid and short CBIOS for EP, so of  course the "original" CP/M from DR can run on EP too, but still, IS-DOS is hard to beat, because you can also use the good things for EXDOS too with it (or even EXOS commands are available from IS-DOS too directly). Native CP/M BDOS implements some file system (I don't know it too much) which sounds a horror for me, eg almost as many exact formats (especially sector "skews" and similar things) exists as CP/M platforms :shock: I just "had to" mention these as you wrote "it looks like ISDOS has a lot common with cpm". Well, no wonder, because IS-DOS is "the CP/M" for EP with extra stuffs :) Though I am not so familiar with IS-DOS to tell, if there are major/minor compatibility issues compared with a DR CP/M BDOS system ... My personal opinion only: I think CP/M compatibility was a design concept for EP, even EXDOS has some notions (without IS-DOS too, in once) to be quite similar to CP/M maybe for easier IS-DOS CP/M implementation then. Again: if I remember correctly when once I tried to dig into EXDOS a bit :)

Quote
There's no mention of seeking or random access of files.

Hmm, maybe because some should use EXOS for that (opening, then reading/writing channel, set channel status call - which allows seeks etc). EXOS internally of course will use EXDOS if the channel refers for a file on a disk, and not some other entity, like a DISPLAY: channel (which is not so much seekable of course, for example).

About your C code examples, FILE* stuffs, etc: well, as far as I can see, my views on this topic are somewhat different. Your approach is about the correct ("C standard") implementation which of course is the better one. I usually have the habit to "ignore" this (well ...) since I often feel it gives too much complexity for a 8 bit system with limited resources. I must admit, my viewpoint is not so nice at all :) I should not comment these topics further, since it seems you are quite good in it already :)

Quote
Another question about the keyboard:  is there a list of standard ascii codes for keypresses returned by the EP firmware somewhere?  I'm not sure what to do about returning ascii codes for ALT keys and some special keys.  I realize the function keys are macros on the EP but in the c lib it's lower level so there is no macro expansion and key codes would have to be returned.

Maybe this can help?

http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/keyboard/Ch2.html

About function keys: I am not sure about that, of course, they are just keys like others, just maybe EXOS "translates" the keypresses for the programmed string as 'faked keypresses' (or such) when a function key is pressed?

http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/keyboard/Ch3.html

Offline gflorez

  • EP addict
  • *
  • Posts: 3615
  • Country: es
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #40 on: 2015.August.27. 01:14:06 »
Yes, there are different CPU clocks, hardware modifications, not from stock, but the compensation for that variations  is planned to be made by the firmware MCU inside the adapter.

The entermice wil be a complex piece of hardware, firmware and software mix.

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #41 on: 2015.August.27. 04:07:16 »
Thanks for the information on the mouse -- I think there is enough information there.  One thing I am wondering about is if the mouse ISR will always run on VBI interrupt?  Ie- you plug in the hardware and then its ROM plugs itself into the VBI interrupt at initialization.  The reason why I ask is under a C program you may want to take control of interrupts yourself, just as you might want to do in an assembly program.  I had anticipated that the clib would supply the driver software (this is how it's done for other machines) but if the mouse firmware runs at 50Hz, it's going to be reading and clearing the mouse state itself.  If that's going to be the case then there would have to be one mouse routine that reads the built-in driver's updated variables when interrupts are owned by the EP and another that reads the mouse hw directly when the interrupts are owned by the program.

About your C code examples, FILE* stuffs, etc: well, as far as I can see, my views on this topic are somewhat different. Your approach is about the correct ("C standard") implementation which of course is the better one. I usually have the habit to "ignore" this (well ...) since I often feel it gives too much complexity for a 8 bit system with limited resources. I must admit, my viewpoint is not so nice at all :) I should not comment these topics further, since it seems you are quite good in it already :)

Well I think people don't even try to do sophisticated things in z80 or at least the number of examples is small.  EXOS is one example :)  In z88dk I'm pretty confident we could fit an OS with standard C library, FAT filesystems and all that in under 24k.  There are no shortcuts being taken -- the parts of the C library that are implemented are complete.

Something like this which I used to test the error detection of strtol:

Code: [Select]
#include <stdlib.h>
#include <errno.h>

main()
{
   char *buf = 0;
   size_t sz;
  
   while (1)
   {
      printf("\n> ");
      
      fflush(stdin);
      getline(&buf, &sz, stdin);
      
      printf("= %ld\n", strtol(buf, 0, 10));

      perror(0);
      errno = 0;
   }
}

works as expected.  There's a lot of hidden complexity there, the most obvious are the steps taken to make printf efficiently communicate with the stream.  But getline() is another big one -- it needs to efficiently gather input from the stream up to a '\n' and not only that but dynamically grow a buffer to accommodate the line being read.  getline() here is actually built on a vector<char> within the z88dk lib and growth is via realloc().  realloc() is written to be very fast -- if the allocated memory must be moved, it is moved into the largest hole in the heap so another move will not occur.  If the buffer handed to getline is 0 (NULL), realloc will begin by allocating the largest available block in the heap.

So yeah, things like vector<char> are in the library and are exposed to the user as container types modelled on C++ STL.  This is all in z80 assembly language and it's all efficiently implemented.  We never lose sight of performance, which is really what you are concerned with I think so we do both non-standard and standard C things with the library.

Quote
Maybe this can help?
http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/keyboard/Ch2.html

I don't know how missed that :P

Offline gflorez

  • EP addict
  • *
  • Posts: 3615
  • Country: es
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #42 on: 2015.August.27. 09:22:23 »
Yes, you can load the mouse driver or not. It is not in Rom. It works as an extension to Exos:

https://enterpriseforever.com/programming/universal-mouse-driver/?action=dlattach;attach=13253

You can load it directly from Basic or Exos. Then to initialize it you must execute ":pb".

As you don't own a mouse interface you can try the internal joystick.

Once loaded the driver and initialized, this little Basic program will set the system for you and will open the required channels:

100 PROGRAM "mouse_test.bas"
110 GRAPHICS ! Usually the video channel is number £101:
120 SET 189,0 !  internal joystick as input device
130 SET 180,101 ! Video channel to put the mouse on. Only graphics.
140 SET 183,255 ! Colour of the pointer
150 OPEN £1:"mouse:" ! Opens a channel on the mouse device

Move the keyboard joystick to see the effect. Observe that the Basic program has ended.


« Last Edit: 2015.August.27. 10:01:21 by gflorez »

Offline Zozosoft

  • Global Moderator
  • EP addict
  • *
  • Posts: 14779
  • Country: hu
    • http://enterprise.iko.hu/
Re: Enterprise C compiler for PC
« Reply #43 on: 2015.August.27. 09:27:41 »
Yes, you can load the mouse driver or not. It is not in Rom.
Currently :-)

Offline gflorez

  • EP addict
  • *
  • Posts: 3615
  • Country: es
    • Támogató Támogató
Re: Enterprise C compiler for PC
« Reply #44 on: 2015.August.27. 10:14:35 »
Hello Zozo. How it can be done, allocating memory and placing there the "modifiable" memory section?