OPTION EXPLICIT

'LED1 is SD_LED and LED2 is USB_LED
CONST SD_LED = 20	'GP15
CONST USB_LED = 26 	'GP20
SETPIN SD_LED, DOUT	'on
SETPIN USB_LED, DOUT'on
PIN(SD_LED)=1
PIN(USB_LED)=0

'IR Receiver
SETPIN GP22, IR 				'allocate pin
DIM INTEGER DevCode, KeyCode	'variables to use
DIM INTEGER newCode, newKey
newCode=0
newKey=0
IR DevCode, KeyCode, IRInt 		'and set up IR interrupt

'IC2, IC3 memory chips are on SPI2
CONST IC2_CS=10				'GP7
CONST IC3_CS=12				'GP9
SETPIN IC2_CS, DOUT
SETPIN IC3_CS, DOUT
PIN(IC2_CS)=1				'idle high
PIN(IC3_CS)=1				'idle high
SETPIN GP8,GP11,GP10,SPI2
SPI2 OPEN 10000000, 0, 8	'manually open SPI
DIM SPI2_RX AS INTEGER		'for incoming data
DIM I AS INTEGER

PRINT "TERMINAL BACKPACK PICOMITE DEMO"

I2C2_SCAN

PRINT "IC2 ID:&H";HEX$(READMEMID(IC2_CS),8);". IC2 IS ";GETCHIPNAME$(IC2_CS)
'PRINT "ADD:";: FOR I = 0 to 15: PRINT " ";HEX$(I,2);:NEXT I:PRINT
'PRINT "MEM:";: FOR I = 0 to 15: PRINT " ";HEX$(READMEMBYTE(IC2_CS,I),2);:NEXT I:PRINT
PRINT "IC3 ID:&H";HEX$(READMEMID(IC3_CS),8);". IC3 IS ";GETCHIPNAME$(IC3_CS)
'PRINT "ADD:";: FOR I = 0 to 15: PRINT " ";HEX$(I,2);:NEXT I:PRINT
'PRINT "MEM:";: FOR I = 0 to 15: PRINT " ";HEX$(READMEMBYTE(IC3_CS,I),2);:NEXT I:PRINT

PRINT "READY"

DIM KEY_BUFFER AS STRING
DIM OLD_KEY_BUFFER AS STRING
DIM KEY_ENTRY AS STRING
KEY_BUFFER=""
PRINT CWD$;">";

DO	''main loop
	KEY_ENTRY=INKEY$	
	IF LEN(KEY_ENTRY)>0 THEN
		'PRINT ASC(KEY_ENTRY) 'debugging
		IF ASC(KEY_ENTRY)=8 THEN 	''backspace			
			KEY_ENTRY=""
			IF LEN(KEY_BUFFER)>0 THEN KEY_BUFFER=LEFT$(KEY_BUFFER,LEN(KEY_BUFFER)-1)
		ENDIF
		IF ASC(KEY_ENTRY)=128 THEN ''up, repeat previous
			KEY_ENTRY=""
			KEY_BUFFER=OLD_KEY_BUFFER
			PRINT CHR$(13);"                        ";	''wipe
		ENDIF
		IF ASC(KEY_ENTRY)=27 THEN 	''escape
			KEY_ENTRY=""	''blank
			KEY_BUFFER=""
			PRINT	''start new line
		ENDIF
		KEY_BUFFER=KEY_BUFFER+KEY_ENTRY
		PRINT CHR$(13);CWD$;">";KEY_BUFFER;"    ";CHR$(13);CWD$;">";KEY_BUFFER;
	ENDIF
	IF ASC(RIGHT$(KEY_BUFFER,1))=13 THEN CHECK_CMD
LOOP

