; Orange programmer module v4.8
; (c) 2010-2014 CnCLab
; Atmel AVR AT90CAN128

;CHIP=AT90CAN32,32K,at90can.hpl
;AREA=FLASH,32K(128),0
;AREA=EEPROM,1K
;AREA=FUSES,3
;AREA=LOCK,1
;IMAGE=atm128

;CHIP=AT90CAN64,64K,at90can.hpl
;AREA=FLASH,64K(128),0
;AREA=EEPROM,2K
;AREA=FUSES,3
;AREA=LOCK,1

;CHIP=AT90CAN128,128K,at90can.hpl
;AREA=FLASH,128K(128),0
;AREA=EEPROM,4K
;AREA=FUSES,3
;AREA=LOCK,1

;Tested AT90CAN128


ALLPINS=0
;INFO="AVR Adapter"
OPTIONS=mf,   ;FLASH: no modify, skip blank
CDELAY=4 ; minimum periods for the serial clock (SCK) > 4 XTAL1 clock cycle!

PINO=SCK,  0  ;PB1 10
PINO=MOSI, 2  ;PE0 2
PING=MISO, 1  ;PE1 3
PINO=RESET,3  ;20


PINO=GND,255  ;22,53,63
PINO=VCC,254  ;VCC,AVCC 21,52,64

BUSO=CFREQ,128 ;XTAL1 24

R9=Lock,C6,BLB12,BLB11,BLB02,BLB01,LB2,LB1
R10=CKSEL,L,"0000: Ext Clk,0001: IntRC 1MHz,0010: IntRC 2MHz,0011: IntRC 4MHz,0100: IntRC 8MHz,0101: ExtRC 0.9MHz,0110: ExtRC 0.9-3.0M,0111: ExtRC 3.0-8.0M,1000: ExtRC 8.0-12.0M,1001: LowFreq Crystal,1010: Crystal/Ceramic,1011: Crystal/Ceramic,1100: Crystal 0.9-3.0,1101: Crystal 0.9-3.0,1110: Crystal 3.0-8.0,1111: Crystal 3.0-8.0"
R11=SUT,C2,1,0
R12=CKOUT,L,"0 - On,1 - Off"
R13=CKDIV8,L,"0 - On,1 - Off"

R14=BOOTRST,L,"0 - Boot Loader","1 - Application"
R15=BOOTSZ,L,"32 pages,16 pages,8 pages,4 pages"
R16=EESAVE,L,"0 - Save,1 - Clear"
R17=WDTON,L,"0 - On,1 - Off"
;The SPIEN Fuse is not accessible in serial programming mode
R18=JTAGEN,L,"0 - On,1 - Off"
R19=OCDEN,L,"0 - On,1 - Off"

;TA0SEL Reserved for factory tests
R1A=BODLEVEL,L,"000:2.5V,001:2.6V,010:2.7V,011:3.8V,100:3.9V,101:4.0V,110:4.1V,111:BOD DISABLE"


[_DOUTIN]
R1=0
LOOP=(7,0){MOSI=R0[I],SCK=1,R1[I]=MISO,SCK=0}

[_DOUT]
;LOOP=(7,0){MOSI=R0[I],SCK=P}
; fast out
MOSI=R0[7],SCK=P
MOSI=R0[6],SCK=P
MOSI=R0[5],SCK=P
MOSI=R0[4],SCK=P
MOSI=R0[3],SCK=P
MOSI=R0[2],SCK=P
MOSI=R0[1],SCK=P
MOSI=R0[0],SCK=P


[_DIN]
R0=0
;LOOP=(7,0){SCK=1,R0[I]=MISO,SCK=0}
; fast in
SCK=1,R0[7]=MISO,SCK=0
SCK=1,R0[6]=MISO,SCK=0
SCK=1,R0[5]=MISO,SCK=0
SCK=1,R0[4]=MISO,SCK=0
SCK=1,R0[3]=MISO,SCK=0
SCK=1,R0[2]=MISO,SCK=0
SCK=1,R0[1]=MISO,SCK=0
SCK=1,R0[0]=MISO,SCK=0

