' Rabbit_1.Bas
'
' Interface with Z-World SF1010 serial flash expansion card (4MB).
'
' This program writes 528 bytes to buffer 1 and then reads them back
' byte by byte using the buffer read mode.  8-bit serial output on MOSI
' and 8-bit serial input on MOSI uses "bit-bang".  SPI Modes 0 and 3 are
' used (data clocked in on rising edge of CLK, data clocked out on
' falling edge of CLK).
'
' copyright, Lisa P. Mickens, Morgan State University, Nov. 2001

Const SPI_CS as Byte = 13		'Definition of BX24 pins
Const SPI_CLK as Byte = 14
Const MOSI as Byte = 15
Const MISO as Byte = 16

Const B1_Write as Byte = bx10000100	'Definition of AT45DB321 commands
Const B1_Read as Byte = bx11010100

Sub Main()
  Dim Address as Integer
  Dim Data as Byte

  Call OpenSerialPort (1, 19200)

  For Address = 0 to 527			'Write data to Buffer 1
    Data = CByte((Address MOD 10) + 1) 		'Make up some data
    Call WriteB1 (Address, Data)
  Next

  For Address = 0 to 527			'Read data from Buffer 1
    Data = ReadB1 (Address)
    Call PutB(Data)
    If (((Address+1) MOD 10) <> 0) Then		'Put 10 values to a line
      Call PutByte (Asc(" "))
    Else
      Call NewLine()
    End If
  Next
End Sub

Sub WriteB1 (byVal Address as Integer, ByVal Data as Byte)
  Dim N as Byte, Dummy as Byte, DCare as Byte, Addr_Hi as byte, Addr_Lo as byte

  DCare = bx00000000					'Don't Care byte
  Addr_Hi = CByte((CByte(Address\256) AND bx00000011))	'Set up address bytes
  Addr_Lo = CByte (Address MOD 256)

  Call PutPin (SPI_CS, 1)	'Bring CS High
  Call PutPin (SPI_CLK, 0)	'Make sure CLK is low
  Call PutPin (MOSI, 0)		'Bring MOSI low
  Call PutPin (SPI_CS,0)	'Bring CS Low to initiate

  Dummy = SPI_IO (B1_Write)	'Send Buffer 1 Write opcode
  Dummy = SPI_IO (DCare)	'8 Don't care bits
  Dummy = SPI_IO (Addr_Hi)	'6 Don't care bits and 2 Address bits
  Dummy = SPI_IO (Addr_Lo)	'8 Address bits
  Dummy = SPI_IO (Data)		'Send data byte

  Call PutPin (SPI_CS, 1)	'End session
End Sub

Function ReadB1 (ByVal Address as Integer) as Byte
  Dim Dummy as Byte, DCare as byte, Addr_Hi as byte, Addr_Lo as byte

  DCare = bx00000000					'Don't Care byte
  Addr_Hi = CByte((CByte(Address\256) AND bx00000011))	'Set up address bytes
  Addr_Lo = CByte (Address MOD 256)

  Call PutPin (SPI_CS, 1)	'Bring CS High
  Call PutPin (SPI_CS, 0)	'Bring CS Low to initiate

  Dummy = SPI_IO (B1_Read)	'Send Buffer 1 Read opcode
  Dummy = SPI_IO (DCare)	'Send 8 Don't care bits
  Dummy = SPI_IO (Addr_Hi)	'Send 6 Don't care bits and 2 Address bits
  Dummy = SPI_IO (Addr_Lo)	'Send 8 Address bits
  Dummy = SPI_IO (DCare) 	'Send Don't Care byte
  ReadB1 = SPI_IO (DCare)	'Read data byte

  Call PutPin (SPI_CS, 1) 	'Bring CS High to end session
End Function

Function SPI_IO (ByVal X as Byte) as Byte	'"bit-bang" I/O technique
  Dim N as Byte, Val as Byte

  For N = 1 to 8
    If ( (X AND bx10000000) <> 0) Then		'Set up MOSI
       Call PutPin (MOSI, 1)
    Else
       Call PutPin (MOSI, 0)
    End If

    Call PutPin (SPI_CLK, 1)			'And then provide CLK pulse
    Val = (Val * 2) + GetPin (MISO)		'Set up MISO
    Call PutPin (SPI_CLK, 0)

    X = X * 2					'Move next bit into MSB position
  Next
  SPI_IO =  (Val XOR bx11111111)		'Inversion
End Function