; Orange programmer module v1.14  for Orange4/5
; (c) 2009-2015 CnCLab
; Samsung, Hynix NAND Flash Memory 5bytes addr.,2K page +ECC



;Hynix
; CHIP=H27U2G8F ECC,270336K(2112),H27U2G8Fe.HP4  ;256MB
; VCC=3250                                                        

; tested: H27U2G8F2CT

INFO="NAND FLASH Adapter"
INFOFILE="k9k4g08.txt"

SOCKET=0
CDELAY=0
ALLPINS=48
OPTIONS=f

;Input pins:
PINI=P0,0,29
PINI=P1,1,30
PINI=P2,2,31
PINI=P3,3,32
PINI=P4,4,41
PINI=P5,5,42
PINI=P6,6,43
PINI=P7,7,44

;Output pins:
PINO=CLE,8,16	;	Command Latch Enable    
PINO=ALE,9,17	;	Address Latch Enable    
PINO=CE,10,9	;	Chip Enable             
PINO=RDE,11,8	;	Read Enable             
PINO=WE,12,18	;	Write Enable            

BUSO=DATAO,0
BUSI=DATAI,0

;Power pins:
PINO=Vcc1,254,23	;     +5V
PINO=Vcc2,254,44	;     +5V
PING=GND,255,40		;     GND
PING=Vss1,255,1		;     GND
PING=Vss2,255,22	;     GND


BUSO=PULLUP,255
;R10=PAGE,H
R12=Erase,L,Cancel,Erase

;[!#SETUP]
;R10=0

[INIT]
DATAO=Z
CE=1,RDE=1,WE=1
ALE=0
CLE=0
;PULLUP=1
P=10

RDE=1,CE=0,CLE=1,ALE=0
DATAO=90h		;cmd readid
WE=N
ALE=1,CLE=0
DATAO=0			;ADR A0-A7
WE=N
DATAO=Z ; HiZ state
ALE=0,P=15
RDE=0,P=15
R0=DATAI   ;
RDE=1
CE=1
R0?0xFF{PRINT=A("Chip answer error [%02XH]\nContinue?",R0) ;check id
RA?0{EXIT}
}


[_SENDADR]
CLE=0,ALE=1
DATAO=0			;ADR A0-A7
WE=N
;R0=/256,R0=&0xF,DATAO=R0	;ADR A8-A15
DATAO=0			;ADR A8-A15
WE=N

R0=ADR
R0=/$BLOCKSIZE,DATAO=R0		;ADR A12-A19...
WE=N

R0=>>8
DATAO=R0			;ADR A20...A27 
WE=N

R0=>>8,R0=&0xF
DATAO=R0			;ADR A28...A29 
WE=N
ALE=0

[_CMD]
ALE=0
CLE=1
DATAO=R0		;cmd 
WE=N
CLE=0


[_RDSTAT]
RDE=1,CE=0
_CMD(70h)			;cmd
ALE=1
DATAO=Z ; HiZ state
P=15
ALE=0,RDE=0
P=15
R0=DATAI
RDE=1
CE=1

[_READ]
RDE=1,CE=0
_CMD(0x00)			;cmd rd
_SENDADR
_CMD(0x30)		;cmd rd2
DATAO=Z ; HiZ state
R0=DATAI
P=28     ;Data Transfer from Cell to Register 
$MODE?!0{P=$MODE}
ALE=0,RDE=0
R0=DATAI
DATA=R0
RDE=1,CE=1

[READBLOCK]
RDE=1,CE=0
_CMD(0x00)	    ;cmd rd
_SENDADR
_CMD(0x30)	    ;cmd rd2
DATAO=Z,R0=DATAI ; HiZ state

;Data Transfer from Cell to register tR
;H27U2G8F2CT- 25us
;HY27UH088G - 30us
;K9K8G08U1A - 25us
;K9G8G08U1A - 60us !!!
P=28   ;меньше не делать!
$MODE?!0{P=$MODE}

;LOOP($BLOCKSIZE){
;RDE=0
;DATA=DATAI
;RDE=1
;ADR=+1
;}

R0=$BLOCKSIZE,R0=/2
LOOP(R0){
RDE=0
DATA=DATAI
RDE=1
ADR=+1
RDE=0
DATA=DATAI
RDE=1
ADR=+1
}


CE=1
CE=0
_CMD(0xFF)	;rst
CE=1

[WRITEINIT]
;WP=1
P=20

[WRITEBLOCK]
RDE=1,CE=0

_CMD(0x80)			;cmd
_SENDADR
ALE=0
LOOP($BLOCKSIZE){
R0=DATA
DATAO=R0
WE=N
ADR=+1
}


_CMD(0x10)			;cmd program
;P=500
;CE=1
P=10
;_RDSTAT
;PRINT=S("Status0=%02lX",R0)

CLE=0
LOOP=(1000){
_RDSTAT
;PRINT=S("Write Status=%02lX",R0)
R0=&0x40	;busy bit
R0?!0{BREAK}
P=10
}
R0?0{PRINT=("Page write error!")}
;_RDSTAT
;PRINT=S("Status=%02lX",R0)


[READID]
RDE=1,CE=0,CLE=1,ALE=0
DATAO=90h			;cmd
WE=N
ALE=1,CLE=0
DATAO=0			;ADR A0-A7
WE=N

DATAO=Z ; HiZ state
ALE=0
P=10
RDE=0,P=10
R0=DATAI    ;1
RDE=1,P=10,RDE=0,P=10
R1=DATAI    ;2
RDE=1,P=10,RDE=0,P=10
R2=DATAI    ;3
RDE=1,P=10,RDE=0,P=10
R3=DATAI    ;4
RDE=1

CE=1
PRINT=S("ID=%02lX %02lX %02lX %02lX",R0,R1,R2,R3)
R0=<<8,R0=|R1
R0=<<8,R0=|R2

R4=R3,R4=&3, R4=+1
PRINT=L("Page Size=%uK\n",R4)

; 0-64K, 1-128K, 2-256K
R4=R3,R4=>>4,R4=&3
R5=64
R4?1{R5=128}
R4?2{R5=256}
PRINT=L("Block Size=%uK\n",R5)

R5=R0
_RDSTAT
PRINT=L("Status=%02X\n",R0)
R0=R5
;PRINT=L("R0=%04X",R0)

["Erase"] 
R12=0
GET=("Erase",R12)
RA?0{EXIT}
R12?0{EXIT}
;WP=1
R13=$SIZE
;Erase block=128K or 256K
;R13=/131072 ;128*1024
R13=/135168 ;128*1024

;K9K4G Only address A18 to A29 is valid
;K9L8G Only address A19 to A30 is valid while A12 to A18 is ignored


R11=0
PRINT=P(R11,R13)
PRINT=S("Erase Page (%u blocks)...",R13)
LOOP=(R13){
;PRINT=S("Erase %u",R11)
PRINT=P(R11)

RDE=1,CE=0
_CMD(0x60)			;cmd

ALE=1
R0=R11,R0=<<6
DATAO=R0		        ;ADR A12
WE=N

R0=R11,R0=>>2
DATAO=R0			;ADR A20...A27 page!
WE=N

R0=>>8,R0=&0xF
DATAO=R0			;ADR A28...A29 page!
WE=N

ALE=0

_CMD(0xD0)			;cmd program
CE=1
P=3000   ;                    Block Erase Time 3 ms max
R11=+1
}