' Program: MMC.BAS written using Bascom-AVR ver 1.11.6.66
' Basic program to interface with a MMC module using the SPI protocol.
'
'                 BETA CODE
'      **** NOT FOR COMMERCIAL USE *****
'            Ver. 0.0.1  May, 2002
'
' Project Reference: MMC-M163
' MCU: Atmel Mega163
' Software: Bascom-AVR ver 1.11.6.66
' Atmel Programmer: STK500 development board set at 3.3v.
'                 ISP and terminal output
'
' Initial Date: May 18, 2002
' Projected Completion Date: Unknown
'
' Author: Ranjit Diol
'         rsdiol@compsys1.com
'         http://www.compsys1.com/workbench
'
'***************************************************************
'                      (c) COMPSys, 2002
'                     All Rights Reserved
'***************************************************************

'
'   DISCLAIMER: This file is being released as non-commericial
'   software. It is being provided "AS IS", neither the author,
'   nor COMPSys shall be held liable for any damages caused
'   by its use either directly or indirectly in any form or manner.
'
'===============================================================
'
'Brief: The MMC is a 3volt part therefore all data lines
'       must be conditioned if interfacing with a 5v mcu.
'       Or, a 3.3v MCU can be used such as the AT103L or the AT90LS8535
'
'IMPORTANT NOTE:
'       In SPI mode the MMC's minimum block size is 512 bytes
'       therefore data has to be accumulated first either in an eeprom
'       or in memory before sending it out as a chunk of 512 bytes.
'
'       MMC pins in SPI mode:
'            Pin1:ChipSelect(SS),Pin2:MMC input(MOSI),Pin3:GND,Pin4:3V+,
'            Pin5:Clock(SCK), Pin6:GND, Pin7:MMC output(MISO)
'       M163 pins:
'            Portb.4 SS
'            Portb.5 MISO
'            Portb.6 MOSI
'            Portb.7 SCK
'
'
'==============================================================

$regfile = "m163def.dat"                                    'MCU
$crystal = 3690000                                          'Set for STK500

'SERIAL I/O
'Aux RS232 port on STK500 used
'Hardware RX,TX pins PD0,PD1 used
'Baud 19200
$baud = 19200


'Configure for software SPI
'                    MISO           MOSI             SS             SCK
Config Spi = Soft , Din = Pinb.6 , Dout = Portb.5 , Ss = Portb.4 , Clock = Portb.7
Ddrb = &B10111111


'Constants
Const Msbl = 0
Const Msbh = 1
Const Dly = 2
Const Bits8 = 8
Const Bits16 = 16
Const Bits32 = 32

'Variables
Dim Res(16) As Byte
Dim Indat(512) As Byte                                      'Memory buffer for temp storage.
Dim Dat As Byte
Dim Resp As Byte
Dim Resp2 As Word
Dim I As Word
Dim J As Word
Dim X As Byte
Dim Y As Byte
Dim K As Byte
Dim Bout As Byte
Dim Addr1 As Byte
Dim Addr2 As Byte
Dim Addr3 As Byte
Dim Addr4 As Byte
Dim Addr As Long
Dim Saddr As Long
Dim Eaddr As Long
Dim W_key As String * 1
Dim Maddr1 As Long
Dim Maddr2 As Long
Dim Chkres As Byte
Dim Rbytes As Word
Dim Chr As String * 1
'Aliases
Cs Alias Portb.4
Clk Alias Portb.7
Miso Alias Pinb.6                                           'inp
Mosi Alias Portb.5                                          'out                                      'out

'Declarations
Declare Sub Mprint
Declare Sub Minit
Declare Sub Mstatus
'Declare Sub Mwrite(byval Bout As Byte , Byval Addr As Long )
Declare Sub Mwrite(byval Maddr1 As Long , Byval Maddr2 As Long)
Declare Sub Mread(byval Rbytes As Word , Byval Addr As Long )
Declare Sub Merase(byval Saddr As Long , Byval Eaddr As Long)
Declare Sub Getk
Declare Sub Chkresp(byval Chkres As Byte)
Declare Sub Ld_array
Waitms 300


Spiinit




'******** MAIN PROGRAM *************
Main:
                                                 'First Ascii Character

Print "     MMC Simple Test Program"
Print "   written in BascomAVR 11.11.66"
Print "COMPSys http://www.compsys1.com/workbench"
Print "        (c) COMPSys 2002"
Print "========================================="
Print "This program will initialize and then"
Print "erase a portion of the MMC and will then"
Print "write ASCII characters.Finally, it will"
Print "read the characters stored"

Gosub Getk

Print "Initializing MMC"

'Initialize the MMCC
Minit

Print "Erase from &H0000 to &H01FF"
Gosub Getk

'Call Erase Subroutine Enter Startaddr , Endaddr
Merase &H00000000 , &H000001FF

Print "Erased! Now read the erased portion"
Gosub Getk
Print "Reading:"
'Call read sub from 512 from address are put in array INDAT
Mread 512 , &H00000000
For I = 1 To 512
   K = Indat(i)
   Print K;
Next I
Print

Print "Fill &H0000 to &H01FF with ASCII characters"
Gosub Getk

'Load the ASCII chars into the array
Ld_array


'call write subroutine as: maddr1, maddr2 32bit addresses
'data which is loaded in the INDAT array is written
Mwrite &H00000000 , &H000001FF

Print "512 Chars written, now read them back"
Gosub Getk

'Call read sub from 512 from address are put in array INDAT
Mread 512 , &H00000000

