IDE CDROM Interface

from ROB BOARDMAN [rob at BOARDMANR.FREESERVE.CO.UK]

;CDROM IDE INTERFACE

;TESTED ON MODELS CREATIVE SB CR-581-J (QUAD SPEED)
;& GOLDSTAR (LG) CRD-8400C (40X SPEED)
;
;SHORT PROGRAMME TO CONTROL A CDROM VIA THE IDE
;ONLY SENDS A FEW COMMANDS BUT ITS A START
;Ryan Pogge says:
;The next step is to read the TOC and create some type of list from that on the PIC
;looks like it is a matter of sending  8c 0 e 0 0 0 0    , and getting 9 bytes back.
;anyone who is interested I have a couple of links that may be of some use
;http://www.geocities.com/SiliconValley/Hardware/2342/mp3player.html this is a 68HC11 based MP3 player with an IDE CD-ROM, I suspect this will have mush pertinate info.
;http://www-stu.cai.cam.ac.uk/~atm26/electronics/panasoniccd.html list of error codes
;http://www.mp3ar.com/  (this is a cd based mp3 player with free source code!)
;http://www.spectsoft.com/mp3tech/  (good CD, MP3, and IDE stuff here)
;http://www.angelfire.com/ms/mp3player/page17.html
;http://www.faqs.org/faqs/pc-hardware-faq/enhanced-IDE/part2/
;http://pages.hotbot.com/cooking/anton_verheijen/main.html
;http://www.imbdev.com/ (MAS3507 proto boards)

;COMMANDS SENT DEPENDING ON PORTB PINS 5/4/3 & RE2
;EJECT/LOAD/PLAY STATED MSF/ STOP.
;CURRENTLY SUPPORTS NO INTERRUPT HANDLING OR ERROR CONDITIONS
;RETURNED FROM IDE

;SET YOUR CDROM TO MASTER DEVICE

;**********************************************************************
;SEE DOC ATA Packet Interface for CD-ROMs SFF-8020i

;    Filename:	    COM1.asm
;    Date:
;    File Version:    VER1
;
;    Author:ROB BOARDMAN                                                          *
;    Company:

;**********************************************************************
;USING 16MHZ CRYSTAL & PIC NO OTHER IC'S REQUIRED MAY WORK AT 20MHZ
;SOME PINS ON PORTB ARE SWITCH INPUTS
;IF USING RE2 AS SWITCH INPUT ADD PULLUP RESISTOR

;PIN CONNECTIONS
;
;	PIC	IDE                                                                  *
;	PORTA
;	0	37	CS0
;	1	38	CS1
;	2	35	A0
;	3	33	A1
;	4	36	A2
;	5	34	PDIAG

;	PORTB
;	0	1	RESET
;	1	27	IORDY
;	2	31	IRQ
;	3
;	4
;	5
;	6
;	7

;	PORTC
;	0	3	D0
;	1	5	D1
;	2	7	D2
;	3	9	D4
;	4	11	D5
;	5	13	D6
;	6	15	D7
; M. Adam Davis says:
; it looks like you've almost got the listing backwards...
; Is it supposed to be:
;       PORTC
;       0       17      D0
;       1       15      D1
;       2       13      D2
;       3       11      D3
;       4       9       D4
;       5       7       D5
;       6       5       D6
;       7       3       D7

;	PORTD
;	0	4	D8
;	1	6	D9
;	2	8	D10
;	3	10	D11
;	4	12	D12
;	5	14	D13
;	6	16	D14
;	7	18	D15

;	PORTE
;	0	25	nDIOR
;	1	23	nDIOW

;		2	GND
;		19	GND
;		22	GND
;		24	GND
;		26	GND
;		30	GND
;		40	GND

;This example has a couple of switches connected for various CD functions as follows
;RB3	EJECT DISC	internal pullup
;RB4	STOP DISC	internal pullup
;RB5	PLAY DISC	internal pullup
;RE2	LOAD DISC 	Note use pull resistor


;*************************************************************************
;*************************************************************************
;*************************************************************************
;*************************************************************************

	list      p=16f877            ; list directive to define processor
	#include <p16f877.inc>        ; processor specific variable definitions


	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _DEBUG_OFF & _CPD_OFF



;***** VARIABLE DEFINITIONS


DELAY0	equ	$2C
DELAY1	equ	$2D
DELAY2	equ	$2E

FLAGREG	equ	$2F

