Shop OBEX P1 Docs P2 Docs Learn Events
Chapter 9 Official Guide, changing the base pin on the SD card — Parallax Forums

Chapter 9 Official Guide, changing the base pin on the SD card

SteveWoodroughSteveWoodrough Posts: 190
edited 2012-03-07 18:02 in Propeller 1
I'm going through the exercise in Chapter 9 of the Official Guide, and I'm having trouble changing the SD card pin outs to work with my setup. If I use the base pin of 2 everything works just fine. But if I try to change the base pin to something other than 2 the SD card will not mount and log data. I think the reason is the given pin sequece is somehow backwards from the logic. Here are the actual pin numbers that work:

Pin 2 CS
Pin 3 DI
Pin 4 SCLK
Pin 5 DO

This sequence works just fine and creates a data table log on the SD card when the base pin is specified to be 2. What is strange is that per the documentation in the code, DO should be the base pin followed by SCLK, DI and CS. So for some reason the code works as published but when I try to change the pin selections, it does not work.

Below is the main code and the two other referenced objects.

Thank You
Steve



''***************************************
''*  Main Sensor Logger code            *
''*  Author: Joshua Hintze              *
''*  Copyright (c) 2009                 *
''***************************************

CON

  'Set operating speed to 80 MHz per core thus we operate at ~20 MIPS 1/4 of clock rate
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000

  START_LOGGING_SWITCH = 16
  STOP_LOGGING_SWITCH = 17
  
  LED_MOUNT_SD = 18
  LED_GPS_SATS = 19
  LED_HEART_BEAT = 20
  LED_PRESS_GOOD = 21
  LED_RECORDING = 22


OBJ

  text  : "TV_Text"             ''TV Terminal is used for debug
  gps   : "GPS_IO_mini"         ''Simple GPS COG serial parser. Reads in NMEA sentences 
  sdfat : "fsrw"                ''Fat16 SD card object
  alt   : "abs_pressure_01"     ''Absolute pressure sensor
  conv  : "numbers"             ''Conversion for string to number and vice versa
  
var
   byte tbuf[20]
   long stringptr
   long stringlen
   long sdmounted
   long sdrecording        
  
   
