// ###########################################################################
// #
// # OSCASDMMCCard - Definition of OSCA SD/MMC Card Emulation Class
// # Copyright (C) 2009-2011 Tony Friery [DialTone]
// #
// # ALL RIGHTS RESERVED
// #
// ###########################################################################

#ifndef OSCASDMMCCardH
#define OSCASDMMCCardH

#include <vcl.h>
#include "z80.h"

///////////////////////////////////////////////////////////////////////
//
//		Identifiers and Defines for the SD Card Protocol
//
///////////////////////////////////////////////////////////////////////

// Common command set
#define CMD0_GO_IDLE_STATE          	0x00
#define CMD1_SEND_OPCOND            	0x01
#define CMD9_SEND_CSD               	0x09
#define CMD10_SEND_CID              	0x0a
#define CMD12_STOP_TRANSMISSION     	0x0b
#define CMD13_SEND_STATUS           	0x0c
#define CMD16_SET_BLOCKLEN          	0x10
#define CMD17_READ_SINGLE_BLOCK     	0x11
#define CMD18_READ_MULTIPLE_BLOCK   	0x12
#define CMD24_WRITE_BLOCK           	0x18
#define CMD25_WRITE_MULTIPLE_BLOCK  	0x19
#define CMD27_PROGRAM_CSD           	0x1b
#define CMD28_SET_WRITE_PROT        	0x1c
#define CMD29_CLR_WRITE_PROT        	0x1d
#define CMD30_SEND_WRITE_PROT       	0x1e
#define CMD32_ERASE_WR_BLK_START_ADDR 	0x20
#define CMD33_ERASE_WR_BLK_END_ADDR   	0x21
#define CMD38_ERASE                 	0x26
#define CMD55_APP_CMD               	0x37
#define CMD56_GEN_CMD               	0x38
#define CMD58_READ_OCR              	0x3a
#define CMD59_CRC_ON_OFF            	0x3b

// Application-specific commands (always prefixed with CMD55_APP_CMD)
#define ACMD13_SD_STATUS            	0x0d
#define ACMD22_SEND_NUM_WR_BLOCKS   	0x16
#define ACMD23_SET_WR_BLK_ERASE_COUNT 	0x17
#define ACMD41_SEND_OP_COND         	0x29
#define ACMD42_SET_CLR_CARD_DETECT  	0x2a
#define ACMD51_SEND_SCR             	0x33

// R1 format responses (ORed together as a bit-field)
#define R1_NOERROR   	0x00
#define R1_IDLE      	0x01
#define R1_ERASE     	0x02
#define R1_ILLEGAL   	0x04
#define R1_CRC_ERR   	0x08
#define R1_ERASE_SEQ 	0x10
#define R1_ADDR_ERR  	0x20
#define R1_PARAM_ERR 	0x40

// R2 format responses - second byte only, first is identical to R1
#define R2_LOCKED    	0x01
#define R2_WP_FAILED 	0x02
#define R2_ERROR     	0x04
#define R2_CTRL_ERR  	0x08
#define R2_ECC_FAIL  	0x10
#define R2_WP_VIOL   	0x20
#define R2_ERASE_PARAM 	0x40
#define R2_RANGE_ERR 	0x80

///////////////////////////////////////////////////////////////////////
//
//		Definition of SD/MMC Handler Class
//
///////////////////////////////////////////////////////////////////////


class TOSCASDCard
{
	private:
		typedef enum {
			SD_CMDWAIT,			// Waiting Command Value
			SD_WAITA1,			// Waiting Address Part 1
			SD_WAITA2,			// Waiting Address Part 2
			SD_WAITA3,			// Waiting Address Part 3
			SD_WAITA4,			// Waiting Address Part 4
			SD_WAITCHK,			// Waiting Checksum
			SD_WAITWRSTART,	// Waiting Write Start Token
			SD_EXECUTE			// Executing Command
		} SDOpModes;

		bool					fSPIEnabled;		// FPGA SPI Enabled
		bool					fPowered;			// POWER active on card
		bool					fSelected;			// CS active on card
		bool					fSPISpeed;			// (false = 250KHz, true = 8MHz)
		SDOpModes			fCurrentOpMode;
		byte					fCurrentCommand;
		unsigned int		fCurrentParams;
		TMemoryStream		*fImageStream;
		byte					fOutputBuffer[1024];
		word					fBufferWritePointer;
		word					fBufferReadPointer;
		bool					fWaitingAppCmd;
		word					fWriteOffset;
		bool					fIsReading;
		bool					fIsWriting;
		bool					fChangesPending;

		byte __fastcall	Encode(byte Seed, byte Input, byte Depth);
		byte __fastcall 	MakeCommandCRC(byte Command, unsigned int params);
		void __fastcall	AddToQueue(byte Value);
		void __fastcall	FlushQueue(void);
		void __fastcall 	HandleCommand(byte Checksum);

	public:
		void __fastcall	AttachImage(UnicodeString imageName);
		void __fastcall	WriteToImage(UnicodeString imageName);
		bool __fastcall	GetChangesPending(void);
		byte __fastcall	GetCtrl2Port(void);
		void __fastcall	WriteCtrl2Port(byte Value);
		void __fastcall	WriteCtrl1Port(byte Value);
		byte __fastcall	GetByte(void);
		void __fastcall	WriteByte(byte Value);
		void __fastcall	Reset(void);
		void __fastcall	Tick(unsigned int NumCycles);
		bool __fastcall	GetBusy(void);
		bool __fastcall	IsReading(void);
		bool __fastcall	IsWriting(void);
		bool __fastcall	IsAttached(void);

		__fastcall 			TOSCASDCard();
		__fastcall			~TOSCASDCard();
};

//---------------------------------------------------------------------------

#endif