'The array is now loaded
'Call print sub print 512 bytes stored in INDAT array
Mprint

Print
Print "End of MMC test"
Xloop:
Set Cs
Shiftout Mosi , Clk , Dat , Msbl
Endloop:
Goto Endloop

End                                                         'end program
'************ END OF PROGRAM **************



'======= SUB ROUTINES AND FUNCTIONS =======

'*** INITIALIZATION OF MMC ***
Sub Minit
Set Cs
Dat = &HFF
For I = 1 To 10
  Shiftout Mosi , Clk , Dat , Msbl
Next I
Resp = 255
Reset Cs

Cmd0:
Dat = &H40
Shiftout Mosi , Clk , Dat , Msbl
Addr = &H00000000
Shiftout Mosi , Clk , Addr , Msbl
Dat = &H95
Shiftout Mosi , Clk , Dat , Msbl

Chkresp &H01

'For debugging
'Lcd "C0:" ; Hex(resp)
                                       'Initialized
Set Cs
Waitms 50
Reset Cs
Dat = &HFF

'If it does not initialize correctly
'it will hang in the following loop
Cmd1:
While Resp <> &H00
Set Cs
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl
Reset Cs
Dat = &H41
Shiftout Mosi , Clk , Dat , Msbl
Addr = 0
Shiftout Mosi , Clk , Addr , Msbl
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl
Wend

Dat = &HFF
Set Cs

'For debugging
'Lcd "C1:" ; Hex(resp)

Print "MMC initialized"
End Sub

'**** READ routine assumes ADDR uses Status subroutine *****
Sub Mread(byval Addr As Long)
Set Cs
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl
Reset Cs
Dat = &H51
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Addr , Msbl
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl

'While Resp <> 0
'Shiftin Miso , Clk , Resp , Msbl
'Wend

Chkresp &H00

'While Resp <> &HFE
 'Shiftin Miso , Clk , Resp , Msbl
'Wend

Chkresp &HFE

'For debugging
'Lcd Hex(resp)

For I = 1 To 512
    Shiftin Miso , Clk , Resp , Msbl
    Indat(i) = Resp
    'For debugging
    'Lcd Hex(resp);
Next I

Shiftin Miso , Clk , Resp , Msbl
Shiftin Miso , Clk , Resp , Msbl

Set Cs
Mstatus
End Sub


'****Block Start Tag / End Tag and ERASE ****
Sub Merase(byval Saddr As Long , Byval Eaddr As Long)

'Erase first 1024 bytes

'Block START TAG
Cmd32:

Set Cs
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl
Reset Cs
Dat = &H60
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Saddr , Msbl
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl

Chkresp &H00

'Block END TAG
Cmd33:

Set Cs
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl
Reset Cs
Dat = &H61
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Eaddr , Msbl
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl

Chkresp &H00


'ERASE SELECTED BLOCK
Cmd38:
Set Cs
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl
Reset Cs
Dat = &H66
Shiftout Mosi , Clk , Dat , Msbl
Addr = 0
Shiftout Mosi , Clk , Addr , Msbl
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl

Chkresp &H00

Mstatus
End Sub

'** WRITE Routine assumes ADDR, BOUT uses Status subroutine **
'Sub Mwrite(byval Bout As Byte , Byval Addr As Long)
Sub Mwrite(byval Maddr1 As Long , Byval Maddr2 As Long)
Cmd24:
Set Cs
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl
Reset Cs
Dat = &H58
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Maddr1 , Msbl
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl

Chkresp &H00

'For debugging
'Lcd "C24:" ; Hex(resp)

'Send data token
Dat = &HFE
Shiftout Mosi , Clk , Dat , Msbl

'For I = Maddr1 To Maddr2
For I = 1 To 512
   Dat = Indat(i)
   Shiftout Mosi , Clk , Dat , Msbl
Next I

Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl

'If Y = &H05 write is a success
Y = Resp And &H0F

'If Resp = 0 the MMC is busy
Shiftin Miso , Clk , Resp , Msbl

Chkresp &H00


'Lowerline
'For debugging
'Lcd "Wr:" ; Hex(y)

Set Cs
Mstatus
End Sub

'Get MMC Status
Sub Mstatus
Cmd13:
Set Cs
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp , Msbl
Reset Cs
Dat = &H4D
Shiftout Mosi , Clk , Dat , Msbl
Addr = 0
Shiftout Mosi , Clk , Addr , Msbl
Dat = &HFF
Shiftout Mosi , Clk , Dat , Msbl
Shiftout Mosi , Clk , Dat , Msbl
Shiftin Miso , Clk , Resp2 , Msbl

'For debugging
'lcd "Status:" ; Hex(resp2)

Set Cs
'Return
End Sub

'Display data in the array
Sub Mprint
For I = 1 To 512
Dat = Indat(i)
Chr = Chr(dat)
Print Chr ;
Next
End Sub

Sub Getk
Print "Press any key to continue...."
W_key = Waitkey()
End Sub


Sub Chkresp(byval Chkres As Byte)
'NOTE:If the addr is incorrect it will
'never exit the following loop!
'You may want to loop it approx 255 times
'and then if it fails go to an error routine

While Resp <> Chkres
Shiftin Miso , Clk , Resp , Msbl
Wend
End Sub

Sub Ld_array
K = &H21
For I = 1 To 512
Indat(i) = K
Incr K
If K > &H7E Then K = &H21
Next I
End Sub



'===============
'  END OF CODE
'===============