[!#SETUP]
$WDELAY=5000 ;tWD_FLASH minimum - 4.5 ms


[_RDLOCKO]
_DOUT(0x58)  ;rd lock bits
_DOUT(0x00) 
_DOUT(0x00) 


[_RDLOCK]
_DOUT(0x58)  ;rd lock bits
_DOUT(0x00) 
_DOUT(0x00) 
_DIN

[_WRLOCK]
_DOUT(0xAC) ;Write lock bits
_DOUT(0xE0)
_DOUT(0x00)
R0=DATA
R0=|0xC0,_DOUT
P=10000


[_RDFUSE]
R7=ADR
R7?0{
_DOUT(0x50)   ;Read Fuse LOW
_DOUT(0x00)
}
     
R7?1{     
_DOUT(0x58)   ;Read Fuse High 
_DOUT(0x08)
}
 
R7?2{         
_DOUT(0x50)   ;Read Fuse ext
_DOUT(0x08)
}
_DOUT(0x00)

;_DIN	;read


[_WRFUSE]
R7=ADR
R7?0{
_DOUT(0xAC) ;Fuse LOW
_DOUT(0xA0)
}

R7?1{
_DOUT(0xAC) ;Fuse High 
_DOUT(0xA8)
}

R7?2{
_DOUT(0xAC) ;Fuse Ext
_DOUT(0xA4)
}

_DOUT(0x00)
R0=DATA
_DOUT
P=10000


[INIT]
SCK=0
MISO=Z
CFREQ=2000000       ;2MHz

RESET=0,P=20000     ;min 20ms

;R5=0
LOOP=(32){    ; 32 attempts
RESET=1,P=500
RESET=0,P=15000
_DOUT(0xAC) ;Programming Enable
_DOUT(0x53)
_DOUTIN(0x00)
R3=R1
_DOUT(0)
R3?0x53{BREAK}
;PRINT=("ANSWER: %02lX",R1)

;R5=+1,R5?>16{$CDELAY=+1,PRINT=L(".")}  ;if no answer - decrees speed
}
R3?!0x53{PRINT=("ANSWER ERROR: %02lX",R3),EXIT}

P=10

; check ID code
_DOUT(0x30)
_DOUT(0x00)
_DOUT(0x00)
_DIN
R0?!0x1E{PRINT=A("MCU return wrong ID code (%02lX)",R0)
RA?0{EXIT}
}
;PRINT=L("$CDELAY=%u\n",$CDELAY)

$AREA?<2{ ;flash and ee can read in secured state
RE?<4{
_RDLOCK
R0=&3
R0?0{PRINT=S("#MCU memory locked!")}
}
}

[_RDFL]
R0=0x20            ;program memory area
R1=ADR,R0[3]=R1[0] ;Hi/Lo
_DOUT
LOOP=(16,9){MOSI=ADR[I],SCK=P}
LOOP=(8,1){MOSI=ADR[I],SCK=P}
_DIN		;return R0


[READ]
$AREA?0{
R0=0x20            ;program memory area
R1=ADR,R0[3]=R1[0] ;Hi/Lo
_DOUT
;LOOP=(16,9){MOSI=ADR[I],SCK=P}
R0=ADR,R0=>>9,_DOUT
;LOOP=(8,1){MOSI=ADR[I],SCK=P}
R0=ADR,R0=>>1,_DOUT
}
$AREA?1{
_DOUT(0xA0)      ;eeprom area
LOOP=(15,8){MOSI=ADR[I],SCK=P}
LOOP=(7,0){MOSI=ADR[I],SCK=P}
}

$AREA?2{  ;fuse
_RDFUSE
}

$AREA?3{  ;LOCK
_RDLOCKO
}

_DIN		;common
DATA=R0


[WRITE]
$AREA?0{
PRINT=("Only Page Write Supported!")
EXIT
}

$AREA?1{
_DOUT(0xC0) ;eeprom memory area
LOOP=(15,8){MOSI=ADR[I],SCK=P}
LOOP=(7,0){MOSI=ADR[I],SCK=P}
R0=DATA,_DOUT
P=10000 ; tWD_EEPROM minimum 9.0 ms
}


$AREA?2{
_WRFUSE
}

$AREA?3{
_WRLOCK
}


[WRITEBLOCK]
; FLASH area
R7=ADR	;check empty (0xFF) block
;LOOP=($BLOCKSIZE){
;R1=DATA
;R1?!0xFF{BREAK}
;ADR=+1
;}
;R1?0xFF{RETURN}
;ADR=R7

LOOP=($BLOCKSIZE){
R0=0x40 ;program memory
R1=ADR,R0[3]=R1[0],_DOUT 	;Hi/Lo
R0=0,_DOUT
LOOP=(8,1){MOSI=ADR[I],SCK=P}
R0=DATA,_DOUT
P=10
ADR=+1
}
;Write Program memory Page:
ADR=R7
_DOUT(0x4C)
LOOP=(16,9){MOSI=ADR[I],SCK=P}
LOOP=(8,6){MOSI=ADR[I],SCK=P}
LOOP=(5,1){MOSI=0,SCK=P}
_DOUT(0) 		;dummy data

;Data Polling Flash. will not work for the value 0xFF
;R2=DATA
;R2?0xFF{P=$WDELAY,RETURN}  ;tWD_FLASH minimum - 4.5 ms
;LOOP(2000){
;_RDFL
;R2?R0{BREAK} ;Ok
;P=5
;}
;R2?!R0{PRINT=S("#Write timeout! [%02X]",R0)}

;AT90CAN specific Poll RDY/BSY
LOOP(500){
_DOUT(0xF0)
_DOUT(0x00)
_DOUT(0x00)
_DIN
R0=&1
R0?0{BREAK}
P=10
}


[WRITEEND]
P=10000
RESET=1,P=20
;RESET=0,P=20000




["!#~Fuse Editor"]
$AREA=2 ;FUSE

R10=0,R11=0,R12=0,R13=0
R14=0,R15=0,R16=0,R17=0
R18=0,R19=0,R1A=0

ADR=0, R0=DATA  ;Low fuse

R10=R0,R10=&0xF	;R10=CKSEL,L
R11[0]=R0[4]    ;R11=SUT,L,1,2,3,4           
R11[1]=R0[5]
R12[0]=R0[6]    ;R12=CKOUT 
R13[0]=R0[7]    ;R13=CKDIV8

ADR=1,R0=DATA

R14[0]=R0[0]	;R14=BOOTRST,C1
R15[0]=R0[1]	;R15=BOOTSZ,L,"32 pages,16 pages,8 pages,4 pages"
R15[1]=R0[2]	
R16[0]=R0[3]	;R16=EESAVE
R17[0]=R0[4]	;R17=WDTON
;SPIEN not accessible
R18[0]=R0[6]	;R18=JTAGEN
R19[0]=R0[7]	;R18=OCDEN

ADR=2,R0=DATA	;EXT

R1A[0]=R0[1]	;BODLEVEL
R1A[1]=R0[2]
R1A[2]=R0[3]

GET=("Fuses",R10,R11,R12,R13,R14,R15,R16,R17,R18,R19,R1A)

RA?0{EXIT}

;PRINT=("%lX",R11)
R10?0{  ;CKSEL
PRINT=A("This fuses value require Ext. Clock, continue?")
RA?0{EXIT}
}

ADR=0
R0=R10,R0=&0xF	;R10=CKSEL,L
R0[4]=R11[0]    ;R11=SUT,L,1,2,3,4           
R0[5]=R11[1]
R0[6]=R12[0]    ;R12=CKOUT 
R0[7]=R13[0]    ;R13=CKDIV8
DATA=R0

ADR=1
R0=0xFF
R0[0]=R14[0]	;R14=BOOTRST,C1
R0[1]=R15[0]	;R15=BOOTSZ,L,"32 pages,16 pages,8 pages,4 pages"
R0[2]=R15[1]	
R0[3]=R16[0]	;R16=EESAVE
R0[4]=R17[0]	;R17=WDTON
R0[5]=0 ;SPIEN not accessible
R0[6]=R18[0]	;R18=JTAGEN
R0[7]=R19[0]	;R18=OCDEN
DATA=R0

ADR=2
R0=0xFF	;EXT
R0[1]=R1A[0]	;BODLEVEL
R0[2]=R1A[1]
R0[3]=R1A[2]
DATA=R0


["!#~Lock Editor"]
$AREA=3 ;Lock
R9=DATA
GET=("Lock",R9)
RA?0{EXIT}
R9=|0xC0
DATA=R9

[READID]
_DOUT(0x30)
_DOUT(0x00)
_DOUT(0x00)
_DIN
R2=R0,R2=<<8

_DOUT(0x30)
_DOUT(0x00)
_DOUT(0x01)
_DIN
R2=|R0,R2=<<8

_DOUT(0x30)
_DOUT(0x00)
_DOUT(0x02)
_DIN
R0=|R2

;R2?0x1E9581{PRINT=("ID: %06lX - AT90CAN32",R2),EXIT}
PRINT=S("ID: %06lX",R0)


["Read Calibration"]
_DOUT(0xF0)
_DOUT(0x00)
_DOUT(0x00)
_DIN
PRINT=("Calibration = %02XH",R0)


[Erase]
_DOUT(0xAC) ;Chip Erase
_DOUT(0x80)
_DOUT(0x00)
_DOUT(0x00)

P=50000

; Check
ADR=0
_RDFL ;Read program memory area ;ADR 0
R0?!0xFF{PRINT=E("Erase error")}

R0?0xFF{PRINT=S("Erase finished")}
RESET=1,P=2000
RESET=0,P=500000



[END]
RESET=1
CFREQ=0
;EO=1,P=10 ;BB off