Shop OBEX P1 Docs P2 Docs Learn Events
Cogjects - load cog code from SD and save hub ram — Parallax Forums

Cogjects - load cog code from SD and save hub ram

Dr_AculaDr_Acula Posts: 5,484
edited 2011-04-29 01:03 in Propeller 1
Attached is an early version of a Cogject loader. Take a typical object from the Obex, split it into its Spin and PASM components, compile the PASM part, rename the binary file as a .cog file, copy it to an SD card and then load it through a common location in hub ram.

Why bother? Well, normally every cog that is loaded leaves its image in hub ram. In a worst case scenario, you might load 7 cogs each with 2k of code making a total of 14k. That is a significant part of the total 32k in hub.

With the advent of many boards with sd cards, as well as fast sd card code, it is now possible to load cogs from the sd card.

It ends up pretty easy to use once the code has been written. Just two lines of spin code:
  ReadCogFile(string("Serial.Cog"))
  cognew(@cogarray+24, serial.start(31,30,0,115200))   

The first line reads the file into a cog array. And the second line starts the cog using parameters from the standard Start method.

Attached is some demo code. I have the keyboard and the serial driver working - so you just need to copy serial.cog and keyboard.cog to the sd card.

At the moment this is using the VGA driver from Kyedos as the display. The next challenge is to put the video driver into a cog as well. And a TV driver. And a graphics driver, so you can boot up with text and then change to graphics on the fly...

The underlying SD driver is Kye's SD driver from a few months back.

We can save a lot of space on this program. Compile it on BST with the "remove unused methods" checkbox ticked and it is a lot smaller as almost all the sd driver code is not used.

Also, it may be possible to recycle the SD cog code space as the generic cog array.

Building .cog files depends on the style of the original author. Chip Gracey's original objects tend to group variables and pass a pointer to the start of the first variable. Kye uses a method of poking new values into the hex code, and we can do this too after the .cog file has been loaded off the sd card, thanks to an idea from Ariba where you create a variable length dummy array in the middle of the cog code so that the program fills from the bottom up and the variables fill from the top down.

Another advantage of cogjects is you can use the same ones for other languages, eg Basic and C. Indeed, these two cogjects were originally written and tested in Catalina before being used here in Spin.

I hope others might find this useful. I'd like to think we could add some more cogjects to the library fairly quickly.

My next one to do is the standard VGA driver and then the mouse.

Addit April 10th, including a demo program that loads and unloads the following:
1) Serial
2) Keyboard
3) Mouse
4) VGA 80x40 text
5) VGA 100x50 text
6) VGA 128x64 text
7) VGA 160x120 with 64 color graphics
8) VGA 320x240 with 4 color graphics
9) External ram driver

Addit - the April 10th zip still was running the cog from the .DAT section. Deleted this in the April 11 version and fixed a minor bug in the .cog code (my apologies to the 2 people who have downloaded the April 10th version)
«13