pub main | gmt, r

  'Start the required cogs
  gps.start(1, 9600)            'Initialize on pin 0 at 4800 baud                                           
  text.start(12)                'TV terminal begins at pin 12
  alt.start                     'Initialize and run the alt sensor (ABS pressure)
  conv.init                     'Initialize the conversion object

  sdrecording := 0              'Start off not recording until a button is pressed

  {
    The order of the pins goes as follows:
    FirstPin = DataOut from SD card (MISO on propeller)
    NextPin = Clk for the SD card (SCLK) 
    NextPin = DataIn to the SD card (MOSI on propeller)
    NextPin = ChipSelect (Controls SD card CS) 
  }

  dira[18..23]~~                'Flag LEDs to show we have are succsessfull
  outa[18..17]~~                'LEDs on mean OK

  if \sdfat.mount(2) <> 0            'Mount SD card starting on pin 2
    outa[LED_MOUNT_SD] := 0
    text.str(string(13,"Failed to mount SD"))
    sdmounted := 0
  else
    sdmounted := 1
    text.str(string("Mounted.", 13))
    text.str(string("Dir: ", 13))
    sdfat.opendir
    repeat while 0 == sdfat.nextfile(@tbuf)
      text.str(@tbuf)
      text.out(13)
    text.str(string("That's the dir", 13))
    text.out(13)

  'Pause for one second
  waitcnt(1*clkfreq + cnt)

  repeat r from 0 to 16
    text.out(13)


  ' Start drawing to the TV  
  repeat
    ' Set the terminal X and Y position back to 0,0
    text.out($0A) ' Pass in the column flag
    text.out(0)   ' Now the X position = 0
    text.out($0B) ' Pass in the row flag
    text.out(0)   ' Now the Y position = 0  
    text.str((string("Latitude ")))
    text.str(gps.N_S)
    text.out($20)
    text.str(gps.latitude_degpart)
    text.out($20)
    text.str(gps.latitude_minpart)        
    text.out(13)
    text.str((string("Longitude ")))
    text.str(gps.e_w)
    text.out($20)    
    text.str(gps.longitude_degpart)
    text.out($20)
    text.str(gps.longitude_minpart)        
    text.out(13)
    text.str((string("GPS Altitude ")))
    text.str(gps.GPSaltitude)
    text.out(13)
    text.str((string("Speed ")))
    text.str(gps.speed)
    text.out(13)
    text.str((string("Satellites ")))
    text.str(gps.satellites)
    text.out(13)
    text.str((string("Time GMT ")))
    text.str(gps.time)
    text.out(13)
    text.str((string("Date ")))
    text.str(gps.date)
    text.out(13)
    text.str((string("Heading ")))
    text.str(gps.heading)
    text.out(13)
    text.str(string("temp "))
    text.dec(alt.get_temperature)
    text.out(13)
    text.str(string("pressure "))
    text.dec(alt.get_pressure)    
    text.out(13)
{    text.dec(alt.get_c1)
    text.out($20)
    text.dec(alt.get_c2)
    text.out($20)
    text.dec(alt.get_c3)
    text.out($20)
    text.dec(alt.get_c4)
    text.out($20)
    text.dec(alt.get_c5)
    text.out($20)
    text.dec(alt.get_c6)
    text.out(13)
    text.dec(alt.get_d1)
    text.out($20)    
    text.dec(alt.get_d2)
    text.out($20)    
    text.dec(alt.get_calib_temp)
    text.out($20)    
    text.dec(alt.get_dt)
    text.out($20)    
    text.out(13)    
}

    'now output to the file the values we have
    if sdrecording == 1
      \sdfat.sdstr(gps.latitude_degpart)
      \sdfat.sdstr(string(", "))
      \sdfat.sdstr(gps.latitude_minpart)
      \sdfat.sdstr(string(", "))      
      \sdfat.sdstr(gps.N_S)
      \sdfat.sdstr(string(", "))
      \sdfat.sdstr(gps.longitude_degpart)
      \sdfat.sdstr(string(", "))
      \sdfat.sdstr(gps.longitude_minpart)
      \sdfat.sdstr(string(", "))      
      \sdfat.sdstr(gps.e_w)
      \sdfat.sdstr(string(", "))
      \sdfat.sdstr(gps.GPSaltitude)
      \sdfat.sdstr(string(", "))
      \sdfat.sdstr(gps.speed)
      \sdfat.sdstr(string(", "))        
      \sdfat.sdstr(gps.satellites)
      \sdfat.sdstr(string(", "))        
      \sdfat.sdstr(gps.time)
      \sdfat.sdstr(string(", "))        
      \sdfat.sdstr(gps.date)
      \sdfat.sdstr(string(", "))        
      \sdfat.sdstr(gps.heading)
      \sdfat.sdstr(string(", "))        
      \sdfat.sddec(alt.get_temperature)
      \sdfat.sdstr(string(", "))        
      \sdfat.sddec(alt.get_pressure)
      \sdfat.sdstr(string(13,10))        
      \sdfat.pflush

    if conv.FromStr(gps.satellites,conv#DEC) < 3
      outa[LED_GPS_SATS] := 0
    else
      outa[LED_GPS_SATS] := 1

    if (alt.get_temperature > 200) and (alt.get_temperature < 300)
      outa[LED_PRESS_GOOD] := 1
    else
      outa[LED_PRESS_GOOD] := 0

    'Check for switch press
    if (sdrecording == 0) and (ina[START_LOGGING_SWITCH] == 0)
      OpenNewFile
      if(sdrecording == 1)
        outa[LED_RECORDING] := 1

    if (sdrecording == 1) and ina[STOP_LOGGING_SWITCH] == 0
      sdrecording := 0
      outa[LED_RECORDING] := 0  

      
   'toggle heartbeat led
    !outa[LED_HEART_BEAT]   
       
    'now wait some time before doing it again            
    waitcnt(clkfreq / 4 + cnt)


PUB OpenNewFile | index, fptr

  'Now check to see if the SD card was mounted successfully. If it was we need to find a file
  'to open. In this case we will attempt to open a file in read mode named sensorXX.log where XX
  'ranges from 00 to 99. If the read fails it means there isn't a file that exists and therefore
  'we can use that file name  
  if sdmounted == 1
    repeat index from 0 to 99
      bytemove(@tbuf[0],string("sensor"),6)
      stringptr := conv.ToStr(index,conv#DEC) + 1        'for some reason it puts a space on the front (+/- sign maybe?)
      stringlen := strsize(stringptr)
      bytemove(@tbuf[6],stringptr,stringlen)
      bytemove(@tbuf[6+stringlen],string(".log"),4)
      tbuf[10+stringlen] := 0
      if(\sdfat.popen(@tbuf, "r")) == -1
        quit
    fptr := sdfat.popen(@tbuf, "w")
    sdfat.sdstr(string("Lat Deg, Lat Min, Lat (N/S), Long Deg, Long Min, Long (W/E), GPS Alt, Speed, Sats, Time GMT, Date, Heading, Temp, Pressure",13,10))
    text.str(string("Openned file named: "))
    text.str(@tbuf[0])
    sdrecording := 1


    
DAT

{{
&#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;
}}    

{{
'   fsrw.spin 1.6  Copyright 2008   Radical Eye Software
'
'   See end of file for terms of use.
'
'   This object provides FAT16 file read/write access on a block device.
'   Only one file open at a time.  Open modes are 'r' (read), 'a' (append),
'   'w' (write), and 'd' (delete).  Only the root directory is supported.
'   No long filenames are supported.  We also support traversing the
'   root directory.
'
'   In general, negative return values are errors; positive return
'   values are success.  Other than -1 on popen when the file does not
'   exist, all negative return values will be "aborted" rather than
'   returned.
'
'   Changes:
'       v1.1  28 December 2006  Fixed offset for ctime
'       v1.2  29 December 2006  Made default block driver be fast one
'       v1.3  6 January 2007    Added some docs, and a faster asm
'       v1.4  4 February 2007   Rearranged vars to save memory;
'                               eliminated need for adjacent pins;
'                               reduced idle current consumption; added
'                               sample code with abort code data
'       v1.5  7 April 2007      Fixed problem when directory is larger
'                               than a cluster.
'       v1.6  23 September 2008 Fixed a bug found when mixing pputc
'                               with pwrite.  Also made the assembly
'                               routines a bit more cautious.
'
'   Third Party Changes:
'       v1.7  20 December 2008  Changes by John Twomey AKA: QuattroRS4
'                               ------------------------------------------------
'                               Added 'SDstr' to Simplify Writing of strings
'                               to SD Card. Use as follows -
'                               sdfat.sdstr(string("Test String"))
'                               sdfat.sdstr(string("Test String",13,10))
'                               the latter example adds CR & LF.
'
'                               Added 'SDdec' to simplify writing of decimal
'                               values to SD Card. Use as follows -
'                               sdfat.sddec(25)
'                               The above example writes 25 to SDCard. 
'
'                               Added 'SDhex' to Simplify Writing of Hexadecimal
'                               values to SD Card'. Use as follows -
'                               sdfat.sdhex(25)
'                               The above example writes 19 to SD card.
'                                                      
'                               Added 'SDbin' to Simplify Writing of Binary                                  
'                               to SD Card'. Use as follows -
'                               sdfat.sdbin(254,8)
'                               The above example writes 11111110 to SD card.
'
'                               Comments added to Code Additions also.
'                               ------------------------------------------------
'
'
}}                              
'
'   Constants describing FAT volumes.
'
con
   SECTORSIZE = 512
   SECTORSHIFT = 9
   DIRSIZE = 32
   DIRSHIFT = 5
'
'   The object that provides the block-level access.
'
obj
   sdspi: "sdspi"
var
'
'
'   Variables concerning the open file.
'
   long fclust ' the current cluster number
   long filesize ' the total current size of the file
   long floc ' the seek position of the file
   long frem ' how many bytes remain in this cluster from this file
   long bufat ' where in the buffer our current character is
   long bufend ' the last valid character (read) or free position (write)
   long direntry ' the byte address of the directory entry (if open for write)
   long writelink ' the byte offset of the disk location to store a new cluster
   long fatptr ' the byte address of the most recently written fat entry
'
'   Variables used when mounting to describe the FAT layout of the card.
'
   long rootdir ' the byte address of the start of the root directory
   long rootdirend ' the byte immediately following the root directory.
   long dataregion ' the start of the data region, offset by two sectors
   long clustershift ' log base 2 of blocks per cluster
   long fat1 ' the block address of the fat1 space
   long totclusters ' how many clusters in the volume
   long sectorsperfat ' how many sectors per fat
'
'   Variables controlling the caching.
'
   long lastread ' the block address of the buf2 contents
   long dirty ' nonzero if buf2 is dirty
'
'  Buffering:  two sector buffers.  These two buffers must be longword
'  aligned!  To ensure this, make sure they are the first byte variables
'  defined in this object.
'
   byte buf[SECTORSIZE] ' main data buffer
   byte buf2[SECTORSIZE] ' main metadata buffer
   byte padname[11] ' filename buffer
pri writeblock2(n, b)
'
'   On metadata writes, if we are updating the FAT region, also update
'   the second FAT region.
'
   sdspi.writeblock(n, b)
   if (n => fat1 and n < fat1 + sectorsperfat)
      sdspi.writeblock(n+sectorsperfat, b)
pri flushifdirty
'
'   If the metadata block is dirty, write it out.
'
   if (dirty)
      writeblock2(lastread, @buf2)
      dirty := 0
pri readblockc(n)
'
'   Read a block into the metadata buffer, if that block is not already
'   there.
'
   if (n <> lastread)
      flushifdirty
      sdspi.readblock(n, @buf2)
      lastread := n
pri brword(b)
'
'   Read a byte-reversed word from a (possibly odd) address.
'
   return (byte[b]) + ((byte[b][1]) << 8)
pri brlong(b)
'
'   Read a byte-reversed long from a (possibly odd) address.
'
   return brword(b) + (brword(b+2) << 16)
pri brwword(w, v)
'
'   Write a byte-reversed word to a (possibly odd) address, and
'   mark the metadata buffer as dirty.
'
   byte[w++] := v
   byte[w] := v >> 8
   dirty := 1
pri brwlong(w, v)
'
'   Write a byte-reversed long to a (possibly odd) address, and
'   mark the metadata buffer as dirty.
'
   brwword(w, v)
   brwword(w+2, v >> 16)
pub mount(basepin) | start, sectorspercluster, reserved, rootentries, sectors
{{
'   Mount a volume.  The address passed in is passed along to the block
'   layer; see the currently used block layer for documentation.  If the
'   volume mounts, a 0 is returned, else abort is called.
}}
   sdspi.start(basepin)
   lastread := -1
   dirty := 0
   sdspi.readblock(0, @buf)
   if (brlong(@buf+$36) == constant("F" + ("A" << 8) + ("T" << 16) + ("1" << 24)))
      start := 0
   else
      start := brlong(@buf+$1c6)
      sdspi.readblock(start, @buf)
   if (brlong(@buf+$36) <> constant("F" + ("A" << 8) + ("T" << 16) + ("1" << 24)) or buf[$3a] <> "6")
      abort(-20) ' not a fat16 volume
   if (brword(@buf+$0b) <> SECTORSIZE)
      abort(-21) ' bad bytes per sector
   sectorspercluster := buf[$0d]
   if (sectorspercluster & (sectorspercluster - 1))
      abort(-22) ' bad sectors per cluster
   clustershift := 0
   repeat while (sectorspercluster > 1)
      clustershift++
      sectorspercluster >>= 1
   sectorspercluster := 1 << clustershift
   reserved := brword(@buf+$0e)
   if (buf[$10] <> 2)
      abort(-23) ' not two FATs
   rootentries := brword(@buf+$11)
   sectors := brword(@buf+$13)
   if (sectors == 0)
      sectors := brlong(@buf+$20)
   sectorsperfat := brword(@buf+$16)
   if (brword(@buf+$1fe) <> $aa55)
      abort(-24) ' bad FAT signature
   fat1 := start + reserved
   rootdir := (fat1 + 2 * sectorsperfat) << SECTORSHIFT
   rootdirend := rootdir + (rootentries << DIRSHIFT)
   dataregion := 1 + ((rootdirend - 1) >> SECTORSHIFT) - 2 * sectorspercluster
   totclusters := ((sectors - dataregion + start) >> clustershift)
   if (totclusters > $fff0)
      abort(-25) ' too many clusters
   return 0
pri readbytec(byteloc)
'
'   Read a byte address from the disk through the metadata buffer and
'   return a pointer to that location.
'
   readblockc(byteloc >> SECTORSHIFT)
   return @buf2 + (byteloc & constant(SECTORSIZE - 1))
pri readfat(clust)
'
'   Read a fat location and return a pointer to the location of that
'   entry.
'
   fatptr := (fat1 << SECTORSHIFT) + (clust << 1)
   return readbytec(fatptr)
pri followchain | clust
'
'   Follow the fat chain and update the writelink.
'
   clust := brword(readfat(fclust))
   writelink := fatptr
   return clust
pri nextcluster | clust
'
'   Read the next cluster and return it.  Set up writelink to
'   point to the cluster we just read, for later updating.  If the
'   cluster number is bad, return a negative number.
'
   clust := followchain
   if (clust < 2 or clust => totclusters)
      abort(-9) ' bad cluster value
   return clust
pri freeclusters(clust) | bp
'
'   Free an entire cluster chain.  Used by remove and by overwrite.
'   Assumes the pointer has already been cleared/set to $ffff.
'
   repeat while (clust < $fff0)
      if (clust < 2)
         abort(-26) ' bad cluster number")
      bp := readfat(clust)
      clust := brword(bp)
      brwword(bp, 0)
   flushifdirty
pri datablock
'
'   Calculate the block address of the current data location.
'
   return (fclust << clustershift) + dataregion + ((floc >> SECTORSHIFT) & ((1 << clustershift) - 1))
pri uc(c)
'
'   Compute the upper case version of a character.
'
   if ("a" =< c and c =< "z")
      return c - 32
   return c
pri pflushbuf(r, metadata) | cluststart, newcluster, count, i
'
'   Flush the current buffer, if we are open for write.  This may
'   allocate a new cluster if needed.  If metadata is true, the
'   metadata is written through to disk including any FAT cluster
'   allocations and also the file size in the directory entry.
'
   if (direntry == 0)
      abort(-27) ' not open for writing
   if (r > 0) ' must *not* allocate cluster if flushing an empty buffer
      if (frem < SECTORSIZE)
         ' find a new clustercould be anywhere!  If possible, stay on the
         ' same page used for the last cluster.
         newcluster := -1
         cluststart := fclust & constant(!((SECTORSIZE >> 1) - 1))
         count := 2
         repeat
            readfat(cluststart)
            repeat i from 0 to constant(SECTORSIZE - 2) step 2
               if (buf2[i]==0 and buf2[i+1]==0)
                  newcluster := cluststart + (i >> 1)
                  if (newcluster => totclusters)
                     newcluster := -1
                  quit
            if (newcluster > 1)
               brwword(@buf2+i, -1)
               brwword(readbytec(writelink), newcluster)
               writelink := fatptr + i
               fclust := newcluster
               frem := SECTORSIZE << clustershift
               quit
            else
               cluststart += constant(SECTORSIZE >> 1)
               if (cluststart => totclusters)
                  cluststart := 0
                  count--
                  if (count < 0)
                     r := -5 ' No space left on device
                     quit
      if (frem => SECTORSIZE)
         sdspi.writeblock(datablock, @buf)
         if (r == SECTORSIZE) ' full buffer, clear it
            floc += r
            frem -= r
            bufat := 0
            bufend := r
         else
            ' not a full blockleave pointers alone
   if (r < 0 or metadata) ' update metadata even if error
      readblockc(direntry >> SECTORSHIFT) ' flushes unwritten FAT too
      brwlong(@buf2+(direntry & constant(SECTORSIZE-1))+28, floc+bufat)
      flushifdirty
   if (r < 0)
      abort(r)
   return r
pub pflush
{{
'   Call flush with the current data buffer location, and the flush
'   metadata flag set.
}}
   return pflushbuf(bufat, 1)
pri pfillbuf | r
'
'   Get some data into an empty buffer.  If no more data is available,
'   return -1.  Otherwise return the number of bytes read into the
'   buffer.
'
   if (floc => filesize)
      return -1
   if (frem == 0)
      fclust := nextcluster
      frem := SECTORSIZE << clustershift
      if (frem + floc > filesize)
         frem := filesize - floc
   sdspi.readblock(datablock, @buf)
   r := SECTORSIZE
   if (floc + r => filesize)
      r := filesize - floc
   floc += r
   frem -= r
   bufat := 0
   bufend := r
   return r
pub pclose | r
{{
'   Flush and close the currently open file if any.  Also reset the
'   pointers to valid values.  If there is no error, 0 will be returned.
}}
   r := 0
   if (direntry)
      r := pflush
   bufat := 0
   bufend := 0
   filesize := 0
   floc := 0
   frem := 0
   writelink := 0
   direntry := 0
   fclust := 0
   return r
pri pdate
{{
'   Get the current date and time, as a long, in the format required
'   by FAT16.  Right now it"s hardwired to return the date this
'   software was created on (April 7, 2007).  You can change this
'   to return a valid date/time if you have access to this data in
'   your setup.
}}
   return constant(((2007-1980) << 25) + (1 << 21) + (7 << 16) + (4 << 11))
pub popen(s, mode) | i, sentinel, dirptr, freeentry
{{
'   Close any currently open file, and open a new one with the given
'   file name and mode.  Mode can be "r" "w" "a" or "d" (delete).
'   If the file is opened successfully, 0 will be returned.  If the
'   file did not exist, and the mode was not "w" or "a", -1 will be
'   returned.  Otherwise abort will be called with a negative error
'   code.
}}
   pclose
   i := 0
   repeat while (i<8 and byte[s] and byte[s] <> ".")
      padname[i++] := uc(byte[s++])
   repeat while (i<8)
      padname[i++] := " "
   repeat while (byte[s] and byte[s] <> ".")
      s++
   if (byte[s] == ".")
      s++
   repeat while (i<11 and byte[s])
      padname[i++] := uc(byte[s++])
   repeat while (i < 11)
      padname[i++] := " "
   sentinel := 0
   freeentry := 0
   repeat dirptr from rootdir to rootdirend - DIRSIZE step DIRSIZE
      s := readbytec(dirptr)
      if (freeentry == 0 and (byte[s] == 0 or byte[s] == $e5))
         freeentry := dirptr
      if (byte[s] == 0)
         sentinel := dirptr
         quit
      repeat i from 0 to 10
         if (padname[i] <> byte[s][i])
            quit
      if (i == 11 and 0 == (byte[s][$0b] & $18)) ' this always returns
         fclust := brword(s+$1a)
         filesize := brlong(s+$1c)
         if (mode == "r")
            frem := SECTORSIZE << clustershift
            if (frem > filesize)
               frem := filesize
            return 0
         if (byte[s][11] & $d9)
            abort(-6) ' no permission to write
         if (mode == "d")
            brwword(s, $e5)
            freeclusters(fclust)
            flushifdirty
            return 0
         if (mode == "w")
            brwword(s+26, -1)
            brwlong(s+28, 0)
            writelink := dirptr + 26
            direntry := dirptr
            freeclusters(fclust)
            bufend := SECTORSIZE
            fclust := 0
            filesize := 0
            frem := 0
            return 0
         elseif (mode == "a")
' this code will eventually be moved to seek
            frem := filesize
            freeentry := SECTORSIZE << clustershift
            if (fclust => $fff0)
               fclust := 0
            repeat while (frem > freeentry)
               if (fclust < 2)
                  abort(-7) ' eof repeat while following chain
               fclust := nextcluster
               frem -= freeentry
            floc := filesize & constant(!(SECTORSIZE - 1))
            bufend := SECTORSIZE
            bufat := frem & constant(SECTORSIZE - 1)
            writelink := dirptr + 26
            direntry := dirptr
            if (bufat)
               sdspi.readblock(datablock, @buf)
               frem := freeentry - (floc & (freeentry - 1))
            else
               if (fclust < 2 or frem == freeentry)
                  frem := 0
               else
                  frem := freeentry - (floc & (freeentry - 1))
            if (fclust => 2)
               followchain
            return 0
         else
            abort(-3) ' bad argument
   if (mode <> "w" and mode <> "a")
      return -1 ' not found
   direntry := freeentry
   if (direntry == 0)
      abort(-2) ' no empty directory entry
   ' write (or new append): create valid directory entry
   s := readbytec(direntry)
   bytefill(s, 0, DIRSIZE)
   bytemove(s, @padname, 11)
   brwword(s+26, -1)
   i := pdate
   brwlong(s+$e, i) ' write create time and date
   brwlong(s+$16, i) ' write last modified date and time
   if (direntry == sentinel and direntry + DIRSIZE < rootdirend)
      brwword(readbytec(direntry+DIRSIZE), 0)
   flushifdirty
   writelink := direntry + 26
   fclust := 0
   bufend := SECTORSIZE
   return 0
pub pread(ubuf, count) | r, t
{{
'   Read count bytes into the buffer ubuf.  Returns the number of bytes
'   successfully read, or a negative number if there is an error.
'   The buffer may be as large as you want.
}}
   r := 0
   repeat while (count > 0)
      if (bufat => bufend)
         t := pfillbuf
         if (t =< 0)
            if (r > 0)
               return r
            return t
      t := bufend - bufat
      if (t > count)
         t := count
      bytemove(ubuf, @buf+bufat, t)
      bufat += t
      r += t
      ubuf += t
      count -= t
   return r
pub pgetc | t
{{
'   Read and return a single character.  If the end of file is
'   reached, -1 will be returned.  If an error occurs, a negative
'   number will be returned.
}}
   if (bufat => bufend)
      t := pfillbuf
      if (t =< 0)
         return -1
   return (buf[bufat++])
pub pwrite(ubuf, count) | r, t
{{
'   Write count bytes from the buffer ubuf.  Returns the number of bytes
'   successfully written, or a negative number if there is an error.
'   The buffer may be as large as you want.
}}
   t := 0
   repeat while (count > 0)
      if (bufat => bufend)
         t := pflushbuf(bufat, 0)
      t := bufend - bufat
      if (t > count)
         t := count
      bytemove(@buf+bufat, ubuf, t)
      r += t
      bufat += t
      ubuf += t
      count -= t
   return t
pub pputc(c)
{{
'   Write a single character into the file open for write.  Returns
'   0 if successful, or a negative number if some error occurred.
}}
   if (bufat == SECTORSIZE)
      pflushbuf(SECTORSIZE, 0)
   buf[bufat++] := c
   return 0
Pub SDStr(ptr)
{{
' Addition by John Twomey AKA: QuattroRS4
' Routine added to write a string
' Use as follows in Program  -
' sdfat.sdstr(string("this string will be written to SDcard"))
'
' can also do -
' sdfat.sdstr(string("this string will be written to SDcard",13,10))
' the above adds CR & LF (Carriage Return and Line Feed) 
}}
  repeat while byte[ptr]
    pputc(byte[ptr++])


PUB SDdec(value) | i

{{
' Addition by John Twomey AKA: QuattroRS4
' Routine added to write decimal values to SD Card
' Use as follows in Program  -
' sdfat.sddec(25)  ' writes 25 to SDCard
}}


  if value < 0
    -value
    pputc("-")

  i := 1_000_000_000

  repeat 10
    if value => i
      pputc(value / i + "0")
      value //= i
      result~~
    elseif result or i == 1
      pputc("0")
    i /= 10

PUB SDhex(value, digits)

{{
' Addition by John Twomey AKA: QuattroRS4
' Routine added to write hexadecimal values to SD Card
' Use as follows in Program  -
' sdfat.sdhex(25)  'this example writes 19 to SD card
}}

  value <<= (8 - digits) << 2
  repeat digits
    pputc(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))

PUB SDbin(value, digits)
{{
' Addition by John Twomey AKA: QuattroRS4
' Routine added to write  Binary number to SD Card
' Use as follows in Program  -
' sdfat.sdbin(254,8)  'this example writes 11111110 to SD card
}}

  value <<= 32 - digits
  repeat digits
    pputc((value <-= 1) & 1 + "0")


pub opendir | off
{{
'   Close the currently open file, and set up the read buffer for
'   calls to nextfile.
}}
   pclose
   off := rootdir - (dataregion << SECTORSHIFT)
   fclust := off >> (clustershift + SECTORSHIFT)
   floc := off - (fclust << (clustershift + SECTORSHIFT))
   frem := rootdirend - rootdir
   filesize := floc + frem
   return 0
pub nextfile(fbuf) | i, t, at, lns
{{
'   Find the next file in the root directory and extract its
'   (8.3) name into fbuf.  Fbuf must be sized to hold at least
'   13 characters (8 + 1 + 3 + 1).  If there is no next file,
'   -1 will be returned.  If there is, 0 will be returned.
}}
   repeat
      if (bufat => bufend)
         t := pfillbuf
         if (t < 0)
            return t
         if (((floc >> SECTORSHIFT) & ((1 << clustershift) - 1)) == 0)
            fclust++
      at := @buf + bufat
      if (byte[at] == 0)
         return -1
      bufat += DIRSIZE
      if (byte[at] <> $e5 and (byte[at][$0b] & $18) == 0)
         lns := fbuf
         repeat i from 0 to 10
            byte[fbuf] := byte[at][i]
            fbuf++
            if (byte[at][i] <> " ")
               lns := fbuf
            if (i == 7 or i == 10)
               fbuf := lns
               if (i == 7)
                  byte[fbuf] := "."
                  fbuf++
         byte[fbuf] := 0
         return 0
{{
'  Permission is hereby granted, free of charge, to any person obtaining
'  a copy of this software and associated documentation files
'  (the "Software"), to deal in the Software without restriction,
'  including without limitation the rights to use, copy, modify, merge,
'  publish, distribute, sublicense, and/or sell copies of the Software,
'  and to permit persons to whom the Software is furnished to do so,
'  subject to the following conditions:
'
'  The above copyright notice and this permission notice shall be included
'  in all copies or substantial portions of the Software.
'
'  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
'  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
'  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
'  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
'  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
'  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
'  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}}






'   sdspi:  SPI interface to a Secure Digital card.
'
'   Copyright 2008   Radical Eye Software
'
'   See end of file for terms of use.
'
'   This version is in Spin so it is very slow (3Kb/sec).
'   A version in assembly is about 100x faster.
'
'   You probably never want to call this; you want to use fswr
'   instead (which calls this); this is only the lowest layer.
'
'   Assumes SD card is interfaced using four consecutive Propeller
'   pins, as follows (assuming the base pin is pin 0):
'                3.3v
'              &#61463; &#61463; &#61463; &#61463; &#61463; &#61463;
'              &#61628; &#61628; &#61628; &#61628; &#61628; &#61628; 20k
'   p0 &#9472;&#9472;&#9472;&#9472;&#61629;&#61630;&#9472;&#9472;&#9531;&#9472;&#9532;&#9472;&#9532;&#9472;&#9532;&#9472;&#9532;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; do
'   p1 &#9472;&#9472;&#9472;&#9472;&#61629;&#61630;&#9472;&#9472;&#9472;&#9472;&#9531;&#9472;&#9532;&#9472;&#9532;&#9472;&#9532;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; clk
'   p2 &#9472;&#9472;&#9472;&#9472;&#61629;&#61630;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9531;&#9472;&#9532;&#9472;&#9532;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; di
'   p3 &#9472;&#9472;&#9472;&#9472;&#61629;&#61630;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9531;&#9472;&#9532;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; cs (dat3)
'         150          &#9492;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; irq (dat1)
'                        &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; p9 (dat2)
'
'   The 150 ohm resistors are current limiters and are only
'   needed if you don't trust your code (and don't want an SD
'   driven signal to conflict with a Propeller driven signal).
'   A value of 150 should be okay, unless you've got some
'   unusually high capacitance on the line.  The 20k resistors
'   are pullups, and should be there on all six lines (even
'   the ones we don't drive).
'
'   This code is not general-purpose SPI code; it's very specific
'   to reading SD cards, although it can be used as an example.
'
'   The code does not use CRC at the moment (this is the default).
'   With some additional effort we can probe the card to see if it
'   supports CRC, and if so, turn it on.   
'
'   All operations are guarded by a watchdog timer, just in case
'   no card is plugged in or something else is wrong.  If an
'   operation does not complete in one second it is aborted.
'
con
   sectorsize = 512
   sectorshift = 9
var
   long di, do, clk, cs, starttime
pri send(outv)
'
'   Send eight bits, then raise di.
'
   outv ><= 8
   repeat 8
      outa[clk] := 0
      outa[di] := outv
      outv >>= 1
      outa[clk] := 1
   outa[di] := 1
pri checktime
'
'   Did we go over our time limit yet?
'
   if cnt - starttime > clkfreq
      abort -41 ' Timeout during read
pri read | r
'
'   Read eight bits from the card.
'
   r := 0
   repeat 8
      outa[clk] := 0
      outa[clk] := 1
      r += r + ina[do]
   return r
pri readresp | r
'
'   Read eight bits, and loop until we
'   get something other than $ff.
'
   repeat
      if (r := read) <> $ff
         return r
      checktime
pri busy | r
'
'   Wait until card stops returning busy
'
   repeat
      if (r := read)
         return r
      checktime
pri cmd(op, parm)
'
'   Send a full command sequence, and get and
'   return the response.  We make sure cs is low,
'   send the required eight clocks, then the
'   command and parameter, and then the CRC for
'   the only command that needs one (the first one).
'   Finally we spin until we get a result.
'
   outa[cs]~
   read
   send($40+op)
   send(parm >> 15)
   send(parm >> 7)
   send(parm << 1)
   send(0)
   send($95)
   return readresp
pri endcmd
'
'   Deselect the card to terminate a command.
'
   outa[cs] := 1
   return 0
pub start(basepin)
'
'   Initialize the card!  Send a whole bunch of
'   clocks (in case the previous program crashed
'   in the middle of a read command or something),
'   then a reset command, and then wait until the
'   card goes idle.  If you want to change this
'   method to make the pins not be adjacent, all you
'   need to do is change these first four lines.
'
   cs := basepin++
   di := basepin++ 
   clk := basepin++
   do := basepin
'
   outa[clk] := outa[di] := outa[cs] := 1
   dira[clk] := dira[di] := dira[cs] := 1
   starttime := cnt
   repeat 600
      read
   cmd(0, 0)
   endcmd
   repeat
      cmd(55, 0)
      basepin := cmd(41, 0)
      endcmd
      if basepin <> 1
         quit
   if basepin
      abort -40 ' could not initialize card
   return 0
pub readblock(n, b)
'
'   Read a single block.  The "n" passed in is the
'   block number (blocks are 512 bytes); the b passed
'   in is the address of 512 blocks to fill with the
'   data.
'
   starttime := cnt
   cmd(17, n)
   readresp
   repeat sectorsize
      byte[b++] := read
   read
   read
   return endcmd
{
pub getCSD(b)
'
'   Read the CSD register.  Passed in is a 16-byte
'   buffer.
'
   starttime := cnt
   cmd(9, 0)
   readresp
   repeat 16
      byte[b++] := read
   read
   read
   return endcmd
}
pub writeblock(n, b)
'
'   Write a single block.  Mirrors the read above.
'
   starttime := cnt
   cmd(24, n)
   send($fe)
   repeat sectorsize
      send(byte[b++])
   read
   read
   if ((readresp & $1f) <> 5)
      abort -42
   busy
   return endcmd
{{
'  Permission is hereby granted, free of charge, to any person obtaining
'  a copy of this software and associated documentation files
'  (the "Software"), to deal in the Software without restriction,
'  including without limitation the rights to use, copy, modify, merge,
'  publish, distribute, sublicense, and/or sell copies of the Software,
'  and to permit persons to whom the Software is furnished to do so,
'  subject to the following conditions:
'
'  The above copyright notice and this permission notice shall be included
'  in all copies or substantial portions of the Software.
'
'  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
'  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
'  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
'  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
'  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
'  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
'  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}}


Comments

  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2012-03-03 15:20
    Hi SteveWoodrough;

    Did you add the 20K pullup resisters?

    I have connected my SD card to all kinds of different pins.

    Duane J
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2012-03-03 16:19
    I forgot, but there is a short thread on this:

    This is how I made a bunch of these SD card adapters:
    http://forums.parallax.com/showthread.php?130083-SD-Card-Pins
    http://www.rayslogic.com/propeller/Programming/SD_Card/SD_Card.htm
    The basic SD card wiring is shown below. "Pull-up" refers to a 20K
    pull up resistor from the pin indicated to +3.3V. For the Demo
    Board version, the pins are as indicated below.
    For the Proto Board version,
    P0 = I/O pin 8,  P1 = I/O pin  9, P2 = I/O pin 10, P3 = I/O pin 11.
    For the Hydra version, 
    P0 = I/O pin 16, P1 = I/O pin 17, P2 = I/O pin 18, P3 = I/O pin 19.
    For the PropStick version, 
    P0 = I/O pin 27, P1 = I/O pin 28, P2 = I/O pin 33, P3 = I/O pin 34.
    http://forums.parallax.com/showthread.php?130083-SD-Card-Pins
    http://www.rayslogic.com/propeller/Programming/SD_Card/SD_Card.htm
    
    SD CARD 
    Socket 
    Pin-out:
     
    PIN         SD CARD      Prop I/O        Demo Proto Hydra PropStick
    -------------------------------------------------------------------
     1 (NC)
     2         (PIN-9) DAT2      20K Pull-up
     3         (PIN-1) CS    A22 20K Pull-up P3   P11   P19   P27
     4         (PIN-2) DI    A23 20K Pull-up P2   P10   P18   P28
     5         (PIN-3) GND                   GND  GND   GND   P29
     6         (PIN-4) +3.3V                 VCC  VCC   VCC   P32
     7         (PIN-5) CLK   A24 20K Pull-up P1   P9    P17   P33
     8         (PIN-6) GND                   GND  GND   GND   P29  
     9         (PIN-7) DO    A25 20K Pull-up P0   P8    P16   P34
    10         (PIN-8) DAT1      20K Pull-up
    11 (CD SW)
    
    -------------------------------------------------------------------
    
  • SteveWoodroughSteveWoodrough Posts: 190
    edited 2012-03-03 17:44
    I'm using the Parallax boards with the 10K resistors. I'm pretty sure this is a software issue since it works just fine on pins 2-5 but not for other pin configurations. Reading the code it's not clear to me how the pin assignments are made. Thanks Steve
  • SteveWoodroughSteveWoodrough Posts: 190
    edited 2012-03-04 13:06
    Update: I can get the code to mount the SD card when I specify a base pin of 2 OR 3 but not 4 or any other pin number.

    I think the problem is in the code excerpt below. If I force the pins to be specific values:

    cs := 2 di := 3 clk := 4 do := 5

    cs := 3 di := 4 clk := 5 do := 6

    the SD cards mounts and records GPS data just fine.


    if I use

    cs := 4 di := 5 clk := 6 do := 7

    then the SD card will not mount.

    Any ideas are welcome...

    Thanks!!



    pub start(basepin)
    '
    '   Initialize the card!  Send a whole bunch of
    '   clocks (in case the previous program crashed
    '   in the middle of a read command or something),
    '   then a reset command, and then wait until the
    '   card goes idle.  If you want to change this
    '   method to make the pins not be adjacent, all you
    '   need to do is change these first four lines.
    '
       cs := basepin++
       di := basepin++ 
       clk := basepin++
       do := basepin
    '
       outa[clk] := outa[di] := outa[cs] := 1
       dira[clk] := dira[di] := dira[cs] := 1
       starttime := cnt
       repeat 600
          read
       cmd(0, 0)
       endcmd
       repeat
          cmd(55, 0)
          basepin := cmd(41, 0)
          endcmd
          if basepin <> 1
             quit
       if basepin
          abort -40 ' could not initialize card
       return 0
    
    
  • Cluso99Cluso99 Posts: 18,069
    edited 2012-03-04 15:54
    It is normal to have the lowest pin as DO then CLK then DI then CS. The basepin would be P0, etc.
    You can individually specify the pins by using the startxxxx(x,x,x,xO method instead of the start method. I cannot recall the exact name of the startxxxx method so you will need to look at the driver.
    Although what I have said here does not make sense with the results you seem to be getting, perhaps this will help.
    BTW the order of the cs,di,clk,do lines in your quoted code does not make sense. Also I presume your example of setting cs, di etc on the one line is just a representation because you cannot set these on the one line in spin.
    One last comment. I presume you dont have anything else on the lines 0-7 of the prop that could interfere.
  • SteveWoodroughSteveWoodrough Posts: 190
    edited 2012-03-04 17:23
    Thank you for the reply. Starting with the last comment, the pins are unencumbered and the test is done on a Demo Board.

    With regard to the paramerters that work listed as:
    cs := 2 di := 3 clk := 4 do := 5

    cs := 3 di := 4 clk := 5 do := 6

    I wrote all on one line just for clarity. Within the code each is on a seprate line.

    My pin setup is taken directly from P.323 of the Official guide which lists:
    Pin 2 CS
    Pin 3 DI
    Pin 4 SCLK
    Pin 5 DO

    I agree that is not the pin setup implied by the code, DO should be the lowest Pin number, but regardless it works.

    Just for grins I did attempt to run DO to Pin 2, SCLK to PIN 3, DI to PIN 4, and CS to PIN 5 but it would not work.

    You mention a Startxxx method that allowed individual pin selection. I cannot locate in the code I downloaded. I'm wondering if the code I downloaded has been replaced or updated. The code I got was downloaded from an FTP site listed in the book not from the OBEX. I'm not married to this code set, and if there is a better GPS data logger I'd be more than happy to try it out.

    Best Regards,
    Steve
  • PublisonPublison Posts: 12,366
    edited 2012-03-06 13:18
    Steve,

    I think if you are using the entire file from the Official Guide, and try to move the pins up to P04 or P05, you are stepping on the pin parameters that the Barometer has set.

    If all you want is data logging with GPS, may I point you to this thread:

    http://forums.parallax.com/showthread.php?104049-Google-Earth-GPS-SD-Card-Logger-COMPLETE!

    It works great, and I have been using it for over two years on a 2GB uSD card.

    I believe you could change the pins in this program.

    Jim

    EDIT: Sometimes people put the Base Pin to equal the high pin and count down from there. (IE Base pin P04 then count down to P0)
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-03-06 14:21
    Steve,

    If your code called sdfat.mount(2) and it worked OK, then you must have DO on P2, SCLK on P3, DI on P4 and CS on P5. There is no way that it would work with the pinout that you described. Therefore, you must be confused about the labelling of the pins, and have it in the reversed order. When you moved to pins P3, P4, P5 and P6 did you change the call to mount to sdfat.mount(3)? This should have worked if you maintained the same pin order that you used before.

    Dave
  • SteveWoodroughSteveWoodrough Posts: 190
    edited 2012-03-06 18:52
    Jim,
    Thank You, I'll check that out. Right now everything is a learning experience. In writing my response below I just caught what you are saying. With my changes I'm trying to make PIN 7 do two things at once. Let me whack the pressure sensor object or free up references to PIN 7 and see if that fixes it. Like I said...Everything is a learing experience.

    Dave,
    Thank you for making me quintuple check my wiring and making me really think why it does work! I've attached photos of the SD card and now everybody can see just how bad my soldering skills are! As you can see the DO pin is near the card center and CS towards one edge. I've marked the backside of the card since that is the side nearest me. I also include a picture of the wiring on the Demo Board. This wiring sequence is exactly what is written on page 323 of the Official Guide. The software is the download from the FTP site, and when setup EXACTLY as prescribed....it works!!! I do not know enough to do this wrong, all I do is follow the instructions! When I follow the instructions, IT WORKS!! ;-)

    The difficulty comes in when I try to use alternate pin outs.

    I do not know very much except that in the bowels of the SDSPI object provided from the FTP site it is written:

    cs := basepin++
    di := basepin++
    clk := basepin++
    do := basepin

    That seems a strange way to assign pins but if I understand this correctly, with basepin starting at 2, this would make CS = 2, post increment so that DI = 3, post increment so that CLK = 4, post increment so that DO = 5

    Reflecting on this more deeply I think Jim is correct. I'm having PIN 7 try to do two things at once. Not a good strategy....
    1024 x 768 - 102K
    1024 x 768 - 113K
    1024 x 768 - 103K
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-03-06 19:29
    The sdspi.spin file in the obex contains the following code
       do := basepin++
       clk := basepin++ 
       di := basepin++
       cs := basepin
    
    In this version, the base pin is D0. In your version the base pin is CS, and the pins are in the reverse order. So your wiring is correct for your version of sdspi. If you move CS, DI, CLK and DO to P3, P4, P5 and P6 mount(3) should work for you.

    I am confused why your version of sdspi.spin has the pins in the reverse order. Where did you get that file?

    BTW, there is a more recent version of FSRW that has a mount_explicit method that allows you to specify each of the pins independently. It's version 2.6. I suppose that with version 1.6 the sdspi.spin file had to be modified to accomodate pin assignments that didn't increment by 1 starting from DO.
  • PublisonPublison Posts: 12,366
    edited 2012-03-07 08:50
    Dave Hein wrote: »
    I am confused why your version of sdspi.spin has the pins in the reverse order. Where did you get that file?

    Hi Dave,

    The code came from here:

    ftp://ftp.propeller-chip.com/PCMProp/Chapter_09/Source/

    I
    would say Joshua did code it a little differently than normal, (reversing the base pin to be the higher number).

    Jim
  • SteveWoodroughSteveWoodrough Posts: 190
    edited 2012-03-07 18:02
    Whoo Hoo! Jim gets the gold star. Edit it out the PIN 6 and 7 references, and it works just fine.

    Thank You Dave and others who put a bit of time into this.
Sign In or Register to comment.