; Orange programmer module v4.2 ; (c) 2000-2015 CnCLab ;CHIP=PIC16F505,1023x12,P16F505.hpl ;AREA=CODE,1023x12,0 ;AREA=ID,4x12,0x400,0x800 ;AREA=CONFIG,1x12,0,0x1FFE ; based on PIC12F510.HPL ;Orange3,4,5,SE ;primary tested ; OSCALL вынесен из общего адресного пространства ; Для изменения использовать команду Erase ; Запоминать и восстанавливать значение 3FF & 404 ; Начальная область не закрывается битом CP!!! OPTIONS=f,f, ALLPINS=14 INFO="PIC Adapter" PING=SDA,1,13 ;RB0 PINO=CLK,0,12 ;RB1 PINO=MCLR,5,4 ;/MCLR PINO=VDD,254,1 ;Vdd PING=GND,255,14 ;Vss CDELAY=2 R1=CONFIG,H R10=MCLR,L,0:RB3,1:MCLR R11=CP,L,0:On,1:Off R12=WDT,L,0:Off,1:On R13=FOSC,L,000:LP,001:XT,010:HS,011:EC,100:INOSC-RB4,101:INOSC-CLKOUT,110:EXTRC-RB4,111:EXTRC-CLKOUT R16=CALIBRATION,H4 R17=OSCCAL,H4 ;R18 - ID ;R8 use for store address [_PULSE] CLK=1,P=2,CLK=0,P=2 [_COMMAND] ; R0 - CMD P=1 LOOP=(0,5){SDA=R0[I],CLK=P} P=1 [_OUTWORD] SDA=0,CLK=1,CLK=0 LOOP=(0,13){SDA=R0[I],_PULSE} SDA=0,CLK=1,CLK=0 [_INWORD] R1=0 SDA=1,_PULSE LOOP=(0,13){_PULSE,R1[I]=SDA} SDA=1,_PULSE [_INCADD] R8=ADR LOOP=(0x800){ ;increment address to current value! R9?R8{BREAK} _COMMAND(6) ;INCADD R9=+1 } [!#SETUP] $WDELAY=5000 [_INIT] VCC=1 CLK=0,SDA=0 $VERSION=/65536 ;PRINT=("%u",$VERSION) MCLR=0,CLK=0,SDA=0 $VERSION?3{ PRINT=S("Power up...") P=600000 ;charge Vpp cap! } ;VCC=0 P=50000 VPP=12000,P=10 ;O4! MCLR=1 ;Vcc pulse for re-enter prg mode ;Programm/Verify Mode! P=200000 PRINT=S(" ") [INIT] ;PRINT=L("init...\n") _INIT R9=0 ;current address register $AREA?0{ ;code _COMMAND(6) ;INCADD ;goto 0 address! } $AREA?1{ ;ID _COMMAND(6) ;INCADD ;goto 0 address! ;PRINT=L("GOTO %03X",RC); LOOP(RC){_COMMAND(6)} ;INCADD 400h } ;-------------------------------------------------------- ;------------------------------------------------- [_FUSE2BIT] ; unpack config word ; 5 4 3 2 1 0 ; MCLRE CP WDTE FOSC2 FOSC1 FOSC0 R10=0,R11=0,R12=0,R13=0 R13[0]=R1[0],R13[1]=R1[1],R13[2]=R1[2] ;FOSC R12[0]=R1[3] ;WDTE R11[0]=R1[4] ;CP R10[0]=R1[5] ;MCLR [_BIT2FUSE] ;copy separate bits to config word R1=0xFFF R1[0]=R13[0],R1[1]=R13[1],R1[2]=R13[2] ;FOSC R1[3]=R12[0] ;WDTE R1[4]=R11[0] ;CP R1[5]=R10[0] ;MCLR [_READFUSES] ; только после входа! _COMMAND(4) ;RDPROG _INWORD ;PRINT=("Configuration Word = %04lX",R1) ;copy config world to separate bits ADR=0 DATA=R1 [_WRITEFUSES] ; только сразу после входа! ADR=0 R1=DATA R1=|0x3FC0 _COMMAND(2) ;LDPROG _OUTWORD(R1) ;config _COMMAND(8) ;BEGPRG P=20000 _COMMAND(0xE) ;ENDPRG ; check? _COMMAND(4) ;RDPROG R2=R1 _INWORD R1=&0x3F R2=&0x3F R1?!R2{PRINT=("Write error! [%04lX]",R1)} ;-------------------------------------------------------- [READ] $AREA?2{_READFUSES,RETURN} _INCADD _COMMAND(4) ;RDPROG _INWORD DATA=R1 [WRITE] $AREA?2{_WRITEFUSES,EXIT} R0=DATA,R0=&0x0FFF,R0?0x0FFF{RETURN} ;не пишем пустые во FLASH для ускорения _INCADD _COMMAND(2) ;LDPROG _OUTWORD(DATA) _COMMAND(0x8) ;BEGPRG P=$WDELAY _COMMAND(0xE) ;ENDPRG [~!#Fuse Editor"] $AREA=2 ;FUSES R1=DATA _FUSE2BIT GET=("Edit Fuses",R10,R11,R12,R13) RA?0{EXIT} _BIT2FUSE DATA=R1 ["~Read Calibration"] $AREA?!0{PRINT=E("Select CODE Area first!"),EXIT} ; OSCCAL: _INIT R9=0 ;current address register _COMMAND(6) ;goto 0000 ADR=0 LOOP=($SIZE){_COMMAND(6)} ;INCADD goto 0x3FF _COMMAND(4) ;RDPROG Reset Vector _INWORD R16=R1 ;LOOP=(6){ ;_COMMAND(6) ;INCADD - goto 0x404 ;_COMMAND(4) ;RDPROG Backup OSCCAL ;_INWORD ;PRINT=L("%04X\n",R1) ;} LOOP=(5){_COMMAND(6)} ;INCADD - goto 0x404 _COMMAND(4) ;RDPROG Backup OSCCAL _INWORD R17=R1 MCLR=0,VPP=0,P=5000 CLK=0,SDA=0 GET=("OSCALL",R16,R17) ;---------------------------------------------------------------------- ;Перед стиранием кристалла необходимо запомнить: ;Read and save 0x3FF oscillator calibration ;bits and 0x404 backup OSCCAL bits ;into computer/programmer temporary memory. ;---------------------------------------------------------------------- [Erase] $AREA?!0{PRINT=E("Select CODE Area first!"),EXIT} PRINT=S("Erase...") ; Save OSCCAL: ADR=0 LOOP=($SIZE){_COMMAND(6)} ;INCADD goto 0x3FF _COMMAND(4) ;RDPROG _INWORD R16=R1 LOOP=(5){_COMMAND(6)} ;INCADD - goto 0x404 _COMMAND(4) ;RDPROG _INWORD R17=R1 ;PRINT=("OSCCAL = %04lX %04lX",R16,R17) ADR=$SIZE R17?!0x3FFF{DATA=R17} ; Restore OSCALL : GET=("Restore OSCALL value ?",R16,R17) RA?0{ ;no erase OSCALL VPP=0,MCLR=0,P=100,VCC=0,P=100000 ;power off _INIT _COMMAND(6) _COMMAND(6) ;goto _COMMAND(9) ;Bulk Erase P=40000 RETURN } _COMMAND(9) ;Bulk Erase P=40000 DATA=R16 ;OSCALL to dump PRINT=S("Restore OSCALL value %04lX",R17) MCLR=0,VPP=0,P=1000 VCC=0,P=100000 VCC=1,P=100000 _INIT ADR=0 LOOP=($SIZE){ ;Goto 0x3FF _COMMAND(6) ;INCADD } _COMMAND(6) _COMMAND(2) ;LDPROG _OUTWORD(R16) _COMMAND(8) ;BEGPRG P=50000 _COMMAND(0xE) ;ENDPRG LOOP(5){ ;Goto 0x404 _COMMAND(6) ;INCADD } _COMMAND(2) ;LDPROG _OUTWORD (R17) _COMMAND(8) ;BEGPRG P=50000 _COMMAND(0xE) ;ENDPRG [END] MCLR=0,VPP=0,P=5000 CLK=0,SDA=0,VCC=0,P=10000 ;PRINT=("END")