SUB CHECK_CMD
	KEY_BUFFER=UCASE$(KEY_BUFFER)
	OLD_KEY_BUFFER=LEFT$(KEY_BUFFER,LEN(KEY_BUFFER)-1)	''store previous, stripping CR
	PRINT
	IF (LEFT$(KEY_BUFFER,2)="IR") THEN IR_WAIT
	IF (LEFT$(KEY_BUFFER,4)="HELP") THEN SHOW_HELP
	IF (LEFT$(KEY_BUFFER,3)="DIR") THEN DIR_CMD
	IF (LEFT$(KEY_BUFFER,2)="A:") THEN DRIVE "A:":KEY_BUFFER=""
	IF (LEFT$(KEY_BUFFER,2)="B:") THEN DRIVE "B:":KEY_BUFFER=""
	IF (LEFT$(KEY_BUFFER,3)="CD ") THEN CHDIR_CMD
	IF (LEFT$(KEY_BUFFER,2)="CD") THEN PRINT "PLEASE SPECIFY A FILENAME":KEY_BUFFER=""
	IF (LEFT$(KEY_BUFFER,4)="TIME") THEN CHECK_RTC:PRINT TIME$:KEY_BUFFER=""
	IF (LEFT$(KEY_BUFFER,4)="DATE") THEN CHECK_RTC:PRINT DATE$:KEY_BUFFER=""
	IF (LEFT$(KEY_BUFFER,4)="DEL ") THEN DEL_CMD
	IF (LEFT$(KEY_BUFFER,3)="DEL") THEN PRINT "PLEASE SPECIFY A FILENAME":KEY_BUFFER=""
	IF (LEFT$(KEY_BUFFER,6)="MKDIR ") THEN MKDIR_CMD
	IF (LEFT$(KEY_BUFFER,5)="MKDIR") THEN PRINT "PLEASE SPECIFY A FILENAME":KEY_BUFFER=""
	IF (LEFT$(KEY_BUFFER,4)="TONE") THEN TONE_CMD
	IF LEN(KEY_BUFFER)>0 THEN PRINT "UNKNOWN COMMAND, TRY HELP"	''commands should clear buffer before returning
	KEY_BUFFER=""
	PRINT CWD$;">";
END SUB

SUB TONE_CMD
	LOCAL INTEGER FREQ,DUR
	KEY_BUFFER=RIGHT$(KEY_BUFFER,LEN(KEY_BUFFER)-4)
	FREQ=VAL(KEY_BUFFER)
	IF FREQ<100 THEN FREQ=440	'default
	IF INSTR(KEY_BUFFER,",")>0 THEN
		DUR=VAL(MID$(KEY_BUFFER,INSTR(KEY_BUFFER,",")+1,6))
	ELSE
		DUR=1000
	ENDIF
	IF DUR>10000 THEN DUR=10000	'sanity check
	'PRINT FREQ,DUR
	ON ERROR SKIP 	
	PLAY TONE FREQ, FREQ, DUR
	IF MM.ERRNO <> 0 THEN
		PRINT MM.ERRMSG$	
	ELSE
		PAUSE DUR
	ENDIF
	KEY_BUFFER=""
END SUB

SUB DEL_CMD
	KEY_BUFFER=RIGHT$(KEY_BUFFER,LEN(KEY_BUFFER)-4)
	ON ERROR SKIP 
	KILL KEY_BUFFER
	IF MM.ERRNO <> 0 THEN PRINT MM.ERRMSG$	
	KEY_BUFFER=""
END SUB

SUB MKDIR_CMD
	KEY_BUFFER=RIGHT$(KEY_BUFFER,LEN(KEY_BUFFER)-6)
	ON ERROR SKIP 
	MKDIR KEY_BUFFER
	If MM.ERRNO <> 0 THEN PRINT MM.ERRMSG$	
	KEY_BUFFER=""
END SUB

SUB CHECK_RTC
	ON ERROR SKIP 
	RTC GETTIME
	If MM.ERRNO <> 0 THEN PRINT MM.ERRMSG$
END SUB

SUB DIR_CMD
	IF LEFT$(CWD$,1)="B" THEN PIN(SD_LED)=0	''flicker on activity
	LOCAL STRING F$
	LOCAL INTEGER DN
	LOCAL INTEGER FN
	IF LEN(KEY_BUFFER)=3 THEN
		KEY_BUFFER="*.*"
	ELSE
		KEY_BUFFER=RIGHT$(KEY_BUFFER,LEN(KEY_BUFFER)-4)
	ENDIF	
	DN=0
	FN=0
	F$ = DIR$(KEY_BUFFER, DIR)
		DO WHILE F$ <> ""
		DN=DN+1
		PRINT F$
		F$ = DIR$()
	LOOP	
	F$ = DIR$(KEY_BUFFER, FILE)
		DO WHILE F$ <> ""
		FN=FN+1
		PRINT F$
		F$ = DIR$()
	LOOP	
	'ON ERROR SKIP 	
	'If MM.ERRNO <> 0 THEN PRINT MM.ERRMSG$
	KEY_BUFFER=""
	PRINT DN; " DIRECTORIES AND ";FN;" FILES FOUND"
	PRINT MM.INFO(free space);" BYTES FREE"
	PIN(SD_LED)=1
