Shop OBEX P1 Docs P2 Docs Learn Events
PropBasic: SD Card — Parallax Forums

PropBasic: SD Card

VonSzarvasVonSzarvas Posts: 3,262
edited 2010-09-24 08:23 in Propeller 1
OK, So here it is "SDplay.pbas" !

I have moved the core code into sd.lib

Functions currently included are:

SD_OPEN
SD_READID
SD_READSIZE
SD_READ <sectoraddr>
SD_WRITE <sectoraddr>
SD_CLOSE

BB_PUT <index> - Helper routine to pack 512 bytes into 128 longs; needed as COG limit is 496 longs without LMM!
BB_GET <index>

Assumes you have a serial terminal connected at 57600 on pin 30, and the SD card reader attached according to the pins in SDplay.pbas

Run the program ( a 2500ms delay at the start is to allow me time to click Enable on the PST after upload! )

Then the PST will blank and prompt you to insert card.

A screenshot of what to expect is attached, along with the all files you need. I am attaching 2 files by JonnyMac (delays.lib, serial.lib) without his permission, so hopefully I will not get beaten!

Note, I had the lib files in a subfolder "Library". You might need to check the LOAD statements in SDplayXX.pbas if you store your libs elsewhere!

As said before, the concept here is to provide mass storage (ala EEprom). It is not a FAT based library. This lib will be ideal for dataloggers who would have a dedicated PC program to read back the data and stick into a spreadsheet or database for analysis. (I could write the necessary program if someone needs it). -- OR just use it as cheap mass storage on your Propeller project and never move the SD card to your PC!

Finally, this is still a work in progress. I have more methods to add and no doubt stuff to improve.

If you use this, please do send feedback good or bad (especially bad!). I really would like to fix any bugs, and the more cards that can be tested the better!

___________________________________________________________________________________________________

Release History:

2010.Sep.24 - sd.lib updated to fix misreading of the card multiplier (thanks to MAX72)

2010.Sep.14 - Modified blocksize to always be 512 bytes/sector and calculate totalsectors correctly (as we always read/write in 512byte blocks, regardless of the card block size)

2010.Sep.09. - 1st Version
«1

