Shop OBEX P1 Docs P2 Docs Learn Events
Standards for hardware, file types and OS features, please chime in - Page 7 — Parallax Forums

Standards for hardware, file types and OS features, please chime in

123457»

Comments

  • hippyhippy Posts: 1,981
    edited 2008-07-02 17:50
    The string packing is in PinDefs_Library_006.spin as "PUB Pack" - But don't use what's there at present !!!

    Had a design cock-up and have re-written it so encoding is now msb clear, five 5-bit chars then one 6-bit char. This allows names which can be xxxx00 to xxxx39 and also allows numbers $8000_0000 upwards. I have some PowerBasic source as well which matches what the Spin code does ( how I got all those constants worked out to start with ).

    I'll release the latest Pindefs_006.zip in a short while ( wrong OS at present ). Have done some code trimming since the last version and shaved a good few bytes off the size. If you loom in that file ( especially PUB Alias you'll see some nifty footwork tweaking stuff on the stack to get parameter values and set result values without having to pass those down the chain of objects ( less code, less pushes, less time ). This could be applicable to your BIOS.

    I tried similar to what you have but got myself completely twisted in circles. I don't think I've really got to grips with the way Spin does its encapsulation and not being able to import constants from higher objects except at runtime meant I was forever battling Spin to do it how I wanted to.

    I did however have one flash of inspiration when it comes to redirecting output to various devices routed at run time ( necessary for a Basic interpreter and a BIOS using 'file handles' ) and that's to limit the device driver to just one output function - PrintString. That way you're only ever passing string pointers around and processing can then be applied to that pointed to string in any order you want. It's also character-based ( the one character long string ) but try and still think of it as a pointer still, likewise a number is pointed at; just not a very pretty looking or conforming string yet. I found it a convenient way to do ByRef calls without having to think about it. Intermediate processing can use its own buffer and silently swap the return pointer to its own rather than the original ( ideally needs a string malloc ). Not sure if that helps you or if I've explained it that well, but I think the message is "pointers good" smile.gif
  • sploopidysploopidy Posts: 1
    edited 2008-07-02 21:33
    I recently created "PorthOS users" as a group on myspace. If you would like to become a member, just click on the link below and it will take you to the group:


    http://groups.myspace.com/porthos
  • jazzedjazzed Posts: 11,803
    edited 2008-07-03 00:54
    hippy said...
    If you loom in that file ( especially PUB Alias you'll see some nifty footwork tweaking stuff on the stack to get parameter values and set result values without having to pass those down the chain of objects ( less code, less pushes, less time ). This could be applicable to your BIOS.
    Yea, I was scratching my head over that one awhile [noparse]:)[/noparse]·I didn't dig too deep, but if @result is the return code stack position, that opens some interesting possibilities for later. Thanks.
    hippy said...
    I did however have one flash of inspiration when it comes to redirecting output to various devices routed at run time ( necessary for a Basic interpreter and a BIOS using 'file handles' ) and that's to limit the device driver to just one output function - PrintString. That way you're only ever passing string pointers around and processing can then be applied to that pointed to string in any order you want. It's also character-based ( the one character long string ) but try and still think of it as a pointer still, likewise a number is pointed at; just not a very pretty looking or conforming string yet. I found it a convenient way to do ByRef calls without having to think about it. Intermediate processing can use its own buffer and silently swap the return pointer to its own rather than the original ( ideally needs a string malloc ). Not sure if that helps you or if I've explained it that well, but I think the message is "pointers good" smile.gif
    I'll have to give the actual print implementation more thought, but I do have a stdio redirection scheme now [noparse]:)[/noparse] Good ideas there turn.gif

    I've imported the EEPROM and SD card code. My "case server" is optimized for size now. Some testing shows that "if, if, if" beats "case" a little on memory size; probably sucks on performance though so I just left it as case. Had a bunch of extra return := .... there is only one now. Also recalculating pointers for args is expensive, so I just added vars for the first 4 args ....

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-07-03 08:13
    jazzed said...
    On consistent interface, TV/VGA are simple to do, and serial port is a super-set of them. Other devices have different requirements. In the linux world all devices are files and can be used with open, close, select, read, and write; of course there is overhead with that, and I doubt it can be done with Propeller. Even if possible, it would most likely not be welcomed [noparse]:)[/noparse]

    This is basically what the latest version of DOL does but it is a bit of mucking around with the method table and its not really coder friendly unless we have a good pre-processor. I'd post the code but its not quite working yet [noparse]:)[/noparse]. I've basically used a pseudo object tree so that you can have standard method calls for things like input and output that will work with multiple sources. For example you should be able to load a file and have it output sd, screen or serial all from the control of a command line without recompiling anything. You could even start new tv drivers on any group of pins at runtime or another complete sd card driver if you wanted to (completely independent and on a different pin group with the pins selected from the command line). And there is not all that much overhead except that you need to have a sd card and memory manager driver running. Of course, if we had a pre-processor you could simply do something like this but its not as much fun since you can't change things at runtime.

    OBJ
    #ifdef USE_SERIAL
    out : "fullDuplexSerial
    #endif
    
    #ifdef USE_VGA
    out : "tv_terminal"
    #endif
    
    ...and whatever others
    
    PUB start
    #ifdef USE_SERIAL
    out.start(TX_PIN,RX_PIN,BAUD_RATE)
    #else ifdef USE_VGA  'can you do this? I haven't used pre-processor directives enough to know.
    out.start(VGA_BASE_PIN)
    #endif
    out.str(string("Hello world"))
    
    



    With this the pin constants could be set by the ide using either a text configuration file or a gui.

    *New idea if we make a new ide. (possibly without but would need an OS on the propeller and a bit of extra work by the programmer)

    We could have a post processor to put the pin settings at the end of an eeprom file before programming the chip. This would get around needing a whole heap of methods just to set/copy values at startup. It would even work for precompiled eeprom files if they all followed the same standard. The table could be customised for each application by having a simple text file to go along with the application that tells the pre-processor and post-processor what is where. Then the use would be simply
    PUB start
      tv.start(byte[noparse][[/noparse]TV_BASE_PIN])
    
    


    The text config file could be something like this
    TV_BASE_PIN=12
    SERIAL_PIN=14
    
    


    Everything in the config file would be included in the order listed too keep things simple so you would need to remove what you weren't using to save space. We could even write a post processor to run in an OS on the propeller if people wanted it. The standard would just have to list a bunch of standard names so that you didn't have to keep creating the same file over and over. You could even do something like this
    TV_BASE_PIN=default
    SERIAL_PIN=14
    
    


    This file could be put in the same folder as the project. Whenever the post-processor finds a default it looks for that value in a standard library so you don't have to keep re-entering the values. And it would even work for binaries smile.gif.

    Advantages are that it should be easy to use with minimal space and speed impacts however the big disadvantage is that it will require some new tools...

    Post Edited (stevenmess2004) : 7/3/2008 8:20:45 AM GMT
  • hippyhippy Posts: 1,981
    edited 2008-07-03 18:23
    stevenmess2004 said...

    *New idea if we make a new ide. (possibly without but would need an OS on the propeller and a bit of extra work by the programmer)

    We could have a post processor to put the pin settings at the end of an eeprom file before programming the chip. This would get around needing a whole heap of methods just to set/copy values at startup. It would even work for precompiled eeprom files if they all followed the same standard. The table could be customised for each application by having a simple text file to go along with the application that tells the pre-processor and post-processor what is where.

    Excellent idea, I think you've cracked it. It's fired off a neuron so please bare with me because this sounds different to what you propose but it gels at the end ...

    *All* programs at run-time should pull the hardware pin mapping data from top of RAM ( which is where it will be when an Eeprom has just been bootloaded or a program downloaded ) and use that. Doesn't matter how people use that data, directly or by copying to a database, what database format they use, what API they have or use. I'd have that table as hashed pairs; pin name plus pin number used.

    When compiling code the compiler *always* writes the pin information to top of the image. This can be taken from either source code or from an external file specified for the compiler. The user compiling will specify their own hardware they use.

    When bootloading/downloading the top of RAM/Eeprom will be set to what that hardware pins are. Thus compile-download programs work, download to Eeprom then reboot programs work.

    If the .eeprom has been saved to SD Card, the OS which loads it makes sure it doesn't overwrite what's at top of RAM. Thus OS-loaded programs work, using the data which will have been put at top of RAM when the OS itself booted.

    Really it now boils down to specifying what format the data should be at the top of image/Eeprom/RAM and altering the compiler to put that data at the top of image. It is already possible to do this with the PropTool and have it work...

    1) Compile, F8, save .eeprom
    2) Run a utility which puts the pindef data in the .eeprom
    3) Use F8, load the .eeprom, download to RAM/Eeprom

    It's a bit cumbersome and it's also necessary to add some additional code into the image so the PropTool will load it when patched and restore the image to what it should have been to start with.

    But, putting aside the how to of doing it, it's really now a question of what format the data at top of Eeprom should be. My preference would be two longs per entry. The PackedString name as the key value of the data and a long which holds the data. Although a slight over-kill it makes alignment easier, it also allows data other than pins to be stored, ie IP Addresses, MAC Addresses, other preferences. Anything over 32-bits can be stored as multiple parts.

    For the Mk I Propeller, I guess 128 longs would be enough for most platform definitions, 192 longs on the Mk II. This is not a fixed overhead, depends on what the hardware is. It's easy enough to generate 'that won't fit' at compiler or OS loading time, also it's extensible, just takes more image from the top.

    This is how to get the pindef ( hardware pin available for platform ) info into the Eeprom, it doesn't cover getting the pin mapping for whatever an app might want to use. It can be done the same way as I've been doing, write ones own handler which instead of using a local array uses top of RAM ( in fact my code can change easily to do that and going for 32-bit data reduces my code size a lot - I'll do that change before releasing the next version ) or put a table of pins needed within the Image for the app which I think is what stevenmess2004's original idea was.
  • hippyhippy Posts: 1,981
    edited 2008-07-03 18:38
    A technical aside ...

    We don't want any data table being put at the end of an image. That simply slows download to that
    of a 32KB image ( 256KB on a Mk II ).

    The image can however be modified so the data table is after the end of the user program and a
    post-load fixup program included. When booted that fixup program runs, copies the data table to
    end of image, resets other image information to how it should be and restats Cog 0. At that point
    it's as if an unmodified image had been loaded with the data table having magically appeared at
    the top of RAM.

    This was all proven to work when trying to help Phil Pilgrim (?) get data poked into a .eeprom
    and avoid the PropTool rejecting it.
  • jazzedjazzed Posts: 11,803
    edited 2008-07-03 18:53
    hippy said...
    ... I'd have that table as hashed pairs; pin name plus pin number used.
    Funny you mention that. I've been working on a hashtable module for relatively small data-sets (256 or less entries). Having a linear array lookup is not so bad, but with spin's execution time, a large number of lookups can become painfully slow. Just for development speed, I'm implementing a checksum-hash-chained table with mask up to $FF. If you have a better idea for the calculating the hash, let me know. I'm considering the Jenkins hash, but I don't know if it's appropriate for such a small data set.

    I was wondering how you would force the data in a predefined location also, but looks like·that's in the works.

    @Steven, If you want to start an IDE project, it may be time for a dedicated thread. I'm certainly interested; Eclipse might·serve as an appropriate IDE platform. Of course there's nothing wrong with starting from scratch other than time used developing a new IDE.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    Post Edited (jazzed) : 7/3/2008 9:21:26 PM GMT
  • hippyhippy Posts: 1,981
    edited 2008-07-04 00:31
    Here's the latest of my versions attached. A few changes. Had to go easy on using relative to
    @result references because the call depth changes depending on how the call is made, direct
    or through a helper function. Moved the pindefs table to top of memory.

    I did find one useful trick ( also posted to Tricks and Traps )which is to return from deeply
    nested methods by using abort rather than return. This gives quite a saving as all stack un-
    popping is handled within the single abort not fall through returns. See AbortTimeTest.spin
    for demonstration.

    @ jazzed : The @result is very useful, not just for accessing parameters and return results
    on the stack but data in the method call stack frame. This way any method can determine
    its own address, should be handy for function pointers and things ... not correct but the principle is ...

    PRI SomeMethod | me
      me := MyAddress
    
    PRI MyAddress
      return long[noparse][[/noparse] @result - N ]
    
    
    

    Post Edited (hippy) : 7/4/2008 12:37:34 AM GMT
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-07-04 08:01
    Hippy, I haven't had time to look at your code yet but I will tomorrow.

    To get around the loading problems of putting the table at the top of ram why not put it at the bottom right after the header? Since all the spin code is position independent all we should need to do is to move the data and change the pointers to the first object, first var space and the stack. That would get around the size problem and also keep the table in a fixed memory location. Can you change the position of the first object though or is it hard coded into the bootloader?

    @jazzed, I should start a thread but I don't have any time to put into it at the moment [noparse]:([/noparse] and I was thinking more along the lines of Eclipse rather than developing something from scratch. Someone has already done the work to get it running with propellant so that's a good start.
  • jazzedjazzed Posts: 11,803
    edited 2008-07-04 09:41
    Steven,

    Yes, I have a simple spin project in Eclipse using the C/C++ perspective view ... that's where we can use a makefile. It's not as good as the other languages in Eclipse without the features I mentioned before such as ctrl-click on a function name to zoom in on the implementation. I suspect that spin syntax will be a hurdle to overcome; perhaps the parser that was started can help. The other issue is users having cpp, though this is easily solved with Cygwin for PC. For professionals, that's not a problem of course, but no one should be left out.

    I have plenty of time for stuff like this, but I need to work on projects that will eventually create revenue [noparse]:)[/noparse] Maybe there is a way to sell a plug-in, but I doubt anyone here would buy it [noparse]:)[/noparse] I am very spoiled by having done many projects in the Eclipse Java perspective. Having the same for spin would be a great benefit. I'll start an Eclipse thread tomorrow maybe.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • hippyhippy Posts: 1,981
    edited 2008-07-04 17:19
    stevenmess2004 said...
    To get around the loading problems of putting the table at the top of ram why not put it at the bottom right after the header? Since all the spin code is position independent all we should need to do is to move the data and change the pointers to the first object, first var space and the stack. That would get around the size problem and also keep the table in a fixed memory location. Can you change the position of the first object though or is it hard coded into the bootloader?

    The first object and start-up can be moved and that's been the key to this working.

    Unfortunately it seems Spin is not 100% position independent. I thought it was but what I'm seeing with LookUp and LookDown shows it isn't. LookUp and LookDown both provide a 'bale out' address for a match and that's absolute not relative ...

    ====                                  ; PUB Main
    ====                                  ;   result := LookUp( result : "AB" )
    ====                                  ;   result := LookUp( result : "CD" )
    
                                          ALIGN    STACK          ; For S3 
    
          +0000                  VL1:     LONG     0              ; Unexpected Result Variable Used
    
                                          ALIGN    SPIN 
    
    0018         36              S3:      PUSH     1
    0019         38 13                    PUSH     19             ----. $13 + $10 = $23
    001B         60                       PUSH     VL1.LONG           | 
    001C         38 41                    PUSH     65                 |
    001E         10                       LOOKUP                      |
    001F         38 42                    PUSH     66                 |
    0021         10                       LOOKUP                      |
    0022         0F                       LOOKEND                     |
    0023         61                       POP      VL1.LONG       <---'
    
    0024         36                       PUSH     1
    0025         38 1F                    PUSH     $1F            ----. $1F + $10 = $2F
    0027         60                       PUSH     VL1.LONG           |
    0028         38 43                    PUSH     67                 |
    002A         10                       LOOKUP                      |
    002B         38 44                    PUSH     68                 |
    002D         10                       LOOKUP                      |
    002E         0F                       LOOKEND                     |
    002F         61                       POP      VL1.LONG       <---'
    
    0030         32                       RETURN 
    
    



    That's thrown a spanner into a few things I'd been thinking about.

    Not everything's lost though. Although we cannot insert data at the beginning we can put it as close to the end of the actual code as possible. The best place so far is where the stack starts ( header, DAT, code, VAR, stack ) so that minimises the lengthening.

    I've got some test code which does that and is working well. With a small amount of tweaking and a slightly more complicated fixup routine it should be possible to put it where the VAR section is at the end of code which will be the minimal increase in file/download size. Will work on that later.

    It should still be possible to move the vars and stack upwards and that opens the door for injecting permanent code ( position independent Spin or PASM ). That will have uses, such as transparently making Spin use a RAM Spin interpreter rather than ROM - One of my plans now we can do that is a Spin Interpreter where each Cog can run multiple Virtual Spin Cogs in parallel. Providing execution speed isn't important, one could run 8 Spin Cogs plus 7 PASM Cogs on a Propeller !

    The nice thing about this injection technique is it's transparent to the programmer. They code as normal then just run the injector app they need to apply. This is how I'd now look at integrating C with Spin.

    It's a shame that either PropTool nor Propellent give out any symbol or image information because that would make it even more flexible, being able to add post-compilation linking. A Spin program could specify a C subroutine simply by prefixing it's name with "C_" and creating an empty "PRI C_Name(args)" stub. Could still be done with "PRI C_Name(args) / LinkToC(String("Name"),argCount)" but not half as nice, wasteful overhead and an awful lot more work for the linker ( it has to walk the image ).

    Another use for post processing, not particularly needing injection but working at the image level, is code optimisation; disassemble to bytecode, optimise then re-assemble.

    Even with the current limitations it does open the door to a lot of possibilities, and "too much effort" is always offset by desirability and need. Most hacking has been done at source level or at run-time and image manipulation hasn't been appreciated for its full potential.
  • stevenmess2004stevenmess2004 Posts: 1,102
    edited 2008-07-05 00:10
    Isn't the $13 and $1F just the offset from the current pBase?

    From this code from the interperter
    spcurr  if_nc           mov     pcurr,pbase             'set call pcurr (c=0)
            if_nc           add     pcurr,x
    
                            jmp     #loop
    


    It looks like it is and that means that its still position independent.

    Post Edited (stevenmess2004) : 7/5/2008 12:16:13 AM GMT
  • hippyhippy Posts: 1,981
    edited 2008-07-05 03:01
    I see what you mean, if pBase moves with the code then the destinations remain the same.
    Not position independent in way I'd normally use the term but it does work that way if the
    entire object / program is moved.

    Which is what DOL relies on smile.gif I think I was looking at too small a granularity, and had also
    forgotten what I knew. I suppose we're all going to have think about documenting some of
    this fancy footwork one day.
  • vampyrevampyre Posts: 146
    edited 2008-07-08 03:19
    Just wanted everyone to know i havn't abandoned this project, i've just been tied up. Im still working on what i'm now calling the Spring standard - a hardware standard for dummies. I'll have some documentation and examples posted at some point.
  • simonlsimonl Posts: 866
    edited 2008-07-16 09:31
    @hippy: Just got around to reading your 'Platform Indipendent Programming' guide - very good ideas smile.gif

    In that PDF you mention EditPindefs.exe, but I've been unable to find it! Please would you point me in the right direction?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheers,

    Simon
    www.norfolkhelicopterclub.co.uk
    You'll always have as many take-offs as landings, the trick is to be sure you can take-off again ;-)
    BTW: I type as I'm thinking, so please don't take any offense at my writing style smile.gif
  • hippyhippy Posts: 1,981
    edited 2008-07-17 04:56
    EditPindefs.exe ... a figment of my imagination at the present time ... and yours too now smile.gif

    It's on the list of projects to do, but not sure when.
  • simonlsimonl Posts: 866
    edited 2008-07-17 14:03
    ROFL! Thanks hippy smile.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheers,

    Simon
    www.norfolkhelicopterclub.co.uk
    You'll always have as many take-offs as landings, the trick is to be sure you can take-off again ;-)
    BTW: I type as I'm thinking, so please don't take any offense at my writing style smile.gif
Sign In or Register to comment.