#DEFINE ERROR	0X2F,0	;ERROR STATUS
#DEFINE SECONDWR 0X2F,1

TEMP1	equ	$30
TEMP	equ	$31
TEMP0	equ	$32

REGISTER	equ	$33
ACCA	equ	$34
PACK	equ	$35
TEXT	equ	$36


status_temp	equ	$3E
w_temp	equ	$3F


CTRL	equ	0
CMD	equ	1
DRIVE0	equ	0
;**************************************************
;PIN ASSIGNMENTS TO IDE
#DEFINE nCS1FX	0X05,0
#DEFINE nCS3FX	0X05,1
#DEFINE	DA0	0X05,2
#DEFINE	DA1	0X05,3
#DEFINE	DA2	0X05,4
#DEFINE	nDASP	0X05,5
#DEFINE	nDIOR	0X09,0
#DEFINE	nDIOW	0X09,1
#DEFINE	INTRQ	0X06,2
#DEFINE	IORDY	0X06,1
#DEFINE	RESET	0X06,0
;***************************************************
;THESE ARE SIGNALS WHICH END UP ON PORTA
;ADDRESSES VARIOUS REGISTERS WITHIN THE IDE DEVICE

COMMANDREG	equ	%00011110	;WRITE
STATUSREG	equ	%00011110	;READ
DATAREG	equ	%00000010

;BITS WITHIN STATUS REG OF IDE
BSY	equ	7
DRQ	equ	3

;BITS WITHIN Interrupt Reason Register
CoD	equ	0
IO	equ	1

#DEFINE DELAYS

;**********************************************************************
	org	$000
	nop
;*** WARNING: PCLATH register bits are in STATUS PAx bits. Or use PAGE/IREAD if possible
;		clrf    PCLATH            ; ensure page bits are cleared
	clr	PCLATH	; ensure page bits are cleared
	jmp	init	;


	org	$004	; interrupt vector location
	mov	w_temp, W	; save off current W register contents
	mov	W, STATUS	; move status register into W register
	mov	status_temp, W	; save off contents of STATUS register


	mov	W, status_temp	; retrieve copy of STATUS register
	mov	STATUS, W	; restore pre-isr STATUS register contents
	swap	w_temp
	mov	W, <>w_temp	; restore pre-isr W register contents
;*** WARNING: SX saves/restores W, STATUS, and FSR automatically.
;		retfie                    ; return from interrupt
	reti	; return from interrupt

;**************************************************************************
;**************************************************************************

		; initialization routine
		;SETUP ALL PORTS

init	setb	STATUS.RP0	;SET PAGE 1

	mov	W, #%00100000	;
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;        MOVWF   TRISA
	mov	TRISA, W

	mov	W, #%00111110	;
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;        MOVWF   TRISB
	mov	TRISB, W

	mov	W, #%11111111
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;        MOVWF	TRISC
	mov	TRISC, W

	mov	W, #%11111111
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;	MOVWF	TRISD
	mov	TRISD, W

	mov	W, #%00000100
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;	MOVWF	TRISE
	mov	TRISE, W

	mov	W, #%10000110
	mov	ADCON1, W

;*** WARNING: OPTION register is accessed only by MOV !OPTION, W.
;        BCF	OPTION_REG,NOT_RBPU	;PULLUPS ON
	clrb	OPTION_REG.NOT_RBPU	;PULLUPS ON

	clrb	STATUS.RP0	;BACK TO PAGE 0
	clr	RA
	clr	RB
	clr	RC
	clr	RD
;*********************************************************
	clrb	RESET	;SETUPS IDE AND RESETS
	call	PAUSE
	setb	nCS1FX
	setb	nCS3FX
	setb	nDIOR
	setb	nDIOW
	call	PAUSE
	call	PAUSE
	setb	RESET
	call	PAUSE
	call	PAUSE
	call	PAUSE
	call	PAUSE
	call	PAUSE
	clr	FLAGREG
	jmp	START
;***************************************
;***************************************
;***************************************
PAUSE
        IFDEF DELAYS
	clr	!WDT
	mov	W, #255	;
	mov	DELAY0, W	;
DELLP	decsz	DELAY0	;
	jmp	DELLP	;
	ENDIF
	ret
