Shop OBEX P1 Docs P2 Docs Learn Events
qZ80 - the third shot - Page 5 — Parallax Forums

qZ80 - the third shot

1235789

Comments

  • pullmollpullmoll Posts: 817
    edited 2010-04-23 15:45
    Ouch! A nasty bug in patching the DPBs for drives B: and C:. I padded the 19 byte DPB to 20 bytes to keep the long alignment after the DPBs. However I forgot to change the line that addresses one of the 3 DPBs, so I was patching at DPB1 - 1 and at DPB2 - 2 and the results are fatally wrong. Please update before trying to do anything on drive B: or C:

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-23 22:56
    I just found the B and C drive bug now. Obtaining patch...

    Ok, that works fine.

    I've attached a slightly modified version of xmodemf. (f stands for Fast)

    When xmodem starts it sends a NAK byte ten times then gives up. It can't start transferring until the first one has been received at the other end. So if you make the timing loop too long it takes ages to give up if the transfer failed. But if you make it too short, there isn't time to type "XMODEMF" at the other end. I've tweaked the timing so it is about 1 second between NAKs, and about 10 seconds to time out on an error.

    The standard version of xmodem is 14 times slower, so takes 14 seconds to even start a transfer.

    Also in the zip above is a file AUTOEXEC.SUB and this contains the text "MPM" which auto boots MPM on startup. I think it is stable enough that CPM is not needed. The advantage of this is that the VGA monitor comes to life with no need to have the PC on.

    I'm going to have a go at rewriting some LCD code. It is much easier to use Juergen's routines that poking out bytes in assembly one nibble at a time. Port $30 is the control port and port $31 is the data port. I tried
    out (&H30),13 and it turned on the cursor
    out (&H30),148 and it moved the cursor to the third line

    These are the control codes. They are pretty much the same for all parallel LCDs - I've tried 8x2, 16x2 and 20x4 from many brands and even including OLED displays. In terms of dollars per character, I think 20x4 displays work out one of the cheapest ways of displaying things on the propeller.

    ;1 Clear display and move to the start of the first line
    ;2 Move the cursor and display ‘window’ to the start of the first line
    ;4 Set ‘right to left printing’ mode
    ;5 Set ‘scroll printing to the left’ mode
    ;6 Set ‘left to right printing’ mode
    ;7 Set ‘scroll printing to the right’ mode
    ;10 Turn visual LCD screen off
    ;12 Hide cursor
    ;13 Make cursor flash (and turn it on)
    ;14 Turn visual LCD screen (and non flashing cursor) on
    ;16 Move cursor left one position
    ;20 Move cursor right one position
    ;24 Scroll display ‘window’ left one position
    ;28 Scroll display ‘window’ right one position
    ;128 Move cursor to the start of the first line
    ;192 Move cursor to the start of the second line
    ;148 move cursor to start of 3rd line
    ;212 move cursor to start of 4th line
    
    



    At the moment the LCD boots up but the screen is blank. I want to display a little signon message, and I think this shows one of the advantages of an operating system. It is quite possible to write some spin code to print something on the display but it takes up space and there isn't much space left (there never is!!). So - write it in Z80 assembly, compile it (either on a PC or on the propeller), and add an extra line to the autoexec. The program is LCDBOOT and it just displays a one line MPM signon message on the display "MP/M II V2.1" so it shows the display is working.

    See attached files.
    Warts and all this is a little MPM terminal driver program. Prints on the last line, the scrolls up when that line is full. It is a little slow compared to assembly.
        $lines
        dim common byte lcdbuffer(80)    
        common column=integer
    
    procedure redraw
        var i=integer
        out (30H),128
        for i=0 to 19
            out (31H),lcdbuffer(i)
        next i
        out(30H),192
        for i=20 to 39
            out (31H),lcdbuffer(i)
        next i
        out (30H),148
        for i=40 to 59
            out (31H),lcdbuffer(i)
        next i
        out (30H),212
        for i=60 to 79
            out (31H),lcdbuffer(i)
        next i
        out (30H),212  rem cursor to start of last line
    end
    
    
    procedure linefeed
        var i,j,n=integer
        for i=0 to 2
            n=i*20
            for j=0 to 19
                lcdbuffer(n+j)=lcdbuffer(n+j+20)
            next j
        next i
        for j=60 to 79
            lcdbuffer(j)=" " rem last line is now blank
        next
        column=0 rem equivalent to carriage return
        redraw
    end
    
    procedure backspace
        var i=integer
        out (30H),212        rem cursor to beginning of line 4
        if column>0 then
            begin
                lcdbuffer(column+60-1)=32  rem blank
                column=column-1
                out (30H),212      rem cursor to beginning of line 4
                for i=0 to 18
                    out (31H),32    rem clear last line
                next i
                out (30H),212     rem cursor to beginning of line 4
                for i=0 to column-1
                    out (31H),lcdbuffer(60+i)
                next i
            end
    end
    
    procedure startup
        var i=integer
        for i=0 to 79
            lcdbuffer(i)=32 rem clear the buffer
        next i
        redraw
        out (30H),1   rem clear screen
        out (30H),13  rem cursor on
        out (30H),212 rem cursor on last line
    end
    
    procedure lcdterminal(c=integer)
        rem the 'case' command would be useful but can't seem to do >= or nn to nn
        out (30H),13            rem cursor on
        if c=8 then backspace
        if c=10 then linefeed
        if c >= 32 and c<127 then
            begin
                if column<=19 then
                    begin
                        if column=19 then out (30H),12 rem cursor off for last char in line
                        out (31H),c
                        lcdbuffer(60+column)=c         rem store in last line buffer
                        column=column+1
                    end
                if column>=20 then linefeed
            end
    end
    
    procedure lcdprint(s=string)
        var i,c=integer
        for i=1 to len(s)
            c=asc(mid(s,i,1))
            lcdterminal c
        next i
    end
    
    procedure lcdcrlf
        lcdterminal 10
    end
    
    Rem ************ MAIN **************
        print "Clearing LCD"
        startup
        print "LCD driver program"
        lcdprint "abcdefghijklmnopqrstuvwxyz"
        lcdcrlf
        lcdprint "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        lcdterminal 8   rem backspace
        lcdprint "hello"
        lcdcrlf
        lcdprint "this works!"
    end
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller

    Post Edited (Dr_Acula) : 4/24/2010 2:06:31 AM GMT
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-24 07:26
    This is a little terminal program writtin in sbasic. It runs on USER2 on the second serial port. I've put another button on the IDE so that I can hit 'compile' and it automatically uses the SIMH to compile, then downloads, and then does a PIP from user 0 over to user 2.

    My setup is that I have the vb.net IDE running on serial port 0, and the local keyboard/vga on user 1 (not doing anything at the moment) and on serial port 1 I have a terminal program.

    So if I run this program on user2, up comes the prompt for user 0 and everything typed goes to user 0 and then comes back. This concept could be extended to any user, enabling any MPM user to take over another user.

    What is the point? Well, this is the first step in capturing data packets on the second serial port, decoding them and sending them to user 0. If raw bytes work, then packets should work too...

    comment
        This program takes characters from the second serial port and routes them to user 0
        ** This must be run from USER2 so PIP it over using
        PIP TERM2.COM[noparse][[/noparse]G2]=TERM2.COM
        constat_port        =    $10        ' console 0 status port (on SIO #0)
        condata_port        =    $11        ' console 0 data port (on SIO #0)
        punstat_port        =    $12        ' punch 1 status port
        pundata_port        =    $13        ' punch/reader 1 data port
        con1stat_port        =    $14        ' console 1 status port (on Keyboard / VGA)
        con1data_port        =    $15        ' console 1 data port (on Keyboard / VGA)
        con2stat_port        =    $16        ' console 2 status port (on SIO #1)
        con2data_port        =    $17        ' console 2 data port  (on SIO #1)
        wrap0_port        =    $20        ' stuff data to console 0 input buffer
        wrap1_port        =    $21        ' stuff data to console 1 input buffer
        wrap2_port        =    $22        ' stuff data to console 2 input buffer
    end
        rem turn off any other keyboard scanning
        $lines
    
    procedure scaninput2
        var b,c=integer
        c=inp(16H)            rem returns 2 if no data, 3 (I think) if data
        if c<>2 then
            begin
                b=inp(17H)  rem clear the data
                out (31H),b rem send to 20x4 LCD for debugging purposes
                out (20H),b rem send to console 0 input buffer
            end    
    end
    
    procedure controlP
        out (20H),16       rem send ^P to user 0 so user 0 directs output to the printer buffer
        out (12H),3        rem set head and tail to be equal 
    end
    
    procedure readprintbuffer
        var a,b=integer
        a=inp(12H)        rem is there a character ready?
        if a=3 then
            begin
                b=inp(13H)    rem read the data from the print buffer
                out (17H),b    rem send it out the second serial port
            end
    end
    
    rem ************ MAIN **************
        print "Route data from the second serial port to user 0"
        controlP        rem tell user 0 to output to the print buffer
        var a=integer
        a=0
        repeat
            begin
                scaninput2
                readprintbuffer
            end
        until a<>0
    end
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller

    Post Edited (Dr_Acula) : 4/24/2010 8:33:31 AM GMT
  • BaggersBaggers Posts: 3,019
    edited 2010-04-24 08:01
    So have we got any clear specs for me to go by?
    So far I have only 2KB of HUB-RAM, and one cog?
    Is that right? and you want it in colour, or will B&W like the tv suffice? ( maybe a 40x25 display with colour, and 80x25 B&W ) ?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    http://www.propgfx.co.uk/forum/·home of the PropGFX Lite

    ·
  • pullmollpullmoll Posts: 817
    edited 2010-04-24 08:03
    I just thought it may be helpful to be able to swap user 0 and user 1 devices, so that user 0 would be on PS/2 keyboard / VGA and user 1 the first serial port.
    I now did add a #define USER0_PS2_VGA to cpm.spin that swaps all the input and output vectors if defined. Startup messages still go to the SIO port, because the VGA/TV frame buffer shares memory with the io.spin cog init data.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects

    Post Edited (pullmoll) : 4/24/2010 8:09:01 AM GMT
  • pullmollpullmoll Posts: 817
    edited 2010-04-24 08:21
    Baggers said...
    So have we got any clear specs for me to go by?
    So far I have only 2KB of HUB-RAM, and one cog?
    Is that right? and you want it in colour, or will B&W like the tv suffice? ( maybe a 40x25 display with colour, and 80x25 B&W ) ?

    Well, the suggestion I made was to rather go with a 1 or 2 character rows buffer for a 80x25 or 80x40 display and have this buffer filled up by another cog (there is one left) that pulls the frame buffer data out of external RAM just in time.

    You have 3 cogs, if you need them, but 40x25 is not too useful with CP/M. At least 64 columns would be required, and 80 columns would be great.

    I think if you manage to do 80x<anything> with a color attribute per character, then it is no big step to not use a large chunk of hub RAM, but instead write a sync long in hub RAM after each character row - or on the last scanline of a character row - so that the other cog knows when to fill up the character/attribute row that was just sent to the display from external memory. In other words: double buffering on a character row basis. I didn't calculate the cycles this takes, so it may be impossible to have enough data ready in time. 160 bytes at a rate of 15625/<font height> Hz IIRC!? That is abt. 312500 bytes per second and should be possible.

    If that fails, we still can try to make room for the frame buffer by e.g. loading cogs from SD through a shared memory block in hub RAM.

    And if that fails, then there's the last possibility of using the 8085 emulation instead of the Z80. That one leaves > 2500 longs free in hub RAM. It is just not yet working fully with MP/M interrupts, but I think I could fix it.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects

    Post Edited (pullmoll) : 4/24/2010 8:55:42 AM GMT
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-24 08:35
    I thought I would write the terminal router program in C as well. Just to learn a bit of C. And to use a language (unlike sbasic) that is used by more than one person in the world. Fortunately, sbasic was built on Pascal and C, and so is actually quite easy to translate. begin={, and end=}, and there are just slight syntax differences with input and output.

    /*
    MPM Terminal program connects user 2 to user 0
    */
    #include <stdio.h>
    
    main()
    {
        char a;
        iobreak(0);             /* no ^C and no keyboard scanning*/
        printf("User 2 terminal program linking to User 0\n");
        controlP();            /* send output from user 0  to print buffer */
        a=0;                /* so never exits */
        while (a == 0)
            {
                scaninput2();
                readprintbuffer();
            }
    }
    
    scaninput2()
        {
            char b,c;
            c=inp(0x16);
            if (c !=2)
                {
                    b=inp(0x17);
                    outp (0x31,b);
                    outp (0x20,b);
                }
        }
    
    controlP()
        {
            outp (0x20,16);       /* send ^P to user 0 so user 0 directs output to the printer buffer */
            outp (0x12,3);    /* rem set head and tail to be equal */
        }
    
    readprintbuffer()
        {
            char a,b;
            a=inp(0x12);        /* is there a character ready? */
            if (a == 3)
                {
                    b=inp(0x13);        /* get the character */
                    outp (0x17,b);    /* and send it out */
                }    
        }
    
    



    I note the addition swapping user 0 and user1. Yes, this could be very handy. For development, keep user0 as the serial port so you can use the SIMH to do the rapid compilation. But for a 'standalone' board, swap them over so the local keyboard and display can be used to run programs.

    Just a minor issue. When I push the reset button it always boots CP/M but there is only about a 75% chance it will run the autoexec and load MPM. Then MPM sometimes does not load fully - about a 90% chance of loading. Then when I download a program to user 0, that is about a 90% chance of success. Then when I autorun PIP to move the file to user2, that is only about a 70% chance of success. The problem is that 00.75*0.9*0.9*0.7 is only 0.42. So overall the odds of getting a file compiled and running is not great. I'm not sure what the reliability problem is, but I'm wondering if it is that file issue, and I note the suggestion made above about disabling interrupts. Would this sacrifice much in terms of performance? Probably not for me, I hardly ever am reading/writing the disk from two users at the same time.

    @baggers, re color, if ;you have a buffer 80x40 currently storing a byte which is a byte that stores a text character, and you change that so the byte stores a block of color, then does that mean you don't need any more memory? You just have a 'text mode' and a 'graphics mode'??

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller
  • pullmollpullmoll Posts: 817
    edited 2010-04-24 08:47
    Dr_Acula said...
    I thought I would write the terminal router program in C as well.

    Welcome to the wonderful world of how-to-shoot-in-your-foot languages smile.gif
    Most C coders use for (;[noparse];)[/noparse] for an endless loop, as this emits no additional code at all. Some use while (1), while that may actually emit the code to test the always true condition.
    Dr_Acula said...
    ... I note the suggestion made above about disabling interrupts. Would this sacrifice much in terms of performance? Probably not for me, I hardly ever am reading/writing the disk from two users at the same time.

    You can try this yourself by modifying MPMXIOS.MAC. Search for the hdretry: label and put a DI after it, then put an EI before the or a after the second if banked section. Then run DO SYSMPM. If that helps, I will put it in the default disk.

    Another thing to try would be to fill the entire memory with 0s. I once had the strange effect that after uploading to the prop RAM I was again in MPM, without CP/M really booting.

    FWIW: With the DI/EI in place I get 10 out of 10 tries to boot CP/M. I also get 10 out of 10 tries with AUTOEXEC.SUB containing MPM. Perhaps it's no software issue after all?

    I'm away for today now. For those who hadn't realized it: I accidentally left CPU_8085 defined in cpm.spin, so don't you wonder why your Z80 programs don't work smile.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects

    Post Edited (pullmoll) : 4/24/2010 9:35:20 AM GMT
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-24 10:04
    That sounds worth a try. How do you rebuild images from MPMXIOS.MAC? Is it the standard SIMH version/rebuild or are we using modified versions now?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller
  • Cluso99Cluso99 Posts: 18,069
    edited 2010-04-24 10:32
    Baggers: And we forgot, all with 1pin TV too! LOL

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-24 12:07
    Re "I accidentally left CPU_8085 defined in cpm.spin," - my version is z80 but I haven't updated for a little while. Every five minutes a new and better version is released! I'll get the latest one now.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller
  • BaggersBaggers Posts: 3,019
    edited 2010-04-24 12:29
    Lol Cluso99 [noparse]:)[/noparse]

    pullmoll, ok, the issue I'm thinking is will it be able to get the data fast enough into hub-ram without slowing down your Z80? as it will be a huge drain on the sram bus? at 60fps reading in 80*60 * 2 is ( 4800 * 2 = 9600 * 60 = 576,000 bytes per second. )
    are you sure you want to put this workload on the external SRAM bus?

    even 80*30 double height, is still going to be 288,000 bytes per second through external sram.

    Baggers.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    http://www.propgfx.co.uk/forum/·home of the PropGFX Lite

    ·
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-24 12:49
    Ok, EI and DI inserted
    hdretry:
        if banked
        di
        call    swtuser
        endif
        ld    a, (hdcmd)
        out    (hdskPort), a        ; send command
        ld    b, 6            ; 6 bytes to send
        ld    hl, diskno
    hdloop:    ld    a, (hl)
        inc    hl
        out    (hdskPort), a
        dec    b
        jp    nz, hdloop
        in    a, (hdskPort)        ; perform command and get result
        if banked
        push    af
        call    swtsys
        pop    af
        endif
        ei
        or    a            ; result is ok?
        ret    z            ; yes, done
        dec    (hl)            ; decrement retry count
        jp    nz, hdretry        ; retry twice
        ret                ; return with <A> = error code
    
    



    These errors tend to come up when the system has hung and is being rebooted. I am susptecting the memory is not being erased, as you say. I'll do some testing for a few days.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller
  • MaxSMaxS Posts: 19
    edited 2010-04-24 22:26
    Dr_Acula said...
    I thought I would write the terminal router program in C as well. Just to learn a bit of C. And to use a language (unlike sbasic) that is used by more than one person in the world. Fortunately, sbasic was built on Pascal and C, and so is actually quite easy to translate. begin={, and end=}, and there are just slight syntax differences with input and output.

    Writing an application that loops waiting for something on a multi-tasking operating system can be a little in-efficient.· Your process becomes compute bound and you consume a large part of the available cpu power doing the loop.· Every time your process is sheduled to run it uses up its quota looping.· This reduces the available cpu for other processes.· Once you have got your application sorted out maybe you can look into ways of releasing the cpu or better still let the os manage your i/o.· That way your process can wait on a character and not consume all the available cpu power.·
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-25 02:25
    MaxS, that is a fascinating concept.

    I've used something similar in visual basic for years - the .doevents method where you hand back control to windows for a while. eg I've got some code that reads off huge text files off the disk in vb.net and this tends to completely hang windows. So - put in .doevents every 20 records. (thinking about it, MPM and windows have a lot in common. Multiple 'users' or 'windows'. Multitasking between virtual machines. Issues regarding prioritising. Perhaps best not to mention there is a later version of CP/M that does indeed have graphical (text based) windows, where you can have wordstar in one and basic in another).

    So - MPM is running and we are running a program and we really don't need any more CPU cycles as the program is just polling the keyboard. How could that work? Could you have an OUT statement that brings forward the next interrupt cycle?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller

    Post Edited (Dr_Acula) : 4/25/2010 2:30:33 AM GMT
  • pullmollpullmoll Posts: 817
    edited 2010-04-25 06:43
    Baggers said...
    Lol Cluso99 [noparse]:)[/noparse]

    pullmoll, ok, the issue I'm thinking is will it be able to get the data fast enough into hub-ram without slowing down your Z80? as it will be a huge drain on the sram bus? at 60fps reading in 80*60 * 2 is ( 4800 * 2 = 9600 * 60 = 576,000 bytes per second. )
    are you sure you want to put this workload on the external SRAM bus?

    even 80*30 double height, is still going to be 288,000 bytes per second through external sram.

    Baggers.

    We can do 80x40 with a 8x8 font, not 80x60. And I think that 80x24 or 25 should be ok as well, as this is the "normal" terminal size. Well, of course it would slow down the Z80, because the SRAM bus has to be locked to the video code for a burst read of each character row. I was thinking of using one of the available 16KB chunks beyond the banked areas and preferably with a pitch of 256 bytes per character row, so that the reads could be done as fast as possible with only changing the lower address latch.
    I'm sure this will slow down the Z80 by 20-30%. If we go with 80x25 = 4000 bytes char/attr = 1000 longs, then perhaps we can find two pages of cog init data that can be re-used as frame buffers.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects

    Post Edited (pullmoll) : 4/25/2010 6:49:06 AM GMT
  • pullmollpullmoll Posts: 817
    edited 2010-04-25 06:45
    Dr_Acula said...
    Ok, EI and DI inserted
    hdretry:
        if banked
        di
    ...
    
    


    The di should be outside the if banked, because the ei is outside too.
    Dr_Acula said...
    These errors tend to come up when the system has hung and is being rebooted. I am susptecting the memory is not being erased, as you say. I'll do some testing for a few days.

    Ok, I'll add code to zap the entire 512KB at reset. It can't hurt and should only take a few seconds.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects

    Post Edited (pullmoll) : 4/25/2010 6:52:17 AM GMT
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-25 06:50
    If you can do it with cog init ram that would be better. I've got code doing that and it works fine and I reused the keyboard cog. The code I have been using (now obsolete given MPM is working) is a combination of code from many different authors so the bits of leftover cog memory ended up all over hub ram. But so much of the MPM code has been built from nothing and is brand new so maybe you can group together cog code so it ends up leaving a bigger amount of hub ram free?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller
  • pullmollpullmoll Posts: 817
    edited 2010-04-25 07:34
    Dr_Acula said...
    If you can do it with cog init ram that would be better. I've got code doing that and it works fine and I reused the keyboard cog. The code I have been using (now obsolete given MPM is working) is a combination of code from many different authors so the bits of leftover cog memory ended up all over hub ram. But so much of the MPM code has been built from nothing and is brand new so maybe you can group together cog code so it ends up leaving a bigger amount of hub ram free?

    Either that or we could perhaps split the character data and color data into two ranges? Unless the video code needs to access both with the same rdword or rdlong that should be possible. The io.spin cog init RAM is already used as text buffer for VGA and TV80.
    I think it is practially impossible to have multiple cog init RAM ranges in sequence, because every object module has a few lines of spin code. You could overwrite that spin code once it was run and isn't used anymore.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects

    Post Edited (pullmoll) : 4/25/2010 8:20:48 AM GMT
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-25 09:34
    I'll fix that DI/EI thing now.

    I just thought of something. With text you store 80x40=3200 bytes. But you only ever need to display bytes 0-127 (or to be precise, 32 to 126).

    So that leaves values 128 to 255 unused. That is 128 possible values and for a VGA display, there are only 4x4x4=64 possible values anyway.

    So, could it work if text bytes were 0-127, and for values 128 to 128+64, you displayed a coloured block? I don't think you could mix text and graphics, but that may not matter.

    This takes no extra memory at all. Is 80x40 good enough resolution for games?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller

    Post Edited (Dr_Acula) : 4/25/2010 9:47:18 AM GMT
  • pullmollpullmoll Posts: 817
    edited 2010-04-25 10:03
    Dr_Acula said...
    I'll fix that DI/EI thing now.

    I just thought of something. With text you store 80x40=3200 bytes. But you only ever need to display bytes 0-127 (or to be precise, 32 to 126).

    So that leaves values 128 to 255 unused. That is 128 possible values and for a VGA display, there are only 4x4x4=64 possible values anyway.

    So, could it work if text bytes were 0-127, and for values 128 to 128+64, you displayed a coloured block? I don't think you could mix text and graphics, but that may not matter.

    This takes no extra memory at all. Is 80x40 good enough resolution for games?

    You forgot the inverse attribute which is defined by setting bit #7 of a character. The mode you are suggesting is similar to the one used by Video-Text. There is a block graphics mode which defines the colour of the following characters by one of 8 codes that also takes up a position in the screen, so graphics can't start at the very first column. I don't think it is practical, though.

    I would not insist on the 40 rows, because this is quite a hunk of memory compared to 25 rows. The latter may be possible with colour attributes per character while the former is probably just too much data. But I'd say let's see what Baggers comes up with and how we can use it.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects

    Post Edited (pullmoll) : 4/25/2010 1:49:00 PM GMT
  • pullmollpullmoll Posts: 817
    edited 2010-04-25 10:06
    I extended the external memory access through ports. You can now address all 7 of the high memory ranges of the 7 banks through a simple output port command. Version 0.9.25 supports this.
    Writing 16+bank to port 18 ($12) selects another bank and also swaps the head and tail pointers out + in, so every bank has its own pair of pointers. Here's some sample code.
    10 OUT 18,3
    20 FOR I = 1 TO 7
    30 OUT 18, 16+I : REM select bank 1 to 7
    40 LPRINT "Bank number #";I
    50 NEXT I
    60 FOR I = 1 TO 7
    70 READ BANK
    80 OUT 18, 16+BANK
    90 IF INP(18) <> 3 THEN 120
    100 PRINT CHR$(INP(19));
    110 GOTO 90
    120 NEXT I
    130 DATA 3, 2, 5, 4, 1, 7, 6
    
    


    It writes a different string to each bank and then reads them back in the sequence define byte the data statement.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects
  • BaggersBaggers Posts: 3,019
    edited 2010-04-25 11:15
    ok I'll see what I can come up with [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    http://www.propgfx.co.uk/forum/·home of the PropGFX Lite

    ·
  • pullmollpullmoll Posts: 817
    edited 2010-04-26 22:46
    @Dr_Acula: For your networking code you may want to take a look at http://www.seasip.demon.co.uk/Cpm/bdos.html. It seems there is a CP/Net extension to CP/M which has a number of extended BDOS calls. Look at function 66, send message, which could give an example on formatting messages to exchange between nodes on your network.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects
  • BaggersBaggers Posts: 3,019
    edited 2010-04-27 12:53
    Hi Guys,
    5Mhz is pushing it, there's no way it can be done with a single cog, even if you have the waitvid's already generated in COG-RAM, it still can't push 80 waitvids out fast enough to do 8 pixels at 640x480 resolution.
    Unless someone else knows of a way, and can prove me wrong, which I'd quite happily admit to being wrong, should this be the case [noparse]:D[/noparse]

    Cheers,
    Baggers.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    http://www.propgfx.co.uk/forum/·home of the PropGFX Lite

    ·
  • pullmollpullmoll Posts: 817
    edited 2010-04-27 13:04
    Baggers said...
    Unless someone else knows of a way, and can prove me wrong, which I'd quite happily admit to being wrong, should this be the case [noparse]:D[/noparse]

    Well, not with different colours, unfortunately. I got an 80x25 TV monochrome driver working timing wise by combining 4 characters into one waitvid of 24 pixels (6x9 font). It's probably the number of hub RAM accesses required that makes it impossible to do 80 waitvids in one line with a 5MHz crystal. Perhaps you can reduce that figure by reading more than one character / attribute at a time?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-04-27 14:15
    Re CP/Net, the packet format I'm using is rather similar to that protocol. But for wireless, each packet needs a checksum, as it is quite possible that two packets get transmitted at the same time, or a garage door opener nearby upsets a packet. I don't think CP/M ever faced this problem as connections were wired and hence 100% reliable. The code is coming together. I'm doing it in vb.net first as it is quicker to debug (and because one of the nodes will be on a PC anyway). vb.net translates quite easily to sbasic or C.

    Re the color problem, what is the problem again, baggers?

    I recall when Bean came up with propbasic I had a little demo program putting quite small squares all over the screen with random colors. Not sure how much ram it used.

    I don't know much about graphics. But one thing that I've thought about - if you define a line of, say, 80 blocks of random colours, and you then build a line with those colors, you can repeat that line over and over eg 640/40 times, or more. That would give more time to build up the next line?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.smarthome.viviti.com/propeller
  • pullmollpullmoll Posts: 817
    edited 2010-04-27 14:58
    Dr_Acula said...
    I don't know much about graphics. But one thing that I've thought about - if you define a line of, say, 80 blocks of random colours, and you then build a line with those colors, you can repeat that line over and over eg 640/40 times, or more. That would give more time to build up the next line?

    The problem is that emitting the line alone already does not work. If I got Baggers right, he was trying to generate the PASM code for a scanline so that no conditional code would be there, and this still wasn't fast enough to do 80 waitvids in one scanline. In other words: it doesn't matter too much if the generated code changes once every line or every 8 or 40 lines, because it isn't fast enough anyway.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects
  • BaggersBaggers Posts: 3,019
    edited 2010-04-27 16:20
    pullmoll, the TV has a Horizontal timing of ~62.5us NTSC or ~64us in PAL, in VGA it's a half that, ~31.something ( can't remember off hand, as I'm hungry, and in need of going to get some food lol ) thus even with 80 waitvid instructions one after the other, there still isn't enough speed at 5Mhz crystal ( 20mips ) to keep the sync, ie my VGA monitor doesn't sync to it.

    DrAcula, the issue is that because you want colour per 8x8 character, the prop just simply isn't fast enough at 5Mhz to output the waitvid instructions faster than the pixels are being drawn.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    http://www.propgfx.co.uk/forum/·home of the PropGFX Lite

    ·
  • pullmollpullmoll Posts: 817
    edited 2010-04-27 19:01
    Baggers said...
    pullmoll, the TV has a Horizontal timing of ~62.5us NTSC or ~64us in PAL, in VGA it's a half that, ~31.something ( can't remember off hand, as I'm hungry, and in need of going to get some food lol ) thus even with 80 waitvid instructions one after the other, there still isn't enough speed at 5Mhz crystal ( 20mips ) to keep the sync, ie my VGA monitor doesn't sync to it.

    Uh, I see. I didn't know that the difference was that much. With 31.25µs (let's assume that is it) that is 32kHz per scanline. Assuming 540 scanlines (480 active, 42 blanking and 18 sync) you are around 59.25Hz frame rate. Wouldn't it be possible to drop the frame rate to ~30Hz? On a classic monitor that would be flickering like mad, while I don't think you would see the difference on a LCD / TFT monitor.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Pullmoll's Propeller Projects
Sign In or Register to comment.