Shop OBEX P1 Docs P2 Docs Learn Events
SD2.0 Full FAT32/16 File Sytem Driver - You there! Yes you, viewing this forum. - Page 10 — Parallax Forums

SD2.0 Full FAT32/16 File Sytem Driver - You there! Yes you, viewing this forum.

14567810»

Comments

  • KyeKye Posts: 2,200
    edited 2010-12-13 06:42
    The code I gave you was just to show how to use the function "playWav"... Since you didn't have the file "Music.wav" or "voice.wav" in the root directory of the SD card nothing would play.

    Make a wav file called "music.wav" and put it onthe root directory of the SD card. Make sure then all the pin assignments are good. Then run the code.

    Then remove all the parts you don't need and add in what you do need.
  • Dan EDan E Posts: 61
    edited 2010-12-14 14:26
    I was able to receive sound out my speakers, but just clicking, I made it a loop just to make sure, and the result was a continuous beep. I'm somewhat sure the problem is my stereo amplifier. I received an extension on my school project, so now I have time to get the right amplifier. My previous amp was a crappy one from radioshack.

    I tried searching for the MAX4411ETP headphone driver from the demo board, but I believe they are only sold in large quantities, and to vendors only.

    Any suggestions other than purchasing a demoboard for an amp?

    Thanks,
    Dan.
  • KyeKye Posts: 2,200
    edited 2010-12-14 16:41
    @ DanE - You really shouldn't be using this thread to work with me about your problem. Please make a new thread about your problem and dicuss what issues you are having.

    I say this because this thread is soposed to be able the File system driver... you are hijacking the thread right now.

    If I can answer a question you have I will do it in another thread.

    Thanks,
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-21 17:11
    Hi Kye,

    I am currently working on cog code that can be loaded and reloaded many times, and I would like to use your SD card driver.

    I have rewritten the standard serial driver and the keyboard driver and learned a lot about how to write such code.

    A fundamental concept is that cogs cannot access outside variables - the only variables they can access are passed when the cog is started. The cog then uses 'par' to access these.

    Of course, 'par' could point to an array of 10,000 variables, or it could point to a screen buffer, or maybe it could be just one variable.

    The quick and simple test to see if cog code accesses outside variables is to comment out everything outside the cog code (except the start routine) and see if it will compile with F8.

    Your SD driver is very close and because everything is in groups, I think this may be possible to code.

    Below is your code with almost everything commented out. It fails on 'cardblockarray' which is in the global variables group.

    I think the variables that one needs to look at are from
    ' Data
    down.

    I guess what I am wondering is how many variables get accessed in Spin, as these are harder to find (maybe I need to do the reverse of what I am doing and comment out all the cog/dat section and see how many variables come up in Spin as not being defined.

    Was your code Chip Gracey's style where all common cog/spin variables are in one contiguous block?

    I see you have a lot of variables defined within the 496 longs of the cog code, and maybe one could pass a 'par' to the beginning of this group?

    I'd like to use your SD card driver as a common driver for reloadable Spin/Big Spin/Catalina/BCX Basic as I've found it to be the driver that works with the most SD cards.

    Do you think it would be possible to group together all common spin/cog variables into one block?
  • KyeKye Posts: 2,200
    edited 2011-03-21 18:09
    Use this version. Its the newest and hopefully final version I will have to work on unless I need to add new features. It will be available later from Parallax Inc with extensive documentation when parallax Semi conductor comes out. I really shouldn't be releasing it online... but there's no harm in doing so, actually benefit instead.

    Stop using the 2.0 or 3.0 versions. (The 3.0 version is good - 2.0 is buggy however). This new version is slightly faster and works better under the hood in a few areas. I've had 100% compatibly with everything I've tried - even MMC!!!

    Um, as for commenting stuff out. Look at the "startFATEngine" function. It sets up the driver to run...My code works by putting the addresses of the variables to access in the cog image and then launching it. Works better when using non long variables... and IMOis much cleaner than using the par register.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-21 20:46
    Thanks Kye!

    I'll check out the new code.
    My code works by putting the addresses of the variables to access in the cog image and then launching it. Works better when using non long variables... and IMOis much cleaner than using the par register.

    Ah, that is a useful little insight.

    Ok, one of the things I am attempting to do is to separate out the cog part of code and the hub common variables. Many obex code examples only use a few hub variables - eg 7 longs. But every time a cog is started, it uses 496 longs, most which then goto waste once the cog is loaded (I say mostly, because there is code around to recycle this hub ram, eg in the CP/M emulation).

    So one solution is to load all cogs through the same 496 longs of hub memory. That can save up to 14k of hub ram in a typical program running all 8 cogs.

    But... where do you get the cog data from, as there is no point just getting it from somewhere else in hub. The answer is from an sd card, and here your code becomes central to solving this problem.

    The big problem is the data you load off an sd card. It is no longer cog code with variables all nicely named and easy to reference. It looks more like this (this is a C version, but the principle is the same for Big Spin and Basic):
    	unsigned long serial_cog[511] = 
           {
               0xa0bca9f0, 0x80fca810, 0x08bcaa54, 0xa0fcb201, 
               0x2cbcb255, 0x80fca804, 0x08bcaa54, 0xa0fcbe01, 
               0x2cbcbe55, 0x80fca804, 0x08bcae54, 0x80fca804, 
               0x08bcb054, 0x80fca804, 0x08bcb454, 0xa0bcc05a, 
               0x80fcc010, 0x627cae04, 0x617cae02, 0x689be85f, 
               0x68abec5f, 0xa0fcc833, 0x5cbcbc64, 0x627cae01, 
               0x613cb3f2, 0x5c640016, 0xa0fcb809, 0xa0bcba58, 
               0x28fcba01, 0x80bcbbf1, 0x80bcba58, 0x5cbcbc64, 
               0xa0bca85d, 0x84bca9f1, 0xc17ca800, 0x5c4c001f, 
               0x613cb3f2, 0x30fcb601, 0xe4fcb81e, 0x28fcb617, 
               0x60fcb6ff, 0x627cae01, 0x6cd4b6ff, 0x08bcabf0, 
               0x80bcaa5a, 0x003cb655, 0x84bcaa5a, 0x80fcaa01, 
               0x60fcaa0f, 0x083cabf0, 0x5c7c0016, 0x5cbcc85e, 
               0xa0bca9f0, 0x80fca808, 0x08bcaa54, 0x80fca804, 
               0x08bcac54, 0x863caa56, 0x5c680033, 0x80bcac60, 
               0x00bcc256, 0x84bcac60, 0x80fcac01, 0x60fcac0f, 
               0x083cac54, 0x68fcc300, 0x2cfcc202, 0x68fcc201, 
               0xa0fcc40b, 0xa0bcc7f1, 0x627cae04, 0x617cae02, 
               0x6ce0c201, 0x29fcc201, 0x70abe85f, 0x7497ec5f, 
               0x80bcc658, 0x5cbcc85e, 0xa0bca863, 0x84bca9f1, 
               0xc17ca800, 0x5c4c004d, 0xe4fcc446, 0x5c7c0033
           };
    

    I agree with you that 'par' may not be the most efficient, as you need some precious cog code to then move all the variables to where they are needed. I think your method is going to save some cog space - and I like that!

    eg - this is the beginning of the standard serial driver.
    entry                   mov     t1,par                'get structure address
                            add     t1,#4 << 2            'skip past heads and tails
    
                            rdlong  t2,t1                 'get rx_pin
                            mov     rxmask,#1
                            shl     rxmask,t2
    
                            add     t1,#4                 'get tx_pin
                            rdlong  t2,t1
                            mov     txmask,#1
                            shl     txmask,t2
    
                            add     t1,#4                 'get rxtx_mode
                            rdlong  rxtxmode,t1
    
                            add     t1,#4                 'get bit_ticks
                            rdlong  bitticks,t1
    
                            add     t1,#4                 'get buffer_ptr
                            rdlong  rxbuff,t1
                            mov     txbuff,rxbuff
                            add     txbuff,#16
    

    With 8000 longs in hub ram for a program, and only 496 in a cog, it makes more sense to me to put this sort of data manipulation in a program in Hub (ie in Spin, or C or whatever).

    So... I think you might be onto something with your solution that pokes data in directly.

    I wonder if this leads next to a discussion about some sort of standard?

    Where would you put your variables?

    1) Put them at the beginning of the cog code, with a jmp to the code?
    2) Put them at the end of the cog code?

    I think they are more commonly placed at the end, but this sort of thing could be flexible.

    But how does the cog code know where the variables are? (I'm thinking about the example of a piece of standalone cog code that has been compiled with an absolute minimal bit of startup code)
    CON
      _clkfreq = 80_000_000
      _clkmode = xtal1 + pll16x
    
    PUB Main
        coginit(1,@cogstart,0)  ' cog 1, cogstart, dummy value
    
    DAT
                      org 0
    cogstart          wrbyte  testvalue, testvariable ' test value A
                      jmp #cogstart
    
    testvariable      long    5000           ' test memory location 5000
    testvalue         long    65             ' ascii A
                      fit 496
    

    Of course, in this example, it knows where its own internal variables are. And if you add more code, it just moves them down a bit to make room.

    But then how does the calling code know where the variables are? All the calling code has is access to that array of long data.

    Is there a way of padding cog code?

    eg
    DAT
     myprogram code
      pad to long 400
      variables from 400 to 496
    

    Could we use ORG 400 to do the padding?

    Addit: the manual suggests maybe you can use ORG, but testing this does not seem to work
    CON
      _clkfreq = 80_000_000
      _clkmode = xtal1 + pll16x
    
    PUB Main
        coginit(1,@cogstart,0)  ' cog 1, cogstart, dummy value
    
    DAT
                      org 0
    cogstart          wrbyte  testvalue, testvariable ' test value A
                      jmp #cogstart
    
                      org 400
    
    testvariable      long    5000           ' test memory location 5000
    testvalue         long    65             ' ascii A
                      fit 496
    

    If this does not work, maybe it is easier to put a jmp as the first instruction, then put the data at the beginning of the code. Then the calling spin/C code will know that long 0 is the jmp, and it knows how long the variables are, so it knows how many and where to poke the data?
  • KyeKye Posts: 2,200
    edited 2011-03-22 07:27
    There's just some longs in the bottom of the cog image that you set equal to addresses. Note I also use the par register too but only for one variable.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-03-22 08:02
    Kye:
    Why not use a hidden file as the first entry in each directory to support long file names? This solution was very common before the LFN extensions. I know that it is a bit non standard, though if it is just used on the Prop what difference does it make, and it means that you do not have to worry about the FAT Patent. Just have an entry for each file in a form similar to:

    MYTESTF.EXT : " My test file.ext"

    If you keep the file containing the long names sorted to the same order as the entries in the directory, there would not be to much of a speed hit.
  • KyeKye Posts: 2,200
    edited 2011-03-22 13:40
    My driver is just a library to assist you in doing just that. I'm not focused on the implementation. If you need LFNs do what you describe.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2011-03-22 14:33
    Just trying to help. I am trying to write all my own code. Thank you though.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-22 16:01
    Thanks Kye. So three is one PAR - I'll need to check that one.

    On another thread there has been some very helpful advice on ORG and it looks like one way to place variables in known places is to put the variables before the cog code. Then put a jmp as the first instruction.

    Then a calling program knows where the variables are, even if the cog code was loaded off a file or from external memory.

    I'll try reordering the cog code and see if this works!
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-23 03:37
    Kye, over on this thread http://forums.parallax.com/showthread.php?130482-How-does-ORG-work Ariba has come up with a clever way to pad out the middle of a cog program so that the code goes in from zero up, and the data fits from 496 down.

    fti496 is very useful here and there is also the possibility that the code and data overwrite each other.

    The important number here is the number of longs in the data section. Too many and it won't fit in 496 longs. Too few and it gives another error - code >32k.

    So I tried adding such a padding array into the middle of the sd driver code:
        long $FFFFFFFF[386-$]  
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    '                       Data
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    

    and then by a process of trial and error worked out that only a value of 386 works. I am guessing that this means there are 496-386=110 longs in the data section.

    But it only works with a value of 386. Can I assume from this that the cog code is almost full, ie within one long of being filled up?
  • KyeKye Posts: 2,200
    edited 2011-03-23 07:30
    Yeah, its almost full. Ya know, if you just read the ASM code and click on the variable names using the propeller tool it will tell you the address of the last "res" and "long" inside the cog. But, yeah, the cog is almost full. Count the instructions by hand if you need too.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-23 15:53
    Clicking on the variable names? Hey, that works! Just hit F9 first. Thanks!

    I think I might write a demo cogjects program in Spin. I have one in C but I think it might be a simpler demo to do one in Spin. The Fat driver will end up at the core of this program because the very first thing it needs to do is to load cog code off the sd card. My vague idea here is that if we can save 14k of hub ram then we could write bigger programs without needing external memory. BRB!
Sign In or Register to comment.