; Orange programmer module v3.0 - Orange3,4,5,SE
; (c) 2008-2015 CnCLab
;CHIP=PIC16F54,512x12,p16f54.hpl
;AREA=CODE,512x12,0
;AREA=USER_ID,4x12,0x400
;AREA=CONFIG,1x14,0x1FFE


; Tested

ALLPINS=18
INFO="PIC Adapter"
OPTIONS=f

;
PING=SDA,1,13 ;RB7
PINO=CLK,0,12 ;RB6
PINO=MCLR,5,4  ;/MCLR

PING=GND,255,5  ;Vss

CDELAY=2


R12=CP,L,0:On,1:Off
R13=WDTE,L,0:Off,1:On
R14=FOSC,L,00:LP,01:XT,10:HS,11:RC

R16=Erase,L2,Flash,Flash&ID

[_PULSE]
CLK=1,P=1,CLK=0,P=1

[_COMMAND]
; R0 - CMD
LOOP=(0,5){SDA=R0[I],_PULSE}

;PRINT=L("CMD=%02X\n",R0)

[_OUTWORD]
SDA=0,_PULSE
LOOP=(0,11){SDA=R0[I],_PULSE}
SDA=0
_PULSE
_PULSE
SDA=0,_PULSE


[_INWORD]
R1=0
SDA=1,_PULSE
LOOP=(0,11){_PULSE,R1[I]=SDA}
_PULSE
_PULSE
SDA=1,_PULSE

;Flash - 0000h
;ID    - 0200h
;Config- 03FFh
[_INCADD]
R8=ADR
R0=RC,R0=/2
R8=+R0
R8=&0x3FF
LOOP=(0xFFF){  ;increment address to current value!
R9?R8{BREAK}
_COMMAND(6) ;INCADD
R9=+1
R9=&0x3FF
}


[_FUSE2BIT]
; unpack config word
R12=0,R13=0,R14=0
R12[0]=R1[3]	;CP
R13[0]=R1[2]	;WDTE
R14[1]=R1[1]	;FOSC1
R14[0]=R1[0]	;FOSC0

[_BIT2FUSE]
;copy separate bits to config word
R1=0xFFF
R1[3]=R12[0]	;CP
R1[2]=R13[0]	;WDTE
R1[1]=R14[1]	;FOSC1
R1[0]=R14[0]	;FOSC0
;PRINT=("Configuration Word = %04lX",R1)




;The OSC must not have 72 osc clocks while the device MCLR is between VIL and VIHH.
[INIT]
VPP=0
MCLR=0,CLK=0,SDA=0,P=100
$VERSION=/65536
$VERSION?3{
P=150000
}
CLK=0,SDA=0,P=20
MCLR=1  ;Programm/Verify Mode!
VPP=13000,P=20000	; min delay for O4!
SDA=1,P=500
R9=0x3FF ;current address register

$AREA?0{
RE?!4{ ;not user functions
_COMMAND(6) ;INCADD	;goto 0 address!
R9=0
}
}
$AREA?2{RC=0x7FE}  ;internal address


[READ]
$AREA?!2{
_INCADD
}

_COMMAND(4)          ;RDPROG
_INWORD
DATA=R1 


[WRITE]
$AREA?0{R0=DATA,R0=&0xFFF,R0?0xFFF{RETURN}}   ;не пишем пустые во FLASH для ускорения

$AREA?!2{
_INCADD
}

_COMMAND(2)          ;LDPROG

R0=DATA
_OUTWORD

_COMMAND(8) ;BEGPRG
P=10000
_COMMAND(0xE) ;ENDPRG


[~!#"Fuse Editor"]
$AREA=2	;FUSES
R1=DATA
_FUSE2BIT
GET=("Edit Fuses",R12,R13,R14)
RA?0{EXIT}
_BIT2FUSE
DATA=R1


[Erase]
GET=("Erase",R16)
RA?0{EXIT}
;To perform a Bulk Erase of the program memory, configuration fuses and user IDs, the following
;sequence must be performed 
;1. Enter Program/Verify mode
;2. Increment PC to 0x200 (first user ID location)
R16?1{
LOOP=(0x201){_COMMAND(6)} ;INCADD
}

_COMMAND(9) ;ERASE
P=50000


[END]
MCLR=0
VPP=0
CLK=0,SDA=0