Comments

  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-03-23 19:42
    While this is interesting. I must ask why. once all your cogs are loaded you can overwrite the hub mem. And as far as loading from some device (SD in this case) there is already some code to do this, and I would expect there to be more as time goes (Perhaps even ATA).

    Though nice code.
  • RossHRossH Posts: 5,345
    edited 2011-03-23 19:48
    Hi David,

    Yes, once all the cogs are loaded you can overwrite the Hub Mem their code used. But there are two problems with this:

    1. The memory is not necessary contiguous - you could be left with 2k block sprinkled throughout your memory map.

    2. You cannot easily re-use the space freed up for more code. This means you are effectively limited to 16k of code space.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-23 20:10
    RossH has explained that very well.

    The 2k blocks of code left over from loading cogs end up scattered all over hub memory. As far as I know, recycling that memory has only ever really been done with the CP/M emulation, and even then it only used some of the potential memory.

    And as Ross says, you can't put any program code in that memory. Only data.

    So in practice, you are coding away, compiling from time to time and getting more stressed as you can see the available memory running out. What do you do when it does run out? Move to "Big Spin"? (almost ready but not quite). Move to C or Basic running from external memory?

    And I'll add a third scenario where you have a nifty program with an SD card driver, video text driver (3 cogs), mouse, keyboard, serial driver and all the cogs are now used up. And you want to boot up with that, have the user enter some command "run my cool game", and then run a graphics intensive program that uses a 5 cog video driver. And you are almost out of RAM.

    BTW david, you are a legend for taking on the challenge of better TV graphics using external memory!
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-03-23 23:33
    Well done Drac!

    I second what RossH said.

    I just had an idea for poking data and knowing where to poke without placing all the data at the beginning. If the first instruction is a nop with the start of the variables/constants to be poked, then it is easy to pick up.

    I am not sure if this works correctly...
              org          0
    entry  nop         variables        'variables is the cog address of the first variable to be poked
              .....
    
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-24 00:06
    Thanks Cluso - I'll check it out.

    Also there is something Kye mentioned that is very interesting - if you take some pasm code and hit F8 or F9 and then place the cursor over a variable, down the bottom of the screen it tells you in "OBJ" where that variable ends up.

    This assumes that a piece of pasm code is 'stable' and unlikely to change, but there are many objects around where that would be true.

    I've been deep inside Chip's VGA driver code and he uses the term "implant" to describe changing a variable that is somewhere in the middle of code. I may end up noting where the 4 variables end up and adjusting those locations directly.

    I suspect that a variety of techniques will be useful depending on the style of the original obex code.
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-03-24 00:59
    Yes, in proptool lacing the cursor on a variable will give you it's address after compilation. There is also the listings available in both bst and homespun.

    It would be much simpler to modify an object if all that was required was a single nop instruction at the start.

    However, one has to be careful that the codespace is not all used, and also that the position of the start of the code is not used. I say that because in my 1pin TV driver, the font is stored at cog $000. I have a temporary jump instruction to the code which then replaces the first font long with the correct value. I did it this way because it reduced the instructions in the font renderer to give more chars/line for each clock frequency.

    Another advantage to separating the pasm code is the ability to then have the various interfaces (e.g. spin, basic, c, and of course pasm) held separately and compiled within the main program.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-24 05:27
    I have a temporary jump instruction to the code which then replaces the first font long with the correct value. I did it this way because it reduced the instructions in the font renderer to give more chars/line for each clock frequency.

    Yes, it is cunning things like that where maybe we might have to go back to the original author for advice.

    In the process of looking at the VGA driver code there is this
      'implant pin settings
      reg_vcfg := $200000FF + (BasePin & %111000) << 6
      i := $FF << (BasePin & %011000)
    

    and I realise that if you are going to be 'implanting' values (Chip's term, and used by Kye and I'm sure others as well), then the object is going to need access to the cog data.

    As such, I have changed the start routines, so that instead of the cognew being in the Main routine it is now in the object routine. So startup is this
      ReadCogFile(string("Serial.Cog"))
      serial.start(@cogarray,31,30,0,115200)                ' start the cog
      ReadCogFile(string("Keyboard.Cog"))
      kb.start(@cogarray,26,27)                              'start the keyboard 
    

    and an example of the cog load routine
    PUB start(cogarray, rxpin, txpin, mode, baudrate) : okay
    
    '' Start serial driver - starts a cog
    '' returns false if no cog available
    ''
    '' mode bit 0 = invert rx
    '' mode bit 1 = invert tx
    '' mode bit 2 = open-drain/source tx
    '' mode bit 3 = ignore tx echo on rx
    
      stop
      longfill(@rx_head, 0, 4)
      longmove(@rx_pin, @rxpin, 3)
      bit_ticks := clkfreq / baudrate
      buffer_ptr := @rx_buffer
      
      okay := @rx_head ' return the location of the parameter list
      okay := cog := cognew(cogarray, @rx_head) + 1     
    

    which ends up fairly similar to the original code, just that every "start" method is now going to need one variable added = cogarray.

    I think that the VGA startup routine now has enough information to modify the cog code prior to loading.

    @cluso99, I took a look at BST but I could not see how to get the printout of the variable locations. Is that in a compile menu or something?

    Addit: another little edit, now discarding the first 24 bytes so that the array is the same as the one used in C, ie the first cog element is the first one.
    PRI ReadCogFile(Filename)
      result := \fat.openFile(Filename, "R")                ' create file and open file
      result := \fat.readdata(@cogarray,24)                 ' read first 24 bytes and discard
      result := \fat.readdata(@cogarray,fat.filesize-24)    ' read the data into cogarray
      result := \fat.closefile      
    

    This brings up the next question as to what those variables at the bottom of the screen mean.

    Take this little bit of code
                            org    0                         'set origin to $000 for start of program
    myvariable              long $AAAAAAAA
    

    If I do an F9 on that and put the cursor on myvariable, I get
    DAT myvariable = OBJ[$0008] COG[$000]

    from that I would assume that COG is the location of the variable, not OBJ.

    Further down the program though, OBJ increments a lot faster than COG. OBJ seems to be incrementing too fast (it is $0008 even on the first long) but OBJ seems to be incrementing too slow. Which one is pointing to the location of that variable in the compiled code?

    More experiments, the location of a variable seems to be OBJ + $10. This seems a bit odd as I would have expected either no offset, or an offset of $18 (24).

    Any advice here would be most appreciated!
  • RaymanRayman Posts: 13,892
    edited 2011-03-24 06:27
    I definitely like this idea of saving memory space...

    Out of curiosity, would it be easier to have 2 seperate programs. The first one with all the drivers to load the cogs and then bootstrap the second program with the actual program code... (Maybe reserving space at beginning or end of memory for cog communications.)
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-03-24 08:25
    Drac: IIRC in bst (I use the windoze gui, not the comandline) you need to open the listing tab, then recompile and the listing will appear in the listing window.
    As for your example above, cog $000 would be the resulting address in cog.
    I will leave others to comment about the object locations after compile.

    Rather than requiring a spin stub to 'implant' the values, I wonder if
    long variables | varlength << 9
    may be better. This way you would know the length to be copied. In your example above, obviously the array would have to be preset. Your loader would then copy the required variables before performing the cognew function.

    Just trying to find a simple way where the pasm object is the only portion required. This way, the pasm object would be stored identically on the SD card no matter what high level code is used. Then we could just have a whole set of standard objects on the sd card. Perhaps these could then be in a subdirectory called PASMOBJ or something similar.

    You are definately on to a good thing here :)
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-03-24 09:55
    Spinix uses an approach like this, where the cog startup code is seperate from the higher level routines. The boot program installs the file I/O and serial drivers using binaries files that are included within it with the FILE directive. The Spnix kernel is loaded into the high end of memory, and the boot program space is then added to the malloc heap so that other programs can use it. Other drivers are installed by running a "start" program, which terminates after starting the cog. The heap manager keeps track of the free memory that is available.

    A simpler approach would be to just group all the cog startup objects together in memory. The top object would call all the start routines, which would re-use this chunk of memory. A simple memory allocation scheme could be used, which uses two pointers -- one that points to the beginning of the first startup object, and a second pointer that points to the end of the last startup object. This way all of the object's memory could be re-used including the Spin code and method table. The cogs would need to wait for a start signal before they write into their hub memory so they don't overwrite code that hadn't been executed yet.

    Dave
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-24 15:51
    Out of curiosity, would it be easier to have 2 seperate programs. The first one with all the drivers to load the cogs and then bootstrap the second program with the actual program code... (Maybe reserving space at beginning or end of memory for cog communications.)

    I'd need to think about that some more. It depends on the style of the programmer who wrote the object. If they used the PAR method, and all the variables are contiguous, and there are not many variables, then you could allocate fixed areas in hub at the top - x bytes for a keyboard buffer, y bytes for serial etc. If you allocated them in the same order then the second program would know where these buffers are and would be able to use them.

    What I have some reservations about is saying "hub memory area x is always to be allocated for keyboard" because everyones program is going to be different. But what you could have is a starter program that loads keyboard first, then serial and if you start at the top and work down then the second program knows where they are. Your program might load keyboard first then serial, and mine might load serial then keyboard, so this keeps it flexible.

    Another idea is to strip down the sd card code to the absolute minimum. There is a lot of functionality in Kye's code, but also a lot of things can be done in several ways and maybe all that code is not needed.

    One thing I would like to do is to be able to present a shell of a program that has all the basics - display, keyboard, mouse, serial, sd card, but still has plenty of room free for whatever the user wants to code.

    Also I want to document some of the technical aspects of translating objects because I think these techniques are likely to be able to be reused.
  • RaymanRayman Posts: 13,892
    edited 2011-03-24 16:01
    Maybe the loader could inspect the main program's code for some kind of tokens that tell it what objects it needs and where it expect to find them...
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-24 16:09
    That's a good idea. Hmm - could you store such tokens in a cog so they stay static when passing control to the next program?
  • RaymanRayman Posts: 13,892
    edited 2011-03-24 16:15
    The other thought I had is to have two interchangeable versions of the objects... One that is static for development and one that is dynamic via the loader...
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-03-24 18:35
    On the subject of loaders for grabbing machine lang apps from mass storage why not do the same with ATA? It seems to me that this would be a lot simpler. You only need 4 pins for reg select, and 16 for data, unless you do some multiplexing (in which case it would not be to hard to get down to 12 pins ttl, though this would require some extra on board logic, and cost an extra 84 cents [$0.84] US).
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-25 00:08
    Good thinking. In C I am programming big 200-300k programs using external memory, and there is plenty of room to store the cog code for almost every obex one can think of in external memory. It would be very quick to load these in and out of cogs.

    In Spin, all one needs is an external memory driver, and these are fairly straightforward for the Dracblade, C3 and Jazzed's external ram.

    If this system becomes more popular, one could also think about storing cogjects in eeprom.

    I think I have cracked the code for working out the offsets for storing bytes. Let's talk in hex for a bit!

    Compile some typical cog code and put the cursor over a variable and you might get a value of 0x8C. Look at the source code using F8 and it actually is 0x10 higher than this, at 0x9C. But the first 0x18 bytes are discarded, so this is the same as adding 0x10 and then subtracting 0x18, which is the same as subtracting 0x8.

    We discard the first 0x18 bytes of all cogs when loading them. So the answer to locating variables is to do an F9, place the cursor over the variable and then subtract 0x8 from that value. This gives the real location in a piece of cog code that starts at ORG 0.

    And to test this is correct, take a dummy piece of code:
    ORG 0
    myvariable long $AAAAAAAA

    hit F9, you get a value of 0008, subtract 8 and this gives zero which fits with it being the first long.

    Would some kind soul be able to please explain what this line does?
      'implant unique settings and launch first COG
      vf_lines.byte := vf
    

    The only place vf_lines is referenced is in the cog code, but it is a line of code, not a variable viz
    vf_lines                mov     x,#vf                   'do vertical front porch lines (# set at runtime)
                            call    #blank
    
                            jmp     #vsync                  'new field, loop to vsync
    

    entire program
    ''***************************************
    ''*  VGA High-Res Text Driver v1.0      *
    ''*  Author: Chip Gracey                *
    ''*  Copyright (c) 2006 Parallax, Inc.  *
    ''*  See end of file for terms of use.  *
    ''***************************************
    ''
    '' This object generates a 1024x768 VGA signal which contains 128 columns x 64
    '' rows of 8x12 characters. Each row can have a unique forground/background
    '' color combination and each character can be inversed. There are also two
    '' cursors which can be independently controlled (ie. mouse and keyboard). A
    '' sync indicator signals each time the screen is refreshed (you may ignore).
    ''
    '' You must provide buffers for the screen, colors, cursors, and sync. Once
    '' started, all interfacing is done via memory. To this object, all buffers are
    '' read-only, with the exception of the sync indicator which gets written with
    '' -1. You may freely write all buffers to affect screen appearance. Have fun!
    ''
    
    CON
    
    {
    ' 1024 x 768 @ 57Hz settings: 128 x 64 characters
    
      hp = 1024     'horizontal pixels
      vp = 768      'vertical pixels
      hf = 16       'horizontal front porch pixels
      hs = 96       'horizontal sync pixels
      hb = 176      'horizontal back porch pixels
      vf = 1        'vertical front porch lines
      vs = 3        'vertical sync lines
      vb = 28       'vertical back porch lines
      hn = 1        'horizontal normal sync state (0|1)
      vn = 1        'vertical normal sync state (0|1)
      pr = 60       'pixel rate in MHz at 80MHz system clock (5MHz granularity)
    }
    {
    ' 800 x 600 @ 75Hz settings: 100 x 50 characters
    
      hp = 800      'horizontal pixels
      vp = 600      'vertical pixels
      hf = 40       'horizontal front porch pixels
      hs = 128      'horizontal sync pixels
      hb = 88       'horizontal back porch pixels
      vf = 1        'vertical front porch lines
      vs = 4        'vertical sync lines
      vb = 23       'vertical back porch lines
      hn = 0        'horizontal normal sync state (0|1)
      vn = 0        'vertical normal sync state (0|1)
      pr = 50       'pixel rate in MHz at 80MHz system clock (5MHz granularity)
    }
    '{
    ' 640 x 480 @ 69Hz settings: 80 x 40 characters
    
      hp = 640      'horizontal pixels
      vp = 480      'vertical pixels
      hf = 24       'horizontal front porch pixels
      hs = 40       'horizontal sync pixels
      hb = 128      'horizontal back porch pixels
      vf = 9        'vertical front porch lines
      vs = 3        'vertical sync lines
      vb = 28       'vertical back porch lines
      hn = 1        'horizontal normal sync state (0|1)
      vn = 1        'vertical normal sync state (0|1)
      pr = 30       'pixel rate in MHz at 80MHz system clock (5MHz granularity)
    '}
    
    ' columns and rows
    
      cols = hp / 8
      rows = vp / 12
    
    
    VAR long cog[2]
    
    PUB start(BasePin, ScreenPtr, ColorPtr, CursorPtr, SyncPtr) : okay | i, j
    
    '' Start VGA driver - starts two COGs
    '' returns false if two COGs not available
    ''
    ''     BasePin = VGA starting pin (0, 8, 16, 24, etc.)
    ''
    ''   ScreenPtr = Pointer to 8,192 bytes containing ASCII codes for each of the
    ''               128x64 screen characters. Each byte's top bit controls color
    ''               inversion while the lower seven bits provide the ASCII code.
    ''               Screen memory is arranged left-to-right, top-to-bottom.
    ''
    ''               screen byte example: %1_1000001 = inverse "A"
    ''
    ''    ColorPtr = Pointer to 64 words which define the foreground and background
    ''               colors for each row. The lower byte of each word contains the
    ''               foreground RGB data for that row, while the upper byte
    ''               contains the background RGB data. The RGB data in each byte is
    ''               arranged as %RRGGBB00 (4 levels each).
    ''
    ''               color word example: %%0020_3300 = gold on blue
    ''
    ''   CursorPtr = Pointer to 6 bytes which control the cursors:
    ''
    ''               bytes 0,1,2: X, Y, and MODE of cursor 0
    ''               bytes 3,4,5: X, Y, and MODE of cursor 1
    ''
    ''               X and Y are in terms of screen characters
    ''               (left-to-right, top-to-bottom)
    ''
    ''               MODE uses three bottom bits:
    ''
    ''                      %x00 = cursor off
    ''                      %x01 = cursor on
    ''                      %x10 = cursor on, blink slow
    ''                      %x11 = cursor on, blink fast
    ''                      %0xx = cursor is solid block
    ''                      %1xx = cursor is underscore
    ''
    ''               cursor example: 127, 63, %010 = blinking block in lower-right
    ''
    ''     SyncPtr = Pointer to long which gets written with -1 upon each screen
    ''               refresh. May be used to time writes/scrolls, so that chopiness
    ''               can be avoided. You must clear it each time if you want to see
    ''               it re-trigger.
    
      'if driver is already running, stop it
      stop
    
      'implant pin settings
      reg_vcfg := $200000FF + (BasePin & %111000) << 6
      i := $FF << (BasePin & %011000)
      j := BasePin & %100000 == 0
      reg_dira := i & j
      reg_dirb := i & !j
    
      'implant CNT value to sync COGs to
      sync_cnt := cnt + $10000
    
      'implant pointers
      longmove(@screen_base, @ScreenPtr, 3)
      font_base := @font
    
      'implant unique settings and launch first COG
      vf_lines.byte := vf
      vb_lines.byte := vb
      font_third := 1
      cog[1] := cognew(@d0, SyncPtr) + 1
    
      'allow time for first COG to launch
      waitcnt($2000 + cnt)
    
      'differentiate settings and launch second COG
      vf_lines.byte := vf+4
      vb_lines.byte := vb-4
      font_third := 0
      cog[0] := cognew(@d0, SyncPtr) + 1
    
      'if both COGs launched, return true
      if cog[0] and cog[1]
        return true
    
      'else, stop any launched COG and return false
      else
        stop
    
    
    PUB stop | i
    
    '' Stop VGA driver - frees two COGs
    
      repeat i from 0 to 1
        if cog[i]
          cogstop(cog[i]~ - 1)
    
    
    CON
    
      #1, scanbuff[128], scancode[128*2-1+3], maincode      'enumerate COG RAM usage
    
      main_size = $1F0 - maincode                           'size of main program
    
      hv_inactive = (hn << 1 + vn) * $0101                  'H,V inactive states
    
    
    DAT
    
    '*****************************************************
    '* Assembly language VGA high-resolution text driver *
    '*****************************************************
    
    ' This program runs concurrently in two different COGs.
    '
    ' Each COG's program has different values implanted for front-porch lines and
    ' back-porch lines which surround the vertical sync pulse lines. This allows
    ' timed interleaving of their active display signals during the visible portion
    ' of the field scan. Also, they are differentiated so that one COG displays
    ' even four-line groups while the other COG displays odd four-line groups.
    '
    ' These COGs are launched in the PUB 'start' and are programmed to synchronize
    ' their PLL-driven video circuits so that they can alternately prepare sets of
    ' four scan lines and then display them. The COG-to-COG switchover is seemless
    ' due to two things: exact synchronization of the two video circuits and the
    ' fact that all COGs' driven output states get OR'd together, allowing one COG
    ' to output lows during its preparatory state while the other COG effectively
    ' drives the pins to create the visible and sync portions of its scan lines.
    ' During non-visible scan lines, both COGs output together in unison.
    '
    ' COG RAM usage:  $000      = d0 - used to inc destination fields for indirection
    '                 $001-$080 = scanbuff - longs which hold 4 scan lines
    '                 $081-$182 = scancode - stacked WAITVID/SHR for fast display
    '                 $183-$1EF = maincode - main program loop which drives display
    
                            org    0                         'set origin to $000 for start of program
    
    d0                      long    1 << 9                  'd0 always resides here at $000, executes as NOP
    
    
    ' Initialization code and data - after execution, space gets reused as scanbuff
    
                            'Move main program into maincode area
    
    :move                   mov     $1EF,main_begin+main_size-1
                            sub     :move,d0s0              '(do reverse move to avoid overwrite)
                            djnz    main_ctr,#:move
    
                            'Build scanbuff display routine into scancode
    
    :waitvid                mov     scancode+0,i0           'org     scancode
    :shr                    mov     scancode+1,i1           'waitvid color,scanbuff+0
                            add     :waitvid,d1             'shr     scanbuff+0,#8
                            add     :shr,d1                 'waitvid color,scanbuff+1
                            add     i0,#1                   'shr     scanbuff+1,#8
                            add     i1,d0                   '...
                            djnz    scan_ctr,#:waitvid      'waitvid color,scanbuff+cols-1
    
                            mov     scancode+cols*2-1,i2    'mov     vscl,#hf
                            mov     scancode+cols*2+0,i3    'waitvid hvsync,#0
                            mov     scancode+cols*2+1,i4    'jmp     #scanret
    
                            'Init I/O registers and sync COGs' video circuits
    
                            mov     dira,reg_dira           'set pin directions
                            mov     dirb,reg_dirb
                            movi    frqa,#(pr / 5) << 2     'set pixel rate
                            mov     vcfg,reg_vcfg           'set video configuration
                            mov     vscl,#1                 'set video to reload on every pixel
                            waitcnt sync_cnt,colormask      'wait for start value in cnt, add ~1ms
                            movi    ctra,#%00001_110        'COGs in sync! enable PLLs now - NCOs locked!
                            waitcnt sync_cnt,#0             'wait ~1ms for PLLs to stabilize - PLLs locked!
                            mov     vscl,#100               'insure initial WAITVIDs lock cleanly
    
                            'Jump to main loop
    
                            jmp     #vsync                  'jump to vsync - WAITVIDs will now be locked!
    
                            'Data
    
    d0s0                    long    1 << 9 + 1
    d1                      long    1 << 10
    main_ctr                long    main_size
    scan_ctr                long    cols
    
    i0                      waitvid x,scanbuff+0
    i1                      shr     scanbuff+0,#8
    i2                      mov     vscl,#hf
    i3                      waitvid hvsync,#0
    i4                      jmp     #scanret
    
    reg_dira                long    0                       'set at runtime
    reg_dirb                long    0                       'set at runtime
    reg_vcfg                long    0                       'set at runtime
    sync_cnt                long    0                       'set at runtime
    
                            'Directives
    
                            fit     scancode                'make sure initialization code and data fit
    main_begin              org     maincode                'main code follows (gets moved into maincode)
    
    
    ' Main loop, display field - each COG alternately builds and displays four scan lines
    
    vsync                   mov     x,#vs                   'do vertical sync lines
                            call    #blank_vsync
    
    vb_lines                mov     x,#vb                   'do vertical back porch lines (# set at runtime)
                            call    #blank_vsync
    
                            mov     screen_ptr,screen_base  'reset screen pointer to upper-left character
                            mov     color_ptr,color_base    'reset color pointer to first row
                            mov     row,#0                  'reset row counter for cursor insertion
                            mov     fours,#rows * 3 / 2     'set number of 4-line builds for whole screen
    
                            'Build four scan lines into scanbuff
    
    fourline                mov     font_ptr,font_third     'get address of appropriate font section
                            shl     font_ptr,#7+2
                            add     font_ptr,font_base
    
                            movd    :pixa,#scanbuff-1       'reset scanbuff address (pre-decremented)
                            movd    :pixb,#scanbuff-1
    
                            mov     y,#2                    'must build scanbuff in two sections because
                            mov     vscl,vscl_line2x        '..pixel counter is limited to twelve bits
    
    :halfrow                waitvid underscore,#0           'output lows to let other COG drive VGA pins
                            mov     x,#cols/2               '..for 2 scan lines, ready for half a row
    
    :column                 rdbyte  z,screen_ptr            'get character from screen memory
                            ror     z,#7                    'get inverse flag into bit 0, keep chr high
                            shr     z,#32-7-2       wc      'get inverse flag into c, chr into bits 8..2
                            add     z,font_ptr              'add font section address to point to 8*4 pixels
                            add     :pixa,d0                'increment scanbuff destination addresses
                            add     :pixb,d0
                            add     screen_ptr,#1           'increment screen memory address
    :pixa                   rdlong  scanbuff,z              'read pixel long (8*4) into scanbuff
    :pixb   if_nc           xor     scanbuff,longmask       'invert pixels according to inverse flag
                            djnz    x,#:column              'another character in this half-row?
    
                            djnz    y,#:halfrow             'loop to do 2nd half-row, time for 2nd WAITVID
    
                            sub     screen_ptr,#cols        'back up to start of same row in screen memory
    
                            'Insert cursors into scanbuff
    
                            mov     z,#2                    'ready for two cursors
    
    :cursor                 rdbyte  x,cursor_base           'x in range?
                            add     cursor_base,#1
                            cmp     x,#cols         wc
    
                            rdbyte  y,cursor_base           'y match?
                            add     cursor_base,#1
                            cmp     y,row           wz
    
                            rdbyte  y,cursor_base           'get cursor mode
                            add     cursor_base,#1
    
            if_nc_or_nz     jmp     #:nocursor              'if cursor not in scanbuff, no cursor
    
                            add     x,#scanbuff             'cursor in scanbuff, set scanbuff address
                            movd    :xor,x
    
                            test    y,#%010         wc      'get mode bits into flags
                            test    y,#%001         wz
            if_nc_and_z     jmp     #:nocursor              'if cursor disabled, no cursor
    
            if_c_and_z      test    slowbit,cnt     wc      'if blink mode, get blink state
            if_c_and_nz     test    fastbit,cnt     wc
    
                            test    y,#%100         wz      'get box or underscore cursor piece
            if_z            mov     x,longmask
            if_nz           mov     x,underscore
            if_nz           cmp     font_third,#2   wz      'if underscore, must be last font section
    
    :xor    if_nc_and_z     xor     scanbuff,x              'conditionally xor cursor into scanbuff
    
    :nocursor               djnz    z,#:cursor              'second cursor?
    
                            sub     cursor_base,#3*2        'restore cursor base
    
                            'Display four scan lines from scanbuff
    
                            rdword  x,color_ptr             'get color pattern for current row
                            and     x,colormask             'mask away hsync and vsync signal states
                            or      x,hv                    'insert inactive hsync and vsync states
    
                            mov     y,#4                    'ready for four scan lines
    
    scanline                mov     vscl,vscl_chr           'set pixel rate for characters
                            jmp     #scancode               'jump to scanbuff display routine in scancode
    scanret                 mov     vscl,#hs                'do horizontal sync pixels
                            waitvid hvsync,#1               '#1 makes hsync active
                            mov     vscl,#hb                'do horizontal back porch pixels
                            waitvid hvsync,#0               '#0 makes hsync inactive
                            shr     scanbuff+cols-1,#8      'shift last column's pixels right by 8
                            djnz    y,#scanline             'another scan line?
    
                            'Next group of four scan lines
    
                            add     font_third,#2           'if font_third + 2 => 3, subtract 3 (new row)
                            cmpsub  font_third,#3   wc      'c=0 for same row, c=1 for new row
            if_c            add     screen_ptr,#cols        'if new row, advance screen pointer
            if_c            add     color_ptr,#2            'if new row, advance color pointer
            if_c            add     row,#1                  'if new row, increment row counter
                            djnz    fours,#fourline         'another 4-line build/display?
    
                            'Visible section done, do vertical sync front porch lines
    
                            wrlong  longmask,par            'write -1 to refresh indicator
    
    vf_lines                mov     x,#vf                   'do vertical front porch lines (# set at runtime)
                            call    #blank
    
                            jmp     #vsync                  'new field, loop to vsync
    
                            'Subroutine - do blank lines
    
    blank_vsync             xor     hvsync,#$101            'flip vertical sync bits
    
    blank                   mov     vscl,hx                 'do blank pixels
                            waitvid hvsync,#0
                            mov     vscl,#hf                'do horizontal front porch pixels
                            waitvid hvsync,#0
                            mov     vscl,#hs                'do horizontal sync pixels
                            waitvid hvsync,#1
                            mov     vscl,#hb                'do horizontal back porch pixels
                            waitvid hvsync,#0
                            djnz    x,#blank                'another line?
    blank_ret
    blank_vsync_ret         ret
    
                            'Data
    
    screen_base             long    0                       'set at runtime (3 contiguous longs)
    color_base              long    0                       'set at runtime
    cursor_base             long    0                       'set at runtime
    
    font_base               long    0                       'set at runtime
    font_third              long    0                       'set at runtime
    
    hx                      long    hp                      'visible pixels per scan line
    vscl_line2x             long    (hp + hf + hs + hb) * 2 'total number of pixels per 2 scan lines
    vscl_chr                long    1 << 12 + 8             '1 clock per pixel and 8 pixels per set
    colormask               long    $FCFC                   'mask to isolate R,G,B bits from H,V
    longmask                long    $FFFFFFFF               'all bits set
    slowbit                 long    1 << 25                 'cnt mask for slow cursor blink
    fastbit                 long    1 << 24                 'cnt mask for fast cursor blink
    underscore              long    $FFFF0000               'underscore cursor pattern
    hv                      long    hv_inactive             '-H,-V states
    hvsync                  long    hv_inactive ^ $200      '+/-H,-V states
    
                            'Uninitialized data
    
    screen_ptr              res     1
    color_ptr               res     1
    font_ptr                res     1
    
    x                       res     1
    y                       res     1
    z                       res     1
    
    row                     res     1
    fours                   res     1
    
    
    ' 8 x 12 font - characters 0..127
    '
    ' Each long holds four scan lines of a single character. The longs are arranged into
    ' groups of 128 which represent all characters (0..127). There are three groups which
    ' each contain a vertical third of all characters. They are ordered top, middle, and
    ' bottom.
    
    font  long
    
    long  $0C080000,$30100000,$7E3C1800,$18181800,$81423C00,$99423C00,$8181FF00,$E7C3FF00  'top  ascii 0-7
    long  $1E0E0602,$1C000000,$00000000,$00000000,$18181818,$18181818,$00000000,$18181818
    long  $00000000,$18181818,$18181818,$18181818,$18181818,$00FFFF00,$CC993366,$66666666
    long  $AA55AA55,$0F0F0F0F,$0F0F0F0F,$0F0F0F0F,$0F0F0F0F,$00000000,$00000000,$00000000  ' ascii 24 to 31
    long  $00000000,$3C3C1800,$66666600,$7F363600,$667C1818,$46000000,$1B1B0E00,$1C181800  ' 77666600  to 66666600 for the " character (ascii 32
    long  $0C183000,$180C0600,$66000000,$18000000,$00000000,$00000000,$00000000,$60400000
    long  $73633E00,$1E181000,$66663C00,$60663C00,$3C383000,$06067E00,$060C3800,$63637F00
    long  $66663C00,$66663C00,$1C000000,$00000000,$18306000,$00000000,$180C0600,$60663C00
    long  $63673E00,$66663C00,$66663F00,$63663C00,$66361F00,$06467F00,$06467F00,$63663C00
    long  $63636300,$18183C00,$30307800,$36666700,$06060F00,$7F776300,$67636300,$63361C00
    long  $66663F00,$63361C00,$66663F00,$66663C00,$185A7E00,$66666600,$66666600,$63636300
    long  $66666600,$66666600,$31637F00,$0C0C3C00,$03010000,$30303C00,$361C0800,$00000000
    long  $0C000000,$00000000,$06060700,$00000000,$30303800,$00000000,$0C6C3800,$00000000
    long  $06060700,$00181800,$00606000,$06060700,$18181E00,$00000000,$00000000,$00000000
    long  $00000000,$00000000,$00000000,$00000000,$0C080000,$00000000,$00000000,$00000000
    long  $00000000,$00000000,$00000000,$18187000,$18181800,$18180E00,$73DBCE00,$18180000
    
    long  $080C7E7E,$10307E7E,$18181818,$7E181818,$81818181,$99BDBDBD,$81818181,$E7BD99BD  'middle
    long  $1E3E7E3E,$1C3E3E3E,$30F0C000,$0C0F0300,$00C0F030,$00030F0C,$00FFFF00,$18181818
    long  $18FFFF00,$00FFFF18,$18F8F818,$181F1F18,$18FFFF18,$00FFFF00,$CC993366,$66666666
    long  $AA55AA55,$FFFF0F0F,$F0F00F0F,$0F0F0F0F,$00000F0F,$FFFF0000,$F0F00000,$0F0F0000  ' 00000033 to 00000066 for the " character
    long  $00000000,$0018183C,$00000066,$7F363636,$66603C06,$0C183066,$337B5B0E,$0000000C
    long  $0C060606,$18303030,$663CFF3C,$18187E18,$00000000,$00007E00,$00000000,$060C1830
    long  $676F6B7B,$18181818,$0C183060,$60603860,$307F3336,$60603E06,$66663E06,$0C183060
    long  $66763C6E,$60607C66,$1C00001C,$00001C1C,$180C060C,$007E007E,$18306030,$00181830
    long  $033B7B7B,$66667E66,$66663E66,$63030303,$66666666,$06263E26,$06263E26,$63730303
    long  $63637F63,$18181818,$33333030,$36361E36,$66460606,$63636B7F,$737B7F6F,$63636363
    long  $06063E66,$7B636363,$66363E66,$66301C06,$18181818,$66666666,$66666666,$366B6B63
    long  $663C183C,$18183C66,$43060C18,$0C0C0C0C,$30180C06,$30303030,$00000063,$00000000
    long  $0030381C,$333E301E,$6666663E,$0606663C,$3333333E,$067E663C,$0C0C3E0C,$3333336E
    long  $66666E36,$1818181C,$60606070,$361E3666,$18181818,$6B6B6B3F,$6666663E,$6666663C
    long  $6666663B,$3333336E,$066E7637,$300C663C,$0C0C0C7E,$33333333,$66666666,$6B6B6363
    long  $1C1C3663,$66666666,$0C30627E,$180C060C,$18181818,$18306030,$00000000,$0018187E
    
    long  $00000000,$00000000,$00001818,$0000183C,$00003C42,$00003C42,$0000FF81,$0000FFC3  'bottom
    long  $0002060E,$00000000,$18181818,$18181818,$00000000,$00000000,$00000000,$18181818
    long  $18181818,$00000000,$18181818,$18181818,$18181818,$00FFFF00,$CC993366,$66666666
    long  $AA55AA55,$FFFFFFFF,$F0F0F0F0,$0F0F0F0F,$00000000,$FFFFFFFF,$F0F0F0F0,$0F0F0F0F
    long  $00000000,$00001818,$00000000,$00003636,$0018183E,$00006266,$00006E3B,$00000000
    long  $00003018,$0000060C,$00000000,$00000000,$0C181C1C,$00000000,$00001C1C,$00000103
    long  $00003E63,$00007E18,$00007E66,$00003C66,$00007830,$00003C66,$00003C66,$00000C0C
    long  $00003C66,$00001C30,$0000001C,$0C181C1C,$00006030,$00000000,$0000060C,$00001818
    long  $00003E07,$00006666,$00003F66,$00003C66,$00001F36,$00007F46,$00000F06,$00007C66
    long  $00006363,$00003C18,$00001E33,$00006766,$00007F66,$00006363,$00006363,$00001C36
    long  $00000F06,$00603C36,$00006766,$00003C66,$00003C18,$00003C66,$0000183C,$00003636
    long  $00006666,$00003C18,$00007F63,$00003C0C,$00004060,$00003C30,$00000000,$FFFF0000
    long  $00000000,$00006E33,$00003B66,$00003C66,$00006E33,$00003C66,$00001E0C,$1E33303E
    long  $00006766,$00007E18,$3C666660,$00006766,$00007E18,$00006B6B,$00006666,$00003C66
    long  $0F063E66,$78303E33,$00000F06,$00003C66,$0000386C,$00006E33,$0000183C,$00003636
    long  $00006336,$1C30607C,$00007E46,$00007018,$00001818,$00000E18,$00000000,$0000007E
    
    
    
    {{
    
    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    &#9474;                                                   TERMS OF USE: MIT License                                                  &#9474;
    &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
    &#9474;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation    &#9474;
    &#9474;files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,    &#9474;
    &#9474;modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software&#9474;
    &#9474;is furnished to do so, subject to the following conditions:                                                                   &#9474;
    &#9474;                                                                                                                              &#9474;
    &#9474;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&#9474;
    &#9474;                                                                                                                              &#9474;
    &#9474;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE          &#9474;
    &#9474;WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR         &#9474;
    &#9474;COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,   &#9474;
    &#9474;ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                         &#9474;
    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    }}
    
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-03-25 00:57
    Drac: It is loading the #vf constant in that instruction, but only the lowest 8 bits (ie the 9th bit remains untouched and is 0). Remember the endian is reversed so it is the first byte in hub. At compile time and run time (before coginit) the location of vf_lines is a hub address.
    p.s. You cannot see the forest for the trees haha.
    pps I will be out your way at Easter, so will see if we can catch up. Must be time for ano Oz UPE
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-25 01:21
    Yes I think another Oz UPE sounds a very good idea!

    yes, I am so deep inside this code and I know that only one mistake and the whole thing won't work. Is this going to be some sort of "bytemove" taking into account the little endian thing?

    Comparing with the original code, do you think this is on the right track?
    in the main
    VAR
        byte CogArray[2048] ' reserve space for cogs to be loaded
    

    the calling routine from main
      serial.start(@cogarray,other variables...)                ' start the cog  
    

    and in the object
    PUB start(cogarray, BasePin, ScreenPtr, ColorPtr, CursorPtr, SyncPtr) : okay | i, j, reg_dira, reg_dirb, reg_vcfg, sync_cnt                                
      'implant pin settings
      reg_vcfg := $200000FF + (BasePin & %111000) << 6
     ' need to move reg_vcfg to the hub memory location of cogarray plus $8C
      longmove(cogarray+$8C,@reg_vcfg,1)  
      i := $FF << (BasePin & %011000)
      j := BasePin & %100000 == 0
      reg_dira := i & j
      ' need to move reg_dira to the hub memory location of cogarray plus $84
      longmove(cogarray+$84,@reg_dira,1)
      reg_dirb := i & !j
      ' need to move reg_dirb to the hub memory location of cogarray plus $88
      longmove(cogarray+$88,@reg_dirb,1) 
      'implant CNT value to sync COGs to
      sync_cnt := cnt + $10000
      ' need to move reg_dira to the hub memory location of cogarray plus $90 
      longmove(cogarray+$90,@sync_cnt,1)
      ' screen_base is at $01F4 using F9 so subtract $8 gives $1EC
      ' screenptr is passed to this startup routine (don't confuse with screen_ptr)
      'implant pointers
      'longmove(@screen_base, @ScreenPtr, 3)
      longmove(cogarray+$1EC,@ScreenPtr,3)                  ' replaces line above
    
      font_base := @font
      ' ************* got to here ***************
      'implant unique settings and launch first COG
      vf_lines.byte := vf
      vb_lines.byte := vb
    
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-03-25 02:37
    Yes it its just a bytemove, so your longmove should be a bytemove and I think the address is correct.

    I am wondering if you can do something like this...
      ' screen_base is at $01F4 using F9 so subtract $8 gives $1EC
      ' screenptr is passed to this startup routine (don't confuse with screen_ptr)
      'implant pointers
      'longmove(@screen_base, @ScreenPtr, 3)
      longmove(cogarray+$1EC,@ScreenPtr,3)                  ' replaces line above
    
    replace with...
     
      ' screen_base is at $01F4 using F9 so subtract $8 gives $1EC
      'implant pointers
      'longmove(@screen_base, @ScreenPtr, 3)
      longmove(@d0 - @screen_base - $8 + @cogarray,@ScreenPtr,3)                  ' replaces line above
    
    or...
     
    addr := @d0 - @screen_base - $8 + @cogarrya    'order is important to prevent overflow/truncation
    longmove(addr,@ScreenPtr,3)
    
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-25 05:11
    Good thinking.... but you don't have access to d0 any more. That is in a separate file. So you can't do
    longmove(@d0 - @screen_base - $8 + @cogarray,@ScreenPtr,3)
    You don't have access to any variable names in the cog file any more. All you have is a hex file with a couple of thousand bytes, and that you know they start at "cogarray".

    This vga one is pretty messy as there is data being poked to all sorts of locations within the file. Not as simple as the ones that use PAR.
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-03-25 08:29
    Damn! What about this...
    PUB start(cogarray, BasePin, ScreenPtr, ColorPtr, CursorPtr, SyncPtr) : okay | i, j, reg_dira[4], font_base[2]
     
      'implant reg_dira, reg_dirb, reg_vcfg, sync_cnt 
      i := $FF << (BasePin & %011000)
      j := BasePin & %100000 == 0
      reg_dira[0] := i & j
      reg_dira[1] := i & !j      'reg_dirb
      reg_dira[2] := $200000FF + (BasePin & %111000) << 6   'reg_vcfg
      reg_dira[3] := cnt + $10000    'sync_cnt    to sync cogs
      ' now move block reg_dira, reg_dirb, reg_vcfg, sync_cnt into cogarray +$84
      longmove(cogarray+$84,reg_dira,4)   '??? are the @ correct ???
     
      ' screen_base is at $01F4 using F9 so subtract $8 gives $1EC
      ' screenptr is passed to this startup routine (don't confuse with screen_ptr)
      'implant pointers
      'longmove(@screen_base, @ScreenPtr, 3)
      longmove(cogarray+$1EC,@ScreenPtr,3)                  ' replaces line above
     
      'implant unique settings and launch first COG
      font_base[0] := @font                                                       'font_base: same for both
      font_base[1] := 1                                                               'font_third:
      longmove(cogarray+$1EC+$00C,font_base[0],2)     'implant               
      bytemove(cogarray+$???,vf,1)                                       'vf_lines
      bytemove(cogarray+$???,vb,1)                                      'vb_lines
      cog[1] := cognew(@d0, SyncPtr) + 1
     
      'allow time for first COG to launch
      waitcnt($2000 + cnt)
     
      'differentiate settings and launch second COG (note font_base is screen_base +$00C)
      font_base[0] := @font                                                       'font_base: same for both
      font_base[1] := 0                                                               'font_third:
      longmove(cogarray+$1EC+$00C,font_base[0],2)     'implant               
      bytemove(cogarray+$???,vf+4,1)                                  'vf_lines
      bytemove(cogarray+$???,vb-4,1)                                  'vb_lines
      cog[0] := cognew(@d0, SyncPtr) + 1
     
    

    I would think you could insert these two lines at the beginning of the cog code after the d0 line without problems. Then collect these as the offsets into the cogarray rather than using fixed values.
                            org    0                         'set origin to $000 for start of program
    
    d0                      long    1 << 9                  'd0 always resides here at $000, executes as NOP
                              long    (d0 - reg_dira << 9) | (d0 - screen_base)   'NOP - used to find offsets for implant
                              long    (d0 - vf_lines << 9) | (do - vb_lines)             'NOP - used to find offsets for implant
    
    ' Initialization code and data - after execution, space gets reused as scanbuff
    
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-25 17:57
    This is a quick routine to dump the cogject to the screen. Very handy to check values are being poked to the correct place
    PRI Hexdump | i,j,k' print out all the cogject in hex, 32 bytes per line
        k :=0
        repeat i from 0 to 63 ' 2048 bytes is 64 rows x 32 bytes. 
          vt100.hex(k,4)
          vt100.out(32)
          repeat j from 0 to 31
            vt100.hex(cogarray[k],2)
            k +=1
          if k == 1024
            crlf
            printstringcr(string("Hit a key")) ' 2 pages
            kb.getkey    
          crlf
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-25 18:20
    Dr_Acula wrote: »
    Addit: another little edit, now discarding the first 24 bytes so that the array is the same as the one used in C, ie the first cog element is the first one.
    FWIW, if you insist on the hard-wired 24byte offset you better make sure that the SPIN file generating the binary file follows a specific format (no OBJ, no private methods, only one public method). That said, why don't you simply extract the primary DAT block with bstc and use that as your binary? Or do you expect the binary to be functional for normal use?
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-03-25 18:56
    Just a thought; Why not adapt this to also take advantage of SRAM, SDRAM, DRAM, etc.?
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-25 19:30
    you better make sure that the SPIN file generating the binary file follows a specific format (no OBJ, no private methods, only one public method).

    Yes that is what it is. No OBJ, only one PUB with a dummy load of the cog. This is just the bare minimum to get it to compile.

    You can compile it with the Proptool or with BSTC.
    CON
      _clkfreq = 80_000_000                                              ' 5Mhz Crystal
      _clkmode = xtal1 + pll16x                                          ' x 16
    
    PUB Main
        coginit(1,@entry,0)                                        
    DAT
                            org
    entry                   pasm code goes here
    
    Just a thought; Why not adapt this to also take advantage of SRAM, SDRAM, DRAM, etc.?

    Yes, that is a great idea. You can store cogjects anywhere you like. External ram. SD card. Maybe even put them in the unused part of an EEPROM.
  • jazzedjazzed Posts: 11,803
    edited 2011-03-25 21:45
    Dr_Acula wrote: »
    Yes that is what it is.
    There is a way to calculate the start address of cog code in a binary.
    It is done in the spinc.c module included in Catalina.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-25 21:49
    Thanks jazzed - I'll check that out.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-27 06:07
    I seem to have run into a small problem with
      bytemove(cogarray + $9C, vb-4,1)  'replaces   'vb_lines.byte := vb-4
    

    It seems to be copying random data (to the correct place). vb is a constant, not a variable - maybe this is the issue.

    I'm tracing this through by doing a hex dump of the cog memory after it values have been implanted (after being implanted by the second cog load), then comparing this with a screen dump from a working vga driver. There are quite a few differences that I'll need to work on.

    Code is below, and near the bottom is a comment section with the cogject code above the correct code.

    I wonder if I should do something like this instead
    'vf_lines.byte := vf ' original code
      i := vf                                    
      bytemove(cogarray + $1B4, @i,1)
    

    Any help would be most appreciated!

    addit - that does seem to improve things- now have garbage on the screen instead of a blank screen.

    I now realise that these 3 bytes will be different as they point to different locations in each demo program
    longmove(cogarray + $1EC,@ScreenPtr,3) ' replaces line above, screen_base, color_base, cursor_base

    Getting close here
    ''***************************************
    ''*  VGA High-Res Text Driver v1.0      *
    ''*  Author: Chip Gracey                *
    ''*  Copyright (c) 2006 Parallax, Inc.  *
    ''*  See end of file for terms of use.  *
    ''***************************************
    ''
    '' This object generates a 1024x768 VGA signal which contains 128 columns x 64
    '' rows of 8x12 characters. Each row can have a unique forground/background
    '' color combination and each character can be inversed. There are also two
    '' cursors which can be independently controlled (ie. mouse and keyboard). A
    '' sync indicator signals each time the screen is refreshed (you may ignore).
    ''
    '' You must provide buffers for the screen, colors, cursors, and sync. Once
    '' started, all interfacing is done via memory. To this object, all buffers are
    '' read-only, with the exception of the sync indicator which gets written with
    '' -1. You may freely write all buffers to affect screen appearance. Have fun!
    
    ' move font to spin code
    ' move 4 variables regdira regdirb etc to a VAR section
    ' these are going to need to be passed with PAR and replace the 4 variables in the code
    ' also variables like screenbase are inside the cog code.
    ' or, compile the cog code with F8 or F9, then put cursor on a variable and look at the OBJ value
    ' at the bottom of the screen. then poke to these directly
    ' added 4 variables to the start routine
    ' calculated the offsets (subtract $8 from whatever value F9 gives)
    ' longmove to copy these to the cogarray and implant them
    
    
    ''
    
    CON
    
    {
    ' 1024 x 768 @ 57Hz settings: 128 x 64 characters
    
      hp = 1024     'horizontal pixels
      vp = 768      'vertical pixels
      hf = 16       'horizontal front porch pixels
      hs = 96       'horizontal sync pixels
      hb = 176      'horizontal back porch pixels
      vf = 1        'vertical front porch lines
      vs = 3        'vertical sync lines
      vb = 28       'vertical back porch lines
      hn = 1        'horizontal normal sync state (0|1)
      vn = 1        'vertical normal sync state (0|1)
      pr = 60       'pixel rate in MHz at 80MHz system clock (5MHz granularity)
    }
    {
    ' 800 x 600 @ 75Hz settings: 100 x 50 characters
    
      hp = 800      'horizontal pixels
      vp = 600      'vertical pixels
      hf = 40       'horizontal front porch pixels
      hs = 128      'horizontal sync pixels
      hb = 88       'horizontal back porch pixels
      vf = 1        'vertical front porch lines
      vs = 4        'vertical sync lines
      vb = 23       'vertical back porch lines
      hn = 0        'horizontal normal sync state (0|1)
      vn = 0        'vertical normal sync state (0|1)
      pr = 50       'pixel rate in MHz at 80MHz system clock (5MHz granularity)
    }
    '{
    ' 640 x 480 @ 69Hz settings: 80 x 40 characters
    
      hp = 640      'horizontal pixels
      vp = 480      'vertical pixels
      hf = 24       'horizontal front porch pixels
      hs = 40       'horizontal sync pixels
      hb = 128      'horizontal back porch pixels
      vf = 9        'vertical front porch lines
      vs = 3        'vertical sync lines
      vb = 28       'vertical back porch lines
      hn = 1        'horizontal normal sync state (0|1)
      vn = 1        'vertical normal sync state (0|1)
      pr = 30       'pixel rate in MHz at 80MHz system clock (5MHz granularity)
    '}
    
    ' columns and rows
    
      cols = hp / 8
      rows = vp / 12
    
    
    VAR     long          cog[2]
                    
        
    PUB start(cogarray, BasePin, ScreenPtr, ColorPtr, CursorPtr, SyncPtr) : okay | i, j, reg_dira, reg_dirb, reg_vcfg, sync_cnt
    
    '' Start VGA driver - starts two COGs
    '' returns false if two COGs not available
    ''
    ''     BasePin = VGA starting pin (0, 8, 16, 24, etc.)
    ''
    ''   ScreenPtr = Pointer to 8,192 bytes containing ASCII codes for each of the
    ''               128x64 screen characters. Each byte's top bit controls color
    ''               inversion while the lower seven bits provide the ASCII code.
    ''               Screen memory is arranged left-to-right, top-to-bottom.
    ''
    ''               screen byte example: %1_1000001 = inverse "A"
    ''
    ''    ColorPtr = Pointer to 64 words which define the foreground and background
    ''               colors for each row. The lower byte of each word contains the
    ''               foreground RGB data for that row, while the upper byte
    ''               contains the background RGB data. The RGB data in each byte is
    ''               arranged as %RRGGBB00 (4 levels each).
    ''
    ''               color word example: %%0020_3300 = gold on blue
    ''
    ''   CursorPtr = Pointer to 6 bytes which control the cursors:
    ''
    ''               bytes 0,1,2: X, Y, and MODE of cursor 0
    ''               bytes 3,4,5: X, Y, and MODE of cursor 1
    ''
    ''               X and Y are in terms of screen characters
    ''               (left-to-right, top-to-bottom)
    ''
    ''               MODE uses three bottom bits:
    ''
    ''                      %x00 = cursor off
    ''                      %x01 = cursor on
    ''                      %x10 = cursor on, blink slow
    ''                      %x11 = cursor on, blink fast
    ''                      %0xx = cursor is solid block
    ''                      %1xx = cursor is underscore
    ''
    ''               cursor example: 127, 63, %010 = blinking block in lower-right
    ''
    ''     SyncPtr = Pointer to long which gets written with -1 upon each screen
    ''               refresh. May be used to time writes/scrolls, so that chopiness
    ''               can be avoided. You must clear it each time if you want to see
    ''               it re-trigger.
    
      'if driver is already running, stop it
      stop
    
      'implant pin settings
      reg_vcfg := $200000FF + (BasePin & %111000) << 6
     ' need to move reg_vcfg to the hub memory location of cogarray plus $8C
      longmove(cogarray+$8C,@reg_vcfg,1)  
      i := $FF << (BasePin & %011000)
      j := BasePin & %100000 == 0
      reg_dira := i & j
      ' need to move reg_dira to the hub memory location of cogarray plus $84
      longmove(cogarray+$84,@reg_dira,1)
      reg_dirb := i & !j
      ' need to move reg_dirb to the hub memory location of cogarray plus $88
      longmove(cogarray+$88,@reg_dirb,1) 
      'implant CNT value to sync COGs to
      sync_cnt := cnt + $10000
      ' need to move reg_dira to the hub memory location of cogarray plus $90 
      longmove(cogarray+$90,@sync_cnt,1)
      ' screen_base is at $01F4 using F9 so subtract $8 gives $1EC
      ' screenptr is passed to this startup routine (don't confuse with screen_ptr)
      'implant pointers
      'longmove(@screen_base, @ScreenPtr, 3)
      longmove(cogarray + $1EC,@ScreenPtr,3)                ' replaces line above, screen_base, color_base, cursor_base
      'font_base := @font
      longmove(cogarray + $1F8,@font,1)                     ' replaces line above. Location = $200-8 = $1F8
      'implant unique settings and launch first COG
      'vf_lines.byte := vf                                    
      bytemove(cogarray + $1B4, vf,1)                       ' replaces line above, location $1BC - 8 = 1B4, LSB at beginning 
      'vb_lines.byte := vb
      bytemove(cogarray + $9C, vb,1)                        ' replaces line above $A4-8 = $9C, LSB first
      'font_third := 1     
      longmove(cogarray + $1FC,1,1)                         ' replaces line above, $204-8=$1FC, put in value of 1
      'cog[1] := cognew(@d0, SyncPtr) + 1
      cog[1] := cognew(cogarray, SyncPtr) + 1               ' replaces line above
      'allow time for first COG to launch
      waitcnt($2000 + cnt)
    
      'differentiate settings and launch second COG
      'vf_lines.byte := vf+4
      bytemove(cogarray + $1B4, vf+4,1)                       ' replaces line above, location $1BC - 8 = 1B4, LSB at beginning 
      'vb_lines.byte := vb-4
      bytemove(cogarray + $9C, vb-4,1)                        ' replaces line above $A4-8 = $9C, LSB first                                
    
      'font_third := 0
      longmove(cogarray + $1FC,0,1)                         ' replaces line above, $204-8=$1FC, put in value of 0                          
      'cog[0] := cognew(@d0, SyncPtr) + 1
      cog[0] := cognew(cogarray, SyncPtr) + 1               ' replaces line above  
      'if both COGs launched, return true
      if cog[0] and cog[1]
        return true
    
      'else, stop any launched COG and return false
      else
        stop
    
    { for debugging this is a hex dump after values have been implanted in this program
    ' second row is the original (correct) one from chips code.
    ' both of these are the values after the second cog is launched, so vf and vb are different
    0000 0002000091DEBFA01802BC840134FCE41C02BDA01D04BDA01908BC80190ABC80
    0000 0002000091DEBFA01802BC840134FCE41C02BDA01D04BDA01908BC80190ABC80
    
    0020 0138FC80003ABC800436FCE41E40BEA01F42BEA02044BEA021ECBFA022EEBFA0
    0020 0138FC80003ABC800436FCE41E40BEA01F42BEA02044BEA021ECBFA022EEBFA0
    
    0040 18F4FF5823FCBFA001FEFFA0E149BCF80EF0FF580048FCF864FEFFA083017C5C
    0040 18F4FF5823FCBFA001FEFFA0E149BCF80EF0FF580048FCF864FEFFA083017C5C
    
    0060 01020000000400006D0000005000000001D63FFC0802FC2818FEFFA000CE7FFC
    0060 01020000000400006D0000005000000001D63FFC0802FC2818FEFFA000CE7FFC
    
    0080 BE017C5C 0000FF00 00000000 FF040020  4AD21351 03D6FFA0 CEB1FF5C 56D6FFA0  ' lots of diffs here $90
    0080 BE017C5C 0000FF00 00000000 FF040020  C28C030B 03D6FFA0 CEB1FF5C 18D6FFA0  ' this is ok as this is sync_cnt with diff cnt value
                                                                                   ' but at 9C there is a difference too, this is vb -4 which should be $18
                                                                                   
    00A0 CEB1FF5CD9D1BFA0DAD3BFA000DCFFA03CDEFFA0DDD5BFA009D4FF2CDCD5BF80
    00A0 CEB1FF5CD9D1BFA0DAD3BFA000DCFFA03CDEFFA0DDD5BFA009D4FF2CDCD5BF80
    
    00C0 0036FF540038FF5402D8FFA0DFFFBFA000CA7FFC28D6FFA0E8DBBF0007DAFF20
    00C0 0036FF540038FF5402D8FFA0DFFFBFA000CA7FFC28D6FFA0E8DBBF0007DAFF20
    
    00E0 17DAFF29EADBBF800036BF800038BF8001D0FF80ED03BC08E2038C6C94D7FFE4
    00E0 17DAFF29EADBBF800036BF800038BF8001D0FF80ED03BC08E2038C6C94D7FFE4
    
    0100 92D9FFE450D0FF8402DAFFA0DBD7BF0001B6FF8050D67F85DBD9BF0001B6FF80
    0100 92D9FFE450D0FF8402DAFFA0DBD7BF0001B6FF8050D67F85DBD9BF0001B6FF80
    
    0120 EED93F86DBD9BF0001B6FF80B6015C5C01D6FF80EB6BBF5402D87F6101D87F62
    0120 EED93F86DBD9BF0001B6FF80B6015C5C01D6FF80EB6BBF5402D87F6101D87F62
    
    0140 B601485CF1C72361F1C9136104D87F62E2D7ABA0E5D797A002BA5786EB03886C
    0140 B601485CF1C72361F1C9136104D87F62E2D7ABA0E5D797A002BA5786EB03886C
    
    0160 A1DBFFE406B6FF84E9D7BF04E1D7BF60E6D7BF6804D8FFA0E0FFBFA081007C5C
    0160 A1DBFFE406B6FF84E9D7BF04E1D7BF60E6D7BF6804D8FFA0E0FFBFA081007C5C
    
    0180 28FEFFA001CE7FFC80FEFFA000CE7FFC08A0FC28BCD9FFE402BAFF8003BAFFE1
    0180 28FEFFA001CE7FFC80FEFFA000CE7FFC08A0FC28BCD9FFE402BAFF8003BAFFE1
    
    01A0 50D0F380 02D2F380 01DCF380 8BDFFFE4 F0C53F08 00D6FFA0CFB1FF5C83017C5C    ' error 1B4 supposed to implant 13
    01A0 50D0F380 02D2F380 01DCF380 8BDFFFE4 F0C53F08 0DD6FFA0CFB1FF5C83017C5C    ' 2/3 along diff here 00 vs 0D
    
    01C0 01CFFF6CDEFFBFA000CE7FFC18FEFFA000CE7FFC28FEFFA001CE7FFC80FEFFA0
    01C0 01CFFF6CDEFFBFA000CE7FFC18FEFFA000CE7FFC28FEFFA001CE7FFC80FEFFA0
    
    01E0 00CE7FFCCFD7FFE400007C5C  283B0000A8470000F74F00000000080C00B4C404   ' differences here
    01E0 00CE7FFCCFD7FFE400007C5C  8C0C00000C1900005C1900001C03000000000000
    
    0200 800200008006000008100000FCFC0000FFFFFFFF00000002000000010000FFFF
    0200 800200008006000008100000FCFC0000FFFFFFFF00000002000000010000FFFF
    
    0220 030300000301000036C708352C3200009C68FD5C3F61BEA00760FE600378FE2C
    0220 03030000030100000000080C0000103000183C7E00181818003C4281003C4299   ' many diffs here onwards
    
    0240 3079BE680378FE200168FEA01E007C5C025EFE202F33BD50DA32FD801B5EFE28
    0260 2F61BEA0005EBEA0305FBE28C3007C5C2DEDBF680DA6FD50D2AEFD5C2CEDBF68
    0280 12A6FD50D2AEFD5C2DEDBF6CFF5E7E61005FFE74D85EBE680A60FEA0C59AFD5C
    02A0 015EFE292CEDBF74CF96BDA0C69AFD5CA760FEE4D096BDA0C69AFD5CD196BDA0
    02C0 C69AFD5CB788FD5CFA5E7E861600545C00007C5C207C7E612D5B3EF40B60FEA0
    02E0 C59AFD5C10A6FD50D2AEFD5CF2593E61015EFE30CF96BDA0C69AFD5CB860FEE4
    0300 165EFE28FF5F7E6116004C5CFF5EFE6000007C5CCE96BDA0D962BEA012A6FD50
    0320 D2AEFD5CF25B3E61F2593E62C762C2E416627EEC00007C5CC762F2E4C762CEE4
    0340 C762F6E4C762EEE40064FE080064FE280364FE48F165BE800064FEF800007C5C
    0360 00020000C40900000000D8000000D400D200D000D100DB000000D900D700D500
    0380 D3000900600000000000F4F5F0000000F2F3710031000000000000007A007300
    03A0 61007700320000F6000063007800640065003400330000F70000200076006600
    03C0 74007200350000CC00006E006200680067007900360000CD000000006D006A00
    03E0 75003700380000CE00002C006B0069006F0030003900000000002E002FEF6C00
    }    
    
    {
    memory dump from the original vga object - also after values implanted
    0000 0002000091DEBFA01802BC840134FCE41C02BDA01D04BDA01908BC80190ABC80
    0020 0138FC80003ABC800436FCE41E40BEA01F42BEA02044BEA021ECBFA022EEBFA0
    0040 18F4FF5823FCBFA001FEFFA0E149BCF80EF0FF580048FCF864FEFFA083017C5C
    0060 01020000000400006D0000005000000001D63FFC0802FC2818FEFFA000CE7FFC
    0080 BE017C5C0000FF0000000000FF040020C28C030B03D6FFA0CEB1FF5C18D6FFA0
    00A0 CEB1FF5CD9D1BFA0DAD3BFA000DCFFA03CDEFFA0DDD5BFA009D4FF2CDCD5BF80
    00C0 0036FF540038FF5402D8FFA0DFFFBFA000CA7FFC28D6FFA0E8DBBF0007DAFF20
    00E0 17DAFF29EADBBF800036BF800038BF8001D0FF80ED03BC08E2038C6C94D7FFE4
    0100 92D9FFE450D0FF8402DAFFA0DBD7BF0001B6FF8050D67F85DBD9BF0001B6FF80
    0120 EED93F86DBD9BF0001B6FF80B6015C5C01D6FF80EB6BBF5402D87F6101D87F62
    0140 B601485CF1C72361F1C9136104D87F62E2D7ABA0E5D797A002BA5786EB03886C
    0160 A1DBFFE406B6FF84E9D7BF04E1D7BF60E6D7BF6804D8FFA0E0FFBFA081007C5C
    0180 28FEFFA001CE7FFC80FEFFA000CE7FFC08A0FC28BCD9FFE402BAFF8003BAFFE1
    01A0 50D0F38002D2F38001DCF3808BDFFFE4F0C53F080DD6FFA0CFB1FF5C83017C5C
    01C0 01CFFF6CDEFFBFA000CE7FFC18FEFFA000CE7FFC28FEFFA001CE7FFC80FEFFA0
    01E0 00CE7FFCCFD7FFE400007C5C8C0C00000C1900005C1900001C03000000000000
    0200 800200008006000008100000FCFC0000FFFFFFFF00000002000000010000FFFF
    0220 03030000030100000000080C0000103000183C7E00181818003C4281003C4299
    0240 00FF818100FFC3E702060E1E0000001C00000000000000001818181818181818
    0260 0000000018181818000000001818181818181818181818181818181800FFFF00
    0280 663399CC6666666655AA55AA0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F00000000
    02A0 00000000000000000000000000183C3C006666770036367F18187C6600000046
    02C0 000E1B1B0018181C0030180C00060C1800000066000000180000000000000000
    02E0 0000000000004060003E63730010181E003C6666003C66600030383C007E0606
    0300 00380C06007F6363003C6666003C66660000001C000000000060301800000000
    0320 00060C18003C6660003E6763003C6666003F6666003C6663001F3666007F4606
    0340 007F4606003C666300636363003C18180078303000676636000F06060063777F
    0360 00636367001C3663003F6666001C3663003F6666003C6666007E5A1800666666
    0380 00666666006363630066666600666666007F6331003C0C0C00000103003C3030
    03A0 00081C36000000000000000C0000000000070606000000000038303000000000
    03C0 00386C0C0000000000070606001818000060600000070606001E181800000000
    03E0 0000000000000000000000000000000000000000000000000000080C00000000
    0400 00000000000000000000000000000000000000000070181800181818000E1818
    0420 00CEDB73000018187E7E0C087E7E3010181818181818187E81818181BDBDBD99
    0440 81818181BD99BDE73E7E3E1E3E3E3E1C00C0F03000030F0C30F0C0000C0F0300
    0460 00FFFF001818181800FFFF1818FFFF0018F8F818181F1F1818FFFF1800FFFF00
    0480 663399CC6666666655AA55AA0F0FFFFF0F0FF0F00F0F0F0F0F0F00000000FFFF
    04A0 0000F0F000000F0F000000003C181800330000003636367F063C60666630180C
    04C0 0E5B7B330C0000000606060C303030183CFF3C66187E181800000000007E0000
    04E0 0000000030180C067B6B6F67181818186030180C6038606036337F30063E6060
    0500 063E66666030180C6E3C7666667C60601C00001C1C1C00000C060C187E007E00
    0520 30603018301818007B7B3B03667E6666663E66660303036366666666263E2606
    0540 263E260603037363637F63631818181830303333361E3636060646667F6B6363
    0560 6F7F7B7363636363663E06066363637B663E3666061C30661818181866666666
    0580 66666666636B6B363C183C66663C1818180C06430C0C0C0C060C183030303030
    05A0 63000000000000001C3830001E303E333E6666663C6606063E3333333C667E06
    05C0 0C3E0C0C6E333333366E66661C1818187060606066361E36181818183F6B6B6B
    05E0 3E6666663C6666663B6666666E33333337766E063C660C307E0C0C0C33333333
    0600 6666666663636B6B63361C1C666666667E62300C0C060C181818181830603018
    0620 000000007E1818000000000000000000181800003C180000423C0000423C0000
    0640 81FF0000C3FF00000E0602000000000018181818181818180000000000000000
    
    }
    
    PUB stop | i
    
    '' Stop VGA driver - frees two COGs
    
    '  repeat i from 0 to 1
    '    if cog[i]
    '      cogstop(cog[i]~ - 1)
    
    
    CON
    
      #1, scanbuff[128], scancode[128*2-1+3], maincode      'enumerate COG RAM usage
    
      main_size = $1F0 - maincode                           'size of main program
    
      hv_inactive = (hn << 1 + vn) * $0101                  'H,V inactive states
    
    DAT
    
    font  long
    
    long  $0C080000,$30100000,$7E3C1800,$18181800,$81423C00,$99423C00,$8181FF00,$E7C3FF00  'top  ascii 0-7
    long  $1E0E0602,$1C000000,$00000000,$00000000,$18181818,$18181818,$00000000,$18181818
    long  $00000000,$18181818,$18181818,$18181818,$18181818,$00FFFF00,$CC993366,$66666666
    long  $AA55AA55,$0F0F0F0F,$0F0F0F0F,$0F0F0F0F,$0F0F0F0F,$00000000,$00000000,$00000000  ' ascii 24 to 31
    long  $00000000,$3C3C1800,$66666600,$7F363600,$667C1818,$46000000,$1B1B0E00,$1C181800  ' 77666600  to 66666600 for the " character (ascii 32
    long  $0C183000,$180C0600,$66000000,$18000000,$00000000,$00000000,$00000000,$60400000
    long  $73633E00,$1E181000,$66663C00,$60663C00,$3C383000,$06067E00,$060C3800,$63637F00
    long  $66663C00,$66663C00,$1C000000,$00000000,$18306000,$00000000,$180C0600,$60663C00
    long  $63673E00,$66663C00,$66663F00,$63663C00,$66361F00,$06467F00,$06467F00,$63663C00
    long  $63636300,$18183C00,$30307800,$36666700,$06060F00,$7F776300,$67636300,$63361C00
    long  $66663F00,$63361C00,$66663F00,$66663C00,$185A7E00,$66666600,$66666600,$63636300
    long  $66666600,$66666600,$31637F00,$0C0C3C00,$03010000,$30303C00,$361C0800,$00000000
    long  $0C000000,$00000000,$06060700,$00000000,$30303800,$00000000,$0C6C3800,$00000000
    long  $06060700,$00181800,$00606000,$06060700,$18181E00,$00000000,$00000000,$00000000
    long  $00000000,$00000000,$00000000,$00000000,$0C080000,$00000000,$00000000,$00000000
    long  $00000000,$00000000,$00000000,$18187000,$18181800,$18180E00,$73DBCE00,$18180000
    
    long  $080C7E7E,$10307E7E,$18181818,$7E181818,$81818181,$99BDBDBD,$81818181,$E7BD99BD  'middle
    long  $1E3E7E3E,$1C3E3E3E,$30F0C000,$0C0F0300,$00C0F030,$00030F0C,$00FFFF00,$18181818
    long  $18FFFF00,$00FFFF18,$18F8F818,$181F1F18,$18FFFF18,$00FFFF00,$CC993366,$66666666
    long  $AA55AA55,$FFFF0F0F,$F0F00F0F,$0F0F0F0F,$00000F0F,$FFFF0000,$F0F00000,$0F0F0000  ' 00000033 to 00000066 for the " character
    long  $00000000,$0018183C,$00000066,$7F363636,$66603C06,$0C183066,$337B5B0E,$0000000C
    long  $0C060606,$18303030,$663CFF3C,$18187E18,$00000000,$00007E00,$00000000,$060C1830
    long  $676F6B7B,$18181818,$0C183060,$60603860,$307F3336,$60603E06,$66663E06,$0C183060
    long  $66763C6E,$60607C66,$1C00001C,$00001C1C,$180C060C,$007E007E,$18306030,$00181830
    long  $033B7B7B,$66667E66,$66663E66,$63030303,$66666666,$06263E26,$06263E26,$63730303
    long  $63637F63,$18181818,$33333030,$36361E36,$66460606,$63636B7F,$737B7F6F,$63636363
    long  $06063E66,$7B636363,$66363E66,$66301C06,$18181818,$66666666,$66666666,$366B6B63
    long  $663C183C,$18183C66,$43060C18,$0C0C0C0C,$30180C06,$30303030,$00000063,$00000000
    long  $0030381C,$333E301E,$6666663E,$0606663C,$3333333E,$067E663C,$0C0C3E0C,$3333336E
    long  $66666E36,$1818181C,$60606070,$361E3666,$18181818,$6B6B6B3F,$6666663E,$6666663C
    long  $6666663B,$3333336E,$066E7637,$300C663C,$0C0C0C7E,$33333333,$66666666,$6B6B6363
    long  $1C1C3663,$66666666,$0C30627E,$180C060C,$18181818,$18306030,$00000000,$0018187E
    
    long  $00000000,$00000000,$00001818,$0000183C,$00003C42,$00003C42,$0000FF81,$0000FFC3  'bottom
    long  $0002060E,$00000000,$18181818,$18181818,$00000000,$00000000,$00000000,$18181818
    long  $18181818,$00000000,$18181818,$18181818,$18181818,$00FFFF00,$CC993366,$66666666
    long  $AA55AA55,$FFFFFFFF,$F0F0F0F0,$0F0F0F0F,$00000000,$FFFFFFFF,$F0F0F0F0,$0F0F0F0F
    long  $00000000,$00001818,$00000000,$00003636,$0018183E,$00006266,$00006E3B,$00000000
    long  $00003018,$0000060C,$00000000,$00000000,$0C181C1C,$00000000,$00001C1C,$00000103
    long  $00003E63,$00007E18,$00007E66,$00003C66,$00007830,$00003C66,$00003C66,$00000C0C
    long  $00003C66,$00001C30,$0000001C,$0C181C1C,$00006030,$00000000,$0000060C,$00001818
    long  $00003E07,$00006666,$00003F66,$00003C66,$00001F36,$00007F46,$00000F06,$00007C66
    long  $00006363,$00003C18,$00001E33,$00006766,$00007F66,$00006363,$00006363,$00001C36
    long  $00000F06,$00603C36,$00006766,$00003C66,$00003C18,$00003C66,$0000183C,$00003636
    long  $00006666,$00003C18,$00007F63,$00003C0C,$00004060,$00003C30,$00000000,$FFFF0000
    long  $00000000,$00006E33,$00003B66,$00003C66,$00006E33,$00003C66,$00001E0C,$1E33303E
    long  $00006766,$00007E18,$3C666660,$00006766,$00007E18,$00006B6B,$00006666,$00003C66
    long  $0F063E66,$78303E33,$00000F06,$00003C66,$0000386C,$00006E33,$0000183C,$00003636
    long  $00006336,$1C30607C,$00007E46,$00007018,$00001818,$00000E18,$00000000,$0000007E
    
    
    
    {{
    
    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    &#9474;                                                   TERMS OF USE: MIT License                                                  &#9474;
    &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
    &#9474;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation    &#9474;
    &#9474;files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,    &#9474;
    &#9474;modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software&#9474;
    &#9474;is furnished to do so, subject to the following conditions:                                                                   &#9474;
    &#9474;                                                                                                                              &#9474;
    &#9474;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&#9474;
    &#9474;                                                                                                                              &#9474;
    &#9474;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE          &#9474;
    &#9474;WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR         &#9474;
    &#9474;COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,   &#9474;
    &#9474;ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                         &#9474;
    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    }}
    


    Addit: fixed a few lines with the font implants.
      'implant pin settings
      reg_vcfg := $200000FF + (BasePin & %111000) << 6
     ' need to move reg_vcfg to the hub memory location of cogarray plus $8C
      longmove(cogarray+$8C,@reg_vcfg,1)  
      i := $FF << (BasePin & %011000)
      j := BasePin & %100000 == 0
      reg_dira := i & j
      ' need to move reg_dira to the hub memory location of cogarray plus $84
      longmove(cogarray+$84,@reg_dira,1)
      reg_dirb := i & !j
      ' need to move reg_dirb to the hub memory location of cogarray plus $88
      longmove(cogarray+$88,@reg_dirb,1) 
      'implant CNT value to sync COGs to
      sync_cnt := cnt + $10000
      ' need to move reg_dira to the hub memory location of cogarray plus $90 
      longmove(cogarray+$90,@sync_cnt,1)
      ' screen_base is at $01F4 using F9 so subtract $8 gives $1EC
      ' screenptr is passed to this startup routine (don't confuse with screen_ptr)
      'implant pointers
      'longmove(@screen_base, @ScreenPtr, 3)
      longmove(cogarray + $1EC,@ScreenPtr,3)                ' replaces line above, screen_base, color_base, cursor_base
      'font_base := @font
      longmove(cogarray + $1F8,@font,1)                     ' replaces line above. Location = $200-8 = $1F8
      'implant unique settings and launch first COG
      'vf_lines.byte := vf
      i := vf                                    
      bytemove(cogarray + $1B4, @i,1)                       ' replaces line above, location $1BC - 8 = 1B4, LSB at beginning 
      'vb_lines.byte := vb
      i := vb
      bytemove(cogarray + $9C, @i,1)                        ' replaces line above $A4-8 = $9C, LSB first
      'font_third := 1
      i :=1    
      longmove(cogarray + $1FC,@i,1)                         ' replaces line above, $204-8=$1FC, put in value of 1
      'cog[1] := cognew(@d0, SyncPtr) + 1
      cog[1] := cognew(cogarray, SyncPtr) + 1               ' replaces line above
      'allow time for first COG to launch
      waitcnt($2000 + cnt)
    
      'differentiate settings and launch second COG
      'vf_lines.byte := vf+4
      i := vf+4
      bytemove(cogarray + $1B4, @i,1)                       ' replaces line above, location $1BC - 8 = 1B4, LSB at beginning 
      'vb_lines.byte := vb-4
      i := vb-4
      bytemove(cogarray + $9C, @i,1)                        ' replaces line above $A4-8 = $9C, LSB first                                
    
      'font_third := 0
      i := 0
      longmove(cogarray + $1FC,@i,1)                         ' replaces line above, $204-8=$1FC, put in value of 0                          
      'cog[0] := cognew(@d0, SyncPtr) + 1
      cog[0] := cognew(cogarray, SyncPtr) + 1               ' replaces line above  
      'if both COGs launched, return true
      if cog[0] and cog[1]
        return true
    
      'else, stop any launched COG and return false
      else
        stop
    

    Now the screen is the correct color, it is steady but the font data appears to be corrupt

    Very close now!
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2011-03-27 23:13
    Drac, have a look at DOL http://forums.parallax.com/showthread.php?100406-DOL-Dynamic-Object-Loader&p=972330#post972330. It should let you do everything you are doing here but also with spin. The sd driver will need to be updated to a newer version but that shouldn't be too hard. If you have any questions about it send me a pm.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-29 06:34
    stevenmess2004, that looks absolutely fascinating.
    How are you managing to isolate each spin object? I need to check out that code and see how it works.

    Meanwhile, I have finally cracked the vga code.

    This program now loads up Kye's SD driver, which happens to have cog code that I think takes 494 longs. I need to check if it can be padded to 496. It then recycles this cog space to load the keyboad driver, serial driver and the two cogs driving the vga. So already this is saving 8k of hub ram compared with the standard approach.

    See attached.
Sign In or Register to comment.