END SUB

SUB SHOW_HELP
	KEY_BUFFER=""
	PRINT
	PRINT "HELP show this help"
	PRINT "IR start IR receiver"
	PRINT "A:/B: change drive"	
	PRINT "DIR list files/directories"
	PRINT "CD change working directory"
	PRINT "MKDIR create new directory"
	PRINT "DEL delete file"
	PRINT "TIME show time"
	PRINT "DATE show date"
	PRINT "TONE F,T play tone"
	PRINT
END SUB

SUB CHDIR_CMD
	IF LEFT$(CWD$,1)="B" THEN PIN(SD_LED)=0	''flicker on activity
	ON ERROR SKIP 
	CHDIR RIGHT$(KEY_BUFFER,LEN(KEY_BUFFER)-3)
	If MM.ERRNO <> 0 THEN PRINT MM.ERRMSG$
	KEY_BUFFER=""
	PIN(SD_LED)=1
END SUB

SUB IRInt				''update for use outside ISR
	newKey=KeyCode	
	newCode=DevCode
END SUB

FUNCTION READMEMID(CS AS INTEGER) AS INTEGER		'reads ID register
  PIN(CS)=0       		''CS LOW
  SPI2_RX = SPI2(&H9F)   			''read JEDEC Man/Device ID
  READMEMID=SPI2(0)  				''send dummy, get byte 1
  READMEMID=READMEMID*256+SPI2(0)  	''send dummy, get byte 2
  READMEMID=READMEMID*256+SPI2(0)  	''send dummy, get byte 3
  READMEMID=READMEMID*256+SPI2(0)  	''send dummy, get byte 4
  PIN(CS)=1       		''CS HIGH
END FUNCTION

FUNCTION READMEMBYTE(CS AS INTEGER, ADD AS INTEGER) AS INTEGER
  PIN(CS)=0       		''CS LOW
  SPI2_RX = SPI2(&H03)   			''slow read
  SPI2_RX=SPI2((ADD\65536) AND 255)	''address MSB
  SPI2_RX=SPI2((ADD\256) AND 255)	''address 2nd byte
  SPI2_RX=SPI2((ADD) AND 255)		''address LSB
  READMEMBYTE=SPI2(0)  				''send dummy, get result
  PIN(CS)=1       		''CS HIGH
END FUNCTION

FUNCTION GETCHIPNAME$(CS AS INTEGER) AS STRING
  LOCAL INTEGER ID
  ID=READMEMID(CS)
  IF ID=&H0000000D THEN GETCHIPNAME$="ESP PSRAM":EXIT FUNCTION
  IF ID=&HEF401600 THEN GETCHIPNAME$="WINBOND 25Q32":EXIT FUNCTION
  GETCHIPNAME$="UNKNOWN"
END FUNCTION

SUB I2C2_SCAN
	LOCAL INTEGER N,J
	J=0
	PRINT "I2C2 DEVICE SCAN":PRINT "   ";
	FOR N = 0 TO 15: PRINT " x";HEX$(N,1);:NEXT N
	FOR N = 0 TO 127
		IF ((N AND 15)=0) THEN PRINT: PRINT HEX$(N\16,1);"x ";
		IF ((N<8) OR (N>119)) THEN
			PRINT "   ";	''special address
		ELSE
			I2C2 WRITE N,0,1,0
			IF MM.I2C = 0 THEN
				PRINT " ";HEX$(N,2);
				J=J+1
			ELSE
				PRINT " ..";
			ENDIF
		ENDIF
	NEXT N
	PRINT: PRINT J;" DEVICES FOUND":PRINT
END SUB

SUB IR_WAIT
	KEY_BUFFER=""
	PRINT "WAITING FOR IR SIGNAL"
	PRINT "PRESS ANY KEY TO EXIT"
	DO
		IF (newCode <> 0) OR (newKey <> 0) THEN
			PRINT "Received device = " newCode " key = " newKey	''output data
			newCode=0		''reset for next
			newKey=0
		END IF
		IF INKEY$ <>"" THEN EXIT SUB
	LOOP
END SUB	