;************************************************************************
WRITEIDE	setb	nDIOW	;PUTS DATA FROM TEMP0 & TEMP1 REGISTERS
	mov	W, REGISTER	;ON TO IDE DATABUS LINE D0-D15 THEN TOGGLES
	mov	RA, W	;nDIOW PIN (WRITE INSTRUCTION)
	setb	STATUS.RP0
	mov	W, #%00000000
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;        MOVWF   TRISC
	mov	TRISC, W
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;	MOVWF	TRISD
	mov	TRISD, W
	clrb	STATUS.RP0
	mov	W, TEMP0
	mov	RC, W
	mov	W, TEMP1
	mov	RD, W
	clrb	nDIOW
	setb	nDIOW
	setb	STATUS.RP0	;SET PAGE 1
	mov	W, #%11111111	;
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;        MOVWF   TRISC
	mov	TRISC, W
;*** WARNING: TRIS registers are accessed by MOV !Rx, W (M = $0F or $1F).
;	MOVWF	TRISD
	mov	TRISD, W
	clrb	STATUS.RP0
	ret
;******************************************************************
READIDE	nop	;READS IDE DATA BUS D0-D15
	clrb	nDIOR	;PLACES DATA INTO TEMP0 & TEMP1 REGISTERS
	setb	nDIOR
	mov	W, RC
	mov	TEMP0, W
	mov	W, RD
	mov	TEMP1, W
	ret
;********************************************************************
CHKCoD	clrb	ERROR	;CoD=1 IO=0
	mov	W, #%10001010	;ERROR CHECKING NOT YET SUPPORTED
	mov	RA, W
	call	READIDE
	sb	TEMP0.CoD
	setb	ERROR
	snb	TEMP0.IO
	setb	ERROR
	nop
	snb	ERROR
	jmp	TEST5
	ret
TEST5	inc	TEMP
	jmp	CHKCoD
;*******************************************************************
CHKDRQ	clrb	ERROR	;BSY=0 DRQ=1
	call	RDSTATUS	;;ERROR CHECKING NOT YET SUPPORTED
	snb	TEMP0.BSY
	setb	ERROR
	sb	TEMP0.DRQ
	setb	ERROR
	nop
	snb	ERROR
	jmp	TEST6
	ret
TEST6	inc	TEMP
	jmp	CHKDRQ


;******************************************************************

;*******************************************************************
;ROUTINE SENDS 12 BYTE PACKET TO IDE DEVICE

SENDCOM	call	CHKSTATUS	;DO CHECK
 			;***********************************
	mov	W, #COMMANDREG	;POINT TO COMMAND REG THEN SEND
	mov	REGISTER, W	;PACKET OPCODE COMMAND
	mov	W, #$A0
	mov	TEMP0, W
	call	WRITEIDE
			;************************************

			;CHECK STATUS OF IDE
	call	CHKCoD	;CHK CoD & IO & BSY

	call	CHKDRQ	;WAIT FOR DRQ=1


			;************************************

	mov	W, #DATAREG	;POINT TO DATA REGISTER THEN SEND
	mov	REGISTER, W	;12 BYTES TO DATA REGISTER WITHIN IDE (1 PACKET)
	clr	ACCA
NXREG2	call	PACKET
	mov	TEMP0, W
	inc	ACCA
	inc	PACK
	call	PACKET
	mov	TEMP1, W
	call	WRITEIDE
	inc	PACK
	inc	ACCA
	mov	W, #$0C
	mov	W, ACCA-w
	sb	Z
	jmp	NXREG2
	retw	#00H

;END OF PACKET RETURN TO MAIN PROGRAM
;*******************************************************************


;12 BYTE LOOKUP TABLE FOR CDROM COMMANDS
;DEPENDING ON THE VALUE OF PACK LOOKUP JUMPS TO
;RETURNS WITH 1 OF 12 BYTES
;

PACKET	mov	W, PACK
;*** WARNING: PCLATH register bits are in STATUS PAx bits. Or use PAGE/IREAD if possible
;	BCF PCLATH,0
	clrb	PCLATH.0