Comments

  • RsadeikaRsadeika Posts: 3,818
    edited 2010-05-20 21:43
    Looks good Maxwin! I have not run the code just yet, I am still looking at the code. In your pin assignments, what does SD_CARDINPIN do? I have a uController.com SD adapter, and it does not have a pin for that, it has the other pins. If it just tells you that a card is inserted, then I can get around that because the adapter has an LED that visually shows that a card is inserted. But, if you are relying on that for some other purpose, then maybe a detailed explanation maybe in order. More after I run the program.

    Ray
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-05-21 04:54
    Ray, the SD_CARDINPIN is connected to the switch that detects the card. (As you correctly suspected!).

    If you are sure the card is inserted before running the code, the card detection could be removed. Or maybe better, just connect an external switch? If you have the PPDB you could use one of the switches available onboard?
  • RsadeikaRsadeika Posts: 3,818
    edited 2010-05-21 13:19
    @Maxwin, I had a chance to run the program, and I get a line of 'FF'. I have to make the assumption that it is displaying the contents, which happens to be empty. Now that Bean created the LOAD function to read in files as if they were libs, I will have to think about your program, in terms of being a lib file. Now we are all waiting for the heavy duty stuff like create, delete ...

    Ray
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-05-21 13:39
    rsadeika: The line of FF's might be an error. Do you get to the end of the Main program? It should count up through each section.. 1,2,3,4,End.
    If not, where are you getting stuck?

    ps. At my desk now working on putting together the "heavy duty" stuff! Kids allowing, I might even post an update tonight.
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-05-21 13:48
    ... here is a screenshot of what the SDplay5 output should look like on PST.

    I have tested with a 265mb sandisk, and a 2gb kingston.

    I suspect the line of FF's means you are getting stuck somewhere.... Perhaps try again or with a different card - or triple check the connections !
    898 x 638 - 40K
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-09 01:47
    Just a little update...

    I started back on the SDplay in the last few days. All is working... now I am quickly learning how to put a library together and also just finished some helper routines for put/get of the 512 byte blocks in a single cog (rather than using bytes in hub).

    As a little taster, below is the write routine!

    I will post the full library over the weekend.

    FUNC SD_WRITE
    
            ' __param1 is the sector address to write to (0 is reserved, 1 onwards only!)
            ' __param2 is reference to the array holding 512 bytes to write
    
    
            sd_write_status  VAR     LONG = 1
            sd_write_tmp     VAR     LONG
            sd_write_tries   VAR     LONG
    
    
            ' Wait until card is idle
            sd_write_tmp = WAITFORNZ
    
    
            ' Send write command (CMD24 = CMD_WRITE_SINGLE_BLOCK)
            sd_write_tmp = SHOUTCMD 24, __param1   ' <param = sector addr>
    
    
            IF sd_write_tmp = 0 THEN              ' Card ready for write
    
                    LOW SD_CSPIN
    
                            SHOUT $FF               ' Send byte before start token
                            SHOUT $FE               ' Start block token
    
                            ' Actual write - replace with buffered 512 bytes after demo
                            SHOUT $35, 512          ' Sends lots of 5's!
    
                            ' We should send a 16byte CRC after the data.
                            ' It is ignored by the device, so can be any value.
                            SHOUT $95, 2
    
                            sd_write_tmp = SHIN              ' Should be write result
                            
                            sd_write_tmp = sd_write_tmp & 14
                            sd_write_tmp = sd_write_tmp >> 1
    
                            IF sd_write_tmp <> 2 THEN sd_write_return       ' Failed!
    
                            SHOUT $FF, 10           ' Send 10 clocks after write ?
    
                            ' Wait until card is idle
                            sd_write_tmp = WAITFORNZ
    
    
                    HIGH SD_CSPIN
    
                    sd_write_status = 0      ' All OK !
    
            ENDIF
    
            sd_write_return:
            RETURN sd_write_status
    
      ENDFUNC
    
  • BeanBean Posts: 8,129
    edited 2010-09-09 04:16
    Maxwin,
    I'm a little concerned about this line in your code:

    sd_write_tmp = SHOUTCMD 24, __param1 ' <param = sector addr>

    I don't think it will work right, because __param1 will get set to 24, then __param2 will get set to __param1 (which was already assigned the value of 24).

    You should see something like this in the PASM code:

    mov __param1,#24
    mov __param2,__param1

    The easiest way to avoid this would be to use sd_write_tmp to hold the value in __param1.

    sd_write_tmp = __param1
    sd_write_tmp = SHOUTCMD 24, sd_write_tmp

    Keep up the good work.

    Bean
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-09 05:29
    Thanks for the check. I think some "wires crossed", as SHOUTCMD is a SUB which is called and I pass in 2 args (in this case 24 and the value of __param1)

    This is the PASM around that point of the code:
    mov           __param1,#24                 '        sd_write_tmp = SHOUTCMD 24, __param1   ' <param = sector addr>
                      mov           __param2,__param1           
                      mov           __paramcnt,#2               
                      jmp           #_LMM_CALL                  
                      long          @SHOUTCMD_ret - @__Init     
                      long          @SHOUTCMD - @__Init         
                      mov           sd_write_tmp,__param1       
    
    
    

    .. anyhow it works ok so I won't fiddle with it just yet !!

    Cheers!
  • BeanBean Posts: 8,129
    edited 2010-09-09 08:08
    Well if it's working, it is just by "happy accident".

    The first instruction put the value 24 into __param1, then the value in __param1 is loaded into __param2. So __param2 will ALWAYS be 24 instead of what was originally in __param1.

    Bean
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-09 08:57
    ...ah, the penny just dropped..

    It was working when called from COG code, but at the moment I am moving everything to a lib and SUB code, with nice little methods like "SD_OPEN" and "SD_READID"... and of course it means I am now calling a sub from a sub, so the __params would be common.

    Thank you for spotting this! I suspect that might have kept me up late!
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-09 13:21
    Latest version of sd.lib moved to first post in this thread.
  • $WMc%$WMc% Posts: 1,884
    edited 2010-09-09 16:49
    Maxwin:
    '
    Excellent work Dude!!!
    '
    PropBasic is getting better and better!!!
    '
  • BaggersBaggers Posts: 3,019
    edited 2010-09-10 01:35
    Excellent work Maxwin, I was going to look at it, but have been too busy again lately, so you beat me to it, nice work, as PropBasic was needing an SD lib, so Kudos to you :)
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-10 07:15
    Thanks guys!

    Have anyone tried and had success running the code ? Would be good to hear which cards are working (or maybe not!)

    So far I tested:

    1. "Old" 256mb sandisk sd card
    2. 2GB kingston microsd card

    Do not have anything bigger than 2GB, so not sure what would happen there.
  • max72max72 Posts: 1,155
    edited 2010-09-10 14:27
    I had not time to test it yet, but I'll try is ASAP
    Is the driver requiring pull up resistors?
    Massimo
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-11 00:41
    max72:

    I used the circuit shown here (schematic on last page), which does include pull-ups:

    http://www.parallax.com/Portals/0/Downloads/docs/prod/comm/32313-SDCardAdapter-v1.0.pdf
  • max72max72 Posts: 1,155
    edited 2010-09-11 08:09
    Ok,
    my SD card with pull ups is on the Garda lake for the Centomiglia (witout me!!!), so I only have hand soldered veroboard versions with no pullups around.
    I'll give it a try as soon as I can nonetheless.

    Massimo
  • max72max72 Posts: 1,155
    edited 2010-09-13 04:45
    I tested the routine with ucontroller's board.
    I had to change the code because I have not the "inserted" pin, so I disabled the test routines in the main file and in the lib.

    This is the output:

    Insert card : Card inserted.
    Card name=SD256 ,Serial number=1615369124
    Blocksize=512 ,Totalsectors=988160 ,Totalcapacity=505937920
    -- Data Written OK! --
    -- Data Read OK! --
    20 bytes of data back from card:
    ABCDEFGHIJKLMNOPQRST
    End.

    How can I create a test file and fill it with some text?

    I'll try to test it with other cards, and with a no pull-up SD reader.

    Massimo
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-13 05:02
    Hi Massimo!

    Thanks for posting the output. I will need to check over the routine, as your Totalcapacity reading would imply around 500MB card, whereas your card name suggests 256MB. I suspect your card name is correct, as that is an ASCII field.. I will go over my maths...

    Apart from that, you do not "create a test file". You simply read/write from sectors in 512 byte blocks. It is up to your program how you do it, but it is very simple. Just populate the bytebuffer with 512 bytes, then use SD_WRITE <sector number>, from 0 to 988160 (according to your card output).

    Then to read back, call SD_READ <sector number>, and then you will find the contents (512 bytes) in the bytebuffer.

    Will post back later on once I check the Totalcapacity calculation...
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-14 01:59
    Massimo: OK, I checked again, and I always get the correct readings on the few cards I have available to me!

    May I ask:

    1. What type/brand of card you are using ?

    2. If you read the card into the PC (use freeware HxD for example. There is an "Extras" menu to open the disk. Then at top right it will report the total sectors in your card. Also, as you scroll down the card data you can clearly see the per-sector byte size)

    Does it match what my lib reports? Your reading of 988160 total sectors seems high, unless you have a card which uses 256byte sectors perhaps...

    3. Could you try a different card ?

    Thanks !
  • max72max72 Posts: 1,155
    edited 2010-09-14 03:13
    Hi,
    it is a Sandisk 256Mb card.
    At the moment I have not other SD cards available (or free for testing).
    From HxD the sectors count is 494080 and not the 988160 shown at the terminal.

    I retested the card and reformatted it, but with not success.

    I'll test other SD cards as soon as possible.

    Massimo
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-14 03:35
    In the HxD, if you scroll down and check the left hand column (offset), where does your last offset for Sector0 end... 1F0 ?

    -- Also, if you use my lib to write a block of ZERO into the first sector (SD_WRITE 0), does that fix it ?
  • max72max72 Posts: 1,155
    edited 2010-09-14 07:48
    Maxwin wrote: »
    In the HxD, if you scroll down and check the left hand column (offset), where does your last offset for Sector0 end... 1F0 ?

    -- Also, if you use my lib to write a block of ZERO into the first sector (SD_WRITE 0), does that fix it ?

    The Sector 0 ends at 1F0.

    I wrote 0 to the first sector. result is the same, while from the PC I wasn't able to access the card, I had to reformat it.

    I have a couple of old small card (the ones include in digital cameras). They are a sitecom 128Mb and a Canon 16 Mb:

    ? - SDplay -
    Insert card : Card inserted.
    Card name=128MB ,Serial number=269180828
    Blocksize=512 ,Totalsectors=488960 ,Totalcapacity=250347520
    -- Data Written OK! --
    -- Data Read OK! --
    20 bytes of data back from card:
    ABCDEFGHIJKLMNOPQRST
    End.



    ? - SDplay -
    Insert card : Card inserted.
    Card name=S016B ,Serial number=997232359
    Blocksize=512 ,Totalsectors=232960 ,Totalcapacity=119275520
    -- Data Written OK! --
    -- Data Read OK! --
    20 bytes of data back from card:
    ABCDEFGHIJKLMNOPQRST
    End.

    Massimo
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-14 08:10
    So, your sectors are identified as 512 bytes long by HxD. Good so far... :)

    Writing 0's to the first sector would wipe out the FAT indexes, so your PC would no longer recognise the format of the card (of course a re-format puts it back). I was just curious if that made a difference in your case (OK, we can ignore that red herring!)

    I can see your output above on the 2 different cards has the same symptoms. I am beginning to wonder if there was a gremlin in the first published version, or perhaps something you changed might have impacted something... Could I ask you to try re-downloading the sd.lib and re-try ?

    I have just uploaded the latest version to post #1 in this thread.

    Thanks for your efforts!
  • max72max72 Posts: 1,155
    edited 2010-09-14 08:55
    I redownloaded the Sd.lib file.
    Only changes I made are changing pin constants, and commenting out the check of the SD pin, both in the main file and in the lib file.
    Here we have the new dump (16, 128 and 256 Mb cards):

    ? - SDplay - _
    Insert card : Card inserted.
    Card name=S016B ,Serial number=997232359
    Blocksize=512 ,Totalsectors=232960 ,Totalcapacity=119275520
    -- Data Written OK! --
    -- Data Read OK! --
    20 bytes of data back from card:
    ABCDEFGHIJKLMNOPQRST
    End.?

    - SDplay -
    Insert card : Card inserted.
    Card name=128MB ,Serial number=269180828
    Blocksize=512 ,Totalsectors=488960 ,Totalcapacity=250347520
    -- Data Written OK! --
    -- Data Read OK! --
    20 bytes of data back from card:
    ABCDEFGHIJKLMNOPQRST
    End.?

    - SDplay -
    Insert card : Card inserted.
    Card name=SD256 ,Serial number=1615369124
    Blocksize=512 ,Totalsectors=988160 ,Totalcapacity=505937920
    -- Data Written OK! --
    -- Data Read OK! --
    20 bytes of data back from card:
    ABCDEFGHIJKLMNOPQRST
    End.

    Massimo
  • VonSzarvasVonSzarvas Posts: 3,262
    edited 2010-09-14 09:57
    OK, so this is rather wierd!

    I am attaching a debugging version of sd.lib and SDplay.... could you run them on one of your cards and post the results?

    The extra data will show me the "raw" config coming from your cards, so that should help solve it.

    Thanks for sticking with this.

    In the meantime, I will go hunting the house for some more cards to try...
  • max72max72 Posts: 1,155
    edited 2010-09-14 13:49
    I'm away, but I'll test it tomorrow.

    Massimo
  • whiteoxewhiteoxe Posts: 794
    edited 2010-09-15 06:52
    hI, CAN AN sd CARD be put into other thigs or circuis and retrieve the data.

    Could anSD card data be accesses by a keypad with an lcd ?
  • HarleyHarley Posts: 997
    edited 2010-09-15 10:56
    Where does one find PropBASIC? I looked at OBEX and only find snippets and for OLED.

    I would like to have some OS with SD card which I can adapt to use with a 4.3" LCD (Rayman's color touchscreen LCD) and a keyboard. What I've found so far only uses FDS thus requires some sort of other device to display results. The LCD allows display right with the Prop; keyboard usually is a separate though cabled item. I wouldn't want a touchscreen type of 'keyboard', though it probably could be implemented if sufficient RAM allows that code.
  • SapiehaSapieha Posts: 2,964
    edited 2010-09-15 11:08
    hi Harley
    LOOK on this thread.

    Download PropBASIC here... 00.01.02 July 20, 2010
    Harley wrote: »
    Where does one find PropBASIC? I looked at OBEX and only find snippets and for OLED.

    I would like to have some OS with SD card which I can adapt to use with a 4.3" LCD (Rayman's color touchscreen LCD) and a keyboard. What I've found so far only uses FDS thus requires some sort of other device to display results. The LCD allows display right with the Prop; keyboard usually is a separate though cabled item. I wouldn't want a touchscreen type of 'keyboard', though it probably could be implemented if sufficient RAM allows that code.
Sign In or Register to comment.