;*** WARNING: PCLATH register bits are in STATUS PAx bits. Or use PAGE/IREAD if possible
;        BCF PCLATH,1
	clrb	PCLATH.1
	mov	W, PACK
	add	PC, W

	;*************************
	retw	#$1B	;0	STOP DISC COMMAND
	retw	#$00	;1
	retw	#$00	;2
	retw	#$00	;3
	retw	#$00	;4
	retw	#$00	;5
	retw	#$00	;6
	retw	#$00	;7
	retw	#$00	;8
	retw	#$00	;9
	retw	#$00	;10
	retw	#$00	;11
	;******************************************
	retw	#$47	;0		0XC0
	retw	#$00	;1	THIS EXAMPLE PLAYS AT 1min in for 30sec's
	retw	#$00	;2	PLAY DISC AT TIME STATED MIN SEC 1/75/SEC
	retw	#$01	;3	MINUTES STARTING POINT
	retw	#$00	;4	SECONDS STARTING POINT
	retw	#$00	;5	1/75 SEC STARTING POINT (N/A)
	retw	#$01	;6	MINUTES STOPING POINT
	retw	#$1E	;7	SECONDS STOPING POINT
	retw	#$00	;8	1/75 STOPPING POINT	(N/A)
	retw	#$00	;9
	retw	#$00	;10
	retw	#$00	;11
	;******************************************
	retw	#$1B	;0	0X18
	retw	#$00	;1	EJECT DISC COMMAND
	retw	#$00	;2
	retw	#$00	;3
	retw	#$02	;4
	retw	#$00	;5
	retw	#$00	;6
	retw	#$00	;7
	retw	#$00	;8
	retw	#$00	;9
	retw	#$00	;10
	retw	#$00	;11
	;******************************************
	retw	#$1B	;0	0X24
	retw	#$00	;1	LOAD DISC COMMAND
	retw	#$00	;2
	retw	#$00	;3
	retw	#$03	;4
	retw	#$00	;5
	retw	#$00	;6
	retw	#$00	;7
	retw	#$00	;8
	retw	#$00	;9
	retw	#$00	;10
	retw	#$00	;11
	;******************************************
	retw	#$43	;0	0X30
	retw	#$00	;1
	retw	#$00	;2
	retw	#$00	;3
	retw	#$00	;4
	retw	#$00	;5
	retw	#$00	;6
	retw	#$00	;7
	retw	#$08	;8
	retw	#$00	;9
	retw	#$00	;10
	retw	#$00	;11
;******************************************
;******************************************

WRITEHD	mov	W, #%10011010	;WRITE TO HEAD DEVICE REG WITHIN IDE
	mov	REGISTER, W
	mov	W, #%10100000	;SET CDROM HEAD REG TO MASTER
	mov	TEMP0, W
	clr	TEMP1
	call	WRITEIDE
	ret

RDHD	mov	W, #%10011010	;READS HEAD REG
	mov	RA, W	;I USED THIS TO CHECK
	call	READIDE	;IF CDROM WAS SET AS MASTER
	ret

RDSTATUS	mov	W, #%10011110	;READS STATUS REGISTER WITHIN IDE
	mov	RA, W
	call	READIDE
	ret

CHKSTATUS	clrb	ERROR
	call	RDSTATUS
	snb	TEMP0.BSY
	setb	ERROR
	snb	TEMP0.DRQ
	setb	ERROR
	nop
	snb	ERROR
	jmp	TEST4
	ret

TEST4	inc	TEMP
	jmp	CHKSTATUS


;*****************************************
;LOADS PACK REGISTER FOR LOOKUP TABLE
;THEN CALLS ROUTINE TO SEND 12 BYTES (1 PACKET)

PLAY	mov	W, #$0C
	mov	PACK, W
	call	SENDCOM
	ret

STOP	mov	W, #$00
	mov	PACK, W
	call	SENDCOM
	ret

EJECT	mov	W, #$18
	mov	PACK, W
	call	SENDCOM
	ret

LOADDISC	mov	W, #$24
	mov	PACK, W
	call	SENDCOM
	ret

;****************************************************************************
START	call	PAUSE
	call	CHKSTATUS
	call	PAUSE
	nop
	call	WRITEHD	;SETUP FOR MASTER DRIVE
	nop
	call	PAUSE
	call	RDHD	;READ DRIVEHEAD (CHECKING MASTER DRIVE SETTING)OPTIONAL
	call	PAUSE

	;NOTE THERE IS NO DEBOUNCE SOFTWARE AT THE MOMENT
	;SO RELEASE THE BUTTON QUICKLY

TEST1	sb	RB.5
	call	PLAY
	sb	RB.4
	call	STOP
	sb	RB.3
	call	EJECT
	clrb	ERROR
	sb	RE.2
	call	LOADDISC
	call	PAUSE
	call	RDSTATUS
	jmp	TEST1


	END

Also: